DGL
https://delphigl.com/forum/

Variable an Shader übergeben
https://delphigl.com/forum/viewtopic.php?f=20&t=11038
Seite 1 von 3

Autor:  mathias [ Mi Dez 04, 2013 18:06 ]
Betreff des Beitrags:  Variable an Shader übergeben

Mein VertexShader sieht so aus:
Code:
  1. #version 330
  2. // Input vom VBO:
  3. in vec3 inPos;
  4. in vec4 inColor;
  5.  
  6. in float Zoom;
  7.  
  8. // Ausgabe an den Fragmentshader:
  9. out vec4 Color;
  10.  
  11. void main(void)
  12. {
  13.   gl_Position = vec4(inPos, 1.0)+Zoom;
  14.   Color = inColor;
  15. }                  

Wie kann ich einen Wert an Zoom übergeben ?

Wen ich gl_Position = vec4(inPos, 1.0)+1.0; schreibe, dann wird mein Dreiecke obenrechts verkleinert angezeit. Aber ich will das mit meinem Programm machen.

Ich habe es mit glUniform1f probiert.
Code:
  1. procedure TForm1.RenderScene;
  2. begin
  3.   // We just clear color
  4.   glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  5.  
  6.  
  7.   // Triangle render
  8.   glBindVertexArray(uiVAO[0]);
  9.  
  10.   glUniform1f(glGetUniformLocation(ProgramID, PGLCharARB('Zoom')), 1.0);
  11.   glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
  12.  
  13.   // Quad render using triangle strip
  14.   glBindVertexArray(uiVAO[1]);
  15.   glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  16.  
  17.   SwapBuffers(DC);
  18. end;      

Was mache ich schon wieder falsch ?

Autor:  OpenglerF [ Mi Dez 04, 2013 18:27 ]
Betreff des Beitrags:  Re: Variable an Shader übergeben

Werte die von deinen Programm in den Shader wandern sollen, müssen als "uniform" gekennzeichnet werden.
Ersetze das "in" bei "Zoom" durch das Schlüsselwort "uniform".

Und, der Shader wird nicht direkt das machen, was du erreichen willst.
Du führst eine Vektoraddition durch, was erstmal einer Verschiebung entspricht. Anders gesagt, du vergrößerst, X, Y, Z und W um den Wert von "Zoom" was dann am Ende ziemlich komische Ergebnisse liefern wird, wegen der W-Division die anschließend ausgeführt wird. (Nach dem der Vertex Shader ausgeführt wurde, werden im Hintergrund X,Y und Z durch W dividiert. Wenn W 1 ist wie normalerweise, passiert also gar nichts. Wenn man W wie du, verändert könnte man damit eine verschoben inverse Skalierung durchführen, das willst aber eher weniger, nehme ich an.)
Wenn du Verschieben willst, wäre also "vec4(inPos.xyz + Zoom, 1.0);" richtig und "Zoom" müsste ein 3 Komponentenvektor sein. (X, Y und Z halt.)
Oder wenn du skalieren willst(zoomen) müsstest du eine Skalarmultiplikation durchführen: "vec4(inPos.xyz * Zoom, 1.0);"
Wenn du richtig sinnvoll etwas erreichen willst, solltest du dafür auch eher Matrizen verwenden, wie es schon früher die Fixedpipeline tat.

Autor:  glAwesome [ Mi Dez 04, 2013 18:46 ]
Betreff des Beitrags:  Re: Variable an Shader übergeben

Zum Unterschied von in und uniform im Vertexshader:
  • in-Variablen werden für jeden Vertex mit einem neuen Wert belegt, der aus dem VBO kommt. Wo und wie genau die Vertexdaten im VBO gespeichert sind, legst du mit glVertexAttribPointer fest.
  • uniform-Variablen belegst du einmal durch einen glUniform-Aufruf mit einem Wert. Dieser Wert gilt dann im aktuell gebundenen Program so lange für jeden Vertex, bis wieder glUniform aufgerufen wird.

Autor:  mathias [ Mi Dez 04, 2013 19:34 ]
Betreff des Beitrags:  Re: Variable an Shader übergeben

Vielen Dank für die schnelle Antwort.

Jetzt bewegt sich mein in der X und Y - Achse. Das man in der Z-Achse nichts sieht, nehme ich an, das die Darstellung nicht Proportional ist, sonst würde das Dreieck kleiner und grösser werden.
Code:
  1. #version 330
  2. // Input vom VBO:
  3. in vec3 inPos;
  4. in vec4 inColor;
  5.  
  6. uniform vec3 Zoom;
  7.  
  8. // Ausgabe an den Fragmentshader:
  9. out vec4 Color;
  10.  
  11. void main(void)
  12. {
  13.   gl_Position = vec4(inPos.xyz + Zoom, 1.0);
  14.   Color = inColor;
  15. }

Zoom ist eine Variable die ich mit einer Timerfunktion verändere.
Sollte später zoom[0], zoom[1], zoom[3] werden.
Code:
  1. procedure TForm1.RenderScene;
  2. begin
  3.   // We just clear color
  4.   glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  5.  
  6.   glUniform3f(glGetUniformLocation(ProgramID, PGLCharARB('Zoom')), zoom[0], zoom[0], zoom[0]);
  7.  
  8.   // Triangle render
  9.   glBindVertexArray(uiVAO[0]);
  10.  
  11.   glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
  12.  
  13.   // Quad render using triangle strip
  14.   glBindVertexArray(uiVAO[1]);
  15.   glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  16.  
  17.   SwapBuffers(DC);
  18. end;      

Wie kann ich machen, das sich nur das Dreieck bewegt ?
Muss ich das mit den VBOs machen, so wie mit den Farben ?

Autor:  glAwesome [ Mi Dez 04, 2013 22:47 ]
Betreff des Beitrags:  Re: Variable an Shader übergeben

mathias hat geschrieben:
Jetzt bewegt sich mein in der X und Y - Achse.
Leider fehlt das Subjekt.

mathias hat geschrieben:
Das man in der Z-Achse nichts sieht, nehme ich an, das die Darstellung nicht Proportional ist, sonst würde das Dreieck kleiner und grösser werden.
Das liegt daran, dass du die Vertices nicht mit einer perspektivischen Matrix multiplizierst - also das, was du früher mit gluPerspective eingestellt hast.

mathias hat geschrieben:
Zoom ist eine Variable die ich mit einer Timerfunktion verändere.
Dann ist uniform schon richtig.

mathias hat geschrieben:
Wie kann ich machen, das sich nur das Dreieck bewegt?
Im Gegensatz zum Viereck? Einfach vor dem Rendern des Vierecks nochmal glUniform aufrufen, um Zoom auf 0 zu setzen.


Mir ist nicht ganz klar, was du erreichen möchtest. Als Zoom bezeichnet man üblicherweise einen Effekt, der durch das Verändern des View-Frustums erzielt wird. Beim Hineinzoomen würde man z.B. den Parameter fovy der Funktion gluPerspective verringern. Voraussetzung für Zoom ist eine perspektivische Ansicht, die du momentan nicht hast (deine ist orthogonal). Was du in deinem Shader machst, ist eine Translation. Würdest du das + durch ein * ersetzen, hättest du eine Skalierung. Alles sind verschiedene Effekte.

Autor:  mathias [ Do Dez 05, 2013 18:30 ]
Betreff des Beitrags:  Re: Variable an Shader übergeben

Wen ich meinMatrix als Konstante deklariere (momentan ausgeklammert) bleibt das Dreieck stehen, das ist richtig so.
Will ich aber die Matrix über mein Program in den Shader schicken, kommt gar nichts.
Die Zeile mit meinMove funktioniert.
Code:
  1. #version 330
  2. // Input vom VBO:
  3. in vec3 inPos;
  4. in vec4 inColor;
  5.  
  6. uniform vec3 meinMove;
  7. uniform mat4 meinMatrix;
  8.  
  9. //mat4 meinMatrix =mat4(1.0, 0.0, 0.0, 0.0,  
  10. //                                0.0, 1.0, 0.0, 0.0,  
  11. //                                0.0, 0.0, 1.0, 0.0,  
  12. //                                0.0, 0.0, 0.0, 1.0);
  13.  
  14. // Ausgabe an den Fragmentshader:
  15. out vec4 Color;
  16.  
  17. void main(void)
  18. {
  19.   gl_Position = meinMatrix * vec4(inPos.xyz + meinMove, 1.0);
  20.   Color = inColor;
  21. }

Deklaration fMatrix:
Code:
  1.  fMatrix: array[1..16] of GLfloat =
  2.     (1.0, 0.0, 0.0, 0.0,
  3.     0.0, 1.0, 0.0, 0.0,
  4.     0.0, 0.0, 1.0, 0.0,
  5.     0.0, 0.0, 0.0, 1.0);

Aufruf im Program:
Code:
  1.   glUniform3f(glGetUniformLocation(ProgramID, PGLCharARB('meinMove')), 0, 0, 0);
  2.   glUniformMatrix4fv(glGetUniformLocation(ProgramID, PGLCharARB('meinMatrix')), SizeOF(fMatrix), False, @fMatrix);
  3.   glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);


PS:So wie es aussieht, hat es im Tutorial http://wiki.delphigl.com/index.php/Tutorial_glsl einen kleinen Fehler:
Code:
  1. mat4 MyMatrix = mat4(MyVec4, MyVec4, MyVec4, MyVec4);
  2. mat2 MyMatrix = mat4(1.0, 0.0, 0.0, 0.0,
  3.                      0.0, 1.0, 0.0, 0.0,
  4.                      0.0, 0.0, 1.0, 0.0,
  5.                      0.0, 0.0, 0.0, 1.0);

mat2 müsste mat4 heissen.

Autor:  glAwesome [ Do Dez 05, 2013 19:04 ]
Betreff des Beitrags:  Re: Variable an Shader übergeben

mathias hat geschrieben:
Code:
  1. glUniformMatrix4fv(glGetUniformLocation(ProgramID, PGLCharARB('meinMatrix')), SizeOF(fMatrix), False, @fMatrix);
Der zweite Parameter von glUniformMatrix4fv ist nicht richtig. Du möchtest eine Matrix übergeben, demnach muss dort eine 1 stehen. Die Größe ist ja schon durch das "Matrix4fv" im Funktionsnamen klar.
Ich bin mir nicht sicher, ob der letzte Parameter korrekt ist. In C++ wäre fMatrix selbst schon ein Zeiger auf das Array. @fMatrix[1] sollte auf jeden Fall gehen, denke ich. Aber ich bin wie gesagt kein Pascaler.

Ansonsten wäre es natürlich schön zu wissen, was du mit der Matrix im Vertexshader anstellst. Du hast doch nicht etwa die Multiplikation vergessen? :wink:

mathias hat geschrieben:
So wie es aussieht, hat es im Tutorial http://wiki.delphigl.com/index.php/Tutorial_glsl einen kleinen Fehler[...]
Stimmt, das ist falsch. Das tolle am Wiki ist: Du kannst es direkt korrigieren. Einfach rechts oben auf "Anmelden" klicken und dich mit deinem Foren-Account einloggen. Dann erscheint neben jeder Überschrift ein "Bearbeiten". Falls was schief gehen sollte, lässt sich die Änderung ganz leicht wieder rückgängig machen, also nur keine Scheu.

Dies ist ein dezenter Hinweis auf meine Signatur, in der Hoffnung, dass kleine Schrift mehr auffält, als fette gelbe. :)

Autor:  mathias [ Do Dez 05, 2013 20:03 ]
Betreff des Beitrags:  Re: Variable an Shader übergeben

Es lag an der 1.
Die Matrix kann ich jetzt auch Zweidimensional deklarieren.
Code:
  1. const
  2.   fMatrix: array[1..4, 1..4] of GLfloat =
  3.       ((1.0, 0.0, 0.0, 0.0), (0.0, 1.0, 0.0, 0.0), (0.0, 0.0, 1.0, 0.0), (0.0, 0.0, 0.0, 1.0));
  4.  
  5. ...
  6.  
  7.   glUniformMatrix4fv(glGetUniformLocation(ProgramID, PGLCharARB('meinMatrix')), 1, False, @fMatrix);
  8.  


Zitat:
Ansonsten wäre es natürlich schön zu wissen, was du mit der Matrix im Vertexshader anstellst. Du hast doch nicht etwa die Multiplikation vergessen?

Was meinst du mit der Multiplikation, meinst du weil fMatrix in eine Constante ist ?
Wen es dies ist, währe dies nur als Versuch, ob die Variablen richtig übergeben werden.
Oder habe ich noch einen Fehler in dem VertexShader, aber dort hat es ja ein "*" ?

Code:
  1. gl_Position = meinMatrix * vec4(inPos.xyz + meinMove, 1.0);



PS:Das Wiki konnte ich ändern, ich wusste nicht, das ein normaler User dies auch ändern kann. Bekommt ihr eine Benachrichtigung, wen jemand was ändert ?

Autor:  glAwesome [ Do Dez 05, 2013 20:10 ]
Betreff des Beitrags:  Re: Variable an Shader übergeben

mathias hat geschrieben:
Oder habe ich noch einen Fehler in dem VertexShader, aber dort hat es ja ein "*" ?
Hoppla, da muss ich mich verguckt haben. Du multiplizierst den vec4 ja schon mit der Matrix. Im nächsten Schritt könntest du die Translation natürlich noch in die Matrix integrieren, damit du dir die Addition im Shader sparen kannst.

mathias hat geschrieben:
Das Wiki konnte ich ändern, ich wusste nicht, das ein normaler User dies auch ändern kann. Bekommt ihr eine Benachrichtigung, wen jemand was ändert?
Schön, dass es geklappt hat. Jeder, der einen Artikel beobachtet (Haken beim Bearbeiten setzen), bekommt eine Benachrichtigung.

Autor:  mathias [ Do Dez 05, 2013 20:17 ]
Betreff des Beitrags:  Re: Variable an Shader übergeben

Zitat:
Im nächsten Schritt könntest du die Translation natürlich noch in die Matrix integrieren, damit du dir die Addition im Shader sparen kannst.

Zuerst muss ich mich schlau machen, wie das mit den Matrixwerten funktioniert. Wichtig war, das die Matrix richtig in den Shader geschrieben wird, sonst nützt alles probieren mit der Matrix nichts.

Autor:  glAwesome [ Do Dez 05, 2013 20:23 ]
Betreff des Beitrags:  Re: Variable an Shader übergeben

Die Matrizen sind in den entsprechenden Wiki-Artikeln erklärt:
glTranslate, glRotate, glScale, gluPerspective

Autor:  mathias [ So Dez 08, 2013 17:38 ]
Betreff des Beitrags:  Re: Variable an Shader übergeben

Ich habe mir Rotate Funktionen geschrieben, welche auch gut funktionieren.
Nur funktioniert dies nur global über alle Körper. Mit der original Funktion glRotate konnte man lokal ein Element drehen.
Wen ich das immer noch manchen will, sehe ich nur einen Weg, die Koordinaten des Elementes zu ändern.

Oder gibt es da eine Unterstützung von OpenGL ?

Code:
  1. type
  2.   fTMatrix = array[1..4, 1..4] of GLfloat;  
  3.  
  4. procedure RotateX(var Matrix: fTMatrix; Winkel: GLfloat);
  5. var
  6.   y, z: GLfloat;
  7.   i: integer;
  8. begin
  9.   for i := 1 to 3 do
  10.   begin
  11.     y := Matrix[i, 2];
  12.     z := Matrix[i, 3];
  13.     Matrix[i, 2] := y * cos(Winkel) - z * sin(Winkel);
  14.     Matrix[i, 3] := y * sin(Winkel) + z * cos(Winkel);
  15.   end;
  16. end;
  17.  
  18. procedure RotateY(var Matrix: fTMatrix; Winkel: GLfloat);
  19. var
  20.   x, z: GLfloat;
  21.   i: integer;
  22. begin
  23.   for i := 1 to 3 do
  24.   begin
  25.     x := Matrix[i, 1];
  26.     z := Matrix[i, 3];
  27.     Matrix[i, 1] := x * cos(Winkel) - z * sin(Winkel);
  28.     Matrix[i, 3] := x * sin(Winkel) + z * cos(Winkel);
  29.   end;
  30. end;
  31.  
  32. procedure RotateZ(var Matrix: fTMatrix; Winkel: GLfloat);
  33. var
  34.   x, y: GLfloat;
  35.   i: integer;
  36. begin
  37.   for i := 1 to 3 do
  38.   begin
  39.     x := Matrix[i, 1];
  40.     y := Matrix[i, 2];
  41.     Matrix[i, 1] := x * cos(Winkel) - y * sin(Winkel);
  42.     Matrix[i, 2] := x * sin(Winkel) + y * cos(Winkel);
  43.   end;
  44. end;    

Autor:  glAwesome [ So Dez 08, 2013 18:39 ]
Betreff des Beitrags:  Re: Variable an Shader übergeben

Die Matrixfunktionen aus GL1.0 ersetzen nicht einfach die aktuelle Matrix durch eine Rotations-/Translationsmatrix. Sie mulitplizieren die aktuelle Matrix mit der neu berechneten.

Autor:  mathias [ So Dez 08, 2013 22:40 ]
Betreff des Beitrags:  Re: Variable an Shader übergeben

Habe ich das recht verstanden, wen ich mehrere Objekte, z.B. Würfel, jedes einzeln drehen will, muss die Ratation direkt auf die Eckpunkte des Objekts anwenden und dies ohne Shader.

Autor:  OpenglerF [ So Dez 08, 2013 22:48 ]
Betreff des Beitrags:  Re: Variable an Shader übergeben

Nein. Die Shader sind dafür da, Daten auf der Grafikkarte zu verarbeiten, ohne die CPU zu beanspruchen.
Du musst einfach die Matrix im Shader nach für jedes zu renderende Modell neu setzen.

Seite 1 von 3 Alle Zeiten sind UTC + 1 Stunde
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/