Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Fr Jul 18, 2025 00:11

Foren-Übersicht » Programmierung » Shader
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 12 Beiträge ] 
Autor Nachricht
BeitragVerfasst: Do Aug 19, 2010 17:43 
Offline
DGL Member

Registriert: Di Okt 13, 2009 17:25
Beiträge: 365
Programmiersprache: C++
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


Zuletzt geändert von mrtrain am Mi Aug 31, 2011 19:41, insgesamt 2-mal geändert.

Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Do Aug 19, 2010 18:56 
Offline
DGL Member

Registriert: Mo Nov 06, 2006 19:15
Beiträge: 172
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.


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Do Aug 19, 2010 19:00 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
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 ;) )

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Do Aug 19, 2010 19:40 
Offline
DGL Member

Registriert: Di Okt 13, 2009 17:25
Beiträge: 365
Programmiersprache: C++
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?


Zuletzt geändert von mrtrain am Mi Aug 31, 2011 19:41, insgesamt 1-mal geändert.

Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Do Aug 19, 2010 19:54 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Zitat:
Normalerweise hätte es doch einen geben müssen, oder?

Unbenutzte varyings werden möglicherweise automatisch entfernt.

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Do Aug 19, 2010 20:05 
Offline
DGL Member

Registriert: Di Okt 13, 2009 17:25
Beiträge: 365
Programmiersprache: C++
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.


Zuletzt geändert von mrtrain am Mi Aug 31, 2011 19:41, insgesamt 1-mal geändert.

Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Do Aug 19, 2010 20:15 
Offline
DGL Member

Registriert: Mo Nov 06, 2006 19:15
Beiträge: 172
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.)


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Do Aug 19, 2010 21:30 
Offline
DGL Member

Registriert: Di Okt 13, 2009 17:25
Beiträge: 365
Programmiersprache: C++
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! :)


Zuletzt geändert von mrtrain am Mi Aug 31, 2011 19:42, insgesamt 2-mal geändert.

Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Aug 20, 2010 03:24 
Offline
DGL Member

Registriert: Mo Nov 06, 2006 19:15
Beiträge: 172
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.ä. :)


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Aug 20, 2010 12:50 
Offline
DGL Member

Registriert: Di Okt 13, 2009 17:25
Beiträge: 365
Programmiersprache: C++
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*


Zuletzt geändert von mrtrain am Mi Aug 31, 2011 19:42, insgesamt 1-mal geändert.

Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Aug 20, 2010 17:40 
Offline
DGL Member

Registriert: Di Okt 13, 2009 17:25
Beiträge: 365
Programmiersprache: C++
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


Zuletzt geändert von mrtrain am Mi Aug 31, 2011 19:42, insgesamt 1-mal geändert.

Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Aug 20, 2010 18:07 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
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.

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 12 Beiträge ] 
Foren-Übersicht » Programmierung » Shader


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 11 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
cron
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.009s | 16 Queries | GZIP : On ]