DGL
https://delphigl.com/forum/

Linkerfehler abfangen + Problem beim Skinning
https://delphigl.com/forum/viewtopic.php?f=20&t=9420
Seite 1 von 1

Autor:  mrtrain [ Do Aug 19, 2010 17:43 ]
Betreff des Beitrags:  Linkerfehler abfangen + Problem beim Skinning

Ich mal wieder und wieder mit einem Problem. :wink: Ich habe mein Skinningsystem auf Shader umgestellt, bzw. das wollte ich tun, allerdings funktioniert es nicht. Die Vorschläge für die Checkliste Shader bin ich durchgegangen, dabei ist mir aufgefallen, dass folgender Code wahrscheinlich fehlerhaft ist:

Code:
  1. bool CGLSLShader::LinkShader(void)
  2. {
  3.   glAttachShader(hProgram, hVertShader);
  4.   glAttachShader(hProgram, hFragShader);
  5.   glLinkProgram(hProgram);
  6.  
  7.   GLint res = 0;
  8.   glGetProgramiv(hProgram, GL_LINK_STATUS, &res);
  9.   if(res == GL_FALSE)
  10.     return false;
  11.  
  12.   unsigned short a;
  13.   for(a=0; a<VertexFormat.AttributesMax; ++a)
  14.     VertexFormat.Attributes[a].glID = glGetAttribLocation(hProgram, VertexFormat.Attributes[a].Name.c_str());
  15.  
  16.   return true;
  17. }

Denn ich hatte im Vertexshader ein
Code:
  1. varying vec3 N;
stehen und im Fragmentshader nicht. Müsste es dann nicht eigentlich einen Linkerfehler geben?

Naja, ich habe die Zeile dann erstmal entfernt und mit ihr alle Zeilen, die sich auf N beziehen. Allerdings sehe ich nichts. Der Fragmentshader funktionierte in einem anderen Programm einwandfrei, der Vertexshader ist zum ersten Mal im Einsatz, weshalb ich in ihm den Fehler vermute. Ich habe ihn auf das nötigste gekürzt (jetzt hat er kein Skinning mehr), um Fehler auszuschließen, allerdings ist immer noch nichts zu sehen. Hier ist er (tada!):
Code:
  1. attribute vec3 a_Position;
  2. attribute vec3 a_Normal;
  3. attribute vec2 a_TexCoords;
  4. attribute vec2 a_BoneWeights;
  5. //attribute vec3 Tangent;
  6. const int BonesMax = 32;
  7. uniform mat3 BoneMatrices[BonesMax];
  8. uniform vec3 BonePositions[BonesMax];
  9.  
  10. void main(void)
  11. {
  12.   gl_Position =
  13.       gl_ModelViewProjectionMatrix * vec4(a_Position, 0.0);
  14. //  N = gl_NormalMatrix * a_Normal;
  15.  
  16.   gl_TexCoord[0].xy = a_TexCoords;
  17. }

Übrigens funktioniert das kompilieren beider Shader ohne Fehler, das absichtliche Einbauen eines Fehlers führt auch zu einer Fehlermeldung.

Danke schonmal im Vorraus für euren Rat! :)

mrtrain

Autor:  NerdIII [ Do Aug 19, 2010 18:56 ]
Betreff des Beitrags:  Re: Linkerfehler abfangen + Problem beim Skinning

Ich weiß nicht, ob das so schlau ist eine w-Koordinate von 0 anzugeben. Bist du sicher, das es nicht eine 1 sein soll? Das wäre zumindest korrekt wenn du ein glVertex3f nachbauen willst.

Autor:  Coolcat [ Do Aug 19, 2010 19:00 ]
Betreff des Beitrags:  Re: Linkerfehler abfangen + Problem beim Skinning

Du vermutest ja einen Linkerfehler, daher wäre es wohl sinnvoll Vertex- und Fragmentshader zu posten.

Dein testen auf Linkerfehler sieht aber auf den ersten Blick gut aus, wobei du im Fehlerfall die Fehlermeldung vom Linker auslesen solltest.

Ich denke der Fehler liegt hier:
Code:
gl_Position = gl_ModelViewProjectionMatrix * vec4(a_Position, 0.0);

Wenn du die Translation in der Matrix berücksichtigen willst muss es vec4(a_Position, 1.0) lauten. (Edit: Hmpf, NerdIII war schneller ;) )

Autor:  mrtrain [ Do Aug 19, 2010 19:40 ]
Betreff des Beitrags:  Re: Linkerfehler abfangen + Problem beim Skinning

Okay, danke für eure Antworten. Das mit der 0.0 war natürlich ein Fehler und jetzt sehe ich auch was (wenn auch nur Müll :? ). Also hier noch der Fragmentshader:
Code:
  1. uniform sampler2D Texture0;
  2. uniform float fColorness;
  3.  
  4. void main(void)
  5. {
  6.   vec4 color = texture2D(Texture0, gl_TexCoord[0].xy);
  7.   float fBrightness = dot(color, vec4(0.3333333333, 0.3333333333,
  8. 0.3333333333, 0.0));
  9.   gl_FragColor = mix(vec4(fBrightness), color, fColorness);
  10. }

Der interpoliert zwischen Farbe und schwarz-weiß (mir war grad danach 8) ).

Das sieht für mich derzeit nach einem logischen Fehler beim Schreiben in das VBO oder beim Setzen der Vertexattribute aus... Aber ich weiß nicht, ob es so sinnvoll ist, hier tonnenweise Code zu posten. Ich meld mich wieder, wenn ich 'nen genaueren Verdacht hab' oder dran verzweifle.

Achja, zum Linkerfehler: Man nehme einen der beiden Shader und schreibe vor die main() ein "varying vec3 N;". Es war erst beim Vertexshader, ich habe es experimentell auch mal getauscht. Jedenfalls hatte ich die Situation, dass ein Shader die Zeile drin hatte und der andere nicht. Und es hat keinen Linkerfehler gegeben. Normalerweise hätte es doch einen geben müssen, oder?

Autor:  Coolcat [ Do Aug 19, 2010 19:54 ]
Betreff des Beitrags:  Re: Linkerfehler abfangen + Problem beim Skinning

Zitat:
Normalerweise hätte es doch einen geben müssen, oder?

Unbenutzte varyings werden möglicherweise automatisch entfernt.

Autor:  mrtrain [ Do Aug 19, 2010 20:05 ]
Betreff des Beitrags:  Re: Linkerfehler abfangen + Problem beim Skinning

Ja, und Attribute wohl auch. Was ich euch vorhin beim Link-Code vorenthalten habe:
Code:
  1. unsigned short a;
  2. for(a=0; a<VertexFormat.AttributesMax; ++a)
  3.   VertexFormat.Attributes[a].glID = glGetAttribLocation(hProgram, VertexFormat.Attributes[a].Name.c_str());

Bei den VertexAttributen, die ich zwecks Fehlereingrenzung nicht benutzt habe, lieferte glGetAttribLocation 4294967295, aka -1, zurück. Daher habe ich wohl auch nur Müll zu sehen bekommen, statt dem Model, dass ich eigentlich wollte. Allerdings dauert es jetzt ein bisschen, zu testen, ob das der einzige Grund war. Ich meld' mich dann wieder.

Autor:  NerdIII [ Do Aug 19, 2010 20:15 ]
Betreff des Beitrags:  Re: Linkerfehler abfangen + Problem beim Skinning

Das ist kein Bug, sondern ein Feature. Stell dir vor du verwendest Transform-Feedback und möchtest die Werte von N in ein Buffer-Objekt schreiben ohne sie im Fragment-Shader zu verarbeiten. Dann würdest du genau so vorgehen, das varying im Vertex-Shader deklarieren, im Fragment-Shader aber nicht. Umgekehrt ist das allerdings wirklich sinnlos würde ich meinen. :roll: Vielleicht reagieren unterschiedliche Treiber da anders.
(Wenn du willst das ein varying wirklich im gelinkten Programm ausgegeben wird, auch wenn - hardcore-Fall - der Compiler feststellt, dass eine if-Anweisung im Fragment-Shader immer true ergibt, und in diesem Pfad das varying nicht verwendet wird, etc.. etc.. dann kannst du vorm Linken mit ActiveVarying dafür sorgen. Diese Funktion existiert aber in erster Linie für Transform-Feedback.)

Autor:  mrtrain [ Do Aug 19, 2010 21:30 ]
Betreff des Beitrags:  Re: Linkerfehler abfangen + Problem beim Skinning

Transform-Feedback ist doch für GPGPU und sowas auf Karten ab DirectX 10? Naja, so fortgeschritten bin ich leider noch nicht, ich habe ja schon mit einfachen Vertexshadern zu kämpfen. :wink:

Vermutlich liegt der Fehler irgendwie beim Laden der Vertexdaten in den Grafikspeicher. Vielleicht gibt es da ja was zu beanstanden:
Code:
  1. void C3D_Model::LoadToVRAM(void)
  2. {
  3.   glGenBuffers(1, &glVBOID);
  4.   glBindBuffer(GL_ARRAY_BUFFER, glVBOID);
  5.   glBufferData(GL_ARRAY_BUFFER, 40 * IndicesMax, NULL, GL_STATIC_DRAW);
  6.   char* pVBOData = (char*) glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
  7.   float fBoneWeight;
  8.  
  9.   for(unsigned short i=0; i<IndicesMax; ++i)
  10.   {
  11.     memcpy(pVBOData, &(Vertices[VertexIndices[i]].x), 4);  pVBOData += 4;
  12.     memcpy(pVBOData, &(Vertices[VertexIndices[i]].y), 4);  pVBOData += 4;
  13.     memcpy(pVBOData, &(Vertices[VertexIndices[i]].z), 4);  pVBOData += 4;
  14.  
  15.     memcpy(pVBOData, &(Normals[VertexIndices[i]].x), 4);  pVBOData += 4;
  16.     memcpy(pVBOData, &(Normals[VertexIndices[i]].y), 4);  pVBOData += 4;
  17.     memcpy(pVBOData, &(Normals[VertexIndices[i]].z), 4);  pVBOData += 4;
  18.  
  19.     memcpy(pVBOData, &(Texels[TexelIndices[i]].x), 4);  pVBOData += 4;
  20.     memcpy(pVBOData, &(Texels[TexelIndices[i]].y), 4);  pVBOData += 4;
  21.  
  22.     fBoneWeight = BoneWeights[VertexIndices[i]] + float(PrimaryBones[VertexIndices[i]]);
  23.     memcpy(pVBOData, &fBoneWeight, 4);
  24.     pVBOData += 4;
  25.  
  26.     fBoneWeight = float(SecondaryBones[VertexIndices[i]]);
  27.     memcpy(pVBOData, &fBoneWeight, 4);
  28.     pVBOData += 4;
  29.   }
  30.  
  31.   glUnmapBuffer(GL_ARRAY_BUFFER);
  32. }

Sorry, dass ich hier so viel Code poste. Geht das eigentlich mit memcpy()?

edit: Hab's jetzt mal ohne memcpy() gemacht, was eigentlich auch viel eleganter ist. Das Ergebnis ist allerdings das gleiche.

Danke für weitere Antworten! :)

Autor:  NerdIII [ Fr Aug 20, 2010 03:24 ]
Betreff des Beitrags:  Re: Linkerfehler abfangen + Problem beim Skinning

Das sieht mir korrekt aus. Das VBO.UnmapBuffer() am Ende tut auch das richtige?? Transform-Feedback funktioniert auf DirectX 10 Grafikkarten, wie zum Beispiel der Geforce 8600. Du könntest zum Beispiel deine gl_Position Daten nach dem Vertex-Shader in ein VBO schreiben lassen, um sie zu debuggen. So kompliziert ist das gar nicht. Ich verwende TF zum Beispiel so, um an die Bildschirmkoordinaten meiner Vertizes zu kommen. Andere rufen mehrfach hintereinander einen Geometry-Shader auf, der ihre Dreiecke jeweils feiner unterteilt oder lassen ihre Partikelengine auf der Grafikkarte laufen. Also es gibt durchaus eine Menge Anwendungen in denen man tatsächlich Geometrie damit verarbeitet und nicht nach außerirdischem Leben sucht o.ä. :)

Autor:  mrtrain [ Fr Aug 20, 2010 12:50 ]
Betreff des Beitrags:  Re: Linkerfehler abfangen + Problem beim Skinning

Oh, die letzte Zeile habe ich nicht angepasst. Es ist nämlich so, dass ich eine VBO-Klasse habe, deren Methoden ich eigentlich in der C3D_Model::LoadToVRAM aufrufe. Bei VBO.Create und VBO.MapBuffer habe ich in meinem Post "entpackt" um es euch einfacher zu machen, bei VBO.Unmap habe ich es schlicht vergessen. Wird sofort angepasst. Inzwischen habe ich es wie gesagt auch schon ohne memcpy() probiert und der Fehler liegt vermutlich doch nicht beim Laden. *grübel*

Autor:  mrtrain [ Fr Aug 20, 2010 17:40 ]
Betreff des Beitrags:  Re: Linkerfehler abfangen + Problem beim Skinning

So, ich glaube und hoffe den Grund gefunden haben, warum OpenGL nicht tut, was es soll. :D *hoff* Und zwar steht in der OpenGL-Dokumentation zu glVertexAttribPointer, was ich verwende, folgendes:
Zitat:
Each generic vertex attribute array is initially disabled and isn't accessed when glArrayElement, glDrawElements, glDrawRangeElements, glDrawArrays, glMultiDrawArrays, or glMultiDrawElements is called.

Wenn ich mich jetzt nicht vertue, heißt dass das sich glDrawArrays und glVertexAttribPointer nicht miteinander vertragen, richtig? Demnach bräuchte ich jetzt eine Alternative für eine der beiden Funktionen. Hat jemand einen Vorschlag?

edit: Ach Mist, ich hab da wohl die Klammern falsch gesetzt. So ist es wohl gemeint:
Zitat:
Each generic vertex attribute array is initially (disabled and isn't accessed when glArrayElement, glDrawElements, glDrawRangeElements, glDrawArrays, glMultiDrawArrays, or glMultiDrawElements is called.)
Das initially bezieht sich also auch auf das nach dem "and"... oder? Soviel zur Punkt-vor-Strich Regel :wink:

Ich freue mich auf eure Antworten

mrtrain

Autor:  Coolcat [ Fr Aug 20, 2010 18:07 ]
Betreff des Beitrags:  Re: Linkerfehler abfangen + Problem beim Skinning

Zitat:
Wenn ich mich jetzt nicht vertue, heißt dass das sich glDrawArrays und glVertexAttribPointer nicht miteinander vertragen, richtig? Demnach bräuchte ich jetzt eine Alternative für eine der beiden Funktionen. Hat jemand einen Vorschlag?

Wie du schon selbst bemerkt hast musst du die nur einschalten. Das geht mit glEnableVertexAttribArray.

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