Dokumentation Java 3D

Werbung
Dokumentation
Java 3D – Licht und Material
(Von Nicolaus Walter)
1. Licht
In Java 3D können Objekte von einer festgelegten Lichtquelle beleuchtet
werden. Um eine solche Beleuchtung, welche eine Simulation der Realität
darstellt, als dreidimensionales Bild auf einem Computer darstellen zu
können, bedient sich Java 3D Unterschiedlicher Mechanismen, welche,
richtig kombiniert, den gewünschten Eindruck erwecken. Die Mechanismen
sind im Einzelnen Shading, das Model des „Szene Graph“, um die
benötigten Elemente zu modellieren und zusammen wirken zu lassen und
die einzelnen Lichtklassen, welche unterschiedliche Methoden zum
Erscheinen der Lichtquellen zur Verfügung stellen. Nachfolgend sollen
diese Mechanismen genauer erklärt werden.
1.1 Shading
Unter dem Begriff „Shading“ wird in Java eine Methode zum steuern des
Verlaufs von Licht und Schatten auf einem beleuchteten Objekt
verstanden. Dazu stellt Java 3D ein Lichtmodel und einige Funktionen
zum steuern von Qualität und CPU-Nutzung zur Verfügung. Im weiteren
werden die relevanten Sachverhalte des Shading behandelt.
1.1.1 Lighting Model
Das Lighting Model simuliert die physikalischen Eigenschaften von Licht.
Dabei werden drei Vektoren eingeführt, welche zur Berechnung der
Winkel für ein- und ausfallendes Licht benötigt werden. Dies sind der
Lichtvektor, der die Richtung in welcher die Lichtquelle liegt bestimmt,
der Augenvektor, welcher in Richtung des Betrachters weist und der
Vektor der Normalen des Objektes. Die Bedeutung der Surface Normalen
wird weiter unten noch ausführlicher behandelt.
(Quelle: Java 3D Sun Tutorial)
Neben diesen drei Vektoren werden drei in der Realität vorkommende
Reflektionstypen definiert: ambient, diffuse und specular. Dabei ist eine
ambient-Reflektion die Spiegelung einer ambient-Lichtquelle, wobei die
einzelnen Lichtklassen im weiteren Verlauf dieser Dokumentation noch
erklärt werden. Die diffuse-Reflektion ist dagegen die normale Spiegelung
einer
Lichtquelle
und
eine
specular-Reflektion
simuliert
die
hellerleuchteten Stellen auf einem beleuchteten Objekt, welche in
manchen Situationen durch direkte Beleuchtung von einer Lichtquelle
entstehen können.
(Quelle: Java 3D Sun Tutorial)
1.1.2 Qualität oder Schnelligkeit
Wie oben bereits erwähnt bietet das Lichtmodel einen Augen- und einen
Lichtvektor. Diese Vektoren können vom Programmierer als konstant
oder nicht konstant gewählt werden. Ist zum Beispiel die Lichtquelle ein
„directional Light“, so ist der Lichtvektor stets konstant. Während ein
konstanter Vektor die Prozessorlast stark vermindert, bietet ein variabler
Vektor dem Programmierer natürlich mehr Möglichkeiten in der
Gestaltung einer Szene. Daher sollte die Wahl je nach Anforderung wohl
überlegt sein.
1.1.3 Zusammenspiel von Objekten
Java 3D generiert immer nur ein beleuchtetes Objekt auf einmal und kann
daher Beziehungen zwischen Objekten, also zum Beispiel den Schatten
des einen Objektes auf ein anderes zu werfen oder die Reflektion des
einen Objektes als Lichtquelle auf dem anderen zu berücksichtigen, nicht
realisieren. Dies ist erforderlich, da die Komplexität solcher Effekte die
meisten Graphiksysteme überfordern würde. Um einen solchen Effekt
dennoch zu erzielen, müssen daher auf anderem Wege, wie weiter unten
erklärt, die Effekte später in den Szenengraph eingesetzt werden.
1.1.4 Farbmodel
Als Farbmodel wird das bekannte RGB-Model verwendet. Mit diesem
lassen sich eine große Anzahl von Farben generieren, welche auf der
Mischung der Farben rot, grün und blau basieren.
1.1.5 Einflussbereich des Lichtes
Um ein Objekt beleuchten zu können, muss es im Einflussbereich der
Lichtquelle stehen. Dazu muss der Einflussbereich bei der Generierung
einer Lichtquelle angegeben werden. Im einfachsten Fall kann die
Methode setInfluencingBounds() mit einem bounds-Objekt aufgerufen
werden. Weitere Möglichkeiten werden weiter unten noch aufgezeigt.
1.1.6 Shading Model
Beim Schattieren eines Objektes wird jeder Vertex des Objektes einzeln
schattiert. Dies geschieht, indem die Schatten, die von jeder Lichtquelle
für den Vertex generiert werden, aufsummiert werden. Der Rest des
Objektes wird dann abhängig von der gewählten Shading-Funktion auf
Grund der Vertices schattiert.
Dabei sind folgende Schading-Funktionen möglich:
SHADE_GOURAUD
SHADE_FLAT
FASTEST
NICEST
Wobei bei gouraud jedes Pixel einzeln schattiert wird, währen bei flat
jedes Pixel eines Polygons den gleichen Wert für den Schatten erhält.
SHADE_FLAT
(Quelle: Java 3D Sun Tutorial)
SCHADE_GOURAUD
1.2 Lichtklassen in Java 3D
Java 3D bietet vier unterschiedliche Lichtklassen, von denen drei von der
Klasse Light erben. Dies sind die AmbientLight-, die DirectionalLightund die PointLight-Klasse. Von der PointLight-Klasse erbt wiederum die
vierte Klasse, die Klasse SpotLight.
1.2.1 AmbientLight
AmbientLight ist eine Lichtquelle, die überall in der Szene gleichermaßen
auf die Objekte wirkt. Dabei ist das Licht meist ein schwacher Schimmer
und soll den realen Sachverhalt von reflektiertem Licht darstellen, das von
allen Objekten in einem Raum zurückgeworfen und in geringen Maße auf
alle anderen Objekte wirkt, simulieren. Daher ist eine AmbientLightQuelle richtungsunabhängig, die Intensität ist an jeder Stelle gleich und
bewirkt eine ambient-Reflektion bei einem Objekt. Wie bereits im
Lighting Model gezeigt, ist eine ambient-Reflektion eine Graufärbung an
dem Objekt.
1.2.2 DirectionalLight
Möchte man eine sehr weit entfernte Lichtquelle simulieren, etwa die
Sonne, so empfiehlt sich eine DirectionalLight-Quelle einzusetzen.
Hierbei handelt es sich um eine Quelle, deren Intensität nicht mit
zunehmender Entfernung der Lichtquelle zum Objekt abnimmt und bei
welcher der Lichtvektor (siehe oben) für jeden Vertex der gleiche, also
konstant, ist.
(Quelle: Java 3D Sun Tutorial)
Die DirectionalLight-Quelle ist dabei ein helles Licht, welches diffuseund speculart-Reflektionen auslöst. Im Gegensatz zur AmbientLightQuelle
gibt es hier eine Richtung des Lichtes, so dass das Objekt
schattiert wird. Ändert man die Richtung des Lichtes, ändert sich auch die
Schattierung auf dem Objekt.
1.2.3 PointLight
Um nun eine Lichtquelle in eine Szene einzusetzen, welche etwa eine
Glühbirne oder Kerzenflamme simulieren soll, verwendet man ein
PointLight. Diese Klasse von Licht strahlt gleichmäßig in alle Richtungen
und die Intensität des Lichtes nimmt mit der Entfernung des Objektes zur
Lichtquelle hin ab. Der Lichtvektor ist dabei für jeden Vertex abhängig
von der relativen Position zur Lichtquelle und daher nicht konstant. Auch
das PointLight erwirkt diffuse- und specular-Reflektionen.
(Quelle: Java 3D Sun Tutorial)
Das PointLight besitzt außerdem eine Position in der Szene. Diese
Position ist entscheidend für das Shading. Mit sich Ändernder Position
der Quelle ändert sich auch die Schattierung auf den beeinflussten
Objekten.
1.2.4 SpotLight
Unter einem SpotLight versteht man eine Lichtquelle, welche, ähnlich
dem PointLight, eine Position im Raum besitzt und deren Lichtintensität
mit der Entfernung von der Lichtquelle abnimmt. Natürlich werden auch
von dieser Lichtklasse duffuse- und specular-Reflektionen ausgelöst.
(Quelle: Java 3D Sun Tutorial)
Anders als beim PointLight besitzt jedoch das SpotLight eine Richtung.
Neben der Richtung wird auch noch ein Winkel, in dem das Licht
ausgestrahlt wird, angegeben. Außerhalb des Winkels wird kein Licht
produziert. Der Schatten, der vom Shading erzeugt wird, ist abhängig von
dem Winkel, den der Richtungsvektor der Lichtquelle mit dem
Lichtvektor des Objektes aufspannt. Folglich ändern sich die Schatten der
Objekte, wenn sich die Richtung der Lichtquelle oder ihre Position
verändert wird. Das SpotLight kommt immer dann zum Einsatz, wenn
man zum Beispiel eine Taschenlampe oder eine Tischlampe mit
Lampenschirm erzeugen möchte.
1.2.5 Hierarchie der Lichtklassen
(Quelle: Java 3D Sun Tutorial)
1.3 Beleuchtete Szenen
Zum generieren einer gesamten Szene mit Lichtquellen und beleuchteten
Objekten sind mehrere Schritte notwendig. Neben dem Erstellen der
Lichtquellen, müssen für jedes Licht der Wirkungsbereich festgelegt
werden. Außerdem kann ein Objekt nur dann beleuchtet werden, wenn es
eine Surface Normale und Material Eigenschaften besitzt. Java 3D
benutzt,
wie
oben
beschrieben,
das
Lighting
Model
aus
den
Materialeigenschaften eines Objektes, ohne welches das Objekt zwar
koloriert, nicht aber mit Licht und Schatten dargestellt wird. Sollte auch
die Surface Normale fehlen, so bleibt das Objekt völlig weiß. Gibt man
ein Materialobjekt an, aber keine Normale, so wird eine Fehlermeldung
ausgegeben und das Objekt kann nicht gerendert werden.
Eine fehlende Lichtquelle oder das Weglassen oder Falschbestimmen des
Einflussbereiches lässt dagegen ein Objekt von der Lichtquelle unberührt
und ist dementsprechend schwieriger zu entdecken.
(Quelle: Java 3D Sun Tutorial)
1.3.1 Erstellen einer Lichtquelle
Eine neue Lichtquelle kann auf, für Java, gewöhnliche Weise mit dem
„new“-Konstruktor erstellt werden:
AmbientLight ambient = new AmbientLight();
DirectionalLight directional = new DirectionalLight();
PoinLight point = new PointLight();
SpotLight spot = new SpotLight();
AmbientLight Konstruktoren:
AmbientLight()
Produziert ein AmbientLight-Objekt mit default-Werten:
lightOn true
color (1, 1, 1)
AmbientLight(Color3f color)
AmbientLight(boolean lightOn, Color3f color)
DirectionalLight Konstruktoren:
DirectionalLight()
Produziert ein DirectionalLight-Objekt mit default-Werten:
lightOn true
color (1, 1, 1)
direction (0, 0, -1)
DirectionalLight(Color3f color, Vector3f direction)
DirectionalLight(boolean lightOn, Color3f color, Vector3f direction)
PointLight Konstruktoren:
PointLight()
Produziert ein PointLight-Objekt mit default-Werten:
lightOn true
color (1, 1, 1)
position (0, 0, 0)
attenuation (1, 0, 0)
PointLight(Color3f color, Point3f position, Point3f attenuation)
PointLight(boolean lightOn, Color3f color, Point3f position, Point3f
attenuation)
SpotLight Konstruktoren:
SpotLight()
Produziert ein SpotLight-Objekt mit default-Werten:
lightOn true
color (1, 1, 1)
position (0, 0, 0)
attenuation (1, 0, 0)
direction (0, 0, -1)
spreadAngle PI (180 degrees)
concentration 0.0
SpotLight(Color3f color, Point3f position, Point3f attenuation,
Vector3f direction, float spreadAngle, float concentration)
SpotLight(boolean lightOn, Color3f color, Point3f position, Point3f
attenuation, Vector3f direction, float spreadAngle, float
concentration)
1.3.2 Methoden der Lichtquellen
(Auszug aus dem Java 3D Tutorial von Sun)
2. Material
In der Erscheinung(appearence bundle) eines Gegenstandes, kann ein Objekt
der Klasse Material, eine Unterklasse von NodeComponent, initiiert werden.
Dieses Objekt enthält Werte für ambient-, diffuse-, specular-, emessiveFarben und außerdem noch einen Wert shininess. Aus dem Lighting Model
kennen wir bereits die drei ersten Begriffe und in der Tat werden diese Werte
dazu genutzt, die entsprechenden Reflektionen zu berechnen. Der
emessiveColor Wert erlaubt es einem Gegenstand im Dunkeln zu leuchten
und der Wert für shininess ist zusätzlich zur Ermittlung der specularReflektion benötigt.
(Quelle: Java 3D Sun Tutorial)
(Veränderung des shininess-Wertes)
Um überhaupt die Nutzung von Licht zu ermöglichen ist das Material-Objekt
unbedingt
notwendig.
Um
einem
sichtbare
Objekt
seine
Materialeigenschaften zu übergeben, kann in die appearance das MaterialObjekt mit der setMaterial() Methode eingefügt werden.
2.1 Konstruktoren und Methoden für Material
(Auszug aus dem Java 3D Tutorial von Sun)
3. Surface Normale
Wie oben bereits erwähnt, wird für das Shading eine Surface Normale
benötigt. Für ein geometrisches Objekt kann dazu eine der setNormal()
Methoden verwendet werden. Auch ist bei Java 3D ein Normalengenerator
enthalten. Dieser benutzt ein GemetryInfo-Objekt, um eine passende
Normale zu erzeugen. Daher muss der Programmierer seine Geometrie in ein
GeometryInfo-Objekt setzen und anschließend den Normalengenerator mit
jenem Objekt aufrufen, um seiner Figuren mit Normalen auszustatten.
Geometrische Primitive generieren übrigens ihre Normalen automatisch
selbst.
Es kann vorkommen, dass eine Fläche von beiden Seiten zu sehen ist, somit
ihre Normale nur für die Oberseite gültig ist. Deshalb kann man mit der
Methode setBackFaceNormalFlip() für die Unterseite eine eigene Normale
generieren.
(Quelle: Java 3D Sun Tutorial)
Fläche mit Normalen auf Vor-
Fläche mit nur einer
und Rückseite
Normalen auf der Oberseite
4. Einflussbereich des Lichtes festlegen
Wir haben schon festgestellt, dass eine Lichtquelle einen Einflussbereich
besitzt, in dem sie auf sich darin befindliche Objekte wirkt. Nachfolgend
wollen wir die Möglichkeiten zum Festlegen dieses Bereichs besprechen.
4.1 setInfluencingBounds()
Dies ist die einfachste Lösung zum Bestimmen des Einflusses der
Lichtquelle. Man generiert ein bounds-Objekt und verwendet es als
Parameter für die setInfluencingBounds() Methode.
Beispiel:
BoundingSphere myBounds = new BoundingSphere();
_ myLight.setInfluencingBounds( myBounds );
Erzeugt eine Kugel mit default-Werten, deren Mittelpunkt sich im
Koordinatenursprung befindet.
Alle sichtbaren Objekte, die sich innerhalb der Kugel befinden oder diese
berühren, werden beleuchtet. Dabei spielt es keine Rolle, ob sich das Objekt
voll in der Kugel befindet, denn sie bestimmt nur welche Objekte
beleuchtet werden und nicht welche Teile dieser Objekte.
Wird die Lichtquelle verschoben, dann verschiebt sich auch ihr
Einflussbereich entsprechend in der Umgebung. Daher können zwei
Lichtquellen, welche mit dieser Methode den gleichen Einflussbereich
bestimmt haben, letztlich einen unterschiedlichen Einflussbereich haben,
wenn nämlich eine der Lichtquellen verschoben wird.
4.2 setInfluencingBoundingLeaf()
Eine weitere Möglichkeit den Einflussbereich einer Lichtquelle festzulegen,
ist ein BoundingLeaf-Objekt zu erstellen. Ein BoundingLeaf wird direkt in
den Szenen Graph eingefügt und kann daher unabhängig von der
Lichtquelle
verschoben
werden.
Die
Methode
setInfluencingBoundingLeaf() überschreibt die setInfluencingBounds()
Methode und ersetzt so einen eventuell bestimmten Einflussbereich. Das
erstellte BoundinLeaf-Objekt kann auch von mehreren Lichtquellen
verwendet werden und die Lichtquellen unabhängig davon mit einer
TransferGroup verschoben werden. Daher haben zwei Lichtquellen mit
dem gleichen BoundingLeaf auch immer den gleichen Einflussbereich.
(Quelle: Java 3D Sun Tutorial)
Die beiden Lichtquellen werden durch eine TransferGroup bewegt, der
Einflussbereich, ein BoundingLeaf, ändert sich jedoch dadurch nicht!
4.3 Beschränken des Einflussbereiches
Hat man für eine Lichtquelle einen Einflussbereich bestimmt, ob mit einem
bounds- oder mit einem BoundingLeaf-Objekt, ist es möglich mit einer
sogenannten Scope den gewählten Bereich noch einzuschränken. Dies kann
nützlich sein, um Objekte, welche nahe beieinander liegen, leichter zu
trennen, um einen Teil zu beleuchten und einen anderen nicht. Dabei hat
jede Lichtquelle als Standard eine Scope, welche der Scope der sichtbaren
virtuellen Welt entspricht.
Ein weiterer Vorteil einer Scope ist, dass die Renderingzeit verkürzt wird,
da nur der Ausschnitt, welcher durch die Scope bestimmt ist, gerendert
werden muss.
(Quelle: Java 3D Sun Tutorial)
Möglicher Szenen Graph für das Lciht-Scoping
5. Objekte im Dunkeln leuchten lassen
Im Kapitel 2 „Material“ wurde erwähnt, dass einem Sichtbaren Objekt mit
Material-Objekt ein emissiveColor-Wert mitgegeben werden kann. Es wurde
bereits angesprochen, dass er dazu genutzt werden kann, um das Objekt im
Dunkeln leuchten zu lassen. Dabei ist zu beachten, dass das Objekt nicht zu
einer Lichtquelle wird, denn es leuchtet zwar, aber das Licht wirkt sich nicht
auf andere Objekte aus.
Die unbeleuchtete Box am hinteren Ende
der Szene wurde mit emissiveColor zum
leuchten gebracht. Man kann erkennen,
dass die restlichen Objekte in der Szene
davon nicht beeinflusst werden.
(Quelle: Java 3D Sun Tutorial)
6. Schatten
Die Berechnung von Schatten ist dermaßen komplex, dass es von Java 3D
nicht unterstützt wird. Die Komplexität resultiert aus der Frage, ob irgend ein
Punkt beleuchtet wird oder nicht. Dabei müssen alle anderen Punkte in der
Szene, die sich zwischen dem betrachteten Punkt und der Lichtquelle
befinden berücksichtigt werden. Dennoch gibt es viele Verfahren, um
Schatten simulieren zu können. Eine einfache Technik werden wir nun
nachfolgend besprechen.
6.1 Schatten Polygone
Möchte man einen Schatten für ein bestimmtes Objekt generieren, so kann
man ein Polygon in Form des gewünschten Schattens erstellen und an der
benötigten Stelle in die Szene einsetzen. Gibt man dem Objekt keine Material
Komponente, dann wird wie oben beschrieben das Objekt nicht beleuchtet,
aber Koloriert. Folglich kann es schwarz dargestellt werden und damit einen
Schatten simulieren. Da das Polygon scharf dargestellt wird und von keiner
Lichtquelle beeinflusst wird, erscheint es meist unrealistisch.
Gibt man dem Schatten eine Materialkomponente und lässt sie aus dem
Einflussbereich einer oder mehrerer Lichtquellen raus, so erhält man einen
sogenannten schattierten Schatten. Dieser wirkt etwas realistischer als ein
Schatten der mit obiger Methode generiert wurde.
Auf jeden Fall wird es sehr schwierig den Schatten mit einem Objekt mit zu
bewegen. Um dies zu realisieren müssen viele Objekte erstellt werden,
wodurch die Renderperformence deutlich verschlechtert werden kann.
Herunterladen