Hi! I am now trying to learn volume rendering using OpenGL and trying to slice a 3D volume, but I don’t know how to load data into a 3D texture. I searched on the web, but I only found many examples on legacy APIs, not on modern OpenGL APIs. Can you please tell me how to do it? Thank you very much!
My data are structured in row major. For instance, if I have a (2,2,2) voxels, then
data_arr[0] = voxels[0][0][0]
data_arr[1] = voxels[1][0][0]
data_arr[2] = voxels[0][1][0]
data_arr[3] = voxels[1][1][0]
data_arr[4] = voxels[0][0][1]
data_arr[5] = voxels[1][0][1]
data_arr[6] = voxels[0][1][1]
data_arr[7] = voxels[1][1][1]
And the value inside one voxel is unsigned short
value (i.e 16bit unsigned integer).
My code for setting up the 3D texture is
GLuint tex3D;
glGenTextures(1, &tex3D);
glBindTexture(GL_TEXTURE_3D, tex3D);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_REPEAT);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// unsigned short vol_dim[3]; // dimensions of voxels
glTexImage3D(GL_TEXTURE_3D, 0, GL_R16UI,vol_dim[0], vol_dim[1], vol_dim[2], 0, GL_RED_INTEGER, GL_UNSIGNED_SHORT, data_arr);
glGenerateMipmap(GL_TEXTURE_3D);
My rendering function is
void renderFrame() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0);
program->use();
glBindTexture(GL_TEXTURE_3D, tex3D);
program->setUniform("Axis", axis);
program->setUniform("MainAxisTexCoord", mainAxisCoord);
canvas->render(); // canvas is a FBO rectangular
}
And my vertex shader is
#version 450 core
#define X_AXIS 0
#define Y_AXIS 1
#define Z_AXIS 2
uniform float MainAxisTexCoord;
uniform int Axis;
layout (location = 0) in vec3 VertexPosition;
layout(location = 2) in vec2 Tex;
out vec3 texCoord;
void main() {
gl_Position = vec4(VertexPosition, 1.0);
if(Axis == X_AXIS)
texCoord = vec3(MainAxisTexCoord, Tex.s, Tex.t);
else if(Axis == Y_AXIS)
texCoord = vec3(Tex.s, MainAxisTexCoord, Tex.t);
else
texCoord = vec3(Tex, MainAxisTexCoord);
}
My fragment shader is
#version 450 core
in vec3 texCoord;
layout (binding = 0) uniform sampler3D textureMap;
layout (location = 0) out vec4 fColor;
void main()
{
vec3 texColor = vec3(texture(textureMap, texCoord));
fColor = vec4(texColor, 1.0);
// fColor = vec4(texCoord, 1.0);
}
If I uncomment the last line of the code of fragment shader, I can see the result contains gradients of base colors, which means at least texCoord
is correct. But if I comment the last line and want to use the texCoord
to take the value of the 3D texture, I got nothing but just black. I think there must be something wrong with my code that loads data into a 3D texture, but I don’t know how to fix it.