I'm trying to implement ray casting based volume rendering and therefore I'd need to pass a float Array to the fragment shader as a Texture (Sampler3D). I've got a volume datastructure containing all the voxels. Each voxel contains a density value. So for processing I stored the values into a float Array.
//initialize glew, initialize glfw, create window, etc.
float* density;
density = new float[volume->size()];
for (int i = 0; i < volume->size(); i++){
density[i] = volume->voxel(i).getValue();
}
Then I tried creating and binding the textures.
glGenTextures(1, &textureHandle);
glBindTexture(GL_TEXTURE_3D, textureHandle);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
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);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage3D(GL_TEXTURE_3D, 0, GL_LUMINANCE, volume->width(),
volume->height(), volume->depth(), 0, GL_LUMINANCE, GL_FLOAT, density);
In my render loop I try to load the Texture to the uniform Sampler3D.
glClearColor(0.4f, 0.2f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0);
GLint gSampler = glGetUniformLocation(shader->shaderProgram, "volume");
glUniform1i(gSampler, 0);
cube->draw();
So the basic idea is to calculate the current position and direction for ray casting in the Vertex Shader.
in vec3 position;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
uniform vec4 cameraPos;
out vec3 pos;
out vec3 dir;
void main(){
gl_Position = projection * view * model * vec4(position, 1.0);
pos = position;
dir = pos - (inverse(model) * cameraPos).xyz;
}
That seems to work well, so far so good. The fragment shader looks like this. I take some samples along the ray and the one with the largest density value will be taken as a color for red, green and blue.
#version 330 core
in vec3 pos;
in vec3 dir;
uniform sampler3D volume;
out vec4 color;
const float stepSize = 0.008;
const float iterations = 1000;
void main(){
vec3 rayDir = normalize(dir);
vec3 rayPos = pos;
float src;
float dst = 0;
float density = 0;
for(int i = 0; i < iterations; i++){
src = texture(volume, rayPos).r;
if(src > density){
density = src;
}
rayPos += rayDir * stepSize;
//check whether rays are within bounds. if not -> break.
}
color = vec4(density, density, density, 1.0f);
}
Now I've tried inserting some small debug assertions.
if(src != 0){
rayPos = vec3(1.0f);
break;
}
But src seems to be 0 at every iteration of every pixel. Which gets me to the conclusion that the Sampler isn't correctly set. Debugging the C++ code I get the correct values for the density array right before I pass it to the shader, so I guess there must be some opengl function missing. Thanks in advance!