Dear Computer Graphics SE,

I have a RAYMARCHING renderer, that looks up voxel data from a 3D texture. Each cell in the texture can be 0 or 1.

I have a very simple algorithm for calculating the signed distance at a given point p in space. Here is some pseudocode

Let p be some vec3(x,y,z)
Let v = value of the 3D texture at point p (0 or 1)
If v == 1:
If v == 0:
    sdf = cell_width/2.0

This works fine to find the intersection point between the ray and the voxel grid for raymarching, but this totally messes with the normals. More specifically, normals in +x, +y, +z direction work fine, but normals that should be in the -x, -y, -z directions show up as vec3(0.0) instead.

Here is my normal algorithm (glsl):

vec3 get_normal(vec3 intersection){

    vec3 axis1 = intersection+vec3(1.0,0.0,0.0)*normal_epsilon;
    vec3 axis2 = intersection+vec3(0.0,1.0,0.0)*normal_epsilon;
    vec3 axis3 = intersection+vec3(0.0,0.0,1.0)*normal_epsilon;

    float d1 = primary_sdf(axis1);
    float d2 = primary_sdf(axis2);
    float d3 = primary_sdf(axis3);

    vec3 n = normalize(vec3(d1,d2,d3));

    return n;


What is the best way to get a good sdf for my voxel field, that won't break the normals?


1 Answer 1


To estimate the normal at a point, you need to find the gradient of the distance field in the immediate vicinity of the point. You need the rate of change, not the actual values.

vec3 getNormal(vec3 p) {
   return normalize(vec3(
       getSDF(vec3(p.x + EPSILON, p.y, p.z)) - getSDF(vec3(p.x - EPSILON, p.y, p.z)),
       getSDF(vec3(p.x, p.y + EPSILON, p.z)) - getSDF(vec3(p.x, p.y - EPSILON, p.z)),
       getSDF(vec3(p.x, p.y, p.z + EPSILON)) - getSDF(vec3(p.x, p.y, p.z - EPSILON))

However, a set of 1 and 0 values is not a proper signed distance field, so it's not clear if this will work.

  • $\begingroup$ I tested something similar to your solution, but it doesn't really work. I have since solved the problem another way, by constructing a normal via testing neighboring cells. Perhaps I should unlist this question. $\endgroup$ Commented Sep 7, 2021 at 14:31
  • 1
    $\begingroup$ @MichaelSohnen you can not, it has an answer. But why don't you write your own answer? $\endgroup$
    – joojaa
    Commented Sep 8, 2021 at 6:13

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.