# How to read BC4 texture in GLSL?

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.

• "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. – Nicol Bolas Nov 2 '12 at 21:15

First:

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.

• 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 ? – Cyan Nov 2 '12 at 18:59
• Yup, that's all that would need to change in the shader. – postgoodism Nov 2 '12 at 19:03