I'm supposed to receive a texture in BC4 format. In OpenGL, i guess this format is called GL_COMPRESSED_RED_RGTC1.

The texture is not really a "texture", more like a data to handle at fragment shader.

Usually, to get colors from a texture within a fragment shader, i do :

uniform sampler2D TextureUnit;
void main()
   vec4 TexColor = texture2D(TextureUnit, vec2(gl_TexCoord[0]));

the result of which is obviously a v4, for RGBA.

But now, i'm supposed to receive a single float from the read. I'm struggling to understand how this is achieved.

Should i still use a texture sampler, and expect the value to be in a specific position (for example, within TexColor.r ?), or should i use something else ?


In case of having one-channel images you should use texture2D as follows

float TexColor = texture2D(TextureUnit, gl_TexCoord[0]).r

which basically forces to read only the first (and only) channel of the image and stores its value into TexColor. At least, this is how I handle shadow maps for example (which are stored in one-channel images.

  • 1
    \$\begingroup\$ "which basically forces to read only the first (and only) channel of the image and stores its value into TexColor." Um, no. It reads all four; it ignores the other three. \$\endgroup\$ – Nicol Bolas Nov 2 '12 at 21:15

Let's provide a complete answer.


texture2D(TextureUnit, vec2(gl_TexCoord[0]))

Since we're talking about RGTC, we're in GL 3.x+ land. You shouldn't be using texture2D anymore; just use texture. That way, if you change the type of TextureUnit, everything will still work. But that's minor.

Also, vec(gl_TexCoord[0]) is better spelled gl_TexCoord[0].xy. But again, minor.

The main thing is this: accessing a (non-shadow) texture always returns a 4-component vector. It doesn't matter what the texture's format is; it returns 4 components. If a texture doesn't actually provide all of the components, then the missing components will be filled in by the vector (0, 0, 0, 1).

Let's take your format: GL_COMPRESSED_RED_RGTC1. This uses the RGTC1 style of compression, and it provides the RED color component. So it fills in only the red component; every texture access will therefore be (R, 0, 0, 1). If your format was GL_COMPRESSED_RG_RGTC1, then you would get the R and G components; every texture access would provide (R, G, 0, 1).

Therefore, if you want the red component from the texture, just ask for it:

texture(TextureUnit, gl_TexCoord[0].xy).r

Of course, texture swizzling can mess around with this too. But that's a discussion for another time.


From the shader's perspective, a block-compressed texture like BC4/RGTC1 behaves just like any other texture; the GPU hardware automatically handles the block decompression and filtering on your behalf. BC4 is a single-channel texture, so you are correct: use texture2D() -- or texture() in more recent GL versions -- and the data you want will be in the TexColor.r field.

  • \$\begingroup\$ Great answer, thanks ! Another question which is almost the same : later on, i will have to handle BC5 textures (basically, two BC4 textures together). I guess i'll have to fetch the results from R & G fields ? \$\endgroup\$ – Cyan Nov 2 '12 at 18:59
  • \$\begingroup\$ Yup, that's all that would need to change in the shader. \$\endgroup\$ – postgoodism Nov 2 '12 at 19:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.