{
   groundcolor.cal

   Copyright 1998, Mark J. Stock

   An attempt to create a procedural texture to determine the
   underlying color of the ground surface. Returns appropriate
   color for ground surface depending on altitude (Z).

   Inputs:
      The first 6 inputs should match the 6 inputs for
         groundtexture, because the color is somewhat dependent 
         on the underlying texture.
      A1,A3,A5 - perlin noise scales
      A2,A4,A6 - corresponding perlin noise strengths
      A7 - ocean level, in unscaled world coordinates
      A8 - snow line

   Outputs:
      g_red - red component of ground color
      g_grn
      g_blu

   Usage:

void colorfunc ground_col
4 g_red g_grn g_blu groundcolor.cal
0
8 1 1.0 4.561 1.0 28.85 0.7  0.0 250.0

ground_col texfunc ground_tex
4 pertx perty pertz groundtexture.cal
0
6 1 1.0 4.561 1.0 28.85 0.7

ground_tex plastic white
0
0
5 0.8 0.8 0.8  0.0 0.0

}

{ first derivatives }
dx = (-Nx + 
     A2*noise3x(Px/A1,Py/A1,0.0) +
     A4*noise3x(Px/A3,Py/A3,0.0) +
     A6*noise3x(Px/A5,Py/A5,0.0)) / Nz;
dy = (-Ny +
     A2*noise3y(Px/A1,Py/A1,0.0) +
     A4*noise3y(Px/A3,Py/A3,0.0) +
     A6*noise3y(Px/A5,Py/A5,0.0)) / Nz;
slope = abs(dx) + abs(dy);

{ second derivatives }
dxdx = A2/A1*(noise3x(Px/A1-0.1,Py/A1,0.0)-noise3x(Px/A1+0.1,Py/A1,0.0)) +
       A4/A3*(noise3x(Px/A3-0.1,Py/A3,0.0)-noise3x(Px/A3+0.1,Py/A3,0.0)) +
       A6/A5*(noise3x(Px/A5-0.1,Py/A5,0.0)-noise3x(Px/A5+0.1,Py/A5,0.0));
dydy = A2/A1*(noise3y(Px/A1,Py/A1-0.1,0.0)-noise3y(Px/A1,Py/A1+0.1,0.0)) +
       A4/A3*(noise3y(Px/A3,Py/A3-0.1,0.0)-noise3y(Px/A3,Py/A3+0.1,0.0)) +
       A6/A5*(noise3y(Px/A5,Py/A5-0.1,0.0)-noise3y(Px/A5,Py/A5+0.1,0.0));
second = dxdx+dydy;

{ color modifier }
rmod = 0.1*fnoise3(Px*10,Py*10,0.0);

{ water color }
wr = .02;
wg = .2;
wb = .4;

{ lowland color }
lr = .13 + rmod;
lg = .25 + rmod;
lb = .03;

{ highland color }
hr = .25 + rmod;
hg = .35 + rmod;
hb = .15 + rmod;

{ snow brightness }
sb = 0.8;

{ rocky color was 0.15,0.17,0.13}
rr = 0.35 + rmod;
rg = 0.42 + rmod;
rb = 0.28 + rmod;


{ lp1 is neg if water, 0 to 1 if vegetated land, >1 if snow }
lp2 = (Pz-A7)/(A8-A7);
lp1 = lp2*lp2;

lp = noneg(lp1 - second);

{ add something to make areas of high relief (low second
  derivative) appear rocky, what color is rock? light to
  dark gray. That color changes on a large scale, too }
{ this would need to include areas above the snowline }

{ Select water or ground or snow depending on altitude }
g_red = if(slope-6, rr, if(-lp, wr, if(second+2,
          if(lp-1, sb, linterp(lp,lr,hr)), rr)));
g_grn = if(slope-6, rg, if(-lp, wg, if(second+2,
          if(lp-1, sb, linterp(lp,lg,hg)), rg)));
g_blu = if(slope-6, rb, if(-lp, wb, if(second+2,
          if(lp-1, sb, linterp(lp,lb,hb)), rb)));