Z ungenau
-
Hi
Ich hab mal irgendwo gelesen, dass John Carmack in Doom3 erstmal die ganze Szene ohne Farbausgabe rendert, um den Z-Buffer zu füllen. Beim richtigen Rendern werden dann nur noch die Pixel berechnet, die auch wirklich sichtbar sind.
Das wollte ich jetzt auch machen, es funktoniert aber natürlich nicht:( Irgendwie scheint der Z-Buffer oder Direct3D ungenau zu arbeiten.
Beim ersten durchlauf stelle ich folgendes ein:
g_pDev->SetRenderState( D3DRS_ZFUNC, D3DCMP_LESS );
g_pDev->SetRenderState( D3DRS_ZWRITEENABLE, TRUE );und beim zweiten:
g_pDev->SetRenderState( D3DRS_ZFUNC, D3DCMP_EQUAL );
g_pDev->SetRenderState( D3DRS_ZWRITEENABLE, FALSE );Es funktioniert aber nicht, es entstehen diese Flecken die über den ganzen Schirm gehen, je nach Kameraposition. Es flackert alles ziemlich wild umher.
Ich versteh das nicht. Es ist doch die genau gleiche Geometrie, es wird alles genau mit der gleichen Rechnung transformiert. Wie kann es dann sein, dass unterschiedliche Z-Werte rauskommen?
Kann man da noch was machen?
-
D3DRS_ZFUNC, D3DCMP_LESS bedeutet doch nur, dass die Punkte angezeigt werden, die von der Kamera weiter weg sind. Wozu?
-
Ne, ich glaub da hast Du was falsch verstanden. Es geht um die z-werte, die liegen zwischen 0 und 1. '1' bedeutet ganz weit weg
Ich hab aber grade eben mal D3DCMP_GREATER ausprobiert, dann kommt garnix mehr. Ich glaub schon dass ich alles richtig gemacht hab, nur d3d ist halt scheiße
-
nur d3d ist halt scheiße
nö, DU :p
-
Es geht um die z-werte, die liegen zwischen 0 und 1. '1' bedeutet ganz weit weg
Aber net, wenn die Kamera auf 2 steht !!
P.S. mit den Turorials im SDK war das alles recht einfach.
-
Hi,
also die Einstellungen sind korrekt. Zuerst rendert man eigentlich mit LESSEQUAL und dann mit EQUAL aber das würde nicht zu diesem Fehler führen. Da muss noch etwas anderes falsch sein.
Ich rendere meinen DepthBuffer-Pass und den ColorBuffer Path sogar mit denselben (default) Einstellungen ohne etwas zu ändern. Ein LESS Case sollte eigentlich beim zweiten Durchlauf gar nicht auftreten und es gibt auch keine Grafikfehler.
Der Performance-Gewinn ist aber auch nur bei Szenen mit sehr viel Geometrie und Multitexturing oder aufwendigen Pixel-Shadern bemerkbar.
Ciao,
Stefan
-
Hi,
@René
Die DepthBuffer Werte haben nichts mit der Position der Kamera zu tun.Max-Depth-Wert <=> Far Plane Distanz
Min Depth-Wert <=> Near Plane DistanzFür gewöhnlich wählt man den Bereich [0.0f, 1.0f] für den DepthBuffer, wobei der DepthBuffer Wert multipliziert mit dem Wert der FarPlane die eigentliche Distanz in Relation zur Kameraposition ergibt.
Ciao,
Stefan
-
@Stefan Zerbst
Danke für die Info. Bin ziemlicher Neuling in 3D. Musste mich nur zwangsläufig etwas damit beschäftigen.Für gewöhnlich wählt man den Bereich [0.0f, 1.0f] für den DepthBuffer
Wo findet man sowas? Ich meine die Definitionswerte für die Bereiche? Darf z nicht in [-2.0f, 2.0f] liegen? Oder auch x und y?
-
Wenn du das mit dem ZBuffer nicht hinbekommst - nimm den WBuffer. Abundzu spackt der Z
-
lol
-
Original erstellt von Stefan Zerbst:
Für gewöhnlich wählt man den Bereich [0.0f, 1.0f] für den DepthBuffer, wobei der DepthBuffer Wert multipliziert mit dem Wert der FarPlane die eigentliche Distanz in Relation zur Kameraposition ergibt.Man müsste noch den Wert für die Near Plane mit einbinden in diese Berechnung. Außerdem stimmt das so auch nicht, denn ein z-Wert von 1 bedeutet nicht, dass dieser Pixel doppelt so weit von der Kamera entfernt ist wie ein Pixel mit einem z-Wert vom 0.5. Die Genauigkeit des Z-Buffers ist nämlich nicht "linear" verteilt. Siehe DirectX-Dokumentation:
Due to the mathematics involved, the generated z values in a z-buffer tend not to be distributed evenly across the z-buffer range (typically 0.0 to 1.0, inclusive). Specifically, the ratio between the far and near clipping planes strongly affects how unevenly z values are distributed. Using a far-plane distance to near-plane distance ratio of 100, 90% of the depth buffer range is spent on the first 10% of the scene depth range. Typical applications for entertainment or visual simulations with exterior scenes often require far-plane/near-plane ratios of anywhere between 1000 to 10000. At a ratio of 1000, 98% of the range is spent on the 1st 2% of the depth range, and the distribution becomes worse with higher ratios. This can cause hidden surface artifacts in distant objects, especially when using 16-bit depth buffers, the most commonly supported bit-depth.
Ich würde es auch mal bei beiden Durchgängen mit D3DCMP_LESSEQUAL versuchen. Und ansonsten vielleicht mal ein bisschen mit Z-Bias herumexperimentieren.
[ Dieser Beitrag wurde am 25.06.2003 um 17:59 Uhr von TomasRiker editiert. ]
-
-
Ich danke Euch für die Antworten.
Habe grade probiert, bei beiden Durchgängen auf CMP_LESSEQUAL zu stellen. Es funktioniert zwar nicht, man hat aber das Gefühl es läuft etwas besser.
Zum Test hab ich auch mal den Z-Bereich stark eingeschränkt, von 1.0f bis 50.0f, ohne dass es was gebracht hätte.
@ Stefan Z: Wenn das bei Dir geht, kannst Du mal bitte Deine Einstellungen, die Du für wichtig hälst, hier posten? Vielleicht gibts ja was was ich falsch hab oder noch nicht kenn.
Und jetzt schau ich schnell noch was der w-Buffer ist. Hätte nicht gedacht dass ich sowas mal brauche :p
-
@Sven: Wenn du mir nicht glaubst - ich hatte das selbe Problem mit meiner GForce 4 - auf älteren Karten lief es einwandfrei. Zum schluß half nur der W Buffer
http://www.usf.de/forum/Forum1/HTML/001296.html[ Dieser Beitrag wurde am 25.06.2003 um 19:46 Uhr von SnorreDev editiert. ]
-
Hi,
wie bereits gesagt verwende ich keine speziellen Einstellungen, sondern die Default-States von Direct3D. Im zweiten Renderdurchgang schalte ich nur die DepthBuffer Writes aus. Im ersten Durchgang ist natürlich der PixelBuffer aus und es wird nur in den DepthBuffer gerendert.
Das läuft übrigens auch auf einer GeForce4, allerdings ist die FarPlane mit ein 1000.0f recht nah dran womit der DepthBuffer besser arbeitet als mit einer sehr grossen Distanz zwischen Near und Far.
Oder versuch mal was David gesagt hat und rendere mit unterschiedlichem Z-Bias.
Ciao,
Stefan
-
Ich habe auch eine Geforce4. Vielleicht ist die ja schuld.
Ich habe das Problem aber gelöst, mit dem DepthBias. Das hatte ich zwar heute mittag schonmal probiert, da hat es aber nicht funktioniert weil ich es falsch benutzt hab. Auf der Seite von ATI gibts aber ein gutes Beispiel, und jetzt klappts.
So:
Vor dem Z-Pass:
float temp = 0.000001f; g_pDev->SetRenderState( D3DRS_DEPTHBIAS, *((DWORD*) (&temp)) );
Und vor dem richtigen Rendern dann:
float temp = 0.0f; g_pDev->SetRenderState( D3DRS_DEPTHBIAS, *((DWORD*) (&temp)) );
Das ist mal wieder eine der Sachen, die in der SDK wirklich nicht ausreichend erklärt sind.
Danke für Eure Hilfe.
-
Warum machst du erst einen Zeiger und dereferenzierst ihn dann wieder? geht das nicht direkt: SetRenderState( D3DRS_DEPTHBIAS, (DWORD) temp) ); ?
-
Ne dann würde er den Wert in Integer konvertieren, in dem Fall also 0. Man muss die 32Bit des floats nur für C++ als DWORD markieren, weil die Funktion eben ein DWORD erwartet. Der Wert ansich soll aber gleich bleiben.
-
my2c?nt
1. man sollte in jedem pass LESSEQUAL verwenden, läuft schneller, weil die speziellen zbuffer optimierungen dann immer an sind, bei EQUAL muss einiges mehr gerechnet werden in der graka (steht in ATI papern).. liegt zum teil daran dass der zbuffer komprimiert ist und entpackt werden muss für EQUAL
(siehe http://mirror.ati.com/developer/dx9/ATI-DX9_Optimization.pdf s.26)2. wenn man zweimal auf genau die selbe weise dinge berechnet, dann ergibt das auch die selben zwerte, dann hat man im multipass absolut keine probleme und muss weder mit bias noch polygonoffset hantieren. dinge die dabei wichtig sind ist, dass man vertexshader und standart TnL nicht mischt, geforce 3 und 4 karten rechnen anders in denen, sodass es minimale unterschiede gibt, diese aber zfighting hervorrufen.
3. bei einer scene mit nur simpel texturierten polygonen ist es schneller sie direkt zu zeichnen, wenn man viel alphatest benutzt, dann kann dieses multipass sogar um einiges langsammer sein bei simplen dingen. (ja, pixelshader sachen sind da natürlich performanter mit erst zbuffer beschreiben)
carmack hat außerdem keine wahl ob er den zbuffer erst zeichnet oder nicht, weil er vor dem ersten colorpixel die volumes erstellen muss für seine schatten und dafür braucht er den zbuffer.
rapso->greets();
-
Original erstellt von 0x00000001:
**Das ist mal wieder eine der Sachen, die in der SDK wirklich nicht ausreichend erklärt sind.
**Was genau meinst du, das in DWORD casten?! Da gibt's IMHO sogar ein Makro für.