2 Fragen
-
Ich habe 2 Fragen:
1. Nachdem ich nun die OpenGL Spezifikationen gelesen habe, und ich gesehen wieviel deprecated ist, frage ich mich jetzt, ob das noch konform ist:
resizeScene(int width, int height) { glViewport(0,0,width,height); // 2D Projektionsmatrix float projection_matrix[16] = { 2.0f / width, 0.0f, 0.0f, 0.0f, // erste Spalte 0.0f, 2.0f / height, 0.0f, 0.0f, // zweite Spalte 0.0f, 0.0f, -2.0f / 2.0f, 0.0f, // dritte Spalte -1.0f, -1.0f, -1.0f, 1.0f // vierte Spalte }; float modelview_matrix[16] = { 1.0f, 0.0f, 0.0f, 0.0f, // erste Spalte 0.0f, 1.0f, 0.0f, 0.0f, // zweite Spalte 0.0f, 0.0f, 1.0f, 0.0f, // dritte Spalte 0.0f, 0.0f, 0.0f, 0.1f // viere Spalte }; } // im shader gl_Position = projection_matrix * modelview_matrix * position;
2. Ich möchte 3 Polygone zeichnen für die ich drei Farbvektoren habe. Das Problem ist jetzt, dass glColorPointer für jeden Vektor der Polygone einen Farbvektor haben möchte. Muss ich jetzt für jedes Polygon einen eigenen Fragmentshader schreiben, mit dem entsprechenden Farbvektor drin, oder gibt es eine elegantere Möglichkeit?
-
Kleiner Nachtrag:
Ich hab das jetzt mal so ausprobiert und ich habe festgestellt, dass wenn ich das hier im Shader stehen habe:in mat4 projection_matrix; in mat4 modelview_matrix; in vec2 position; void main(void) { gl_Position = gl_ModelViewProjectionMatrix * vec4(position, 0, 1); }
alles Reibungslos läuft.
Wenn ich jetzt aber meine eigenen Matrizen benutze, also so:in mat4 projection_matrix; in mat4 modelview_matrix; in vec2 position; void main(void) { gl_Position = projection_matrix * modelview_matrix * vec4(position, 0, 1); }
bekomme ich immer eine Zugriffsverletzung.
Wieso ist das so?
-
Die Matrizen als uniform deklarieren (du willst sie ja nicht für jedes Vertice einzeln angeben) und dann über glUniformMatrix4fv an den shader übergeben.
Gesetzte uniforms bleiben erhalten bis du relinkst oder sie neu setzt.
Frage 2 hab ich nicht ganz verstanden. Farbwerte sind ganz normale generic vertex attributes. Du deklarierst also entsprechend eine Variable im shader, übergibst die Werte (z.b. durch nen VertexAttribPointer) und arbeitest dann damit.
-
Mit glUniform klappt es jetzt. Aber kann man mit glUniform keine VBO's benutzen?
Nur sitzen meine Polygone jetzt ein bisschen unmotiviert an der falschen Stelle.
Hier mal mein Code:// Shader uniform mat4 projection_matrix; uniform mat4 modelview_matrix; in vec2 position; void main(void) { gl_Position = projection_matrix * modelview_matrix * vec4(position, 0, 1); } // Daten an Shader geben glUseProgram(ShaderProgram); glUniformMatrix4fv(glGetUniformLocation(ProgramObject,"projection_matrix"), 1, false, projection_matrix); glUniformMatrix4fv(glGetUniformLocation(ProgramObject,"modelview_matrix"), 1, false, modelview_matrix); glBindBuffer(GL_ARRAY_BUFFER,vboid[0]); glVertexAttribPointer(glGetAttribLocation(ProgramObject,"position"), 3, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(glGetAttribLocation(ProgramObject,"position")); glUseProgram(0);
Wenn ich die Matrizen transponiere, oder erst die modelview_matrix und dann die projection_matrix multipliziere, seh ich garnichts mehr.
-
Matrize schrieb:
Mit glUniform klappt es jetzt. Aber kann man mit glUniform keine VBO's benutzen?
Doch natürlich. Das eine hat ja mit dem anderen nichts zu tun. Allerdings fehlt in deinem code der DrawCall.
Also etwas in der Art wie glDrawArrays oder glDrawElements etc.
Das würde dann nach glEnableVertexAttribPointer kommen.Matrize schrieb:
Wenn ich die Matrizen transponiere, oder erst die modelview_matrix und dann die projection_matrix multipliziere, seh ich garnichts mehr.
Die Reihenfolge von dir ist schon richtig. Du transformierst ja zuerst in den View-/Eye-Space (modelview_matrix * vec4) und danach in den Clip-Space (projection-matrix). Das stimmt also schonmal.
Ggf. stimmt deine Projection-Matrix nicht - die vierte Spalte sieht ein wenig komisch aus.
P.S.: Da du offensichtlich mit core-Context arbeitest, empfehle ich dir eine geeignete 3D Math library zu verwenden. Ich persönlich mag OpenGL Mathematics ganz gern, da sie auf den GLSL specividations basiert. (Somit brauch ich nicht jedesmal umdenken oder transponieren etc. - da Matrizen in glm auch column-major gespeichert werden ...).
-
inter2k3 schrieb:
Doch natürlich. Das eine hat ja mit dem anderen nichts zu tun. Allerdings fehlt in deinem code der DrawCall.
Also etwas in der Art wie glDrawArrays oder glDrawElements etc.
Das würde dann nach glEnableVertexAttribPointer kommen.Der DrawCall steht dann in der Renderfunktion. Aber wie genau soll das dann mit VBOs funktionieren? Soweit ich weiß, kann man bei glUniform kein Buffer Offset angeben und glVertexAttribPointer brauch ich bei uniforms doch gar nicht?
inter2k3 schrieb:
Die Reihenfolge von dir ist schon richtig. Du transformierst ja zuerst in den View-/Eye-Space (modelview_matrix * vec4) und danach in den Clip-Space (projection-matrix). Das stimmt also schonmal.
Ggf. stimmt deine Projection-Matrix nicht - die vierte Spalte sieht ein wenig komisch aus.
Meine Projektionsmatrix hab ich so berechnet, wie glOrtho es macht.
inter2k3 schrieb:
P.S.: Da du offensichtlich mit core-Context arbeitest, empfehle ich dir eine geeignete 3D Math library zu verwenden. Ich persönlich mag OpenGL Mathematics ganz gern, da sie auf den GLSL specividations basiert. (Somit brauch ich nicht jedesmal umdenken oder transponieren etc. - da Matrizen in glm auch column-major gespeichert werden ...).
Sieht gut aus, das schau ich mir mal an.
Und um nochmal auf die Frage mit den Farbvektoren zurückzukommen.
Wenn ich diese Farbvektoren habe:float color[] = { 1.0f,0.0f,0.0f,1.0f, 0.0f,1.0f,0.0f,1.0f, 0.0f,0.0f,1.0f,1.0f };
Und Ich habe Jetzt 3 Polygone mit sagen wir mal insgesamt 15 Vektoren. Dann würde der erste Farbvektor für den ersten Polygonvektor gelten, der zweite Farbvektor dann für den zweiten Polygonvektor etc.
Was ich jetzt aber möchte ist, dass der erste Farbvektor für die ersten 5 Polygonvektoren gilt. Wie stelle ich das an?
-
Matrize schrieb:
Der DrawCall steht dann in der Renderfunktion. Aber wie genau soll das dann mit VBOs funktionieren? Soweit ich weiß, kann man bei glUniform kein Buffer Offset angeben und glVertexAttribPointer brauch ich bei uniforms doch gar nicht?
Du gibst ja nur die Matrizen mit glUniform an. Den Pointer auf die daten gibst du über glVertexAttribPointer an. Die Vertex-Attribute werden im VBO gespeichert, die Matrizen allerdings nicht.
Also Schritt-für-Schritt:- Matrizen berechnen
- Vertice-Attribute berechnen oder festlegen
- VBO erstellen und Vertice-Daten in VBO laden
- über glUniform dem Vertex-Shader die Matrizen zugänglich machen
- über glVertexAttribPointer den Shadern die Vertice-Attribute zugänglich machen
- DrawCall aufrufen.
Matrize schrieb:
inter2k3 schrieb:
Ggf. stimmt deine Projection-Matrix nicht - die vierte Spalte sieht ein wenig komisch aus.
Meine Projektionsmatrix hab ich so berechnet, wie glOrtho es macht.
[/quote]
Du interpretierst dort aber right und left, top und bottom falsch
Du teilst beispielsweise beim ersten Element 2.0/width, wobei width die Fensterbreite ist. Allerdings ist mit right-left nicht die Fensterbreite gemeint, sondern die Werte, die man normalerweise bei glOrtho angeben würde.Die Matrix für glOrtho (-2,2,-2,2,1,2) würde so aussehen:
float projection_matrix[16] = { 2.0f / (2-(-2), 0.0f, 0.0f, 0.0f, // erste Spalte 0.0f, 2.0f / (2-(-2), 0.0f, 0.0f, // zweite Spalte 0.0f, 0.0f, -2.0f / (2-1) , 0.0f, // dritte Spalte 0.0f, 0.0f, -(2+1)/2-1), 1.0f // vierte Spalte };
alse letztendlich:
float projection_matrix[16] = { 0.5f, 0.0f, 0.0f, 0.0f, // erste Spalte 0.0f, 0.5f, 0.0f, 0.0f, // zweite Spalte 0.0f, 0.0f, -2.0f, 0.0f, // dritte Spalte 0.0f, 0.0f, -3.0f, 1.0f // vierte Spalte };
Matrize schrieb:
Und um nochmal auf die Frage mit den Farbvektoren zurückzukommen.
Wenn ich diese Farbvektoren habe:float color[] = { 1.0f,0.0f,0.0f,1.0f, 0.0f,1.0f,0.0f,1.0f, 0.0f,0.0f,1.0f,1.0f };
Und Ich habe Jetzt 3 Polygone mit sagen wir mal insgesamt 15 Vektoren. Dann würde der erste Farbvektor für den ersten Polygonvektor gelten, der zweite Farbvektor dann für den zweiten Polygonvektor etc.
Was ich jetzt aber möchte ist, dass der erste Farbvektor für die ersten 5 Polygonvektoren gilt. Wie stelle ich das an?Ah verstehe. Hm - da bin ich auch ein wenig überfragt gerade (da selbst noch Anfänger). Eine Möglichkeit wäre die Farben ebenfalls als Uniform zu übergeben und dann über gl_VertexID zu entscheiden, wann welcher Farbwert genommen werden soll.
Du hättest also ein vec3 Array als uniform und setzt die Farbe dann im Shader in der Art:// nicht selbst versucht, einfach so ne Idee im Kopf gerade. vec3 col = colarray[(gl_VertexID/5];
Für die ersten 5 Vertices würde jeweils 0 als arrayIndex rauskommen, für die nächsten 5 würde 1 rauskommen etc.
Ist aber ziemlich umständlich. Da wäre es wohl einfach, einfach für jedes Vertice einen Farbvektor anzugeben.
-
inter2k3 schrieb:
Du gibst ja nur die Matrizen mit glUniform an. Den Pointer auf die daten gibst du über glVertexAttribPointer an. Die Vertex-Attribute werden im VBO gespeichert, die Matrizen allerdings nicht.
Also Schritt-für-Schritt:- Matrizen berechnen
- Vertice-Attribute berechnen oder festlegen
- VBO erstellen und Vertice-Daten in VBO laden
- über glUniform dem Vertex-Shader die Matrizen zugänglich machen
- über glVertexAttribPointer den Shadern die Vertice-Attribute zugänglich machen
- DrawCall aufrufen.
Ja die Vektoren habe ich in einem VBO, aber die Matrizen eben nicht. Mir ist aber auch gerade aufgefallen, dass das wenig Sinn machen würde.
inter2k3 schrieb:
Du interpretierst dort aber right und left, top und bottom falsch
Du teilst beispielsweise beim ersten Element 2.0/width, wobei width die Fensterbreite ist. Allerdings ist mit right-left nicht die Fensterbreite gemeint, sondern die Werte, die man normalerweise bei glOrtho angeben würde.Die Matrix für glOrtho (-2,2,-2,2,1,2) würde so aussehen:
float projection_matrix[16] = { 2.0f / (2-(-2), 0.0f, 0.0f, 0.0f, // erste Spalte 0.0f, 2.0f / (2-(-2), 0.0f, 0.0f, // zweite Spalte 0.0f, 0.0f, -2.0f / (2-1) , 0.0f, // dritte Spalte 0.0f, 0.0f, -(2+1)/2-1), 1.0f // vierte Spalte };
alse letztendlich:
float projection_matrix[16] = { 0.5f, 0.0f, 0.0f, 0.0f, // erste Spalte 0.0f, 0.5f, 0.0f, 0.0f, // zweite Spalte 0.0f, 0.0f, -2.0f, 0.0f, // dritte Spalte 0.0f, 0.0f, -3.0f, 1.0f // vierte Spalte };
Wenn ich glOrtho benutze, habe ich bei einer Fensterbreite von 800 und Höhe von 600 immer das hier im Code stehen:
glOrtho(0,800,0,600,-1,1);
Und wenn ich so wie glOrtho meine eigene Matrix berechnen will, dann solte doch das herauskommen, was ich da stehen habe.
inter2k3 schrieb:
Ah verstehe. Hm - da bin ich auch ein wenig überfragt gerade (da selbst noch Anfänger). Eine Möglichkeit wäre die Farben ebenfalls als Uniform zu übergeben und dann über gl_VertexID zu entscheiden, wann welcher Farbwert genommen werden soll.
Du hättest also ein vec3 Array als uniform und setzt die Farbe dann im Shader in der Art:// nicht selbst versucht, einfach so ne Idee im Kopf gerade. vec3 col = colarray[(gl_VertexID/5];
Für die ersten 5 Vertices würde jeweils 0 als arrayIndex rauskommen, für die nächsten 5 würde 1 rauskommen etc.
Ist aber ziemlich umständlich. Da wäre es wohl einfach, einfach für jedes Vertice einen Farbvektor anzugeben.Danke, das war schonmal ein Gedankenanstoß. Wenn es da keine andere Methode gibt, werde ich es mal so probieren.
-
Dank GLM klappt jetzt alles
Hier der relevante Code f+r die Matrizen:glm::mat4 projection_matrix = glm::ortho(0.0f, width, 0.0f, height); glm::mat4 modelview_matrix = glm::mat4(1.0f); glUniformMatrix4fv(glGetUniformLocation(Shader,"projection_matrix"), 1, false, glm::value_ptr(projection_matrix)); glUniformMatrix4fv(glGetUniformLocation(Shader,"modelview_matrix"), 1, false, glm::value_ptr(modelview_matrix));
-
Jup - sieht gut aus.
Man muss sich ein wenig in glm einarbeiten, aber danach ist es recht intuitiv.
Dann happy coding
-
Ich hab noch mal eine Frage.
Ist das hier deprecated? Aus den OpenGL Specs kann ich das nicht genau erkennen.void init { // ... unsigned short pindices[3]; pindices[0] = 0; pindices[1] = 1; pindices[2] = 2; glGenBuffers(1,&indexid); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexid); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned short)*3, pindices, GL_STATIC_DRAW); // ... } void draw { glUseProgram(Shader); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexid); glDrawElements(GL_TRIANGLES,3,GL_UNSIGNED_SHORT,0); glUseProgram(0); }
Die Shader werden natrülich auch in der Init funktion erstellt und die vertices auch in den Buffer geschrieben.
Mit geht es hier um glDrawElements() und das ich vorher noch den ELEMENT_ARRAY_BUFFER binden muss.
-
Nein, das sind alles core-functions - nichts deprecated.
Einen schnellen Überblick darüber, was deprecated ist oder nicht siehst du in den Quick Reference-Cards. Alles was in blauer Schrift geschrieben ist, ist nur über ein compatibility-profile zugänglich.
-
Danke, die Seiten sidn echt gut
Nur stellen sich mir dadurch wieder 2 Fragen
1. Kann man jetzt wirklich nurnoch Punkte, Linien und Dreiecke zeichnen? Wenn ja, wär das ziemlich mies.
2. Wie soll man Sachen jetzt texturieren. Im Internet findet man nur Tutorial mit gl_TexCoord[] oder glMultiTexcoord0 etc. Aber die sind ja alle deprecated...
-
Matrize schrieb:
Danke, die Seiten sidn echt gut
Nur stellen sich mir dadurch wieder 2 Fragen
1. Kann man jetzt wirklich nurnoch Punkte, Linien und Dreiecke zeichnen? Wenn ja, wär das ziemlich mies.Ja - als Primitiven sind keine quadriliterale mehr erlaubt. Aber da man jedes Rechteck ganz einfach durch 2 Dreiecke zeichnen kann ist dies kein wirklich grosses Problem (oder durch triangle-strip, dann kann man die gleichen 4 Koordinaten verwenden).
Matrize schrieb:
2. Wie soll man Sachen jetzt texturieren. Im Internet findet man nur Tutorial mit gl_TexCoord[] oder glMultiTexcoord0 etc. Aber die sind ja alle deprecated...
Texturkoordinaten werden wie Farbwerte, Vertex-Koordinaten etc. auch ganz normal als Vertex-Attribut an die shader übergeben und durch den rasterizer dann entsprechen für jedes Fragment interpoliert.
Die Texturen werden als uniform sampler übergeben und im shader erfolgt das lookup dann durch eine der vielen LookUp-Funktionen.
-
Weil ich es mit den Texturen noch nicht ausprobiert habe:
Kann ich ein Viereck, dass ich durch GL_TRIANGLE_STRIP gezeichnet habe, genauso wie eins, dass ich durch GL_QUADS gezeichnet habe, texturiert werden?
-
Matrize schrieb:
Weil ich es mit den Texturen noch nicht ausprobiert habe:
Kann ich ein Viereck, dass ich durch GL_TRIANGLE_STRIP gezeichnet habe, genauso wie eins, dass ich durch GL_QUADS gezeichnet habe, texturiert werden?Im Normalfall schon ja.
-
Irgendwie gehen mir die Fragen nicht aus
Wenn ich jetzt eine 2D-Szene zeichnen will, in der ich ein paar Vierecke habe, die sich bewegen und rotieren etc., ist es dann sinnvoller, die Vektoren von den Vierecken zu verändern, damit sie sich bewegen, oder die ModelviewMatrix zu verändern?
-
Du könntest natürlich für jedes Quadrat jedesmal die Koordinaten neu berechnen, dann jedesmal ein neues VBO erstellen oder die VBOs updaten und sie dann zeichnen lassen.
Ich änder lieber die MV-Matrix aus dem einfachen Grund, dass ich dann nur ein VBO brauch, an dem ich auch nichts ändern muss. Das einzige was ich bei jedem Durchgang neu setzen muss wäre also die MV-Matrix. Ist übersichtlicher find ich und auch schneller.
Grundgedanke: Ein Quader ist immer ein Quader, egal wie er orientiert ist, wo er sich befindet und ob er gestaucht oder gestreckt ist. Also geb ich auch nur einmal an, wie er aussieht - und Position, Rotation und Skalierung geb ich nur noch über die MV-Matrix an.
-
Matrize schrieb:
Weil ich es mit den Texturen noch nicht ausprobiert habe:
Kann ich ein Viereck, dass ich durch GL_TRIANGLE_STRIP gezeichnet habe, genauso wie eins, dass ich durch GL_QUADS gezeichnet habe, texturiert werden?Wenn du früher GL_QUADS verwendet hast hat sich einfach der Grafiktreiber intern drum gekümmert deine Quads in Dreiecke zu zerlegen da es sowieso praktisch keine Grafikkarte gibt die wirklich in der Lage ist Quads als Primitiv zu rendern (ich bin mir sicher dass natürlich irgendwer irgendwann schonmal sowas gebaut hat darum will ich die Existenz derartiger Hardware nicht ganz ausschließen, aber das was man heutzutage so als Grafikkarte verwendet kann nur Dreiecke rasterisieren).
Matrize schrieb:
Wenn ich jetzt eine 2D-Szene zeichnen will, in der ich ein paar Vierecke habe, die sich bewegen und rotieren etc., ist es dann sinnvoller, die Vektoren von den Vierecken zu verändern, damit sie sich bewegen, oder die ModelviewMatrix zu verändern?
Naja, das hängt davon ab was genau du machst. Hast du einen haufen Vierecke die alle zusammen ein starres Objekt repräsentieren bzw. eben alle die selbe Bewegung durchführen!? Wenn ja ist es natürlich sinnvoll (weil extrem viel effizienter) die Ausrichtung über Matritzen zu bestimmen. Wenn du einen Haufen Vierecke hast die sich alle unabhängig voneinander bewegen wird es evtl. sinnvoller sein ein dynamisches VBO zu haben und die Positionen der Vertices darin in jedem Frame neu hochzuladen um nicht so viele einzelne draw calls und state changes zu haben.
-
Das mit dem texturieren bekomme ich nicht ganz hin.
1. Ich finde bei google immer nur den Shader Code. Wie ich die Textur nun an den Shader übergebe steht irgenwie nirgends.
2. In allen Tutorials werden immer nur die depreacted Variablen gl_TexCoord[0] und gl_MultiTextCoord0. Wieso reicht hier ein Vertex und wie binde ich die Koordinaten ohne die beiden depreacted Variablen ein?