如何用2D纹理读取GLSL色彩校正所需的8*64规格Hald CLUT图像?
Hey there! Let's walk through how to read an 8x64 Hald CLUT as a 2D texture in GLSL, building on the 8x8 method you already understand.
First, let's clarify the layout of an 8x64 Hald CLUT:
- An 8-level CLUT (8 samples per R/G/B channel) has a total of
8^3 = 512color entries, which fits perfectly into an 8x64 texture (8 rows × 64 columns). - Each row in the texture corresponds to a single B-channel intensity (from 0 to 7, 8 total rows).
- Each row's 64 columns cover all combinations of R and G intensities: R ranges from 0-7 within 8-pixel blocks, and each block corresponds to a G intensity (0-7, 8 blocks total).
Step 1: Map Input Color to CLUT Indices
First, take your normalized input color (0-1 range for R/G/B) and map it to the 0-7 index range used by the 8-level CLUT:
vec3 rgb = texture2D(inputTexture, vTextureCoord).rgb; // Scale 0-1 color to 0-7 index range (since 8 levels = 0 to 7) float rIndex = rgb.r * 7.0; float gIndex = rgb.g * 7.0; float bIndex = rgb.b * 7.0;
Step 2: Calculate 2D Texture UV Coordinates
Convert the 3D R/G/B indices into 2D UV coordinates that match the CLUT's layout:
- The x-coordinate (U) combines R and G:
rIndex + gIndex * 8.0(each G level takes 8 columns for all R values). - The y-coordinate (V) is just the B index, since each row maps to one B level.
- Add
0.5to both coordinates to sample the center of each texture pixel (avoids edge sampling artifacts), then normalize to the 0-1 UV range:
// 64 columns wide, 8 rows tall float u = (rIndex + gIndex * 8.0 + 0.5) / 64.0; float v = (bIndex + 0.5) / 8.0; vec2 clutUV = vec2(u, v);
Step 3: Sample the CLUT and Apply Correction
Sample the CLUT texture with the calculated UV. Make sure your texture is set to LINEAR filtering—this lets the GPU handle smooth bilinear interpolation between adjacent CLUT entries, just like a 3D texture would:
vec3 correctedColor = texture2D(clutTexture, clutUV).rgb; // Preserve the original alpha channel from your input gl_FragColor = vec4(correctedColor, texture2D(inputTexture, vTextureCoord).a);
Critical Texture Settings
Don't forget to configure your CLUT texture correctly when loading it:
- Set filtering to
GL_LINEAR(enables smooth interpolation between CLUT entries). - Set wrap mode to
GL_CLAMP_TO_EDGE(prevents unwanted color wrapping at the edges of the CLUT).
How This Compares to the 8x8 CLUT Method
The 8x8 CLUT likely maps R/G/B indices to 2D coordinates in a more compact grid (e.g., x = R * 8 + G, y = B), but the core logic is the same: translating 3D color indices into 2D texture positions. The 8x64 layout simply spreads the R/G combinations into a single row per B value, which is a standard way to unpack 3D LUTs into 2D textures.
内容的提问来源于stack exchange,提问作者Manish Kumar

