Can a shader produce a fully colored result given a GL_RED texture?

OpenGL beginner here. I was hoping I could do something like transmit a texture using GL_RED and R8, but then have my shader produce a fully colored result. At present even if my shader writes the green and blue colors, they are ignored and I get varying shades of red on the screen. However, if I use swizzle masks and tell it to pull green and blue from the red, I get a nice grayscale image. I want not grayscale, but to treat my unsigned byte as a color map… i.e., different values correspond to different colors. This would save a lot of space, but I can’t get the idea to work. This is for 2D textures. Is this possible and I’m doing something wrong, or do I have to switch to an internal GL_RGB format in order to have my shader produce a colored texture?

Well, that suggests that you’re trying to write all of the components you fetch from the texture directly to the screen. Something that would look like this:


out_color = texture(sampler, uv);

When you fetch a color from a color image format that doesn’t provide all four channels, any unprovided channels will by default be 0. Except the alpha which will be 1. So a red texture will appear… red. Which is why it’s called that :wink:

If you want to broadcast the red component across all 4 components, you can just do that in your shader.


out_color = texture(sampler, uv).rrrr;

You can certainly implement that in a shader, i.e. read a single value from a source texture then use that value to retrieve a colour from a palette texture.

If the palette is a continuous gradient, you can use a normalised (e.g. GL_R8) source texture from which you retrieve a floating-point intensity value between 0.0 and 1.0 via a sampler2D uniform, which is then used as a texture coordinate into the palette texture. E.g.


uniform sampler2D u_texture;
uniform sampler1D u_palette;
in vec2 a_texcoord;
...
    float value = texture(u_texture, a_texcoord);
    gl_FragColor = texture(u_palette, value);

If the palette is a discrete set of colours, you need to use integer colour indices, so the source texture should have a format of GL_RED_INTEGER, an internal format of e.g. GL_R8UI, and be accessed via a usampler2D uniform. The corresponding texel can be retrieved from the palette texture using texelFetch() (which takes integer array indices rather than floating-point coordinates). E.g.


uniform usampler2D u_texture;
uniform sampler1D u_palette;
in vec2 a_texcoord;
...
    uint value = texture(u_texture, a_texcoord);
    gl_FragColor = texelFetch(u_palette, int(value), 0);