/*
*
*    Kind of Hot Lava Shader - Dave Hale
*
*    Malcolm Kesson's Renderman 2
*    Last Updated: May 20th, 2008
*
*    Use sub-surface scattering point cloud data to control the incandescance
*    and other various aspects of the shader. Use ambient occlusion point data
*    to drive a dynamic wrinkle displacement for the "cool" crust edges of the lava. 
*    Essentially the lights will be controlling the "temperature" which will translate
*    into which part of the layers it will display.
*
*/
  
surface dh_lava(
            float    bake = 0,            // [ 1 or 0 ] bake toggle 
                    Ks = 0.5,            // specular brightness
                    Kd = 0.5,            // diffuse brightness
                    Ka = 1,                // ambient brightness
                    roughness = 0.1,     // highlight spread
                    
                    ssintensity = 3,    // subsurface influence intensity
                    maskRampIntensity = -10,
                    looks_good = 0;
  
            output varying float
                    magma_turbFreq = 1;    // hot layer's turbulence frequency
            float   magma_turbCrinkle = 12, // crinkle amount
                    magma_turbDepth = 4,
                    magma_turbIntensity = 20, // intensity overdrive
                    
                    crust_turbFreq = 1,    // crust layer's turbulence frequency
                    crust_turbAmp = 1,  // turbulence amplitude
                    crust_turbDepth = 3, // turbulence depth
                    crust_turbMag = 1.2, // turbulence magnitude
  
                    crust_noiseFreq = 7, 
                    crust_noiseAmp = 1,
                    crust_noiseDepth = 4,
                    crust_noiseMag = 1;
                    
            string    filename = "",        // brickmap location
                    displaychannels = "_area,_radiance_t";
            color    diffusecolor    = color (1), 
                    specularcolor    = color (1);
                )
{
  
    //---------------------------------------------
    //                    Magma Layer
    //---------------------------------------------
  
    // initialize some variables
    float     a = area(P, "dicing"),
            magma_turb = 0,
            i;
    normal    Nn = normalize(N),
            Nf;
    color    rad_t = 0,
            ssdiffusion = 0,
            direct;
    vector    V;
    point    PP = transform("object", P);
        
  
    // pre-calculate values needed for color
    direct    = (Ka * ambient()) + (Kd * diffuse(Nn));
    rad_t    = diffusecolor * direct;
    Nf        = faceforward( normalize(N), I );
    V        = -normalize(I);
  
  
    // generate some turbulent noise
    for(i = 0; i < magma_turbDepth; i = i + 1)
    {
        magma_turb = magma_turb + abs(0.5 - noise(magma_turbCrinkle * magma_turbFreq * PP) ) / magma_turbFreq;
        magma_turbFreq *= 1.2;
    }
    magma_turb *= magma_turbIntensity;
  
  
  
    
    
    //---------------------------------------------
    //                Crust Layer
    //---------------------------------------------
  
    // turbulent noise
    float   j, f = crust_turbFreq, crust_turbAmp = 1;
    float    crust_turb = 0, crust_noise = 0;
    point   p = transform("object", P);
  
  
    for(j = 0; j < crust_turbDepth; j += 1)
    {
        crust_turb += abs(noise(p * f) - 0.5) * crust_turbAmp;
        f *= -2;
        crust_turbAmp *= 0.5;
    }
    crust_turb *= crust_turbMag;
  
    // fractal noise
    float g, h = crust_noiseFreq, crust_noiseAmp = 1;  
  
    for(g = 0; g < crust_noiseDepth; g += 1) {
        crust_noise += (noise(p * h) - 0.5) * crust_noiseAmp;
        h *= 2;
        crust_noiseAmp *= 0.5;
    } crust_noise *= crust_noiseMag;
  
  
    //---------------------------------------------
    //                 Composite    
    //---------------------------------------------
    /* if the bake toggle is on, bake it, otherwise, read in the
    specified brickmap to add in, thanks to Chris Wilson */
    if ((filename != "") && (displaychannels != ""))
    {
        if (bake == 1)
            bake3d(filename, displaychannels, P, Nn, "interpolate", 1,
                       "_area", a, "_radiance_t", rad_t);        
        else        
            texture3d(filename, P, N, "_ssdiffusion", ssdiffusion);
    } 
    
    /* Now that we have everything we need for our two color layers
    let's go ahead and calculate them*/
    color    lavaColor = ( ssdiffusion * ssintensity ) * magma_turb;
  
    color    crustColor = ( ( diffusecolor * direct * crust_turb ) +
                            specularcolor * Ks * specular(Nf, V, roughness) );
            
    /* Temporary mixing ramp, until I figure out how to have the sub-surface values
    drives the mask properly  */
    color   maskRamp = mix(color(1), color(maskRampIntensity), ssdiffusion),
            mrHSV = ctransform("rgb", "hsv", maskRamp),
            layeredColor = mix(lavaColor, crustColor, mrHSV[2]);
    
    Ci = layeredColor * Os;    
//    Ci = mrHSV[2];
    Oi = Os;
  
}