clip mapping

January 23rd, 2007 by Bramz

I’ve added clip mapping (*) to LiAR, which is some sort of alpha channel for surfaces. It can be used to create holes in a surface using a texture. The texture is compared to a threshold to determine where the surface should be removed, so that rays can travel undisturbed through the removed parts.

This is different from using a fully transparent BSDF because the latter will split ray paths by inserting a no-op scattering event. This is especially a major difference for shadow rays in a direct lighting pass: they block on the first scattering event causing the transparent parts to cast shadows. When using clip mapping, no scattering event will be inserted because the surface is not present, and thus shadows will be casted as expected.

a sphere clip mapped by a CheckerVolume

It’s implemented as a special scene object ClipMap that takes a child object and a clip texture. When the object is tested for ray intersections, a candidate intersection with the child object is searched for, and if one is found the clip texture is evaluated using the local intersection context of the child object. If this yields a value above a threshold, the intersection is accepted. Otherwise, a new candidate intersection is searched for with an adjusted near limit of the bounded ray.

It was pretty easy to implement, however not without cost. The intersection context needs to be evaluated independently of the one used for shading. Worse, the used intersection context may be different depending on which level the shader is defined. Also, the function isIntersecting can no longer use any shortcuts, but must perform a full intersection test.

while (true)
{   
    child_->intersect(sample, ray, intersection);
    if (!intersection)
    {
        result.swap(intersection);
        return;
    }
    child_->localContext(sample, ray, intersection, 
        context);

    if (clipMap_->lookUp(sample, context).average()
        >= threshold_)
    {
        intersection.push(this);
        result.swap(intersection);
        return;
    }
    ray = bound(ray, intersection.t(), ray.farLimit()); 
}

You can try it out for yourself using the clip_map.py example in the examples/scenery directory.

(*) The term clip mapping is being used in LightWave 3D and some other renders, and also appears in the book Digital Lighting & Rendering by Jeremy Birn. However is also used for naming the act of loading small parts of huge mipmaps to reduce memory requirements.

Comments are closed.