RenderMan | Poor Man’s Dispersion Shader

I decided to write this shader after I found this thread on usenet : Poor Man’s Dispersion
It describes a simple way to mimic the dispersion of light such a complex medium such as crystal.

The main idea behind is to cast 3 rays of refracted light instead of 1. Each ray will have a slightly different index of refraction (IOR). The 3 resulting values will be recomposited in the red, green and blue component. This is absolutely not physically accurate, but it works quite well, as seen in the figure below (both images were rendered on a RenderDrive).

  1. As mentionned in the newsgroup, this straight method gives three sharp streaks, instead of a continuous spectrum.
  2. That’s why we need to add a rand() function to the IOR offset. And here comes the magic of the RenderDrive, that will automatically supersample each raycast until it sufficiently reduces the noise.

Here is the RSL source of the shader. It uses raytracing extensively, please don’t expect amazingly short rendertimes.

surface PoorDispersion(float ior = 1.5; float dispersion_iota = 0.25;) 
{ 
	point R, T, Nn, Ni; 
	float krefl, ktran, eta; 
	
	Nn = normalize(N); 
	Ni = normalize(I); 
	fresnel(Ni, Nn, 1.0 / ior, krefl, ktran, R, T);
	
	if (isshadowray() != 0) 
	{ 
		Oi = (1.0 - ktran); 
	} 
	else 
	{ 
		eta = ior; Oi = Os; 
		eta += (dispersion_iota * float random()); 
		T = refract(Ni, Nn, 1 / eta); 
		Ci = trace(P, T) * color(1,0,0) * ktran; 
		eta += (dispersion_iota * float random()); 
		T = refract(Ni, Nn, 1 / eta); 
		Ci += trace(P, T) * color(0,1,0) * ktran; 
		eta += (dispersion_iota * float random()); 
		T = refract(Ni, Nn, 1 / eta); 
		Ci += trace(P, T) * color(0,0,1) * ktran; 
		Ci += trace(P, R) * krefl; 
	} 
}

Later on, I tried this shader with the former PRman implementation of Larry Gritz : Entropy. I made a quick comparison :
3. RenderDrive demonstrates its ability to handle crazy raytrace
4. With Entropy the result is really noisy, I should reconsider the brute force approach

Leave a Reply

Your email address will not be published. Required fields are marked *