Ich schreibe eine App, die eine zufällige Insel mit Bäumen bepflanzt. Die Bäume sind derzeit zwei Quads, gekreuzt und mit Texturen gezeichnet. Ich plane komplexere Maschen, die verschiedene Pflanzentypen bilden, z. B. eine Palme, Eiche, Gräser usw.
Das Problem ist, dass ich die Texturen von hinten nach vorne zeichnen muss, weil sie transparent sind. Plan-b ist die Verwendung von Discard im Frag-Shader, aber die Z-Reihenfolge liefert bessere Ergebnisse:
uniform float uTreeAlpha;
uniform sampler2D uTexture;
varying vec2 vTexCoordOut;
void main (void)
{
vec4 colour = texture2D(uTexture, vTexCoordOut);
if (colour.a < 0.1) {
discard;
}
gl_FragColor = vec4(colour.rgb, colour.a * uTreeAlpha);
}
Das zweite Problem ist, dass sich die Reihenfolge je nach Kamera und Aussehen ändert. Ich kenne keine effiziente Methode, um sie in OpenGL in einem einzigen Aufruf zu zeichnen.
Derzeit sieht mein Rendering-Code wie folgt aus:
if cameraChangedFromLastTime() then
sortTreesBackToFront();
end
for i = 0 to trees.size() -1
drawTree()
end
Wobei jeder drawTree () einige Uniformen festlegt, die Textur festlegt und dann glDrawArrays () aufruft. Ich habe einige Optimierungen, um das Festlegen einer Textur oder das Aktualisieren von Texturkoordinaten zu überspringen, wenn der letzte Baum und die aktuelle identisch sind, und einige allgemeine Uniformen außerhalb der Schleife festzulegen und Bäume zu überspringen, die zu weit entfernt sind, aber im Grunde genommen, wenn ich 3000 Bäume habe Gehen Sie 3000 Mal um die Schleife.
Jeder Baum einzeln zu zeichnen ist der Leistungskiller. Wenn ich sie in einem einzigen Aufruf oder in Stapeln (unter Beibehaltung der Z-Reihenfolge) zeichnen könnte, würde ich dies wahrscheinlich in 1/10 der Zeit tun.
Wie würde ich das machen? Denken Sie daran, dass meine Bäume Platzhalter sind und ich schließlich:
- Unterschiedliche Maschen für unterschiedliche Bäume
- Verschiedene Maßstäbe und Winkel für Bäume, um mehr Abwechslung zu bieten
- Unterschiedliche Texturen für unterschiedliche Bäume, möglicherweise mehrere Texturen, die auf ein Netz angewendet werden (z. B. Blätter eine Textur, Stamm eine andere)
- Bäume sind alle miteinander vermischt, so dass es keine einfache Möglichkeit gibt, eine Art und dann eine andere zu zeichnen
- Eine Form einfacher zyklischer Animation (Äste, die im Wind wackeln)
- Alle Texturen würden sich in einem einzigen Atlas befinden
Was ist hier der beste Ansatz? Ist es möglich, in einem Durchgang zu rendern? Wenn ich glDrawElements verwenden würde, um die Indizes, aber nicht die Eckpunkte neu zu erstellen, könnte ich dies erreichen?
quelle
Antworten:
Was Sie wollen, ist Hardware-Instanz . Hinweis: Ich habe dies in XNA (dh DirectX) getan, aber ich weiß nicht viel über OpenGL. Ich bin mir jedoch sicher, dass es eine vergleichbare Funktion gibt. Grundsätzlich geht es darum, die Scheitelpunkte Ihres Baummodells mit einem anderen Scheitelpunktstrom zu verbinden, der Weltkoordinaten für jede Instanz enthält.
quelle
Die Transparenz muss nur bestellt werden, wenn keine additive Mischung verwendet wird. Für eine Tonne entfernter Werbetafeln ist das Mischen nicht erforderlich (Sie können es nicht wirklich sehen). Rendern Sie mindestens die weiteren mit ausgeschnittener Transparenz (Alpha von nur 1 oder 0), und Sie müssen sie nicht sortieren.
Sie können eine Art Sprite-Blatt verwenden, um verschiedene Baumarten mit gebackenen Animationen zu rendern. Zeichnen Sie Maschen für nähere Bäume, die Sie je nach Wind oder was auch immer Sie möchten, mit größerer Genauigkeit animieren können.
quelle