Wie gehen Sie mit mehreren Texturen in einer OpenGL indiziert Pufferarray für die Verwendung mit einem Daten-Shader?
-
16-09-2019 - |
Frage
Ich versuche dieses Papier zu implementieren. Ich habe die meisten davon haben nach unten, aber der Teil über das Senden von beliebigen, nicht-geometrischen Daten an den Shader für die Verwendung bei der Bestimmung und geometrische Kanten Anzeige macht mir Probleme. Ich habe es geschafft, erfolgreich die meisten meiner Daten senden ganz gut mit, was ich kenne VBOs. Ich brauche aber eine große Menge an Daten zu senden, die die Verwendung von mehreren Texturkoordinaten erforderlich macht.
Ich habe implementiert bereits mehrere Varianten von dem, was ich glaube, die richtige Art und Weise der Einrichtung mehrere Sätze von Texturkoordinaten, und die Anweisungen vieler Forum Poster zu sein. Keine Lösungen arbeiten so weit.
Zusammenhang das Programm sendet 4 fast identische Kopien von einem Satz von 4 Ecken, 2 Normalvektoren, ein Schwimmer und eine ganzen Zahl (als Float abgelegt) für jeden eindeutigen Rand im Modell. Ich habe die Daten wie folgt aufgebaut:
v0 is stored in gl_Vertex (vec3)
v1 is stored in gl_Color (vec3)
v2 is stored in gl_MultiTexCoord0 (vec3)
v3 is stored in gl_MultiTexCoord1 (vec3)
n0 is stored in gl_Normal (vec3)
n1 is stored in gl_SecondaryColor (vec3)
r and i are stored in gl_MultiTexCoord2 (vec2)
Der einzige Unterschied zwischen den 4 Kopien ist der i-Wert, der bestimmen hilft, wie die Eckpunkte zu organisieren, ob und wann eine ziehbar Kante gefunden wird.
Wie Sie sehen können, ich brauche mindestens drei Texturkoordinaten. Ich konnte die erste Arbeits (gl_MultiTexCoord0) ganz gut bekommen, aber alle folgenden Texturkoordinaten, obwohl auf der Grafikkarte, erscheinen unkontrollierbares Verhalten zu haben, manchmal arbeiten, aber in der Regel nicht.
Meine Rendering-Funktion aussehen wie folgt verwendet:
void Mesh::RenderLineEdgesGPU()
{
// Enable client state
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_SECONDARY_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
// Turn on edge shader
edgeProgram.Activate();
// Link buffers
// v0
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[0]);
glVertexPointer(3, GL_FLOAT, 0, 0);
// v1
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[1]);
glColorPointer(3, GL_FLOAT, 0, 0);
// v2
glClientActiveTextureARB(GL_TEXTURE0_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[2]);
glTexCoordPointer(3, GL_FLOAT, 0, 0);
// v3
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[3]);
glTexCoordPointer(3, GL_FLOAT, 0, 0);
// n0
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[4]);
glNormalPointer(GL_FLOAT, 0, 0);
// n1
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[5]);
glSecondaryColorPointer(3, GL_FLOAT, 0, 0);
// r and i
glClientActiveTextureARB(GL_TEXTURE2_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[6]);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
// Indicies
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, edgeMeshHandles[7]);
// Draw
glDrawElements(GL_POINTS, EdgeVertexQuantity, GL_UNSIGNED_INT, 0);
// Turn off edge shader
edgeProgram.Deactivate();
// Disable client state
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
Dies war mein Original. Es funktioniert auf jeden Fall für v0, v1 und v2. Es scheint für „r und i“ zu arbeiten, aber das könnte eine Illusion sein. Ich habe nicht die Möglichkeit, noch n0 oder n1 zu testen. v3 geht definitiv nicht. Wie Sie sehen können, bin ich sie als Punkte zeichnen, die mir sagt, wenn sie dort oder nicht (über den Shader) sind. v0, v1 und v2 sind alle da. Der Versuch, das gleiche gilt für v3 Erträge entweder einen einzigen Punkt am Ursprung oder gar nichts zu tun.
an den Vorschlägen, Online Nach suchen, ist hier mein neues Setup:
void Mesh::RenderLineEdgesGPU()
{
// Enable client state
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_SECONDARY_COLOR_ARRAY);
// Turn on edge shader
edgeProgram.Activate();
// Link buffers
// v0
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[0]);
glVertexPointer(3, GL_FLOAT, 0, 0);
// v1
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[1]);
glColorPointer(3, GL_FLOAT, 0, 0);
// v2
glClientActiveTextureARB(GL_TEXTURE0_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[2]);
glTexCoordPointer(3, GL_FLOAT, 0, 0);
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
// v3
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glActiveTextureARB(GL_TEXTURE1_ARB);
glEnable(GL_TEXTURE_2D);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[3]);
glTexCoordPointer(3, GL_FLOAT, 0, 0);
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
// n0
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[4]);
glNormalPointer(GL_FLOAT, 0, 0);
// n1
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[5]);
glSecondaryColorPointer(3, GL_FLOAT, 0, 0);
// r and i
glClientActiveTextureARB(GL_TEXTURE2_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[6]);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
// Indicies
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, edgeMeshHandles[7]);
// Draw
glDrawElements(GL_POINTS, EdgeVertexQuantity, GL_UNSIGNED_INT, 0);
// Turn off edge shader
edgeProgram.Deactivate();
// Disable client state
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
}
Beachten Sie, wie ich die glEnableClientState
/ glDisableClientState
Anrufe rund um den eigentlichen „Laden“ -Liste Koordinate jede Textur getan habe. Ich benutze auch glActiveTextureARB
und glEnable(GL_TEXTURE_2D)
. Während ich glaube, ich könnte verstehen, warum glActiveTextureARB
hier gebraucht wird, Leitbleche die andere mir. Nach dem GLSL Häufige Fehler , bist du eigentlich nicht glEnable(GL_TEXTURE_2D)
verwenden wenn Sie Ihre eigenen Shadern machen, da die Verwendung von Shadern ohnehin diesen Aufruf ignoriert.
Das ist es also. Ich habe so weit gekommen, ohne irgendwelche Tutorials speziell zu finden in der Lage, Adressierung, wie nicht-Textur senden Koordinatendaten in Texturkoordinaten. Vielleicht, wenn jemand ein Tutorial über das weiß, würde mein Problem gelindert werden. Vielen Dank für Ihre Zeit!
Lösung
glClientActiveTextureARB
Änderungen, welche spezifische Texturkoordinateneinheit Anrufe folgenden glEnableClientState(GL_TEX_COORD_ARRAY)
und glTexCoordPointer
verändern wird.
glActiveTextureARB
wirkt glEnable(GL_TEXTURE_2D)
, die, wie Sie erwähnt haben, brauchen Sie nicht für Shadern.
Wenn Sie genau auf den Code schauen, Kommissionierung nur die fünf Anrufe (und deren Äquivalent Disable), hier ist das, was Sie haben:
glClientActiveTextureARB(GL_TEXTURE0_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
glTexCoordPointer(3, GL_FLOAT, 0, 0);
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glActiveTextureARB(GL_TEXTURE1_ARB);
glEnable(GL_TEXTURE_2D);
glTexCoordPointer(3, GL_FLOAT, 0, 0);
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTextureARB(GL_TEXTURE2_ARB);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
glDrawElements(GL_POINTS, EdgeVertexQuantity, GL_UNSIGNED_INT, 0);
Ok, wir schon gesagt, dass glActiveTextureARB und glEnable nicht nützlich sind (übrigens, Sie aktivieren / deaktivieren GL_TEXTURE_2D
ohne Unentschieden dazwischen, das ist nicht sinnvoll), so entfernen sie:
glClientActiveTextureARB(GL_TEXTURE0_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(3, GL_FLOAT, 0, 0);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(3, GL_FLOAT, 0, 0);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTextureARB(GL_TEXTURE2_ARB);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
glDrawElements(GL_POINTS, EdgeVertexQuantity, GL_UNSIGNED_INT, 0);
Was jetzt zeichnet sich durch? 2 Ausgaben:
- Sie Deaktivieren Sie Ihren Client-Zustand, bevor überhaupt die Ausführung Draw
- Sie setzen nicht die Enable-Bit für texture2
Was sollten Sie schreiben? Etwas in diese Richtung: (Vorsicht, Sie werden die BindBuffer ruft zurück zu jedem Pointer Anruf hinzufügen müssen):
// texture coord 0
glClientActiveTextureARB(GL_TEXTURE0_ARB); // program texcoord unit 0
glEnableClientState(GL_TEXTURE_COORD_ARRAY); // enable array data to shader
glTexCoordPointer(3, GL_FLOAT, 0, 0); // say what data
// texture coord 1
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(3, GL_FLOAT, 0, 0);
// texture coord 2
glClientActiveTextureARB(GL_TEXTURE2_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
glDrawElements(GL_POINTS, EdgeVertexQuantity, GL_UNSIGNED_INT, 0);
// done with those texcoord units, turn them off
glClientActiveTextureARB(GL_TEXTURE0_ARB);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTextureARB(GL_TEXTURE2_ARB);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
Einige weiteren Kommentare zu BindBuffer: glBindBufferARB(GL_ARRAY_BUFFER_ARB,...)
ist nicht von den glClientActiveTextureARB
Mitleidenschaft gezogen werden, aber es hat den nächsten glTexCoordPointer
Anruf beeinflussen. Im Wesentlichen, denken Sie an glClientActiveTextureARB
und glBindBufferARB
als zusätzliche Argumente zu glTexCoordPointer
bereitstellt.
Das Letzte, was wollen Sie wahrscheinlich einige dieser VBOs in weniger Puffer zu gruppieren. Etwas für andere vielleicht Frage? (Hinweis, die zwei Argumente glTexCoordPointer
müssen nicht 0 sein)