Das Ein- bzw. Anstellen des Lichtes ist eigentlich sehr einfach. Sie müssen wirklich nur die gewünschten Parameter setzen. Die 3D-Objekte werden dann beim rendern automatisch korrekt beleuchtet, ohne, dass Sie sich um bestimmte mathematische Formeln kümmern müssen. Das Licht wird in 3 Schritten eingestellt:
In DirectXGraphics können Sie mehrere Lichtquellen einstellen. Die genaue Anzahl ist von ihrer Grafikkarte abhängig und lässt sich über die D3DCAPS8 ermitteln. Das Einstellen des Lichtes erfolgt mit folgender Funktion des Direct3DDevices:
function SetLight(const Index : LongWord; var pLight : TD3DLight8) : HResult; |
Index: Jeder Lichtquelle, die Sie definieren, weisen Sie eine Indexzahl zu. Möchten Sie ein bestimmtes Licht ändern oder herausnehmen, können Sie dieses über den Index ansprechen.
pLight: Ein Record des Typs D3DLIGHT8, in dem alle notwendigen Farben und Parameter definiert sind.
Zu jeder Set-Funktion gibt es das entsprechende Gegenstück, die Get-Funktion:
function GetLight(const Index : LongWord; out pLight : TD3DLight8) : HResult; |
GetLight liefert für den angegebenen Index ein Record des Typs D3DLIGHT8 mit den entsprechenden Eigenschaften zurück.
Als kleines Beispiel will ich Ihnen eine Prozedur zeigen, die uns das Eingeben der Parameter für ein Spotlight erleichtert.
|
Einmal eingebunden in Ihrer Anwendung ist das Definieren von Spotlights sehr einfach, weil Sie lediglich eine Prozedur mit allen Parametern aufrufen, die nötig sind. Das spart Zeit und Platz. Der Übung halber habe ich die Prozeduren für ein Point Light und ein Directional Light weggelassen. Aber mit dieser Hilfe dürfte das für Sie jetzt kein Problem sein.
Ambientes Licht setzen Sie mit einem RenderState des Direct3DDevices:
d3ddev8.setrenderstate( D3DRS_AMBIENT, $006B6B6B ); |
Hierbei geben Sie das ambiente Licht als 32-Bit-Wert an. Schwarz ist dabei gleichbedeutend mit keinem ambienten Licht.
Materialeigenschaften eines Objektes werden nach dem gleichen Prinzip in DirectXGraphics gehandhabt, wie Lichter, bis auf den Unterschied, dass Sie jeweils immer nur ein Material zur gleichen Zeit verwenden. Daher fällt die Indexierung der Materialien raus. Das Setzen und Auslesen von Materialien geschieht mit folgenden Funktionen des Direct3DDevices:
function SetMaterial(var pMaterial : TD3DMaterial8) : HResult; function GetMaterial(out pMaterial : TD3DMaterial8) : HResult; |
pMaterial: Ist in beiden Funktionen ein Record des Typs D3DMATERIAL8, das alle Materialeigenschaften beinhaltet.
Auch hier bietet es sich an, eine Funktion zu schreiben, die uns das umständliche Eingeben und Setzen des Materials erleichtert. Diese Funktion könnte zum Beispiel so aussehen:
procedure SetMaterial( _ar, _ag, _ab, _aa, _dr, _dg, _db, _da, _sr, _sg, _sb, _sa, _er, _eg, _eb, _ea, _power: Single); var mtrl : TD3DMATERIAL8; begin ZeroMemory( @mtrl, sizeof( TD3DMATERIAL8 ) ); with mtrl do begin Ambient.r := _ar; Ambient.g := _ag; Ambient.b := _ab; Ambient.a := _aa; Diffuse.r := _dr; Diffuse.g := _dg; Diffuse.b := _db; Diffuse.a := _da; Specular.r := _sr; Specular.g := _sg; Specular.b := _sb; Specular.a := _sa; Emissive.r := _er; Emissive.g := _eg; Emissive.b := _eb; Emissive.a := _ea; Power := _power; end; d3ddev8.SetMaterial( mtrl ); end; |
Sie können auf mehreren Ebenen kontrollieren, ob Sie Licht in Ihrer Szene haben möchten oder nicht. Zum einen können Sie entscheiden, ob die Lichtberechnung überhaupt aktiviert sein soll. Dies stellen Sie über einen Renderstate an, der wie folgt aussieht:
d3ddev8.SetRenderState( D3DRS_LIGHTING, Cardinal( TRUE ) ); |
Mit true oder false in der Cardinal-Funktion entscheiden Sie, ob DirectXGraphics überhaupt irgendwelche Lichtalgorithmen verwenden soll. Geben Sie false an, werden alle Vertices wie beleuchtete Vertices (also ohne Normale) gehandhabt und in ihren Grundfarben dargestellt.
Desweiteren können Sie für jedes einzelne Licht, dass Sie indexiert haben, entscheiden, ob dieses aktiviert sein soll, oder nicht. Die Funktion des Direct3DDevices sieht dafür folgendermassen aus:
function LightEnable(const Index : LongWord; const Enable : BOOL) : HResult; |
Index: Die Indexnummer, dessen Licht Sie an- oder ausschalten wollen.
Enable: true schaltet das Licht an, false aus.
Das Verwenden der Ambient-Farbe des Materials kann einen entscheidenden Nachteil haben. Schattenseiten werden nur in der Ambientfarbe des Materials dargestellt, aber nicht in den eigentlichen Vertexfarben. Die Vertexfarben werden im Schatten praktisch völlig ignoriert. Dieses Problem können Sie lösen, in dem Sie DirectXGraphics mitteilen, dass Sie statt des Material eine andere Quelle für die Ambientfarbe verwenden wollen. Das gilt übrigens nicht nur für Ambient sondern auch für Diffuse, Emissive, Specular:
d3ddev8.SetRenderState( D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1); d3ddev8.SetRenderState( D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_COLOR1); d3ddev8.SetRenderState( D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_MATERIAL); d3ddev8.SetRenderState( D3DRS_SPECULARMATERIALSOURCE, D3DMCS_COLOR2); |
D3DMCS_MATERIAL, D3DMCS_COLOR1 und D3DMCS_COLOR2 sind Bestandteile der D3DMATERIALCOLORSOURCE-Aufzählungen.
Der Zweck oder Nutzen dieser Einstellungen lässt sich schwer erklären. Durch Ausprobieren können Sie am schnellst feststellen, welche Effekte sich damit erzielen lassen. Dazu kann Ihnen aber auch das folgende Beispielprogramm helfen.
Diesmal fällt das Beispielprogramm ein wenig anders aus, als sonst. Es ist zwar auch eine selbstlaufende Demo, aber es ist noch viel mehr als das. Da es recht schwierig ist, auf Anhieb die Zusammenhänge zwischen Vertexfarben, Materialfarben und Lichtfarbe zu verstehen und die vielen Lichtparameter sehr grossen Spielraum lassen, habe ich für Sie ein Programm geschrieben, bei dem Sie zur Laufzeit alle relevanten Dinge verändern und direkt sehen können, welche Auswirkungen das auf die Szene hat (Achtung: nur in der Offline-Version enthalten.
Ich habe das Programm auf den Namen Lichtkasten getauft. Alle Material- und Lichtparameter (bis auf Position und Direction) sind veränderbar. Darüberhinaus können Sie auch noch einige relevanten Renderstates konfigurieren. Nehmen Sie sich Zeit für das Programm und verändern Sie die Vorgaben nach Lust und Laune. Sie werden feststellen, dass nicht jede Lichtart mit jeder Konfiguration realistisch aussieht.
Dieses Programm verwendet einen skalierten Viewport, um die 3D-Szene nur oben links darzustellen. Genauere Informationen zum Thema Viewports finden Sie im Abschnitt Viewports.