Search code examples
openglglslraymarching

Raymarching Clamping coordinate makes weird streched artifacts


I am trying to render a grid of spheres using ray marching. The SDF function looks like:

float sq_layer(vec3 p, vec3 bounding_box_min, vec3 bounding_box_max)
{
         float cell_size = 4.0 / 16.0;
         vec3 p0 = clamp(p.xyz, bounding_box_min, bounding_box_max);
         p0 = mod(p0, cell_size) - cell_size * 0.5f;
         float d_pt = sphereSDF(vec3(p0.x, p0.y, p0.z), 0.05f)
         return d_pt;
}

But I am getting something like this: enter image description here

For some more relevance, I tried changing the code up a bit:

float sq_layer(vec3 p, vec3 bounding_box_min, vec3 bounding_box_max)
{
         vec3 cell_size = (bounding_box_max - bounding_box_min)  / 4.0;
         vec3 p0 = clamp(p.xyz, bounding_box_min, bounding_box_max);
         p0 = mod(p0, cell_size) - cell_size * 0.5f;
         float d_pt = boxSDF(p0, cell_size * 0.35);
         return d_pt;
}

Still I get, enter image description here


Solution

  • Clamping the coordinates the way you do results in your sdf returning a constant distance very close to the surface, hence you're running out of iterations resulting in the artifacts you see. Result of clamping the coordinate on SDF value

    Instead of clamping you want to do an intersection with a box sdf the size of your bounding box:

    float sq_layer(vec3 p, vec3 bounding_box_min, vec3 bounding_box_max)
    {
             float cell_size = 4.0 / 16.0;
             vec3 p0 = mod(p, cell_size) - cell_size * 0.5f;
             float d_pt = sphereSDF(p0, 0.05f);
    
             // the following is just a simplified box sdf
             vec3 bb_extents = (bounding_box_max - bounding_box_min) * .5; 
             vec3 bb_center = bounding_box_min + bb_extents;
             vec3 bb_p = max(abs(p-bb_center)-bb_extents,0.);
             float d_bb = max(max(bb_p.x,bb_p.y),bb_p.z);
    
             // intersect "sphere-field" with bounding box
             return max(d_pt,d_bb);
    }
    

    Using interection to "clamp" the SDF