Fixing transformations and local geometry

April 20th, 2006 by Bramz

Today, I noticed there was something seriously wrong with the way local differential geometry was treated by transformation objects.

Basically, rendering goes like this: find intersection, find geometry of intersection, get shader at intersection, shade using the geometry. However, currently, if the object being intersected is a transformed one (by scenery::Transformation), all local geometry (3D point, normal, …) was transformed to global space, the top level of the transformations. So, all shading was done in global space. Is that bad? Yes. Imagine a sphere that uses a 3D texture like CheckerVolume, and this sphere moves from the left to the right. Because the value of the texture is looked up in global space, this means that the sphere will move while the checkerboard pattern is stuck to its global position. This is not what is wanted. The pattern should be fixed to the object!

OK, seems easy to solve that: don’t transform local geometry! Instead, when shading, transform all global information (eye rays, light rays, …) to local space. Well, not exactly … There’s a bit of a problem to this approach: suppose you create a complex object using CSG and some transformations, then every part of that object will have its own local space. If you apply one 3D texture to the complex object, you’ll notice that you won’t get a continuous texture: it will jump from one local space to another.

So, we need a combination of both. Basically, from the observation above, we want to do the shading in the coordinate space of the (compound) object the shader was attached to (let’s call it shader space). The untransformed sphere in the first case, the complete CSG object in the latter. When retrieving local geometry, transform it up (towards global space) until you get to the object with the shader attached. From there, keep track of a single transformation from shader to global space.

Using this approach, we get the following result. One sphere with radius 1 is instanced three times: once without transformation, and two times scaled up by a factor 2.

  • The middle sphere is the untransformed sphere and a shader attached with a standard CheckerVolume texture. For this one, local space = global space = shader space.
  • The left sphere is a second instance of the middle sphere, but scaled up by a factor of two. The shader space is still the local space of the untransformed sphere. As result the texture is scaled up together with the object.
  • The right sphere is a third instance of the same sphere, however this time, the shader is attached to the transformed sphere. This means that the shader space = global space. As result, the pattern has the same size of the untransformed sphere.

Transformations and shader space

script: examples/scenery/transformation.py

One Response to “Fixing transformations and local geometry”

  1. clip mapping // LiAR isn’t a raytracer Says:

    […] 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 […]