DGL
https://delphigl.com/forum/

[solved] glUseProgram scheitert
https://delphigl.com/forum/viewtopic.php?f=20&t=11276
Seite 1 von 2

Autor:  Sellmann [ Mo Nov 24, 2014 10:50 ]
Betreff des Beitrags:  [solved] glUseProgram scheitert

Hallo Leute!
Ich war leider schon länger nicht mehr hier und stolpere natürlich auch gleich mit einem neuen Problem in die Tür.

Es geht diesmal um OpenGL4 und GLSL4 unter Windows7 mit NVidia Quadro 4000 und NVidia GTX 560 Ti (aktuellste Treiber). Programmieren tue ich in C# mittels OpenTK.

Das eigentliche Problem: Ich versuche einen einfachen Standardshader (Vertex+Fragment) zum Laufen zu bekommen. Das scheitert allerdings jedesmal bei glUseProgram(). Der Fehlercode, der mir anschließend von glGetError() gegeben wird ist immer "GL_INVALID_OPERATION". Was mich daran wundert ist, dass alle vorherigen Aufrufe bezüglich des Shaders (Sourcen laden, compilien, attachen, linken) keinen Fehler generieren und auch die InfoLogs nach kompilieren und linken leer sind. Aus der Spezifikation von glUseProgram hab ich heraus gelesen, dass besagter Fehlercode auf eine falsche ID zurückgeführt werden könnte, was ich aber sicher ausschließen kann. Die übergebene ID ist in jedem Fall richtig. Laut NVidia decken die beiden Grafikkarten OpenGL bis Version 4.4 und 4.5 vollständig ab, nutzen tue ich jedoch lediglich "#version 400" in den Shadern. Beide Karten zeigen das gleiche verhalten.

Die Frage ist jetzt, was könnte sich dahinter verbergen? Wo könnte ich meine Fehlersuche fortsetzen? Hat eventuell jemand ein solches Problem schon selbst gehabt und eine Lösung parat?

Gruß, Sellmann.

Vertexshader:
Code:
  1. #version 400
  2.  
  3. layout(location = 0) in vec3 vertex_position;
  4. layout(location = 1) in vec3 vertex_color;
  5.  
  6. out vec3 color;
  7.  
  8. void main ()
  9. {
  10.     color = vertex_color;
  11.     gl_Position = vec4(vertex_position, 1.0);
  12. }


Fragmentshader:
Code:
  1. #version 400
  2.  
  3. in vec3 color;
  4. out vec4 fragColor;
  5.  
  6. void main()
  7. {
  8.     fragColor = vec4(color, 1.0);
  9. }


Edit: Ich hab gerade noch einen Typ-Fehler im Fragmentshader behoben. Das Problem besteht aber weiterhin.

Autor:  glAwesome [ Mo Nov 24, 2014 11:17 ]
Betreff des Beitrags:  Re: glUseProgram scheitert

Das wäre wohl zu einfach, wenn das der Fehler wäre, aber überprüf das mal:
opengl.org hat geschrieben:
GL_INVALID_OPERATION​ is generated if transform feedback mode is active.

Autor:  Sellmann [ Mo Nov 24, 2014 11:31 ]
Betreff des Beitrags:  Re: glUseProgram scheitert

Wie kann ich denn herausfinden, ob der Transform-Feedback-Mode active ist? Ich habe noch nie damit gearbeitet.

Autor:  glAwesome [ Mo Nov 24, 2014 11:33 ]
Betreff des Beitrags:  Re: glUseProgram scheitert

Dann ist es auch nicht aktiv. Es muss was anderes sein...

Autor:  glAwesome [ Mo Nov 24, 2014 11:42 ]
Betreff des Beitrags:  Re: glUseProgram scheitert

Noch 2 Ideen:
- Bist du ganz sicher, dass erst glUseProgram den Fehler auslöst und nicht schon ein Funktionsaufruf davor?
- Hast du auch tatsächlich einen OpenGL 4.0 (oder höher)-Kontext erstellt? Also forward-compatible, wie hier beschrieben: Tutorial OpenGL3 Zeichenkontext

Autor:  Sellmann [ Mo Nov 24, 2014 11:56 ]
Betreff des Beitrags:  Re: glUseProgram scheitert

Zu 1: Ja, da bin ich mir sehr sicher. Das Programm besteht bisher nur aus einem Kontext, Viewport Initialisierung und der Erzeugung der Shader. Nach jedem glXyz() frag ich mittels glGetError() einmal die Fehler ab und erst nach glUseProgram() steht was anderes als "GL_NO_ERROR" drin.

Zu 2: Da ich die mitgelieferte GlControl Komponente aus dem OpenTK-Framework verwende, kann ich nicht genau sagen, ob das intern tatsächlich geklappt hat mit dem GL4-Kontext. Ich geh dem mal auf den Grund und meld mich gleich zurück.

Edit: Ich hab mir jetzt die Kontextgenerierung angeschaut und bin mir sicher, dass ich einen Kontext mit OpenGl v4.4.0 und GlSl v4.40 habe.

Autor:  glAwesome [ Mo Nov 24, 2014 12:32 ]
Betreff des Beitrags:  Re: glUseProgram scheitert

Dann müsste der Fehler ja ebenfalls auftreten, wenn du aus deinem Shader alle OpenGL3+-Spezialitäten entfernst:
Code:
  1. // Vertexshader
  2. attribute vec3 vertex_position;
  3. attribute vec3 vertex_color;
  4.  
  5. varying vec3 color;
  6.  
  7. void main ()
  8. {
  9.     color = vertex_color;
  10.     gl_Position = vec4(vertex_position, 1.0);
  11. }


Code:
  1. // Fragmentshader
  2. varying vec3 color;
  3.  
  4. void main()
  5. {
  6.     gl_FragColor = vec4(color, 1.0);
  7. }


Tut er das?

Autor:  Sellmann [ Mo Nov 24, 2014 13:04 ]
Betreff des Beitrags:  Re: glUseProgram scheitert

Mit dem von dir genannten Shader funktioniert es gar nicht mehr. Es wird zumindest nichts mehr auf den Bildschirm gezeichnet. Nicht einmal die ClearColor wird dargestellt. Scheinbar gibt es dann ein Problem damit, dass ich das CoreProfile von GL4.4 verwende. Ich müsste mich dann mal umschauen, wie ich das CompatibilityProfile mit dem GlControl aktiviere, um auch noch alles verwenden zu dürfen, was ab 3.x als deprecated eingestuft wurde.

Edit: Der Kontext sagt mir zur Laufzeit, dass er im CompatibilityProfile läuft, obwohl das eigentlich nicht der Fall sein sollte. Merkwürdigerweise sollte dein Shader dann doch funktionieren, oder nicht?

Edit2: Ich lese gerade, dass das Core und Compatibility ab 3.2+ identisch sein sollen, was ich irgendwie komisch finde.

Autor:  mathias [ Mo Nov 24, 2014 18:21 ]
Betreff des Beitrags:  Re: glUseProgram scheitert

Eine dumme Farage,
die Shader-Lade-Routine, welche du verwendest, funktioniert diese ?
Wen nicht, dann poste mal diese.

Die Shader bei deinem ersten Post scheinen in Ordnung zu sein.
Kannst noch probieren anstelle von #version 400, #version 330 zu schreiben.

Autor:  Sellmann [ Di Nov 25, 2014 08:23 ]
Betreff des Beitrags:  Re: glUseProgram scheitert

Ja, die Routine funktioniert. Zumindest erhalte ich beim Kompilieren keinen Fehler, das Infolog ist leer und wenn ich den Sourcecode vom Shader abfrage, erhalte ich auch exakt den Inhalt der Datei wieder zurück.

Edit: Ich probier gerade das ganze mit freepascal zum Laufen zu bekommen, um zu gucken, ob es vielleicht am OpenTK Framework liegt. Das Problem ist, dass ich gerade kein Beispiel finden kann, wie ich einen OpenGL 3.x+ Kontext in freepascal erzeuge. Die Beispiele die ich habe sind in C++ und nutzen alle den Typ "PIXELFORMATDESCRIPTOR", den ich nicht finden kann. Sollte es nicht mal eine Methode geben einen 3.x+ Kontext zu erstellen, ohne zuvor einen 2.1 Kontext generieren zu müssen?

Edit2: Hab jetzt den Kontext. Ich kannte die Methode "CreateRenderingContextVersion" noch nicht. Ich schreib dann nochmal, wenn ich den Rest übersetzt hab.

Autor:  Sellmann [ Di Nov 25, 2014 16:00 ]
Betreff des Beitrags:  Re: glUseProgram scheitert

Okay, das ist merkwürdig. Der oben genannte Shader lässt sich ohne Weiteres in freepascal verwenden. Es scheint wohl am Framework selbst zu liegen. Ich glaube dann wende ich mich besser an die Entwickler von OpenTK. Ich kann mir das zwar nicht wirklich vorstellen, weil ich scheinbar der einzige mit dem Problem bin, aber möglich wäre es ja...

Trotzdem vielen Dank!

Autor:  yunharla [ Di Nov 25, 2014 16:57 ]
Betreff des Beitrags:  Re: glUseProgram scheitert

Geh doch mal in den Example Ordner:
C:\Users\Alex\Documents\OpenTK\1.0\Source\Examples

dort ist eigentlich alles drinne was man so braucht. Context Version wird zum Beispiel im Constructor vom Fenster oder GLControl gesetzt.

Autor:  Sellmann [ So Dez 07, 2014 11:05 ]
Betreff des Beitrags:  Re: glUseProgram scheitert

Ich verstehe die Welt nicht mehr!

Ich hab das obige Beispiel in freepascal auf Anhieb zum Laufen bekommen. Jetzt habe ich das ganze erweitert, dass ich meine Scene zunächst in mehrere Texturen render und anschließend als Fullscreen Quad auf den Bildschirm bringe. Klassisches Deffered Rendering halt. Soweit ist auch alles gut. Möchte ich jetzt allerdings den Geometry Shader aus dem Wiki verwenden, um die TBN Matrix für den Normalbuffer zu berechnen, passiert genau das gleiche wie vorher. Alles kompiliert und linkt, aber glUseProgram scheitert. Klammere ich den Geometry Shader aus, erhalte ich zumindest eine gerenderte Szene, ansonsten bleibt das Bild schwarz.

Hierzu sei erwähnt, dass ich den Shader an meinen Vokabular angepasst habe, weil mir die Variablenbezeichnungen nicht gepasst haben. Außerdem hab ich das Versiontag von 330 auf 400 gesetzt und die Variablenübergabe zwischen den Shadern in structs gepackt.

Ich habe ehrlich gesagt keinerlei Ahnung, wie ich die Fehlersuche gestalten soll, da ich ja keine konkreten Hinweise von der Fehlerauswertung erhalte, außer, dass der Geometryshader wohl der ausschlaggebende Punkt ist. Fehlt vielleicht eine Extension? Hab ich eine Namenskonvention verletzt?

Hier einmal alle drei Shader, die ich verwende:

Code:
  1. //Vertexshader
  2. #version 400
  3.  
  4. layout(location = 0) in vec3 vertexPosition;
  5. layout(location = 1) in vec3 vertexNormal;
  6. layout(location = 2) in vec2 vertexUVCoord;
  7.  
  8. uniform mat4 Projection;
  9. uniform mat4 View;
  10. uniform mat4 Model;
  11.  
  12. out VertToGeom
  13. {
  14.     vec3 Position;
  15.     vec3 Color;
  16.     vec3 Normal;
  17.     vec2 uvCoord;
  18. } DataOut;
  19.  
  20. void main ()
  21. {
  22.     DataOut.Position = (View * Model * vec4(vertexPosition, 1.0)).xyz;
  23.     DataOut.Color = vec3(1.0, 1.0, 1.0);
  24.     DataOut.Normal = normalize((View * Model * vec4(vertexNormal, 0.0)).xyz);
  25.     //DataOut.Normal = vertexNormal;
  26.     DataOut.uvCoord = vertexUVCoord;
  27.  
  28.     gl_Position = Projection * View * Model * vec4(vertexPosition, 1.0);
  29. }


Code:
  1. //Geometryshader
  2. #version 400
  3.  
  4. layout(triangles) in;
  5. layout(triangle_strip, max_vertices=3) out;
  6.  
  7. // Variablen, die vom Vertex- an den Geometry-Shader weitergereicht werden:
  8. in VertToGeom
  9. {
  10.     vec3 Position[];
  11.     vec3 Color[];
  12.     vec3 Normal[];
  13.     vec2 uvCoord[];
  14. } DataIn;
  15.  
  16. // Variablen, die vom Geometry- an den Fragment-Shader weitergereicht werden:
  17. out GeomToFrag
  18. {
  19.     vec3 Position;
  20.     vec3 Color;
  21.     vec2 uvCoord;
  22.     vec3 Tangent;
  23.     vec3 Bitangent;
  24.     vec3 Normal;
  25. } DataOut;
  26.  
  27. vec3 GetTangent(vec3 A, vec3 B, vec3 C,  vec2 Auv, vec2 Buv, vec2 Cuv)
  28. {
  29.     float Bv_Cv = Buv.y - Cuv.y;
  30.     if(Bv_Cv == 0.0)
  31.     return (B-C)/(Buv.x-Cuv.x);
  32.  
  33.     float Quotient = (Auv.y - Cuv.y)/(Bv_Cv);
  34.     vec3 D   = C   + (B  -C)   * Quotient;
  35.     vec2 Duv = Cuv + (Buv-Cuv) * Quotient;
  36.     return (D-A)/(Duv.x - Auv.x);
  37. }
  38.  
  39. vec3 GetBitangent(vec3 A, vec3 B, vec3 C,  vec2 Auv, vec2 Buv, vec2 Cuv)
  40. {
  41.     return GetTangent(A, C, B,  Auv.yx, Cuv.yx, Buv.yx);
  42. }
  43.  
  44. void main(void)
  45. {
  46.     vec3 T = GetTangent(DataIn.Position[0], DataIn.Position[1], DataIn.Position[2], DataIn.uvCoord[0], DataIn.uvCoord[1], DataIn.uvCoord[2]);
  47.     vec3 B = GetBitangent(DataIn.Position[0], DataIn.Position[1], DataIn.Position[2], DataIn.uvCoord[0], DataIn.uvCoord[1], DataIn.uvCoord[2]);
  48.  
  49.     for(int i=0; i<3; i++)
  50.     {
  51.         DataOut.Position = DataIn.Position[i];
  52.         DataOut.Color = DataIn.Color[i];
  53.         DataOut.uvCoord = DataIn.uvCoord[i];
  54.         DataOut.Tangent = T;
  55.         DataOut.Bitangent = B;
  56.         DataOut.Normal = DataIn.Normal[i];
  57.        
  58.         gl_Position = gl_in[i].gl_Position;
  59.         EmitVertex();
  60.     }
  61. }


Code:
  1. //Fragmentshader
  2. #version 400
  3.  
  4. layout(location = 0) out vec4 fragColor;
  5. layout(location = 1) out vec4 fragNormal;
  6.  
  7. uniform sampler2D ColorMap;
  8. uniform sampler2D NormalMap;
  9.  
  10. in GeomToFrag
  11. {
  12.     vec3 Position;
  13.     vec3 Color;
  14.     vec2 uvCoord;
  15.     vec3 Tangent;
  16.     vec3 Bitangent;
  17.     vec3 Normal;
  18. } DataIn;
  19.  
  20. /*mat3 cotangent_frame( vec3 N, vec3 p, vec2 uv )
  21. {
  22.     vec3 dp1 = dFdx( p );
  23.     vec3 dp2 = dFdy( p );
  24.     vec2 duv1 = dFdx( uv );
  25.     vec2 duv2 = dFdy( uv );
  26.  
  27.     vec3 dp2perp = cross( dp2, N );
  28.     vec3 dp1perp = cross( N, dp1 );
  29.     vec3 T = dp2perp * duv1.x + dp1perp * duv2.x;
  30.     vec3 B = dp2perp * duv1.y + dp1perp * duv2.y;
  31.  
  32.     float invmax = inversesqrt( max( dot(T,T), dot(B,B) ) );
  33.     return mat3( T * invmax, B * invmax, N );
  34. }*/
  35.  
  36. void main ()
  37. {
  38.     mat3 TBN = mat3(DataIn.Tangent, DataIn.Bitangent, DataIn.Normal);
  39.     fragColor = vec4(texture(ColorMap, DataIn.uvCoord).xyz,1.0);
  40.     vec3 n = texture(NormalMap, DataIn.uvCoord).xyz*2.0-1.0;
  41.     vec3 n_transformed = TBN * n;
  42.     fragNormal = vec4(n_transformed*0.5+0.5, 1.0);
  43. }


Edit: Der auskommentierte Code im Fragmentshader kommt von einer anderen Seite, mit deren Hilfe ich zuerst versuchte die TBN-Matrix zuberechnen, aber die Ergebnisse waren irgendwie nicht richtig, deshalb wollte ich das mit dem Geometryshader aus dem Wiki vergleichen. Ich suche den Link dazu mal rauß.

Edit2: http://www.thetenthplanet.de/archives/1180

Autor:  mathias [ So Dez 07, 2014 16:41 ]
Betreff des Beitrags:  Re: glUseProgram scheitert

Zitat:
Klammere ich den Geometry Shader aus, erhalte ich zumindest eine gerenderte Szene, ansonsten bleibt das Bild schwarz.

Dies ist irgendwie komisch, ich habe ein kleines Test-Programm mit einem Geometrie-Shader.
Wen ich dort den Geo-Shader ausklammere, dann bekomme ich einen Link-Fehler, geschwiegen von einem gerenderten Bild.

Hattest du schon mal einen laufenden Geo-Shader ?

Autor:  Sellmann [ So Dez 07, 2014 17:03 ]
Betreff des Beitrags:  Re: glUseProgram scheitert

Nein, bisher habe ich noch keine Geometryshader verwendet. Ist quasi meine Jungfernfahrt auf dem Gebiet.

Edit: Das mit dem Linkerfehler kann daran liegen, dass die Vertex- und Fragmentshader ja ebenfalls mit dem Geometryshader verdrahtet werden. Das löse ich natürlich auch auf, wenn ich den Geometryshader ausklammere. Man könnte sagen, ich passe das Interface dazwischen an, damit keine Abhängigkeit mehr entsteht. Die Funktionsweise der beiden Shader bleibt allerdings gleich. Das Ergebnis ist, dass Vertex- und Fragmentshader problemlos zusammenarbeiten und auch alle Daten und Zugriffe von Texturen, VBOs, VAOs und FBOs richtig verarbeitet werden. Das ganze platzt erst, wenn der Geometryshader eingefügt wird. Wobei jedoch noch angemerkt werden muss, dass der Geometryshader beim Kompilieren keinen Fehler meldet und auch das Shaderprogramm beim Linken den Geometryshader ohne Weiteres zu akzeptieren scheint.

Edit2: Ich häng nochmal die Routine dran, mit der ich den Shader erzeuge. Vielleicht ist da ja noch etwas, was nicht ganz sauber ist. Die glGetError-Aufrufe hab ich der Übersichtlichkeit entfernt.
Code:
  1. procedure TForm1.LoadSceneShader();
  2. var sl: TStringList;
  3.     vertSource, geomSource, fragSource : string;
  4.     vertLength, geomLength, fragLength : integer;
  5.     vert, geom, frag : GLhandle;
  6. begin
  7.   sl := TStringList.Create();
  8.   sl.LoadFromFile('.\Shader\scene.vs');
  9.   vertSource := sl.Text;
  10.   sl.Clear();
  11.  
  12.   sl.LoadFromFile('.\Shader\scene.gs');
  13.   geomSource := sl.Text;
  14.   sl.Clear();
  15.  
  16.   sl.LoadFromFile('.\Shader\scene.fs');
  17.   fragSource := sl.Text;
  18.   sl.Clear();
  19.   FreeAndNil(sl);
  20.  
  21.   vert := glCreateShader(GL_VERTEX_SHADER);
  22.   vertLength := Length(vertSource);
  23.   glShaderSource(vert, 1, @vertSource, @vertLength);
  24.   glCompileShader(vert);
  25.  
  26.   geom := glCreateShader(GL_GEOMETRY_SHADER);
  27.   geomLength := Length(geomSource);
  28.   glShaderSource(geom, 1, @geomSource, @geomLength);
  29.   glCompileShader(geom);
  30.  
  31.   frag := glCreateShader(GL_FRAGMENT_SHADER);
  32.   fragLength := Length(fragSource);
  33.   glShaderSource(frag, 1, @fragSource, @fragLength);
  34.   glCompileShader(frag);
  35.  
  36.   self.fSceneShaderProgram := glCreateProgram();
  37.   glAttachShader(self.fSceneShaderProgram, vert);
  38.   glAttachShader(self.fSceneShaderProgram, geom);
  39.   glAttachShader(self.fSceneShaderProgram, frag);
  40.   glLinkProgram(self.fSceneShaderProgram);
  41.  
  42.   glDeleteShader(vert);
  43.   glDeleteShader(geom);
  44.   glDeleteShader(frag);
  45.  
  46.   glUseProgram(self.fSceneShaderProgram); // <= hier tritt das erste mal eine GL_INVALID_OPERATION auf (Fehlercode 1282)
  47.  
  48.   self.fProjectionID := glGetUniformLocation(self.fSceneShaderProgram, 'Projection');
  49.   self.fViewID := glGetUniformLocation(self.fSceneShaderProgram, 'View');
  50.   self.fModelID := glGetUniformLocation(self.fSceneShaderProgram, 'Model');
  51.   self.fColorTexID := glGetUniformLocation(self.fSceneShaderProgram, 'ColorMap');
  52.   self.fNormalTexID := glGetUniformLocation(self.fSceneShaderProgram, 'NormalMap');
  53.  
  54.   glUseProgram(0);
  55. end;

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