检查sampler2D是否为空。

13

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

这是我的顶点着色器:

#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未初始化或为空,并只返回sprite_color?


绑定一个1x1的纹理,并使用你想要的颜色? - genpfault
3个回答

7
一个采样器不能是“空的”。为了使渲染具有明确定义的行为,必须将有效的纹理绑定到每个采样器引用的纹理单元中。
但这并不意味着你必须从那里绑定的纹理中读取。可以使用uniform值来告诉着色器是否要从纹理中读取数据,这是完全有效的。
但是,您仍然需要在那里绑定一个简单的1x1纹理。确实,您可以在采样器上使用textureSize;如果它是一个1x1的纹理,则无需读取它。请注意,这可能比使用uniform更慢。

我使用这个来生成一个空纹理,但是输出仍然是黑色的。 - bl4ckb0ne
1
您提供的数据量太少了。一个 1x1 RGBA 纹理至少需要4个字节。 - BDL
1
哦,我真是太傻了。我必须深入挖掘才能找到解决方案,但你们两个肯定帮了我很多。我会在第一篇帖子中更新我的解决方案。谢谢! - bl4ckb0ne

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

    // ...
}

-1

我会检查漫反射贴图的rgb长度。但对于高光贴图不起作用。

    vec3 texDiffuseCol = texture2D(diffuseTex, TexCoord).rgb;
    if(length(texDiffuseCol) == 0.0)
    {
        //Texture not present
    }else
    {
        //Texture present
    }

如果没有提供纹理,将会有一个默认的回退到 RGB,即全部为 (0, 0, 0),这并不能解决操作问题。 - Nicholas Jela
有些纹理带有黑色区域,这段代码将无法正常工作。 - Kromster
是的。无法使用镜面纹理。 - Dennis Maina

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接