ideasman42
ideasman42

Reputation: 47968

Mixing RGBA and ALPHA format images in GLSL shaders

I'm editing a shader which was written for RGBA textures.

This works as expected with RGBA textures, eg:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

... then in the glsl shader, its value can be accessed with. texture2D(tex, coord);

This is all working fine.

However, one part of the software uses an alpha-only texture
(where its format arg is GL_ALPHA), eg:

glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA8, x, y, 0, , GL_ALPHA, GL_UNSIGNED_BYTE, NULL);

In this case the RGB components from texture2D() are all zero.


While this is expected behavior, I'd like to know if there is some way to either:


Note that this could be handled with pre-processor defines as a last resort, but it's already full of #if's so I rather avoid if possible since the number of pre-processor combinations increases number of shaders we need to store.

Upvotes: 0

Views: 779

Answers (1)

Nicol Bolas
Nicol Bolas

Reputation: 473212

You can use texture swizzling to set the value extracted from any component of a texture. So if you truly have an alpha-only texture, you can use the swizzle mask to set the RGB values to 1. Or to broadcast the alpha value across the other three. Or you can set them to 0, but that's the default if they're not in the texture.

//Set other components to 1.
GLint swizzleMask[] = {GL_ONE, GL_ONE, GL_ONE, GL_ALPHA};
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);

Obviously the texture must be bound to do that.

But those are your only options. You can't set the missing components to arbitrary values.

And no, there's no way for a shader to detect, from a sampler alone, anything about the format used by that texture. You can of course pass a uniform which the shader can detect and use to make changes about how it uses the extracted value. It wouldn't even be expensive to do so, since your shader code could look like this:

vec4 val = texture(tex_unit, ...);
val.xyz = fill_defaults ? defaults : val.xyz;

A simple ?: on a dynamically uniform value will have no real impact on performance.

Upvotes: 4

Related Questions