Home > Shaders > Curvature

Many times, it is important to know how curved a surface is, or how quickly the surface is changing. This done by computing k, the curvature of the surface. This function returns the minimum and maximum curvature of the surface at a point. The derivation for this function in contained on p. 30 of Advanced Renderman by Apadoca and Gritz. Additionally, MathWorld provides a more thourough (though still esoteric) explanation of curvature at http://mathworld.wolfram.com/Curvature.html.

Quickly, curvature can be calculated with this formula:

If you're good at math, this formula probably comes as second nature. However, if you havent had Calculus II, the meaning is probably just a little foggy. In layman's terms, the first derivative (y') of a value is how quickly the value is changing. The second derivative (y'') is how quickly the rate of change is changing. The first derivates x' and y' measure how fast the surface point is changing. x'' and y'' measure how quickly the rates of change x' and y' are changing themselves. So, the formula calculates how quickly the surface point P is changing along an axis. Then, it compares this value to the change in the tangent of the surface and the angle which the tangent makes with the surface. So, k will be high whenever the surface pinches together. I hope this makes sense, and if it mathematically incorrect, please email me.

Notice is in the image below how the surface color changes quicker when the surface pinches together.

 

 

Since so many people have asked how to do curvature I'm posting my code for this function on my site. However, if you use this code, please be sure to cite Apadoca & Gritz, Mathworld.com, and Matthew Parrott. Enjoy!

void pCurvature(point p; output varying float kmax, kmin)
   {
		/* calculates the min and max curvature at point p.
		derived from Advanced Renderman by Apodoca and Grizt and Mathworld.com
		implementation by Matthew Parrott, mparrott@vt.edu */

		 float ku, kv, kuv; /*curvature in u and v */
		 vector dpdu = Du(p);
		 float ddpddu = length(Du(Du(p)));
		 vector dpdv = Dv(p);
		 float ddpddv = length(Dv(Dv(p)));
		 float ddpdudv = length(Du(Dv(p)));
 
 
		   ku = ddpddu / pow(length(dpdu),2);
		   kv = ddpddv / pow(length(dpdv),2);
		   kuv = ddpdudv / (length(dpdu) * length(dpdv));
   
		   float theta = atan(((2 * kuv) / (ku - kv))) / 2;
		   float pm = 2 * kuv * sin(theta) * cos(theta); /*plus minus portion of curvature */
		   float base = ku*pow(sin(theta),2) + kv*pow(cos(theta),2);
		   float kmaxt = base + pm;
		   float kmint = base - pm;
		   kmax = max(kmaxt,kmint);
		   kmin = min(kmaxt,kmint);
	}

Here is the source code for the shader used to create the above image:

surface curvature(float offset = 0, gain = 1.0;)
{
float kmax, kmin;
pCurvature(P,kmax, kmin);

Oi = Os;
Ci = Oi * Cs * color "hsv" ((kmax + kmin)*gain + offset, 0.8, 0.8);
}