I have a voxel raytracer that is generating some weird shadows and I want to understand what is the source of the problem.

The image is voxelized, resulting in: enter image description here

I then generate Hard shadows from the voxels creating the following image: enter image description here

Up to this point everything works as expected. The voxel map is a 3D image with its associated mipmaps, which have been generated correctly (verified using renderdoc).

So the final step is to sample along the ray accumulating occlusion to generate a final shadow, which results in the following:

enter image description here

In that last image, the shadows of the voxels are very much noticeable and look hard for many of the surfaces.

My main hypothesis as to what could be wrong are, I am using GL_NEAREST for sampling rather than GL_LINEAR. And I may beed more samples, but if I need more samples I am not sure how I should disturb the ray to acquire them.

The shader that generated the last 2 images is:

#version 430

#define PI 3.141592653589793

in vec3 f_pos;
in vec3 f_norm;
in vec3 f_uv;

out vec4 fragment_color;

vec3 light = vec3(-500,640,0);

uniform vec3 camera_position;

uniform float cube_dim;
uniform int voxel_resolution;

uniform layout(binding=0) sampler3D diffuse_map;
uniform layout(binding=1) sampler3D normal_map;

uniform layout(binding=2) sampler2DArray text;
layout(std430, binding = 2) buffer texture_meta_data
    vec2 stretches[];

#define EPSILON 0.01
bool incube(vec3 pos, float size)
        (pos.x >= -size - EPSILON) && (pos.x <= size + EPSILON) &&
        (pos.y >= -size - EPSILON) && (pos.y <= size + EPSILON) &&
        (pos.z >= -size - EPSILON) && (pos.z <= size + EPSILON);

vec4 blinn_phong()
    vec3 pos = f_pos;

    vec4 color = vec4(0);
    vec3 l = vec3(light-f_pos);
        l = normalize(l);
    int image=int(round(f_uv.z));
    float x_stretch = stretches[image].x, y_stretch = stretches[image].y;
    float u = mod(f_uv.x*x_stretch, x_stretch);
    float v = mod(f_uv.y*y_stretch, y_stretch);
    vec3 c = vec3(texture(text, vec3(u,v,image)));

    vec3 n = normalize(f_norm);
    vec3 e = camera_position-f_pos;
    e = normalize(e);
    vec3 h = normalize(e+l);

    color = vec4(c*(vec3(0.5)+0.5*max(0,dot(n,l))) +
        vec3(0.1)*max(0,pow(dot(h,n), 100)), 1);

    return color;


void main()
    fragment_color = blinn_phong();

    float v_size = cube_dim/voxel_resolution;
    vec3 r = f_pos + f_norm*v_size*6;
    vec3 dir = normalize(light-r);
    vec3 start = r+dir*v_size;

    float hit = 1.f;
    float l=0;
    float acc=0;
    vec4 val1, val2;
    while(incube(r, cube_dim) && (l<=length(start-light)/5.f) && acc<1)
        r += dir*v_size*0.2;

        val1 = textureLod(normal_map, (r)*0.5/cube_dim+vec3(0.5), l*0.01);

        acc += val1.a;
    acc = min(acc, 1);
    fragment_color *= (1-acc)*0.8 + 0.2;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.