[Erledigt]Direct3D 8 zu 9 Konvertierung: Falsche Beleuchtung

Für Fragen zu Grafik APIs wie DirectX und OpenGL sowie Shaderprogrammierung.
Antworten
zfxacc32
Beiträge: 27
Registriert: 05.03.2013, 15:24

[Erledigt]Direct3D 8 zu 9 Konvertierung: Falsche Beleuchtung

Beitrag von zfxacc32 »

Hi,

ich habe ein Spiel (ohne Quellcode) von Direct3D 8 nach 9 "konvertiert", indem ich die Direct3D Interfaces gehookt und die Funktionen weitergeleitet habe (mit ein paar Anpassungen von zB. Strukturen/Parametern).
Das funktioniert auch ganz gut, doch mit der Beleuchtung der Charaktere stimmt etwas nicht.

Demonstration:

Normal (Direct3D 8):
licht1-1.jpg
Falsch (Direct3D 9):
licht1-2.jpg
Normal (Direct3D 8):
licht2-1.jpg
Falsch (Direct3D 9):
licht2-2.jpg
Als GIF, wenn ihr es in Bewegung sehen wollt (12 und 18 MB):
http://ecjgtkr5kjn7v92d.blob.core.windo ... licht1.gif
http://ecjgtkr5kjn7v92d.blob.core.windo ... licht2.gif

Ich habe leider nicht so viel Ahnung von Direct3D und frage mich, woran das liegen könnte.
Sind bei Direct3D 9 irgendwelche Standardeinstellungen/States anders? Ich hab in der Doku leider nichts gefunden, sieht alles ziemlich gleich aus.

Bin für jeden Hinweis dankbar.
MfG
Zuletzt geändert von zfxacc32 am 27.01.2016, 11:48, insgesamt 1-mal geändert.
Benutzeravatar
Schrompf
Moderator
Beiträge: 4855
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: Direct3D 8 zu 9 Konvertierung: Falsche Beleuchtung

Beitrag von Schrompf »

Hm. Sieht aus, als würden die Normalen im Skinning anders behandelt. Schau mal nach irgendwelchen States zum Thema "Inverse Transpose". Was auch sein könnte: bei DX8 hat man ja Skinning noch häufig auf der CPU gemacht. Könnte also auch sein, dass die da ein besonders komprimiertes Vertexdatenformat für die Normalen benutzen. Wobei ich glaube, dass das Licht dann nicht so falschrum mitrotieren würde, aber ausschließen würde ich es nicht.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
Krishty
Establishment
Beiträge: 8240
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Direct3D 8 zu 9 Konvertierung: Falsche Beleuchtung

Beitrag von Krishty »

Das mit den GIFs ist eine riesen Hilfe, aber könntest du vielleicht nochmal eins machen, in dem sich ein Character um sich selber dreht? Ich tippe ebenfalls auf Schrompfs Vorschlag, dass die Lichtrichtung beim Bone Skinning nicht transformiert wird. Mit einem GIF von einem Charakter, der sich einmal um sich selber dreht, könnten wir erkennen, ob die Beleuchtung mitrotiert oder nicht oder in die falsche Richtung.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
zfxacc32
Beiträge: 27
Registriert: 05.03.2013, 15:24

Re: Direct3D 8 zu 9 Konvertierung: Falsche Beleuchtung

Beitrag von zfxacc32 »

Klaro, hier bitte, auch als mp4 Video (3.5MB, muss vielleicht manuell gespeichert werden).

Richtig:
http://ecjgtkr5kjn7v92d.blob.core.windo ... light1.gif
http://ecjgtkr5kjn7v92d.blob.core.windo ... light1.mp4

Falsch:
http://ecjgtkr5kjn7v92d.blob.core.windo ... light2.gif
http://ecjgtkr5kjn7v92d.blob.core.windo ... light2.mp4

Nur sagen, wenn ihr noch mehr input braucht :)

Ich gucke mal im assembler, ob ich da was finde...
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: Direct3D 8 zu 9 Konvertierung: Falsche Beleuchtung

Beitrag von dot »

Ja, da werden definitv die Normalen nicht richtig transformiert...
zfxacc32
Beiträge: 27
Registriert: 05.03.2013, 15:24

Re: Direct3D 8 zu 9 Konvertierung: Falsche Beleuchtung

Beitrag von zfxacc32 »

Danke erstmal.
Ich würde das Ganze gerne eingrenzen. Wonach müsste ich suchen? (Wie wird das Transformieren gemacht? Welche D3D Funktionen werden benötigt?)
Woran könnte es liegen, dass es mit Direct3D 9 plötzlich nicht mehr funktioniert? Es wurde ja am Code nichts verändert, bloß das D3D 8 Interface durch das 9er ersetzt.
zfxacc32
Beiträge: 27
Registriert: 05.03.2013, 15:24

Re: Direct3D 8 zu 9 Konvertierung: Falsche Beleuchtung

Beitrag von zfxacc32 »

Was ich herausgefunden habe:
D3DRS_LIGHTING ist false und D3DFVF_NORMAL wird nicht gesetzt.
Es werden auch keine vertex shader benutzt (CreateVertexShader wird nie aufgerufen).

Aber wie funktioniert dann die Beleuchtung?
Zuletzt geändert von zfxacc32 am 26.01.2016, 00:52, insgesamt 1-mal geändert.
Benutzeravatar
Schrompf
Moderator
Beiträge: 4855
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: Direct3D 8 zu 9 Konvertierung: Falsche Beleuchtung

Beitrag von Schrompf »

Fixed Function? Welche FVFs sind denn gesetzt? Und wird der VertexBuffer jedes Frame aktualisiert oder ist der statisch?
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
zfxacc32
Beiträge: 27
Registriert: 05.03.2013, 15:24

Re: Direct3D 8 zu 9 Konvertierung: Falsche Beleuchtung

Beitrag von zfxacc32 »

Schrompf hat geschrieben:Fixed Function?
Heißt das, D3D berechnet die Normalen?
Es wird übrigens SetLight() aufgerufen.
Schrompf hat geschrieben:Welche FVFs sind denn gesetzt? Und wird der VertexBuffer jedes Frame aktualisiert oder ist der statisch?
Mit ziemlicher Sicherheit XYZ, DIFFUSE und TEX.
Die zweite Frage kann ich momentan nicht beantworten, warum ist das denn wichtig? Ich denke mal, dass der VB für die Person immer gleich ist.
Degenerated
Beiträge: 10
Registriert: 19.11.2015, 00:04

Re: Direct3D 8 zu 9 Konvertierung: Falsche Beleuchtung

Beitrag von Degenerated »

zfxacc32 hat geschrieben:Die zweite Frage kann ich momentan nicht beantworten, warum ist das denn wichtig? Ich denke mal, dass der VB für die Person immer gleich ist.
Das muss nicht sein. Gerade damals wurden Animationen oft (immer?) auf der CPU ausgerechnet und dann eben der Buffer neu befüllt, mit den transformierten Vertices.
zfxacc32
Beiträge: 27
Registriert: 05.03.2013, 15:24

Re: Direct3D 8 zu 9 Konvertierung: Falsche Beleuchtung

Beitrag von zfxacc32 »

Okay.
Was ich gerne gewusst hätte, wären alle Möglichkeiten, Beleuchtung zu implementieren.
DirectX 8.1 SDK
When you use Direct3D lighting and materials, you allow Direct3D to handle the details of illumination for you. Advanced users can perform lighting on their own, if desired.
Ich denke damit ist gemeint, dass entweder D3DRS_LIGHTING gesetzt ist und die Normalen mit im Vertexbuffer sein müssen (was scheinbar nicht der Fall ist) oder eben D3DRS_LIGHTING false ist und alle vertex colors manuell ausgerechnet werden müssen.
Stimmt das so?
Benutzeravatar
Schrompf
Moderator
Beiträge: 4855
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: Direct3D 8 zu 9 Konvertierung: Falsche Beleuchtung

Beitrag von Schrompf »

Richtig. Und falls das FVF keine Normalen enthält, geht das automatische Beleuchten nicht. Es kann aber durchaus eine Mischkalkulation sein, bei der das Lighting dann nur noch einen Ambient-Teil statisch aufaddiert und die Werte im VertexBuffer den dynamischen Teil enthalten. Die Leute damals waren kreativ im Erfinden exotischer Speziallösungen.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
zfxacc32
Beiträge: 27
Registriert: 05.03.2013, 15:24

Re: Direct3D 8 zu 9 Konvertierung: Falsche Beleuchtung

Beitrag von zfxacc32 »

// EDIT: Ups, Auslesen der FVF flags korrigiert

Ich habe mich geirrt. Nach einer etwas ausführlicheren Analyse ist nun klar: Es wird D3DFVF_NORMAL benutzt.
So sehen die Aufrufe während dem Zeichnen des Körpers aus:

Zu Beginn:

Code: Alles auswählen

Device::SetTransform: D3DTS_VIEW, 
Device::SetTransform: D3DTS_PROJECTION, 
Device::SetTransform: 256, 
Device::SetTransform: 256 bis 283 
Mehrmals hintereinander:

Code: Alles auswählen

Device::SetRenderState: D3DRS_VERTEXBLEND, D3DVBF_1WEIGHTS, 
Device::SetRenderState: D3DRS_INDEXEDVERTEXBLENDENABLE, true, 
Device::SetIndices: 0, 

// Abwandlung
Device::SetRenderState: D3DRS_VERTEXBLEND, D3DVBF_DISABLE, 
Device::SetRenderState: D3DRS_INDEXEDVERTEXBLENDENABLE, false, 
Device::SetTransform: 256, 
Device::SetIndices: 0, 

Device::SetStreamSource: 0, 327398776, 40, 
Device::SetVertexShader: D3DFVF_XYZB2, D3DFVF_NORMAL, D3DFVF_TEX1, D3DFVF_LASTBETA_UBYTE4 (Abwandlung:  D3DFVF_XYZ, D3DFVF_NORMAL, D3DFVF_TEX1)
Device::SetLight: 
Device::SetRenderState: D3DRS_FOGENABLE, true, 
Device::LightEnable: true, 
Device::SetLight: 
Device::SetLight: 
Device::SetLight: 
Device::SetLight: 
Device::SetRenderState: D3DRS_NORMALIZENORMALS, false, 
Device::SetRenderState: D3DRS_AMBIENT, 
Device::SetMaterial: 
Device::ApplyStateBlock: 25, 
Device::SetRenderState: D3DRS_ALPHATESTENABLE, false, 
Device::SetRenderState: D3DRS_ZWRITEENABLE, true, 
Device::SetRenderState: D3DRS_ZENABLE, D3DZB_TRUE, 
Device::SetRenderState: D3DRS_ZFUNC, D3DCMP_LESSEQUAL, 
Device::SetRenderState: D3DRS_ALPHABLENDENABLE, true, 
Device::SetRenderState: D3DRS_SRCBLEND, D3DBLEND_SRCALPHA, 
Device::SetRenderState: D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA, 
Device::SetTexture: 0, 
Device::SetTextureStageState: 0, D3DTSS_ADDRESSU, D3DTEXTUREADDRESS, 
Device::SetTextureStageState: 0, D3DTSS_ADDRESSV, D3DTEXTUREADDRESS, 
Device::SetTextureStageState: 0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR, 
Device::SetTextureStageState: 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE, 
Device::DrawIndexedPrimitive: D3DPT_TRIANGLELIST, 0, 46, 0, 59, 
State Block 25:

Code: Alles auswählen

Device::SetTextureStageState: 0, D3DTSS_COLOROP, D3DTOP_MODULATE, 
Device::SetTextureStageState: 0, D3DTSS_COLORARG1, D3DTA_TEXTURE, 
Device::SetTextureStageState: 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE, 
Device::SetTextureStageState: 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE, 
Device::SetTextureStageState: 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE, 
Device::SetTextureStageState: 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE, 
Device::SetTextureStageState: 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE, 
Device::SetTextureStageState: 0, D3DTSS_TEXCOORDINDEX, 0, 
Device::SetTextureStageState: 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE, 
Device::SetTextureStageState: 1, D3DTSS_TEXCOORDINDEX, 1, 
Device::SetTextureStageState: 1, D3DTSS_COLOROP, D3DTOP_DISABLE, 
Device::SetTextureStageState: 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE, 
Device::SetTextureStageState: 2, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE, 
Device::SetTextureStageState: 2, D3DTSS_TEXCOORDINDEX, 2, 
Device::SetTextureStageState: 2, D3DTSS_COLOROP, D3DTOP_DISABLE, 
Device::SetTextureStageState: 2, D3DTSS_ALPHAOP, D3DTOP_DISABLE, 
Device::SetTextureStageState: 3, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE, 
Device::SetTextureStageState: 3, D3DTSS_TEXCOORDINDEX, 3, 
Device::SetTextureStageState: 3, D3DTSS_COLOROP, D3DTOP_DISABLE, 
Device::SetTextureStageState: 3, D3DTSS_ALPHAOP, D3DTOP_DISABLE, 
Device::SetTextureStageState: 4, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE, 
Device::SetTextureStageState: 4, D3DTSS_TEXCOORDINDEX, 4, 
Device::SetTextureStageState: 4, D3DTSS_COLOROP, D3DTOP_DISABLE, 
Device::SetTextureStageState: 4, D3DTSS_ALPHAOP, D3DTOP_DISABLE, 
Device::SetTextureStageState: 5, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE, 
Device::SetTextureStageState: 5, D3DTSS_TEXCOORDINDEX, 5, 
Device::SetTextureStageState: 5, D3DTSS_COLOROP, D3DTOP_DISABLE, 
Device::SetTextureStageState: 5, D3DTSS_ALPHAOP, D3DTOP_DISABLE, 
Device::SetTextureStageState: 6, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE, 
Device::SetTextureStageState: 6, D3DTSS_TEXCOORDINDEX, 6, 
Device::SetTextureStageState: 6, D3DTSS_COLOROP, D3DTOP_DISABLE, 
Device::SetTextureStageState: 6, D3DTSS_ALPHAOP, D3DTOP_DISABLE, 
Device::SetTextureStageState: 7, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE, 
Device::SetTextureStageState: 7, D3DTSS_TEXCOORDINDEX, 7, 
Device::SetTextureStageState: 7, D3DTSS_COLOROP, D3DTOP_DISABLE, 
Device::SetTextureStageState: 7, D3DTSS_ALPHAOP, D3DTOP_DISABLE, 
Ja, stimmt, die Animationen werden wohl "manuell" gemacht. Es werden keine Shader verwendet. Der vertex buffer ist auch immer ein anderer..
Das Spiel hat ein eigenes Modellformat. Ich nehme an, dass die Normalen darin gespeichert sind. Doch was ist mit den Animationen? Ist es üblich/sinnvoll, die Normalen für jedes Animationsframe separat zu speichern?

Leider bleibt die Frage offen, wie es sein kann, dass die Normalen plötzlich nicht mehr korrekt sind.. die D3D Funktionen geben auch immer S_OK zurück.
zfxacc32
Beiträge: 27
Registriert: 05.03.2013, 15:24

Re: Direct3D 8 zu 9 Konvertierung: Falsche Beleuchtung

Beitrag von zfxacc32 »

Könnte es vielleicht an der Reihenfolge der Aufrufe liegen?
zB. das Setzen der vertex blending matrices zu Beginn (Device::SetTransform: 256 bis 283). Vielleicht muss das bei D3D 9 anderswo stehen? (Ich weiß, unwahrscheinlich).
Bin momentan ratlos :(

Ich hab auch mal versucht, die Normalen des characters zu zeichnen (bei jedem dazugehörigen DrawIndexedPrimitive() Aufruf die Vertices+Normalen aus dem gesetzten VB in einen eigenen kopieren und als D3DPT_LINELIST darstellen).
Mir werden jedoch nur die Normalen des Kopfes angezeigt, nicht aber die des restlichen Körpers (die Beleuchtung des Kopfes scheint in D3D9 übrigens korrekt, siehe das Gif/Video).
Habe die Koordinaten geloggt, sind bei D3D 8 und 9 dieselben. Ich vermute also, dass es am vertex blending liegt.

Code: Alles auswählen

vertex xyz, vertex+normal xyz

D3DFVF_XYZB3, D3DFVF_NORMAL, D3DFVF_TEX1, D3DFVF_LASTBETA_UBYTE4
-0.0616953 / -0.00293348 / 0.56213 / -0.0614068 / -0.224591 / 0.818684
-0.0456624 / 0.0174519 / 0.581081 / -0.25753 / -0.0290028 / 0.965946
-0.0481068 / 0.0288982 / 0.602599 / -0.188044 / 0.0916261 / 0.826825
...

D3DFVF_XYZ, D3DFVF_NORMAL, D3DFVF_TEX1
-581.704 / 911.786 / 94.8275 / -581.586 / 911.743 / 94.0481
-581.698 / 911.78 / 94.8297 / -581.394 / 911.751 / 94.1153
-581.705 / 911.784 / 94.8255 / -581.382 / 912.247 / 94.0737
...
Der character steht ingame übrigens ca. an Kameraposition 581/911.
zfxacc32
Beiträge: 27
Registriert: 05.03.2013, 15:24

Re: [Erledigt]Direct3D 8 zu 9 Konvertierung: Falsche Beleuch

Beitrag von zfxacc32 »

Geschafft!

Ich hatte ja mal versucht, für diese Engine hardware vertexprocessing zu aktivieren, was aber entweder zu Crashes oder Grafikfehlern führte.
Nun hab ich es endlich geschafft. Es war bloß eine fehlende Nullzeiger-Prüfung, die den Crash verursacht hat.

Netter Nebeneffekt: Die Beleuchtung ist nun auch korrekt!

(Vermutung: D3D9 kommt mit vertex blending und software vertexprocessing nicht so gut klar wie D3D8).
Antworten