Home > Shaders

Bombed Blobby Shader

Blobbies are 3D objects which represent the attractive forces surrounding physical objects. As two objects get closer together, these forces increase in strength. Imagine the gravity fields of the earth and moon reaching out into space and interacting with each other. Or maybe two magnets with iron filings... or maybe two cracked eggs with yokes mixing together. Pretty much in all of these situations, you can imagine something like this:

 

We can also use this concept to create shaders. If two points are close enough on a surface, they will grow together. Forming either a blobby perimeter drawing, or in the case of displacement shaders, raised areas which pile up on each other.

This shader is simple enough. Given a bunch of points, we use the formula:

height = cos(distance(P1,P2))^k.

K should be fairly large, 10 to 30 is usually good. Values less than 1 also provide interesting results as we will see in a moment.

The tough part is figuring out where all these points are on the surface which you're going to be drawing around. To do this, I used a method known as "bombing." Stephen May explains this on his wonderful site, Rman Notes. This algorithm creates a grid over the surface. Then, the x and y ID of each grid cell is used in a noise function to put a point randomly inside the cell. Because the noise is the same for each distinct cell, the points remain in fixed, random locations. Then, these are used to measure the distance between points to create blobbies. Of course, circles may overlap adjacent cells, so in each cell we have to check the 8 surrounding cells for overlapping circles. Here are some variations on the blobby shader:

#define snoise(x) (2*noise(x) -1)
 #define udn(x,lo,hi) (smoothstep(.25, .75, noise(x)) * ((hi) - (lo)) + (lo))
float fbm(float amp, gain, lacunarity, xx)
   {
   float j;
   float fbm;
   float a = amp;
   float x = xx;
   
   for (j = 0; j < 3; j += 1)
   {
   fbm += a * abs(snoise(3 * x));
   a *= gain;
   x *= lacunarity;
   }
   return fbm;
   }
   
   surface blobbyBombing( float freq = 10, maxRad = 0.8, minRad = 0.1, cosPower = 1.0, Km = 1.0, Kd = 0.6)
   {
   float ss = s * freq;
   float tt = t * freq;
   float scell = floor(ss);
   float tcell = floor(tt);
   float slocal = ss - scell;
   float tlocal = tt - tcell;
 float pntSS;
   float pntTT;
   float i,j,dis;
   float value = 0;
   
   for (i = -1; i <= 1; i +=1)
   {
   for (j = -1; j <= 1; j+=1)
   { 
   float noi = noise((scell + i) * 10 + 0.5, (tcell + j) * 10 + 0.5);
   
   pntSS = (scell + i) + udn(noi * 999 , -.5 ,0.5) + 0.5;
   pntTT = (tcell + j) + udn(noi * 1115, -.5 , 0.5) + 0.5;
   dis = sqrt(((ss - pntSS) * (ss - pntSS))
   + ((tt - pntTT) * (tt - pntTT)));
   value += pow(sin(1 - smoothstep(minRad, maxRad, dis)),cosPower);
   }
   }
   
   
   P += normalize(N) * value * Km;
   N = calculatenormal(P);
   Ci = Cs * diffuse(normalize(N)) * Kd;
   }