Shadow Volumes mit beliebiger Geometrie, Teil 2
-
Ich verstehe nicht so recht, was du mit "Ebene des Lichts" meinst? Für mich sieht das fast so aus, als würden nur noch ein paar Polygone gezeichnet, pixelgenau dürfte der Schatten ja nicht sein.
Bye, TGGC \-/
-
Also die Position des Lichtes ist ein Punkt in der Ebene, und der Normalenvektor der Ebene entspricht dem Richtungsvektor des Lichts.
Der sichtbare Streifen ist aber unabhängig von irgendwelchen Polygonen, hier nochmal ein Bild mit dem Wireframe in grün.Es scheint so, als ob der ganze z-Bereich in diesen dünnen Streifen gequetscht wird. Dadurch dann wohl auch die Pixelgenauigkeit.
Wie kann ich denn am einfachsten mal testen, ob der z-Buffer der Shadowmap (also die Shadowmap selbst) richtig erzeugt wird? Am besten als schwarzweiß Bild anzeigen lassen. Geht das?
Ansonsten sieht es so aus, als ob mir wieder einige glückliche Stunden mit Rumprobieren bevorstünden. Ist irgendwie jedesmal so, wenn ich was neues mit D3D machen will.... ich hoffe weiterhin auf Ratschläge von Euche.
-
fang doch mal mit einer einfachereren scene an z.b. zwei planes/boxen, eine kleine auf einer grossen und ne lichtquelle davor.
so ist das echt schwer zu sagen woran es liegen könnte, gibt unheimlich viel was man bei shadowmaps beachten muss und zudem viele implementationsvariationen...
rapso->greets();
-
Ich kriegs einfach nicht hin. Habe versucht, die Beispielprogramme, die ich habe mehr oder weniger direkt zu kopieren, aber es will nicht gehen.
Ich denke, dass es am Projezieren der Shadowmap in den Level liegt. Die Shadowmap selbst sollte eigentlich soweit richtig sein.Ich dachte ja erst, dass das Projezieren schon funktioniert, da ich ein Testbild korrekt aus der Sicht des Lichtes in die Geometrie projeziert habe. Aber anscheinend ist es so, dass nicht nur die ersten beiden Einträge der Texturkoordinate benötigt werden, sondern auch die anderen beiden Ausschlag gebend sind (was ich bei einer 2D Textur nicht unbedingt erwartet hätte).
@rapso: Wenn ich das richtig verstanden habe, dann machst Du ja auch viel bzw. alles mit Shadern. Ich denke mal dann wirst Du mir helfen können. Ich will einfach die Position jeder Vertize(?) im Vertex Shader mit einer Matrix multiplizieren, und das Ergebnis als Texturkoordinate speichern. Also komplett auf dieses EYE_LINEAR_TEXCOORD_ODER_SO Zeugs verzichten.
Bisher sieht diese Matrix M so aus:
matTexAdj = \[ \left( \begin{array}{cccc} 0.5 & 0 & 0 & 0 \\ 0 & -0.5 & 0 & 0 \\ 0 & 0 & fZScale & 0 \\ 0.5 & 0.5 & fBias & 1\end{array} \right)\] fZScale = 2^2^4-1 fBias = -0.0002 \\ matLicht = matLichtView * matLichtProj \\ M = (matLicht * matTexAdj)^TDamit kann man wie gesagt eine Textur in den Level projezieren, nur mit den z-Werten klappt es eben nicht so ganz. Es entsteht dann dieser oben beschriebene Streifen (der von der Breite her übrigens genau der NearPlane der Lichtprojektion entspricht).
In dem NVidia Paper "Hardware Shadow Mapping" wird auch noch irgendwas mit der Kameramatrix gemacht. Habe ich auch schon versucht, aber es hat nicht funktioniert. Und um ehrlich zu sein: Ich hab überhaupt keinen Plan, wie diese ganzen Matrizen letztendlich arbeiten. Und somit kann ich höchstens ein wenig an den Werten rumdrehen, was ich da tue weiß ich aber nicht.Ich hoffe Du (oder jemand anderst) weißt, wie die Matrix aussehen muss
-
Also die Theorie hinter der Schadowmap ist mir klar. Man hat den Z-Buffer quasi in der Textur und alles was "tiefer" ist, ist im Schatten. Praktische Anwendungen habe ich mir aber noch nicht angeschaut. Aber ich nehme mal an, da gibts jetzt auch verschiedene Methoden, wie du sowas renderst. Davon hängt deine Matrize dann sicher auch ab. Also zeig doch mal, was du für Renderstates usw. benutzt. Es muss ja irgendwie ein Test pixel.z < texel.rgb auf der GraKa gemacht werden.
Bye, TGGC \-/
-
0x00000001 schrieb:
Ich kriegs einfach nicht hin. Habe versucht, die Beispielprogramme, die ich habe mehr oder weniger direkt zu kopieren, aber es will nicht gehen.
Ich denke, dass es am Projezieren der Shadowmap in den Level liegt. Die Shadowmap selbst sollte eigentlich soweit richtig sein.Ich dachte ja erst, dass das Projezieren schon funktioniert, da ich ein Testbild korrekt aus der Sicht des Lichtes in die Geometrie projeziert habe. Aber anscheinend ist es so, dass nicht nur die ersten beiden Einträge der Texturkoordinate benötigt werden, sondern auch die anderen beiden Ausschlag gebend sind (was ich bei einer 2D Textur nicht unbedingt erwartet hätte).
@rapso: Wenn ich das richtig verstanden habe, dann machst Du ja auch viel bzw. alles mit Shadern. Ich denke mal dann wirst Du mir helfen können. Ich will einfach die Position jeder Vertize(?) im Vertex Shader mit einer Matrix multiplizieren, und das Ergebnis als Texturkoordinate speichern. Also komplett auf dieses EYE_LINEAR_TEXCOORD_ODER_SO Zeugs verzichten.
Bisher sieht diese Matrix M so aus:
matTexAdj = \[ \left( \begin{array}{cccc} 0.5 & 0 & 0 & 0 \\ 0 & -0.5 & 0 & 0 \\ 0 & 0 & fZScale & 0 \\ 0.5 & 0.5 & fBias & 1\end{array} \right)\] fZScale = 2^2^4-1 fBias = -0.0002 \\ matLicht = matLichtView * matLichtProj \\ M = (matLicht * matTexAdj)^TDamit kann man wie gesagt eine Textur in den Level projezieren, nur mit den z-Werten klappt es eben nicht so ganz. Es entsteht dann dieser oben beschriebene Streifen (der von der Breite her übrigens genau der NearPlane der Lichtprojektion entspricht).
In dem NVidia Paper "Hardware Shadow Mapping" wird auch noch irgendwas mit der Kameramatrix gemacht. Habe ich auch schon versucht, aber es hat nicht funktioniert. Und um ehrlich zu sein: Ich hab überhaupt keinen Plan, wie diese ganzen Matrizen letztendlich arbeiten. Und somit kann ich höchstens ein wenig an den Werten rumdrehen, was ich da tue weiß ich aber nicht.Ich hoffe Du (oder jemand anderst) weißt, wie die Matrix aussehen muss
ich schätze du hast da die oGL sachen von nvidia durchstöbert, dort macht man das damit, bei d3d kannst du dafür versuchen den zbias zu benutzen (SetRenderState...). das problem ist, dass es quasi zfighting zwischen der shadowmap und der geometrie gibt, schliesslich steht in der shadowmap die entfernung zum licht und du berechnest dir ja auch die entfernung zum licht und vergleichst die beiden werde, je nach nachkommerstelle ist dann das ergebniss zufällig. deswegen multipliziert man die entfernung ||licht-pixelposition|| mit einem kleinen skalierungsfaktor (man addiert nicht nur, weil der zbuffer nicht linear ist) und bei d3d addiert man mit zbias dann nen wert drauf für den zcompare, und zwar sind das die zbuffer einheiten und nicht wirkliche entfernungen, weil wie gesagt, wegen des nicht linearen zbuffers würde das anders mit dem addieren nicht funzen.
es gibt leute die auch einen shadowmap pass für die backfaces und einen für die frontfaces machen, wenn man geschlossene objekte hat, dann kann man einen mittelwert bekommen, der immer genau durch die objekte hindurch geht und umgeht so das z-fighting.
rapso->greets();
-
TGGC schrieb:
Also zeig doch mal, was du für Renderstates usw. benutzt. Es muss ja irgendwie ein Test pixel.z < texel.rgb auf der GraKa gemacht werden.
Hm Renderstates brauche ich da so gut wie keine. Nachdem man die Shadowmap gerendert hat, setzt man sie in einen Texturkanal und erstellt die Texturkoordinaten durch geeignete Projektion. Die Textur ist ja ein Z-Buffer, und wenn daraus gesampelt wird, kann das ergebnis nur 0 oder 1 sein ( das Ergebnis des z-Vergleiches). Man muss also nix spezielles einstellen, das sollte automatisch funktionieren. So hab ich das zumindest verstanden.
@rapso: Du bist mir schon wieder voraus, mit dem Bias oder mit z-Fights habe ich noch garkeine Probleme weil bis jetzt überhaupt nichts funktioniert :p
Es geht mir im Moment nur darum, wie ich die Texturkoordinaten für die Shadowmap bekomme. Bei diesen Koordinaten scheint aus irgendweinem Grund die z und w Komponente wichtig zu sein.
Ich habe mal wieder 2 Screenshots gemacht, die mein Problem hoffentlich besser erklären: Bilder
Wie man dort sieht, funktioniert die Projektion für ein normales Bild ganz gut, d.h. die x und y Komponenten der Texturkoordinaten sind richtig. Bleibt nur noch z und eventuell w. Vielleicht muss ich ja doch noch irgendwelche Renderstates bzw. Texturestagestates anmachen. Im VShader transformiere ich einfach nur die Vertexposition mittels der oben beschriebenen Matrix, sonst mache ich damit garnix.
Sag doch mal bitte, wie Du das machst. Du musst ja auch irgendwas mit der Lichtprojektionsmatrix usw. gemacht haben.
-
@rapso: Schade, dass Du nicht geantwortet hast. Ist aber nicht so schlimm, denn 1. hab ich den Fehler mittlerweile selbst gefunden und 2. lag er eh ganz wo anderst
Es ist ganz einfach: Ich habe für die Shadowmap einen 24Bit z-buffer genommen und als Farbpuffer eine 16 Bit Textur. Das geht nicht.Gut, sowas muss man erstmal wissen. Ich ärgere mich aber trotzdem stark über mich selbst, weil ich mal wieder am Optimieren war bevor überhaupt irgendwas funktioniert hat
Vielen Dank nochmal für eure Hilfe (besonders rapso), ich denke mit den Shadowmaps werde ich glücklicher als mit den Volumes. (vor allem wegen der Shader 2.0 Karte die ich bald anlässlich Doom3 kaufe
)
-
It is easier to optimize correct code than to correct optimized code.
Bye, TGGC \-/
-
0x00000001 schrieb:
@rapso: Schade, dass Du nicht geantwortet hast. Ist aber nicht so schlimm, denn 1. hab ich den Fehler mittlerweile selbst gefunden und 2. lag er eh ganz wo anderst
Es ist ganz einfach: Ich habe für die Shadowmap einen 24Bit z-buffer genommen und als Farbpuffer eine 16 Bit Textur. Das geht nicht.Gut, sowas muss man erstmal wissen. Ich ärgere mich aber trotzdem stark über mich selbst, weil ich mal wieder am Optimieren war bevor überhaupt irgendwas funktioniert hat
Vielen Dank nochmal für eure Hilfe (besonders rapso), ich denke mit den Shadowmaps werde ich glücklicher als mit den Volumes. (vor allem wegen der Shader 2.0 Karte die ich bald anlässlich Doom3 kaufe
)
naja, mir viel auch nichts zu deinem problem ein, da wollte ich net dumm rumspinnen.
auf der nvidia konferenz hatten die neue paper zu shadowmapping vorgestellt (laut nvidia sind shadowmaps besser als shadowvolumes) und die wird es bald auf deren hp geben, die werden ein paar z-fighting probleme von dir lösen.
rapso->greets();