4

Im currently in the process of writing a Voxel Cone Tracing Rendering Engine with C++ and OpenGL. Everything is going rather fine, except that I'm getting rather strange results for wider cone angles.

Right now, for the purposes of testing, all I am doing is shoot out one singular cone perpendicularly to the fragment normal. I am only calculating 'indirect light'. For reference, here is the rather simple Fragment Shader I'm using:

#version 450 core

out vec4 FragColor;

in vec3 pos_fs;
in vec3 nrm_fs;

uniform sampler3D tex3D;

vec3 indirectDiffuse();

vec3 voxelTraceCone(const vec3 from, vec3 direction);

void main()
{
    FragColor = vec4(0, 0, 0, 1);
    FragColor.rgb += indirectDiffuse();
}

vec3 indirectDiffuse(){
    // singular cone in direction of the normal
    vec3 ret = voxelTraceCone(pos_fs, nrm);

    return ret;
}

vec3 voxelTraceCone(const vec3 origin, vec3 dir) {
    float max_dist = 1f;
    dir = normalize(dir);

    float current_dist = 0.01f;

    float apperture_angle = 0.01f; //Angle in Radians.

    vec3 color = vec3(0.0f);
    float occlusion = 0.0f;

    float vox_size = 128.0f; //voxel map size

    while(current_dist < max_dist && occlusion < 1) {
        //Get cone diameter (tan = cathetus / cathetus)
        float current_coneDiameter = 2.0f * current_dist * tan(apperture_angle * 0.5f);

        //Get mipmap level which should be sampled according to the cone diameter
        float vlevel = log2(current_coneDiameter * vox_size);

        vec3 pos_worldspace = origin + dir * current_dist;
        vec3 pos_texturespace = (pos_worldspace + vec3(1.0f)) * 0.5f; //[-1,1] Coordinates to [0,1]

        vec4 voxel = textureLod(tex3D, pos_texturespace, vlevel); //get voxel

        vec3 color_read = voxel.rgb;
        float occlusion_read = voxel.a;

        color = occlusion*color + (1 - occlusion) * occlusion_read * color_read;
        occlusion = occlusion + (1 - occlusion) * occlusion_read;

        float dist_factor = 0.3f; //Lower = better results but higher performance hit
        current_dist += current_coneDiameter * dist_factor; 
    }

    return color;
}

The tex3D uniform is the voxel 3d-texture.

Under a regular Phong shader (under which the voxel values are calculated) the scene looks like this: Scene

For reference, this is what the voxel map (tex3D) (128x128x128) looks like when visualized:Voxelmap

Now we get to the actual problem I'm having. If I apply the shader above to the scene, I get following results:

For very small cone angles (apperture_angle=0.01) I get roughly what you might expect: The voxelized scene is essentially 'reflected' perpendicularly on each surface: Small Apperture

Now if I increase the apperture angle to, for example 30 degrees (apperture_angle=0.52), I get this really strange 'wavy'-looking result:

Large Appeture

I would have expected a much more similar result to the earlier one, just less specular. Instead I get mostly the outline of each object reflected in a specular manner with some occasional pixels inside the outline. Considering this is meant to be the 'indirect lighting' in the scene, it won't look exactly good even if I add the direct light.

I have tried different values for max_dist, current_dist etc. aswell as shooting several cones instead of just one. The result remains similar, if not worse.

Does someone know what I'm doing wrong here, and how to get actual remotely realistic indirect light?

I suspect that the textureLod function somehow yields the wrong result for any LOD levels above 0, but I haven't been able to confirm this.

Helliaca
  • 183
  • 2
  • 10
  • 1
    The first thing to check would be if the texture has appropriate MIP maps. Either by using some OpenGL debugger or by rendering a pre-defined lod. Btw, why is `vox_size` in the formula for `vlevel`? – Nico Schertler Aug 05 '18 at 11:51

1 Answers1

1

The Mipmaps of the 3D texture were not being generated correctly. In addition there was no hardcap on vlevel leading to all textureLod calls returning a #000000 color that accessed any mipmaplevel above 1.

Helliaca
  • 183
  • 2
  • 10