I'm trying to load a PNG representing a color look up table, for my color grading shader.
Here is the Neutral LUT png representation:
I'm unsure how to properly load this as a 3d texture and then pass it into my shader. Clearly, there is color transformation occurring, but I end up with a noisy rainbow mess, rather than the neutral image. For example:
Here is how I create the texture
glGenTextures(1, &lut_texture);
glBindTexture(GL_TEXTURE_3D, lut_texture);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB8, 32, 32, 32, 0, GL_RGB,
GL_UNSIGNED_BYTE, &lut_image[0]);
Here is how I pass it into the shader:
glUseProgram(colorGradingProgram);
glUniform1f(glGetUniformLocation(colorGradingProgram, "tex0"), 0);
glUniform1f(glGetUniformLocation(colorGradingProgram, "lut"), 1);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, colorBuffers[0]);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_3D, lut_texture);
drawQuad();
glBindTexture(GL_TEXTURE_3D, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);
glUseProgram(0);
Here is the frag shader (using GLSL 1.x):
uniform sampler2D tex0;
uniform sampler3D lut;
void main(void)
{
vec4 colorIn = texture2D(tex0, gl_TexCoord[0].st);
vec4 colorOut;
colorOut.rgb = texture3D(lut, colorIn.rgb).rgb;
gl_FragColor = colorOut;
}
What I'm most unclear about is dimensions specified for the call to
glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB8, 32, 32, 32, 0, GL_RGB,
GL_UNSIGNED_BYTE, &lut_image[0]);
Depending on what values I use here, my results vary wildly. The closest thing I can get to a neutral image, is using (2,2,2) as width,height,depth, but this does not resonate with me intuitively and is not totally neutral. I do not understand what I am doing wrong or how this is supposed to be achieved (translating the 2d texture to a 3d volume)
Based on my educated guess from the comments above, you need to
GL_RGBA
format.The folowing code should do that (disclaimer -- untested):
glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB8, 32, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 1024);
for(int z = 0; z < 32; ++z) {
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 32*z);
glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, z, 32, 32, 1, GL_RGBA, GL_UNSIGNED_BYTE, &lut_image[0]);
}