OpenGL mit Shader: statt Textur nur schwarz
-
Nachdem mein Programm auf mehreren verschiedenen PC´s funktioniert hat, werden bei einem PC die Texturen nur schwarz dargestellt.
Hier die dafür relevanten Codeausschnitte:Textur laden:
glGenTextures(1, &Groups[i].Material.Textur.ID); //Textur-ID bekommen glBindTexture(GL_TEXTURE_2D, Groups[i].Material.Textur.ID); //Textur-ID binden glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); //In s- und t- Richtung wiederholend glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); if((ImageType == FIT_BITMAP) && (BPP == 24)){ //Wenn Format=Bitmap und 24 bits per pixel glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, bits);} else if((ImageType == FIT_BITMAP) && (BPP == 32)){ //wenn 32 bits per pixel glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, bits);} glGenerateMipmap(GL_TEXTURE_2D); //MipMaps erzeugen glBindTexture(GL_TEXTURE_2D,0); //Textur entbinden
Objekt mit Textur zeichnen:
glActiveTexture(GL_TEXTURE0); //Textur-Unit 0 aktivieren for(int i=0;i<NumGroups;i++){ glUniform4f(in_Material_Loc.Ambient, Groups[i].Material.Ambient[0] ,Groups[i].Material.Ambient[1] ,Groups[i].Material.Ambient[2] ,1.0); //Material laden glUniform4f(in_Material_Loc.Diffuse, Groups[i].Material.Diffuse[0] ,Groups[i].Material.Diffuse[1] ,Groups[i].Material.Diffuse[2] ,1.0); glUniform4f(in_Material_Loc.Specular, Groups[i].Material.Specular[0],Groups[i].Material.Specular[1],Groups[i].Material.Specular[2],1.0); glUniform1f(in_Material_Loc.Shininess, Groups[i].Material.Shininess); glUniform1i(in_Material_Loc.TextureEnabled, Groups[i].Material.Textur.Name[0]); //1. Zeichen im Name 0 -> keine Textur if(Groups[i].Material.Textur.Name[0]){ glBindTexture(GL_TEXTURE_2D, Groups[i].Material.Textur.ID); //Wenn Textur, dann Textur binden glUniform1i(in_Material_Loc.Texture, 0); //Texturunit an Sampler im Shader übergeben } glBindVertexArray(Groups[i].VAO); //VAO binden und zeichnen glDrawArrays(GL_TRIANGLES, 0, Groups[i].NumTriangles*3); }
Fragment-Shader:
#version 110 ... uniform sampler2D DiffuseTexture; ... varying vec2 pass_TexCoord; ... //Pixelfarbe berechnen Anmerkung: einziger Aufruf der Textur und der Texturkoordinaten gl_FragColor = vec4(Light.Color * (texture2D(DiffuseTexture, pass_TexCoord).rgb *(AmbientFaktor + DiffuseFaktor*diffuse) + SpecularFaktor*Material.Specular.rgb*specular), 1.0)*attenuation;
Die Specular-Highlights werden korrekt angezeigt(diese multipliziere ich ja nicht mit der Textur). Wenn ich "texture2D(DiffuseTexture, pass_TexCoord).rgb" durch "vec3(0.8,0.8,0.8)" ersetze, dann wird alles wie zu erwarten dargestellt.
Seltsamerweise funktionieren die mittels Shadowmapping generierten Schatten (Berechnung im Fragment-Shader mit shadow2DProj(ShadowMap, pass_PosInLight).r)Wenn ich mir im gDEBugger die Textur anschaue, dann ist sie richtig geladen.
Hardware, bei der es funktioniert:
NVIDIA GeForce 9600M GT mit aktuellem Treiber (OpenGL 3.3), Windows 7
ATI Mobility Radeon HD 5165 mit älterem Treiber (OpenGL 2.1), Windows 7Hardware, für die das oben geschilderte zutrifft, bei der es also nicht funktioniert:
ATI Mobility Radeon X700 mit aktuellem Treiber (OpenGL 2.1), Windows XPHab schon power-of-2 Texturen und vereinfachte Beispielprogramme ohne Ergebnis versucht.
Was kann da das Problem sein
-
pruefste du die opengl errors?
es koennte out of memory sein (mobile grakas, besonders alte, haben nicht sonderlich viel vram, weil das vom main memory angezapft wird).
x700 ist urisch alt, was fuer ein "neuster" treiber ist es? der selbe wie bei der 5150? oder eine version vom notebook hersteller?
was meinst du mit "ab schon power-of-2 Texturen und vereinfachte Beispielprogramme ohne Ergebnis versucht."? kein ergebniss heisst mit anderen programmen sehen die texturen richtig aus? oder auch schwarz?
es kann auch an falschen mipmaps liegen oder filter flags. stell alles auf nearest, vielleicht klappts.
gDEBugger zeigt leider nur an was zur graka geschickt wird, nicht wie es auf ihr ausschaut :(. versuch auch mal andere formate, z.b. GL_BGRA_EXT als eingabe, vielleicht macht der treiber beim konvertieren etwas falsch.
geh sicher dass die texture nur im fragment program deklariert wird, die neueren beiden koennen im vertex programm texturen nutzen, die x700 meines wissens nach nicht, was vielleicht zu einem fehler fuehren koennte bei einer deklaration, selbst wenn du die textur nicht im vertex program nutzt.
erstmal out-of-ideas.
-
Danke rapso, die Mipmaps waren das Problem.
Genauer gesagt funktionierte das generieren der Mipmaps mit "glGenerateMipmap" nicht.
Der gleiche Fehler ist auch auf einer anderen Grafikkarte mit OpenGL 2.1 aufgetreten.Komisch kommt mir vor, dass laut glew diese Funktion auch von der x700 unterstützt wird.
Heißt das, dass mir glew etwas falsches erzählt oder muss ich irgendetwas besonderes machen, damit glGenerateMipmap funktioniert?
-
vielleicht ist es einfach nur ein treiber bug.
normalerweise generiert man sich mipmaps mit einem externen tool, damit keine ladezeit drauf geht.
falls du es wirklich zur ladezeit machen willst, schreib dir einen einfachen downscaler (einfach nur 2x2 pixel zu einem addieren und durch 4), dann ersparrst du dir die probleme.
grundsaetzlich wuerde ich selten genutzte funktionen meiden bei ogl
-
für alle, die irgendwann das selbe Problem haben, meine Lösung:
habe für den OpenGL 2 Programmzweig "glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);" statt "glGenerateMipmap" verwendet, hatte aber immer noch einige Darstellungsfehler.
Irgenwann habe ich dann power-of-2 Texturen verwendet und der Fehler war weg.
Anscheinend kann eine Grafikkarte, die non-power-of-two Texturen unterstützt, nicht zwingend auch Mipmaps für solche Texturen erzeugen.