Home -> Shaders -> Chromatic Dispersion
Dispersion occurs when different wavelengths of light get seperated as they pass through different materials, creating rainbow effects. As light enters a refractive material, such as glass, its velocity changes, causing the ray to deflect slightly and creating magnified or reduced images. Certain types of materials though, cause light to split apart. This is because each wavelength of light travels at a different velocity and is thus affected by materials differently.

We can approximate the physical laws by using multiple refraction rays, each calculated at a different index of refraction. Then, each ray is multiplied by a single hue, representing a single wavelength. All of the rays are then added together and scaled appropriately. The resulting image exhibits bands of color along areas of high contrast or high curvature.
An important next step would be to be able to transfer the shading color to photons. This could be used to create a prismatic effect.

#include "h:\vsfx727\sl\voronoi.h" surface chrom_dis( float ior = 1.5, /*index of refraction */ iorSpread = 0.2, dispersionSamples = 3.0, blur = 0.2, iorK = 1.0, refractionBias = 2.0, Km = 1.0;) {
/*layer variables */
float layerHump = 0, totalHump = 0;
color layerColor = 0, layerOpacity = 0,
totalColor = 0, totalOpacity = 1;
/*grid variables */
float ss,tt,ls,lt,sCell, tCell;
/* voronoi variables */
float f1,f2;
point pos1,pos2;
/* Initialize Colors */
totalColor = Cs;
totalOpacity = Os;
/*lighting model */
normal Nn = normalize(N);
normal nf = faceforward(Nn,I);
normal In = normalize(I);
float kr, kt;
/*counter variables */
float i,j,k;
/*layer 2: reflections */
/* vector reflectionDirection = reflect(I,N);
layerColor = trace(P,reflectionDirection);
totalColor = layerColor;
*/
totalColor = color(1,0,0);
/*layer 1: refraction */
float tempIor = ior - 0.5 * iorSpread;
float eta = (In.Nn < 0) ? 1/tempIor : tempIor;
vector refractDirection;
float currentHue = 0;
layerColor = color(0);
color rayColor;
for(i = 0; i < dispersionSamples; i += 1)
{
currentHue = i / dispersionSamples;
refractDirection = refract(In, nf, eta) + normalize(vector(noise(random()))) * blur*0.01;
rayColor = trace(P,refractDirection);
layerColor += (color "hsv" (currentHue,1.0,1.0)) * rayColor * (1/dispersionSamples) * iorK;
eta -= iorSpread / dispersionSamples;
}
fresnel(I,N,eta,kr,kt);
/*float refK = max(0,min(1,reflectionBias + reflectionScale*pow((In.Nn),reflectionPower)));*/
/*layerOpacity = color(kt * refractionBias);*/
totalColor = layerColor;
/* Final Computations */
P += totalHump * Nn * Km;
N = calculatenormal(P);
Nn = normalize(N);
nf = faceforward(Nn, I);
Oi = totalOpacity;
Ci = diffuse(nf) * Oi * totalColor;
}
|