I'm designing a sprite class, and I would like to display only a color if no texture is loaded.
Here are my 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);
}
And the 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);
}
My problem is that if I don't bind a texture, it displays only a black sprite. I think the problem is that the texture function in my fragment shader returns a 0, and screw all the formula.
Is there a way to know if the sampler2D is not initialized or null, and just return the sprite_color?
Here below the 2 versions, with and without if... else...
conditional statement. The conditional statement avoids to have to sample the texture if not used.
The uniform int textureSample
is set to 1 or 0 for the texture or the color to show up respectively. Both uniform variables are normally set up by the program, not the shader.
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);
}
// ...
}
A sampler cannot be "empty". A valid texture must be bound to the texture units referenced by each sampler in order for rendering to have well-defined behavior.
But that doesn't mean you have to read from the texture that's bound there. It's perfectly valid to use a uniform
value to tell the shader whether to read from the texture or not.
But you still have to bind a simple, 1x1 texture there. Indeed, you can use textureSize
on the sampler; if it is a 1x1 texture, then don't bother to read from it. Note that this might be slower than using a uniform
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With