19.3. Lookup Table Operations
OpenGL defines a number of lookup tables as part of its fixed functionality. Several are defined as part of the imaging subset. Lookup tables are simply a way of mapping an input value to one or more output values. This operation provides a level of indirection that is often useful for processing color information. The fact that OpenGL has programmable processors means that you can compute the input values as part of a shader and use the output value as part of further computation within the shader. This creates a lot of new possibilities for lookup tables.
A flexible and efficient way to perform lookup table operations with an OpenGL shader is to use a 1D texture map. The lookup table can be an arbitrary size (thus overcoming a common gripe about OpenGL lookup tables often being limited by implementations to 256 entries). You can use the lookup table to map a single input value to a single output value or to a two-, three-, or four-component value. If you want the values returned to be discrete values, set the 1D texture's filtering modes to GL_NEAREST. If you want interpolation to occur between neighboring lookup table values, use GL_LINEAR.
You can use an intensity value in the range [0,1] as the texture coordinate for a 1D texture access. The built-in texture functions always return an RGBA value. If a texture with a single channel has been bound to the texture unit specified by the sampler, the value of that texture is contained in each of the red, green, and blue channels, so you can pick any of them:
float color = texture1D(lut, intensity).r; // GL_PIXEL_MAP_I_TO_I
You can perform an intensity-to-RGBA lookup with a single texture access:
vec4 color = texture1D(lut, intensity); // GL_PIXEL_MAP_I_TO_R,G,B,A
An RGBA-to-RGBA lookup operation requires four texture accesses:
vec4 colorOut; colorOut.r = texture1D(lut, colorIn.r).r; // GL_PIXEL_MAP_R_TO_R colorOut.g = texture1D(lut, colorIn.g).g; // GL_PIXEL_MAP_G_TO_G colorOut.b = texture1D(lut, colorIn.b).b; // GL_PIXEL_MAP_B_TO_B colorOut.a = texture1D(lut, colorIn.a).a; // GL_PIXEL_MAP_A_TO_A
However, if you don't need alpha and you are willing to use a 3D texture to store the color table, you can do an RGB-to-RGB lookup with a single texture access:
colorOut.rgb = texture3D(lut, colorIn.rgb).rgb;
In this case, the variable lut must be defined as a sampler3d, whereas in the previous cases it needed to be defined as a sampler1d.