检查sampler2D是否为空

时间:2017-02-14 23:34:06

标签: opengl glsl

我正在设计一个精灵类,如果没有加载纹理,我想只显示一种颜色。

这是我的顶点着色器

#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);
}

片段着色器:

#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);
} 

我的问题是如果我没有绑定纹理,它只显示一个黑色精灵。我认为问题是片段着色器中的纹理函数返回0,并拧紧所有公式。

有没有办法知道sampler2D是否未初始化或为null,只返回sprite_color?

SOLUTION:

解决方案是生成一个空的1x1纹理并将其绑定。要做到这一点,你必须创建一个4个字符到255的数组(对于RGBA),并给glTexImage2D函数提供1x1的大小,以确保将创建1x1纹理。

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;   
}

2 个答案:

答案 0 :(得分:4)

采样器不能为“空”。有效的纹理必须绑定到每个采样器引用的纹理单元,以便渲染具有明确定义的行为。

但这并不意味着你必须从绑定在那里的纹理中读取。使用uniform值告诉着色器是否从纹理中读取是完全有效的。

但是你仍然必须在那里绑定一个简单的1x1纹理。实际上,您可以在采样器上使用textureSize;如果它是1x1纹理,那么就不用费心去读它了。请注意,这可能比使用uniform慢。

答案 1 :(得分:0)

下面是2个版本,包含和不包含if... else...条件语句。条件语句避免在未使用时对纹理进行采样。

uniform int textureSample设置为1或0,纹理或颜色分别显示。两个统一变量通常由程序设置,而不是着色器。

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);
    }
}