2017-02-14 17 views
3

Ich entwerfe eine Sprite-Klasse, und ich möchte nur eine Farbe anzeigen, wenn keine Textur geladen ist.Überprüfen Sie, ob Sampler2D leer ist

Hier sind mein Vertex-Shader

#version 330 core 
layout (location = 0) in vec4 vertex; // <vec2 pos, vec2 tex> 

out vec2 vs_tex_coords; 

uniform mat4 model; 
uniform mat4 projection; 

void main() 
{ 
    vs_tex_coords = vertex.zw; 
    gl_Position = projection * model * vec4(vertex.xy, 0.0, 1.0); 
} 

Und die Fragment-Shader:

#version 330 core 

in vec2 vs_tex_coords; 

out vec4 fs_color; 

uniform sampler2D image; 
uniform vec3 sprite_color; 

void main() 
{ 
    fs_color = vec4(sprite_color, 1.0) * texture(image, vs_tex_coords); 
} 

Mein Problem ist, dass, wenn ich nicht eine Textur binden, zeigt es nur einen schwarzen Sprit. Ich denke, das Problem ist, dass die Textur-Funktion in meinem Fragment-Shader eine 0 zurückgibt und die ganze Formel verschraubt.

Gibt es eine Möglichkeit zu wissen, ob der sampler2D nicht initialisiert oder null ist, und nur die sprite_color zurückgeben?

LÖSUNG:

Die Lösung war eine leere 1x1 Textur zu erzeugen, und es trotzdem zu binden. Dazu müssen Sie ein Array von 4 Zeichen bis 255 (für RGBA) erstellen und der Funktion glTexImage2D die Größe von 1x1 zuweisen, um sicherzustellen, dass eine 1x1-Textur erstellt wird.

Texture::Texture() 
{ 
    glGenTextures(1, &ID); 

    GLubyte data[] = { 255, 255, 255, 255 }; 

    glBindTexture(GL_TEXTURE_2D, ID); 

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter); 

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); 

    size.x = 1; 
    size.y = 1; 
} 
+0

Binden Sie eine 1x1 Textur mit der gewünschten Farbe? – genpfault

Antwort

2

Ein Sampler kann nicht "leer" sein. Eine gültige Textur muss an die von jedem Sampler referenzierten Textureinheiten gebunden sein, damit das Rendering ein wohldefiniertes Verhalten aufweist.

Aber das bedeutet nicht, dass Sie lesen müssen von der Textur, die dort gebunden ist. Es ist absolut zulässig, einen uniform Wert zu verwenden, um dem Shader mitzuteilen, ob er aus der Textur lesen soll oder nicht.

Aber Sie müssen immer noch eine einfache, 1x1 Textur dort binden. In der Tat können Sie textureSize auf dem Sampler verwenden; Wenn es sich um eine 1x1-Textur handelt, dann sollten Sie nicht davon lesen. Beachten Sie, dass dies möglicherweise langsamer ist als bei Verwendung einer uniform.

+0

Ich benutze [dies] (https://hastebin.com/jivojakusi.hs), um eine leere Textur zu erzeugen, aber ich habe immer noch eine schwarze Ausgabe. – Bl4ckb0ne

+1

Sie liefern zu wenig Daten. Eine 1x1 RGBA Textur benötigt mindestens 4 Bytes. – BDL

+1

Oh, richtig albern mich. Ich musste mehr graben, um eine Lösung zu finden, aber Sie haben mir definitiv geholfen. Ich werde den ersten Beitrag mit meiner Lösung aktualisieren. Vielen Dank – Bl4ckb0ne

0

Hier unten die 2 Versionen, mit und ohne if... else... bedingte Anweisung. Die bedingte Anweisung verhindert, dass die Textur abgetastet werden muss, wenn sie nicht verwendet wird.

Die uniform int textureSample wird auf 1 oder 0 gesetzt, damit die Textur oder die Farbe angezeigt wird. Beide Uniform-Variablen werden normalerweise vom Programm und nicht vom Shader erstellt.

uniform int textureSample = 1; 
uniform vec3 color = vec3(1.0, 1.0, 0.0); 


void main() {  // without if... else... 

    // ... 
    vec3 materialDiffuseColor = textureSample * texture(textureSampler, fragmentTexture).rgb - (textureSample - 1) * color; 
    // ... 
} 


void main() {  // with if... else... 

    // ... 
if (textureSample == 1) {  // 1 if texture, 0 if color 

    vec3 materialDiffuseColor = textureSample * texture(textureSampler, fragmentTexture).rgb; 
    vec3 materialAmbientColor = vec3(0.5, 0.5, 0.5) * materialDiffuseColor; 
    vec3 materialSpecularColor = vec3(0.3, 0.3, 0.3); 

    gl_Color = brightness * 
     (materialAmbientColor + 
     materialDiffuseColor * lightPowerColor * cosTheta/distanceLight2 + 
     materialSpecularColor * lightPowerColor * pow(cosAlpha, 10000)/distanceLight2); 
} 
else { 
    vec3 materialDiffuseColor = color; 
    vec3 materialAmbientColor = vec3(0.5, 0.5, 0.5) * materialDiffuseColor; 
    vec3 materialSpecularColor = vec3(0.3, 0.3, 0.3); 

    gl_Color = brightness * 
     (materialAmbientColor + 
     materialDiffuseColor * lightPowerColor * cosTheta/distanceLight2 + 
     materialSpecularColor * lightPowerColor * pow(cosAlpha, 10000)/distanceLight2); 
    } 
}