Z Buffer in Orthogonaler Projektion
-
- Beiträge: 28
- Registriert: 24.09.2012, 14:49
Z Buffer in Orthogonaler Projektion
Basierend auf dem Andengine SDK versuche ich grad ein kleines Demo mit einer Isometrischen Map zu schreiben. Für meine Sprites habe ich mehrere Spritebatcher, in denen die Sprites nach ZIndex sortiert werden. Problematisch ist das Rendern, da die Buffer (pro Spritebach ein VBO) nacheinander gerendert werden und es hier zu Überschneidungen der Sprites kommt bei der die Renderreihenfolge Fehler verursacht. Ich habe meine Sprites um einen ZIndex erweitert um gegen den Tiefenbuffer zu prüfen. Aber irgendwie klappt das nicht. Obwohl der Depth Test aktiviert ist wird dennoch bei den Sprites der ZWert scheinbar ignoriert und Sprites die hinter anderen liegen müssten, werden aufgrund der Renderreihenfolge, oben auf gerendert.
Muss ich hier etwas besonderes beachten? Ist mein Ansatz überhaupt richtig?
Muss ich hier etwas besonderes beachten? Ist mein Ansatz überhaupt richtig?
- dot
- Establishment
- Beiträge: 1746
- Registriert: 06.03.2004, 18:10
- Echter Name: Michael Kenzel
- Kontaktdaten:
Re: Z Buffer in Orthogonaler Projektion
Hat dein OpenGL Context überhaupt einen Depth Buffer?
-
- Beiträge: 28
- Registriert: 24.09.2012, 14:49
Re: Z Buffer in Orthogonaler Projektion
Ja hat er. 24 Bit. Der Depth Test klappt auch bei 3D Objekten mit perspektivischer Projektion.
- Krishty
- Establishment
- Beiträge: 8350
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: Z Buffer in Orthogonaler Projektion
Wie sieht die Projektionsmatrix aus?
-
- Beiträge: 28
- Registriert: 24.09.2012, 14:49
Re: Z Buffer in Orthogonaler Projektion
Ich benutze nicht glOrhto zum Definieren der Orthogonalen Projektion, sondern eine 4x4 Matrix,
die ich wie folgt als OrthographicOffCenter basierend auf den Vieport Daten berechne und die
der OpenGL Spezifikation folgt:
[ A 0 0 C ]
[ 0 B 0 D ]
[ 0 0 q qn ]
[ 0 0 0 1 ]
Die Werte hierfür sind : createOrthographicOffCenter(0, (float)RES_WIDTH, 0, (float)RES_HEIGHT, 0.1f, 1000.0f)
Gesetzt wird die Matrix wie folgt:
Ich habe einmal mit den Z-Indexwerten herumgespielt. Definiere ich reguläre Z-Werte, wie ich sie auch bei
3D Objekten verwende (-4 Regal, -3 Ritter, -1 Fass) dann erhalte ich folgendes Resultat:
http://s7.directupload.net/file/d/3064/okp777f3_jpg.htm
Nehme ich werte zwischen 0 und 1 (0.4 Regal, 0.2 Ritter, 0.1 Fass) dann erhalte ich folgendes, besseres,
aber noch nicht korrektes Resultat:
http://s7.directupload.net/file/d/3064/eta7ns8z_jpg.htm
Ich meine irgend wo etwas gelesen zu haben, dass in der Orthogonalen Projektion der Depth-Buffer Linear
auf den Wertebereich [-1,1] gemappt wird. Kann es damit zusammenhängen?
die ich wie folgt als OrthographicOffCenter basierend auf den Vieport Daten berechne und die
der OpenGL Spezifikation folgt:
[ A 0 0 C ]
[ 0 B 0 D ]
[ 0 0 q qn ]
[ 0 0 0 1 ]
Code: Alles auswählen
Matrix4 Matrix4::createOrthographicOffCenter(float left, float right, float bottom, float top, float zNear, float zFar)
{
float invRL = 1.0f / (right - left);
float invTB = 1.0f / (top - bottom);
float invFB = 1.0f / (zFar - zNear);
Matrix4 M;
M.zero();
float invRL1 = 2.0f / (right - left);
M.m_a11 = 2.0f * invRL;
M.m_a22 = 2.0f * invTB;
M.m_a33 = -2.0f * invFB;
M.m_a14 = - (right + left) * invRL;
M.m_a24 = - (top + bottom) * invTB;
M.m_a34 = - (zFar + zNear) * invFB;
M.m_a44 = 1.0f;
return M;
}
Gesetzt wird die Matrix wie folgt:
Code: Alles auswählen
GLfloat glMat[16];
mat.get(glMat);
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(glMat);
glMatrixMode(GL_MODELVIEW);
3D Objekten verwende (-4 Regal, -3 Ritter, -1 Fass) dann erhalte ich folgendes Resultat:
http://s7.directupload.net/file/d/3064/okp777f3_jpg.htm
Nehme ich werte zwischen 0 und 1 (0.4 Regal, 0.2 Ritter, 0.1 Fass) dann erhalte ich folgendes, besseres,
aber noch nicht korrektes Resultat:
http://s7.directupload.net/file/d/3064/eta7ns8z_jpg.htm
Ich meine irgend wo etwas gelesen zu haben, dass in der Orthogonalen Projektion der Depth-Buffer Linear
auf den Wertebereich [-1,1] gemappt wird. Kann es damit zusammenhängen?
- dot
- Establishment
- Beiträge: 1746
- Registriert: 06.03.2004, 18:10
- Echter Name: Michael Kenzel
- Kontaktdaten:
Re: Z Buffer in Orthogonaler Projektion
Kann es sein, dass du deine Bilder vertauscht hast!? Deine Matrix definiert ein rechtshändiges Koordinatensystem (positive z Achse zeigt aus dem Bildschirm heraus). Das zweite Bild entspräche genau dem, was ich bei den negativen z-Koordinaten auch erwarten würde. Was mich wundert ist, dass bei den positiven z-Koordinaten überhaupt was gezeichnet wird, imo sollte da eigentlich geclipped werden...
-
- Beiträge: 28
- Registriert: 24.09.2012, 14:49
Re: Z Buffer in Orthogonaler Projektion
Ich habe es noch einmal geprüft, die Bilder sind in der richtigen Reihenfolge. Bei positiven Werten erfolgt
kein clipping.
Ich habe mir mal den gDEBugger installiert und gestartet, noch werde ich aus dem Tool nicht schlau,
aber vielleicht hilft Euch ja die DepthBuffer Info:
http://s7.directupload.net/file/d/3064/ocwgmk6b_jpg.htm
Wenn ich mir die Datenbereiche im Depthbuffer anschaue, dann sind genau die Pixel, die von den
Grafiken belegt sind auch mit Werten < 1.0f belegt, alle übrigen 1.0f. Welcher Wert hier richtig
sein müsste erschließt mich mir (noch) nicht.
kein clipping.
Ich habe mir mal den gDEBugger installiert und gestartet, noch werde ich aus dem Tool nicht schlau,
aber vielleicht hilft Euch ja die DepthBuffer Info:
http://s7.directupload.net/file/d/3064/ocwgmk6b_jpg.htm
Wenn ich mir die Datenbereiche im Depthbuffer anschaue, dann sind genau die Pixel, die von den
Grafiken belegt sind auch mit Werten < 1.0f belegt, alle übrigen 1.0f. Welcher Wert hier richtig
sein müsste erschließt mich mir (noch) nicht.
-
- Beiträge: 28
- Registriert: 24.09.2012, 14:49
Re: Z Buffer in Orthogonaler Projektion
Ich habe mich einmal hingesetzt und das Demo angepasst und zwei solide Flächen hinzugefügt. Und siehe da, bei diesen Flächen klappt es.
Habe auch beide Flächen auf VBO's umgestellt um zu testen ob ich hier einen Fehler hatte, es läuft weiterhin wie gewünscht. Meine Vermutung
ist nun dass es mit dem Alpha-Blending meiner Sprites zusammenhängt ...
Render ich die VBO's meiner SpriteBatcher in der Reihenfolge : Regal, Fass, Ritter und vergebe hierfür die Z-Indexe -4, -2, -3
dann erhalte ich folgendes Bild: http://s7.directupload.net/file/d/3065/7ymmpcmd_jpg.htm
Änder ich die Renderreihenfolge der VBO's auf Regal, Ritter, Fass bei gleichem Index, dann erhalte ich einen korrekten
Output: http://s1.directupload.net/file/d/3065/fstv2oow_jpg.htm
D.h. folgen die VBO's nicht den Z-Index Werten in der Renderaufruffolge, dann gibt es bei Alpha-Blending Probleme. Ich meine irgendwo vorhin
etwas übeflogen zu haben, dass der Z-Buffer Alpha Werte nicht ignoriert und dadurch die Fehler auftreten.
Nun bin ich aber in einem Dilemma. Ich habe mehrere SpriteBatcher (für jeden Textur Atlas einen), mit mehreren, nach Z-Index sortieren Sprites
auf mehrere VBO's verteilt, die ich unmöglich in der korrekten Reihenfolge rendern kann, da ich nicht zwischen den Objekten in den VBO's hin und
her springen kann :(
Eine Möglichkeit die ich als Lösung sehe, ist es einen großen SpriteBatcher zu bauen, anstelle von n-vielen. Das ist technisch weniger das
Problem, doch dann verliere ich doch den Vorteil des Batchers, da ich nicht wie jetzt eine Texturaktivierung für n-viele Sprites durchführen
kann da sie als Bulk gerendert werden, sondern bei jedem Sprite prüfen muss ob die aktuelle Textur mit dem Sprite identisch ist und dann
ggfs. die teure Aktivierung durchführe ...
Wie geht Ihr damit um? Isometrische Maps sind ja keine Seltenheit mehr und ich denke, 60-80% der Sprites haben irgend wie Alpha-Blending
Bereiche (für mein kleines Demo bis auf die Boden Tiles eigentlich jedes Sprite), insbesonders dann, wenn Animationen mit ins Spiel kommen,
wie z.B. bei Lootdrop's usw.
Irgendwie habe ich da grad einen Knoten im Kopf. Gibt es evtl. noch eine anderen Lösungsansatz?
Habe auch beide Flächen auf VBO's umgestellt um zu testen ob ich hier einen Fehler hatte, es läuft weiterhin wie gewünscht. Meine Vermutung
ist nun dass es mit dem Alpha-Blending meiner Sprites zusammenhängt ...
Render ich die VBO's meiner SpriteBatcher in der Reihenfolge : Regal, Fass, Ritter und vergebe hierfür die Z-Indexe -4, -2, -3
dann erhalte ich folgendes Bild: http://s7.directupload.net/file/d/3065/7ymmpcmd_jpg.htm
Änder ich die Renderreihenfolge der VBO's auf Regal, Ritter, Fass bei gleichem Index, dann erhalte ich einen korrekten
Output: http://s1.directupload.net/file/d/3065/fstv2oow_jpg.htm
D.h. folgen die VBO's nicht den Z-Index Werten in der Renderaufruffolge, dann gibt es bei Alpha-Blending Probleme. Ich meine irgendwo vorhin
etwas übeflogen zu haben, dass der Z-Buffer Alpha Werte nicht ignoriert und dadurch die Fehler auftreten.
Nun bin ich aber in einem Dilemma. Ich habe mehrere SpriteBatcher (für jeden Textur Atlas einen), mit mehreren, nach Z-Index sortieren Sprites
auf mehrere VBO's verteilt, die ich unmöglich in der korrekten Reihenfolge rendern kann, da ich nicht zwischen den Objekten in den VBO's hin und
her springen kann :(
Eine Möglichkeit die ich als Lösung sehe, ist es einen großen SpriteBatcher zu bauen, anstelle von n-vielen. Das ist technisch weniger das
Problem, doch dann verliere ich doch den Vorteil des Batchers, da ich nicht wie jetzt eine Texturaktivierung für n-viele Sprites durchführen
kann da sie als Bulk gerendert werden, sondern bei jedem Sprite prüfen muss ob die aktuelle Textur mit dem Sprite identisch ist und dann
ggfs. die teure Aktivierung durchführe ...
Wie geht Ihr damit um? Isometrische Maps sind ja keine Seltenheit mehr und ich denke, 60-80% der Sprites haben irgend wie Alpha-Blending
Bereiche (für mein kleines Demo bis auf die Boden Tiles eigentlich jedes Sprite), insbesonders dann, wenn Animationen mit ins Spiel kommen,
wie z.B. bei Lootdrop's usw.
Irgendwie habe ich da grad einen Knoten im Kopf. Gibt es evtl. noch eine anderen Lösungsansatz?
- dot
- Establishment
- Beiträge: 1746
- Registriert: 06.03.2004, 18:10
- Echter Name: Michael Kenzel
- Kontaktdaten:
Re: Z Buffer in Orthogonaler Projektion
Natürlich, ich hab mich ja auch schon gewundert, was genau du in einem 2D Renderer mit einem Depth Buffer anstellen willst. Der Depth Buffer sortiert dir Pixel nach deren Tiefe und nicht nach deren Alpha Wert. Wenn du ein Sprite mit geringerer Tiefe zuerst zeichnest, dann sind dessen Tiefenwerte im Depth Buffer und Pixel eines weiter hinten liegenden Sprite, das später gezeichnet wird, failen natürlich den Depth Test und werden daher nicht ausgegeben. Du musst deine Sprites von hinten nach vorne sortiert rendern, der Depth Buffer wird dir dabei kein bisschen helfen.
Ja nach Anwendung, könntest du möglicherweise auch einfach mit einer fixen Anzahl an Layern arbeiten, die einfach nacheinander gezeichnet werden, statt einen sortierten Haufen Sprites zu verwalten. Letzteres dürft in deinem Fall allerdings wohl am sinnvollsten sein...
Was genau versprichst du dir von diesem Ansatz mit mehreren SpriteBatchern? Am Ende musst du sowieso alle Commands irgendwie serialisieren...
Ja nach Anwendung, könntest du möglicherweise auch einfach mit einer fixen Anzahl an Layern arbeiten, die einfach nacheinander gezeichnet werden, statt einen sortierten Haufen Sprites zu verwalten. Letzteres dürft in deinem Fall allerdings wohl am sinnvollsten sein...
Was genau versprichst du dir von diesem Ansatz mit mehreren SpriteBatchern? Am Ende musst du sowieso alle Commands irgendwie serialisieren...
-
- Beiträge: 28
- Registriert: 24.09.2012, 14:49
Re: Z Buffer in Orthogonaler Projektion
Einen ordendlichen Performance Boost. Dadurch, dass jeder SpriteBatcher an genau eine Textur oder Atlas gebunden ist, kann ich n-viele Sprites vom selben Typ in einem Pass rendern und benötige nur eine einzige Texturaktivierung. Würde ich einen Batcher für alle Sprites haben, dann kann ich ja nicht mehr mit einem VBO in einem Pass rendern, da ich nicht differenzieren kann, welche Textur zu welchem Geometrie-Teil im VBO aktiviert werden muss. D.h. letztendlich hätte ich ja wieder single Calls pro Sprite (wahrscheinlich auch ein VBO pro Sprite) und keinen Vorteil durch den Batcher :|Was genau versprichst du dir von diesem Ansatz mit mehreren SpriteBatchern?
D.h. sollte ich keine technische Lösung für dieses Dilemma finden, muss ich letztendlich doch wieder auf das direkte Rendern jedes einzelnen Sprite zurückgreifen, zumindest bei denen die über einen Z-Index plaziert werden. Nur bei gleichartigem Z-Index könnte ich den Batcher als Vorteil nutzen, wie z.B. bei Fonts oder UI Elementen.
Daher meine Frage, wie macht Ihr dass, wenn Ihr Isometrische Perspektiven verwendet? Ich habe gesehen, das XNA z.B. einen SpriteBatcher für alle Sprites verwendet, hier ist mir nur nicht klar, wie die das dann mit der Texturaktivierung hin bekommen :?:
Edit:
Hmm, eine Idee hätte ich noch, ich könnte den Batcher so anpassen, dass er sich die aktuelle Textur merkt. Solange ich Sprites hinzufüge, die die gleiche Textur haben, wird die Textur Aktivierung gehalten und die Geometrie addiert und wenn sich dann die Textur ändert, werden die gebatchten Daten gerendert und dann die Aktivierung neu gesetzt. D.h. im Extremfall hätte ich single Calls, aber auch Batchmöglichkeiten. Ich dürfte dann nur noch einen Batcher verwenden und müsste dafür sorgen, dass die Draw-Calls den Z-Index bereits berücksichtigen.
-
- Beiträge: 28
- Registriert: 24.09.2012, 14:49
Re: Z Buffer in Orthogonaler Projektion [Gelöst]
So ich habe wie angekündigt den Batcher umgebaut, in der Basis klappt es schon einmal,
ich kann nun alle Sprites über einen Batcher rendern, damit ist das ZBuffer Problem erledigt :)
ich kann nun alle Sprites über einen Batcher rendern, damit ist das ZBuffer Problem erledigt :)