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!