I'm trying to implement an hybrid renderer based on Vulkan extension VK_NV_ray_tracing. Basically, the rasterizer compute the albedo and depth map of the scene. Then I try to compute the distance from the depth buffer so that I can send a shadow ray from a raygen program to compute direct lighting. I linearize the depth to obtain a correct distance value from the depth buffer. What I am doing is this:

const vec2 texcoord = vec2(gl_LaunchIDNV) / vec2(gl_LaunchSizeNV);
const double z_b = texture(depthBuffer, texcoord).x;
const double depth = (2.0 * near * far) / (far + near - z_b * (far - near));

I am then computing the ray position and direction

const vec2 pixelCenter = vec2(gl_LaunchIDNV.xy) + vec2(0.5);
const vec2 inUV = pixelCenter / vec2(gl_LaunchSizeNV.xy);
const vec2 d = inUV * 2.0 - 1.0;
const vec4 camFront  = cam.viewInverse * vec4(0, 0, 1, 0);
const vec4 camPos    = cam.viewInverse * vec4(0, 0, 0, 1);
const vec4 camTarget = cam.projInverse * vec4(d.x, d.y, 1, 1);
const vec4 camDir    = cam.viewInverse * vec4(normalize(camTarget.xyz), 0);

And the final ray position is then set using the depth I just computed.

const vec3 pos = camPos.xyz + camDir.xyz * float(depth);

The problem here is that the depth seems incorrect because shadows tend to curve at the edges of the screen and do not fit the geometry. bended shadows I think this might be because of the depth buffer value that does not represent the distance from the origin of the camera but from the near plane, which would explain the problem, but I am not sure of that.

Any idea?

  • $\begingroup$ That sounds logical, have you tried taking the pixel position in screenspace and converting that to world space. You would use that in place of the values in const vec4 camPos = cam.viewInverse * vec4(d.x, d.y, 0, 1);. I believe that is the correct value. $\endgroup$
    – ErnieDingo
    Jan 8, 2020 at 21:44
  • $\begingroup$ This is called from a raygen program, I don't think I have access to the pixel position in screenspace :( $\endgroup$
    – antaalt
    Jan 9, 2020 at 9:22

1 Answer 1


Thanks for your help, I fixed it by changing the way i am computing the depth :)

const double z_b = texture(depthBuffer, texcoord).x;
const vec4 clipSpacePosition = vec4(texcoord * 2.0 - 1.0, z_b, 1.0);
vec4 viewSpacePosition = cam.projInverse * clipSpacePosition;
viewSpacePosition /= viewSpacePosition.w;
float depth = length(viewSpacePosition.xyz);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.