Problems rendering to a 3d texture

Hi all, I’m hoping someone can help me with this thing I’ve been stuck with for a few weeks now. Basically what I’m trying to do is voxelize a scene into a 3d texture, then create global illumination (voxel cone tracing) Apparently voxelizing the scene is a simple thing, but no matter what I do, the result is always a black texture, all zeros, I’m using RenderDoc to test it.

I am creating the texture as follows:

glEnable(GL_TEXTURE_3D);
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_3D, textureID);
 //Set wrapping options
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_BORDER);
//Mipmaps
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

glTexStorage3D(GL_TEXTURE_3D, 7, GL_RGBA8, width, height, depth); //64x64x64
glGenerateMipmap(GL_TEXTURE_3D);
glBindTexture(GL_TEXTURE_3D, 0);

Then I render the scene binding to the 3d texture like this:

glBindFramebuffer(GL_FRAMEBUFFER, 0);

//Clear the 3d texture
std::vector<float>color ={0,0,0,0};
glBindTexture(GL_TEXTURE_3D, voxelTex->textureID);
glClearTexImage(voxelTex->textureID, 0, GL_RGBA, GL_FLOAT, &color);
glBindTexture(GL_TEXTURE_3D, 0);

glViewport(0, 0, 64, 64);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glDisable(GL_BLEND);

program_voxelize->use();// init the shader program

//Start binding to the 3d texture
glActiveTexture(GL_TEXTURE2); 
glBindTexture(GL_TEXTURE_3D, voxelTex->textureID);
glBindImageTexture(2, voxelTex->textureID, 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_RGBA8);
glUniform1i(program_voxelize->uniform("texture3D"), 2);

// Then render the scene models
for (int ob=0; ob < m_model.size(); ob++) 
{
   Mtxfuc::MatrixLoadIdentity(&Modelview);
   Mtxfuc::TransformMatrix(&Modelview,Model[ob]->transform);
   glUniformMatrix4fv(program_voxelize->uniform("M"), 1, GL_FALSE, (GLfloat*) &Modelview.m[0][0] );

   glActiveTexture( GL_TEXTURE0 );
   glBindTexture(GL_TEXTURE_2D, material->getDifuseTex().texID);
   glUniform1i(program_voxelize->uniform("albedoMap"),0);

   Model[ob]->BindVao();
   glDrawElements(GL_TRIANGLES, Model[ob]->in.size(), GL_UNSIGNED_SHORT, BUFFER_OFFSET(0));
   Model[ob]->UnbindVao();
}

glGenerateMipmap(GL_TEXTURE_3D);

For the shaders, I am using a geometry shader together with the vertex and fragment shader.
The vertex shader doesn’t have too much:

#version 450 core

layout(location = 0) in vec3 position;
layout (location = 1) in vec2 aTexCoords;
layout(location = 2) in vec3 normal;

out vec3 worldPositionGeom;
out vec3 normalGeom;
out vec2 texGeom;
uniform mat4 M;

void main(){	
	texGeom = aTexCoords;
	worldPositionGeom =  vec3(M * vec4(position, 1.0));
	normalGeom = normalize(mat3(transpose(inverse(M))) * normal);
}

Then for the geometry shader:

#version 450 core

layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;

in vec3 worldPositionGeom[];
in vec3 normalGeom[];
in vec2 texGeom[];

out vec3 worldPositionFrag;
out vec3 normalFrag;
out vec2 TexCoords;

void main(){
    const vec3 N = abs(cross(worldPositionGeom[1] - worldPositionGeom[0], worldPositionGeom[2] - normalGeom[0]));

    for(uint i = 0; i < 3; ++i){
       worldPositionFrag = worldPositionGeom[i].xyz;
       normalFrag = normalGeom[i];
       TexCoords = texGeom[i];

       if (N.z > N.x && N.z > N.y)
        {
            gl_Position = vec4(worldPositionFrag.x, worldPositionFrag.y, 0.0f, 1.0f);
        }
        else if (N.x > N.y && N.x > N.z)
        {
            gl_Position = vec4(worldPositionFrag.y, worldPositionFrag.z, 0.0f, 1.0f);
        }
        else
        {
            gl_Position = vec4(worldPositionFrag.x, worldPositionFrag.z, 0.0f, 1.0f);
        }

          EmitVertex();
    }

    EndPrimitive();
}

And for the fragment shader I’m using the function imageStore():

#version 450 core

#define POINT_LIGHT_INTENSITY 0.96f
// Lighting attenuation factors.
#define DIST_FACTOR 1.1f 
#define CONSTANT 1
#define LINEAR 0
#define QUADRATIC 1

float attenuate(float dist){ dist *= DIST_FACTOR; return 1.0f / (CONSTANT + LINEAR * dist + QUADRATIC * dist * dist); }

struct PointLight {
	vec3 color;
	vec3 position;
	float paddingAndRadius;
};

in vec3 worldPositionFrag;
in vec3 normalFrag;
in vec2 TexCoords;

uniform sampler2D albedoMap;
layout(binding = 2, rgba8) uniform image3D texture3D;

vec3 calculateLight(const PointLight light){
	
	const vec3 direction = normalize(light.position - worldPositionFrag);
	const float distanceToLight = distance(light.position, worldPositionFrag);
	const float attenuation = attenuate(distanceToLight);
	const float d = max(dot(normalize(normalFrag), direction), 0.0f);
	return d * POINT_LIGHT_INTENSITY * attenuation * light.color ;
}

vec3 scaleAndBias(vec3 p) { return 0.5f * p + vec3(0.5f); }
bool isInsideCube(const vec3 p, float e) { return abs(p.x) < 1 + e && abs(p.y) < 1 + e && abs(p.z) < 1 + e; }

void main(){
     vec3 albedo = pow(texture(albedoMap, TexCoords).rgb , vec3(2.2)) ;
     if(!isInsideCube(worldPositionFrag, 0)) return;
     vec3 color = vec3(0.0f);
     
     PointLight light;
     light.color = vec3(100.0,100.0,100.0);
     light.position = vec3(20,10,30);
     color = calculatetLight(light);
     color +=  albedo;

     // Output lighting to 3D texture.
     vec3 voxel = scaleAndBias(worldPositionFrag);
     ivec3 dim = imageSize(texture3D);
     imageStore(texture3D, ivec3(dim * voxel), vec4(color,1.0));
}

And that’s it, I really can’t see where the problem is, apparently everything seems ok to me, but it doesn’t work, the texture is always black, I even tried to force the color imageStore(texture3D, ivec3(dim * voxel), vec4(255)); but nothing, same result.

I am using SDL2 to create the window and the context, maybe the problem is there, maybe it is not creating the context with the correct version of opengl, I don’t know, I am creating it in the following way:

if((SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_GAMECONTROLLER|SDL_INIT_HAPTIC)==-1))
    {
        fprintf(stderr,"Error al iniciar SDL\n", SDL_GetError());
        exit(-1);
    }
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 5);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);

mwindow= SDL_CreateWindow("Test",
                          SDL_WINDOWPOS_CENTERED,
                          SDL_WINDOWPOS_CENTERED,
                          Window.h, Window.w,
                          SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL | SDL_WINDOW_ALLOW_HIGHDPI);

 mainContext = SDL_GL_CreateContext(mwindow);
 SDL_GL_MakeCurrent(mwindow, mainContext);
 SDL_ShowCursor(SDL_ENABLE);
 SDL_GL_SetSwapInterval(1);
 gladLoadGLLoader(SDL_GL_GetProcAddress);

But anyway everything seems ok, I have tried with glGetString(GL_VERSION) to check the actual vesion and it indicates 4.6 not 4.5 but it should work anyway.
I don’t know, I hope someone can see where I’m making the mistake and can help me with this, because no matter how many times I try I don’t see the problem.

Thanks!

No? :worried: I know, maybe it’s hard to see where the fault is without being able to test it. If anyone needs more info just let me know.

Ok, I finally managed to fix it, it was something very stupid. :sweat_smile:
When rendering all the models, instead of ending with:

glGenerateMipmap(GL_TEXTURE_3D); 

I had to indicate again the 3d texture.

 glBindTexture(GL_TEXTURE_3D, voxelTex->textureID);
 glGenerateMipmap(GL_TEXTURE_3D); 

Since when rendering the models I had called glBindTexture(GL_TEXTURE_2D, material->getDifuseTex().texID); before
As simple as that…