/*==================================================================================================
 This work is licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License.
 To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/3.0/ or send a
 letter to Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA.

 Persistence of Vision Ray Tracer Scene Description File
 File: DakotaRedGranite.mcr [beta #1.2]
 Vers: 3.7+
 Desc: Macro for the Dakota Red Granite, based on the original code (MahoganyPol & MahoganyFro) by
       Daniel Mecklenburg Jr. from 1996.
       
       Usage of the macro can be found at end of this file!
       
 Date: 21 May 2021
 Auth: Thomas de Groot

====================================================================================================*/
// These are the parameters controlling the macro. Copy and use in your own scene

// Required parameters:
//#declare CSC   = 2;    //1 = 'raw' sRGB; 2 = sRGB conversion; every other value is rgb
//#declare Pol   = off;  //on = polished; off = frosted
//#declare Typ   = 1;    //1 = no veins; 2 = veins    [2 = still EXPERIMENTAL]
//#declare Pat1  = 2;    //stone pattern: 1 = cells; 2 = step noise; 3 = crackle solid
//#declare Pat2  = 3;    //pigment_pattern: 1 = cells mask; 2 = step noise mask; 3 = crackle solid mask
//#declare Blend = off;   //on = the granite pattern is blended/blurred (weathering); off = the pattern is 'fresh'

// Optional parameters:
//#declare SN_Start = 0.2;    //Step Noise range 0.0 to 1.0, =< SN_End! [default: 0.2]
//#declare SN_End   = 0.8;    //Step Noise range 0.0 to 1.0, >= SN_Start! [default: 0.8]
//#declare SN_Turb  = 0.325;  //Step Noise turbulence [default: 0.325]
//#declare BC_Blur  = 2;      //Blended Cells blurriness [default: 2]

// Optional transforms for the material:
//#declare M_scale = <1.0, 1.0, 1.0>; //be careful with the scaling of the material!
//#declare M_rotat = <0.0, 0.0, 0.0>;
//#declare M_trans = <0.0, 0.0, 0.0>;

// Experimental parameters:
//#declare SS         = off;  //subsurface translucency
//#local Translucency = <0.350, 0.287, 0.260>*5;  //this is an experimental choice
// example code to be copied and changed, to the global_settings of your scene file:
/*  #if (SS)
    //mm_per_unit 50
    subsurface {
      radiosity off
      //samples 100, 40
    }
*/

/*====================================================================================================*/
/*== (0) =============================================================================================*/
// Start of the Dakota Red Granite macro declaration and additional necessary presets

#macro DakotaRedGranite (CSC, Pol, Typ, Pat1, Pat2, Blend, SS)

/*---------------------------------------- Presets -------------------------------------------------*/

#ifndef (_FUNCTIONS_INC)	#include "functions.inc"	 #end

/*----------------------------------------------------------------------------------------------------
  By Bald Eagle: No values in the (s)rgb triplets should ever be zero. First, because there are almost
  never absolutely black objects in real life ("vanta black"); Second, because there is no way to
  modify it with a multiplier. If you had a red value of one millionth, you could multiply that by a
  million to get 1. But anything multiplied by zero is always zero.
----------------------------------------------------------------------------------------------------*/
#local not_0 = 1/265;

/*----------------------------------------------------------------------------------------------------
  By Bald Eagle: Step Noise pattern; with SN_Start and SN_End of the Smoothstep function set both to 
  the same value (0-1) corresponds to the cells pattern; with SN_Start = 0, SN_End = 1 comes as close 
  as this can get to f_noise3d()
----------------------------------------------------------------------------------------------------*/
#ifndef (SN_Start) #local SN_Start = 0.2; #end
#ifndef (SN_End)   #local SN_End   = 0.8; #end
#ifndef (SN_Turb)  #local SN_Turb  = 0.325; #end

// smoothstep function
#local SN_K = function (t1, t2, T) {max (0, min(1, (T-t1)/(t2-t1) ) )}
#local SN_Smoothstep = function (t1, t2, T) {pow (SN_K(t1, t2, T), 2) * (3-2*SN_K(t1, t2, T))}

// mod function that plays nice when crossing 0
#local SN_Mod = function (T) {select (T,  1-mod (abs(T), 1),  mod (abs(T), 1) )}

// smoothstep function
//#local SN_N = function (NN) {floor (NN-0.5) + Smoothstep (SN_Start, SN_End, abs(SN_Mod(NN-0.5)-0.5) )}
#local SN_N = function (NN) {floor (NN) + SN_Smoothstep (SN_Start, SN_End, SN_Mod(NN) )}

/* usage:
#declare StepNoise =
pigment {
  function {f_noise3d (SN_N(x), SN_N(y), SN_N(z))}
  turbulence SN_Turb
}
*/ 

/*----------------------------------------------------------------------------------------------------
  Color Space conversion - A combination of two macros:
  1. Transformation functions from scRGB (linear color space) -> sRGB;
  2. Colour saturation/brightness variation code by Clipka.
     [povray.advanced-users 15-07-2016: Reverse engineering pigments and textures by BaldEagle]
----------------------------------------------------------------------------------------------------*/
//Default Saturation and Brightness values for Clipka's saturation macro:
#ifndef (SatBoost) #declare SatBoost = 0.01; #end
#ifndef (BrightBoost) #declare BrightBoost = -0.1; #end //0 = no brightness change; >0 = brighter; <0 = darker

#macro Convert(CSC, SatBoost, BrightBoost, Color)
  #switch (CSC)
  #case (1)
    #local MyColour = srgb Color;

  #break
  #case (2)
    #local sRGB_Gamma = function(C) {select(C-0.0031308, C*12.92, 1.055*pow(C, 1/2.4)-0.055)}

    #local SB         = SatBoost; // Saturation boost
    #local VB         = BrightBoost; // Brightness ("volume") boost
    #local RawColour  = srgb <sRGB_Gamma(Color.red), sRGB_Gamma(Color.green), sRGB_Gamma(Color.blue)>;
    #local SatColour  = RawColour-SB;
    #local MyColour   = SatColour*(1+VB)*RawColour.gray/SatColour.gray;

  #break
  #else
    #local MyColour = rgb Color;
  #end

  MyColour
#end

/*----------------------------------------------------------------------------------------------------
  By Ive: the 0.5 value for Granite_Specular_strength is just my personal preference and taste because 
  people in the old times did have a tendency to overuse these faked specular highlights way too much 
  making everything look like plastic. 
----------------------------------------------------------------------------------------------------*/
#declare Granite_Specular_strength = 0.5; 
#declare Granite_Reflection_strength = 0.15;

//Two little macros to be applied to the frosted version of the granite:
//A small amount of highlights for realism
#macro Dull_Highlights() 
  specular 0.05
  roughness 0.1         
#end  

//A replacement for the crand in the finish block of the original texture
#macro Crand(Intensity)
  texture {
    pigment {
      granite  
      color_map {
        [1/3 rgb 0.001 transmit 1]
        [2/3 rgb 0.001 transmit max(0,1-Intensity) ]
      }    
      scale 0.05 
    }
  }
#end  

/*----------------------------------------------------------------------------------------------------
  By Tekno Frannansa (23-2-2007): Blended Cells. Offset the unit squares pattern (done in a macro in 
  case I want cells picking patterns). Somehow, cells don't quite line up with the blend gradient, 
  but an addition of .001 completely fixes it!!!
----------------------------------------------------------------------------------------------------*/
#macro mycells(Pat1, Offset)
  #if (Pat1 = 1)
    P_DakotaRed
  #elseif (Pat1 = 2)
	  P_DakotaRed_SN
	#elseif (Pat1 = 3)
	  P_DakotaRed_crackle
	#else
	#debug "\nAttention! Pat1 should be 1, 2 or 3! 3 is used instead.\n"
	  P_DakotaRed_crackle
	#end
	translate Offset + .001
#end

//blur the pattern
#ifndef (BC_Blur) #local BC_Blur = 2; #end

#macro blend(V)
	pigment_pattern {
		//gradient controlling the blend
		gradient V
		//phase .001

		//mess with this colour map to reduce blend region		
		colour_map {
			[0.5-BC_Blur/2 rgb 0]
			[0.5+BC_Blur/2 rgb 1]
		}
	}
	cubic_wave
#end

/*== (1) =============================================================================================*/
// The colour_maps of the Dakota Red Granite

#declare A_DakotaRed_map1 =
array [18][4] {
  {0.00, not_0, not_0, not_0},
  {0.25, 0.059, 0.059, 0.059},

  {0.25, 0.086, 0.027, 0.059},
  {0.35, 0.086, 0.027, 0.059},

  {0.35, 0.118, 0.118, 0.078},
  {0.45, 0.118, 0.118, 0.078},

  {0.45, 0.200, 0.137, 0.110},
  {0.50, 0.150, 0.087, 0.060},
  {0.57, 0.200, 0.137, 0.110},

  {0.57, 0.400, 0.337, 0.310},
  {0.60, 0.350, 0.287, 0.260},
  {0.63, 0.400, 0.337, 0.310},

  {0.63, 0.769, 0.329, 0.298},
  {0.70, 0.669, 0.229, 0.198},
  {0.75, 0.769, 0.329, 0.298},

  {0.75, 0.600, 0.600, 0.600},
  {0.85, 0.550, 0.550, 0.550},
  {1.00, 0.650, 0.650, 0.650}
}


#local C_DakotaRed_map1 = //the granite colour_map proper
color_map {
  #if (version >= 3.8)
    blend_mode 2
  #end

  #for (J, 0, 17, 1)
    #local Entry = Convert (CSC, SatBoost, BrightBoost, <A_DakotaRed_map1[J][1], A_DakotaRed_map1[J][2], A_DakotaRed_map1[J][3]>);
    [A_DakotaRed_map1[J][0] Entry]
  #end 
}

#local A_DakotaRed_map2 =
array [5][5] {
  {0.000, 0.800, 0.800, 0.800, 0.150},
  {0.005, 0.800, 0.800, 0.800, 0.000},
  {0.010, 0.800, 0.800, 0.800, 0.150},
  {0.011, 1.000, 1.000, 1.000, 1.000},
  {1.000, 1.000, 1.000, 1.000, 1.000}
}

#local C_DakotaRed_map2 = //quartz vein colour_map
color_map {
  #if (version >= 3.8)
    blend_mode 2
  #end
  
  #for (J, 0, 4, 1)
    #local Entry = Convert (CSC, SatBoost, BrightBoost, <A_DakotaRed_map2[J][1], A_DakotaRed_map2[J][2], A_DakotaRed_map2[J][3]>);
    [A_DakotaRed_map2[J][0] Entry transmit A_DakotaRed_map2[J][4]]
  #end 
}

/*== (2) =============================================================================================*/
// The different masks used as pigment_pattern for the Dakota Red Granite

#local A_DakotaRed_mask_map = 
array [14][4] {
  {0.00, not_0, not_0, not_0},
  {0.25, 0.000, 0.000, 0.000},

  {0.25, 0.100, 0.100, 0.100},
  {0.35, 0.100, 0.100, 0.100},

  {0.35, 0.250, 0.250, 0.250},
  {0.45, 0.250, 0.250, 0.250},

  {0.45, 0.500, 0.500, 0.500},
  {0.57, 0.500, 0.500, 0.500},

  {0.57, 0.600, 0.600, 0.600},
  {0.63, 0.600, 0.600, 0.600},

  {0.63, 0.700, 0.700, 0.700},
  {0.75, 0.700, 0.700, 0.700},

  {0.75, 0.900, 0.900, 0.900},
  {1.00, 0.900, 0.900, 0.900},
}

#local C_DakotaRed_mask_map = //the mask based on the granite colour_map proper
color_map {
  #if (version >= 3.8)
    blend_mode 2
  #end

  #for (J, 0, 4, 1)
    #local Entry = rgb <A_DakotaRed_mask_map[J][1], A_DakotaRed_mask_map[J][2], A_DakotaRed_mask_map[J][3]>;
    [A_DakotaRed_mask_map[J][0] Entry]
  #end 
}

#local P_DakotaRed_mask =  //mask to distribute large and small minerals using cells
pigment {
  cells warp {turbulence 0.425} //(0.325 is too low)
  color_map {C_DakotaRed_mask_map}
  warp {turbulence 0.1} //some extra turbulence for the mask
  scale 0.075
}

#local P_DakotaRed_mask_SN =  //mask to distribute large and small minerals using step noise
pigment {
	function {f_noise3d (SN_N(x), SN_N(y), SN_N(z))} 
	warp {turbulence SN_Turb octaves 2 lambda 1 omega 2}
  color_map {C_DakotaRed_mask_map}
  //warp {turbulence 0.1} //some extra turbulence for the mask
  scale 0.075
}

#local CrackleMask =
pigment {
  crackle solid
  turbulence 0.1
  lambda 2.5
  omega 0.75
  octaves 5
  scale 0.75
  frequency 1
  phase 0.25
  rotate <0, 45, 60>
  color_map { 
    [0.00 rgb <1.00, 1.00, 1.00> ]
    [0.05 rgb <0.10, 0.10, 0.10> ]
    [0.10 rgb <0.90, 0.90, 0.90> ]
    [0.15 rgb <0.20, 0.20, 0.20> ]
    [0.20 rgb <0.80, 0.80, 0.80> ]
    [0.25 rgb <0.30, 0.30, 0.30> ]
    [0.30 rgb <0.70, 0.70, 0.70> ]
    [0.35 rgb <0.40, 0.40, 0.40> ]
    [0.40 rgb <0.60, 0.60, 0.60> ]
    [0.45 rgb <0.50, 0.50, 0.50> ]
    [0.50 rgb <0.50, 0.50, 0.50> ]
    [0.55 rgb <0.60, 0.60, 0.60> ]
    [0.60 rgb <0.40, 0.40, 0.40> ]
    [0.65 rgb <0.70, 0.70, 0.70> ]
    [0.70 rgb <0.30, 0.30, 0.30> ]
    [0.75 rgb <0.80, 0.80, 0.80> ]
    [0.80 rgb <0.20, 0.20, 0.20> ]
    [0.85 rgb <0.90, 0.90, 0.90> ]
    [0.90 rgb <0.10, 0.10, 0.10> ]
    [0.95 rgb <1.00, 1.00, 1.00> ]
    [1.00 rgb <1.00, 1.00, 1.00> ]
  }
}

/*== (3) =============================================================================================*/
// The pigments for the Dakota Red Granite

#local P_DakotaRed = //basic granite pigment using the cells pattern
pigment {
  cells warp {turbulence 0.425} //(0.325 is too low)
  color_map {C_DakotaRed_map1}
  scale 0.1
}

#local P_DakotaRed_SN = //basic granite pigment using the step noise pattern
pigment {
	function {f_noise3d (SN_N(x), SN_N(y), SN_N(z))} 
	warp {turbulence SN_Turb octaves 2 lambda 1 omega 2}
  color_map {C_DakotaRed_map1}
  scale 0.1
}

#local P_DakotaRed_crackle = //basic granite pigment using the crackle solid pattern
pigment {
  pigment_pattern {CrackleMask scale 0.75}
  color_map {C_DakotaRed_map1}
  scale 0.1
}

#local P_DakotaRed_blend = //basic granite pigment using blended cells pattern
pigment {
	blend(x)
	pigment_map {
	  [0
			blend(y)
			pigment_map {
				[0
					blend(z)
					pigment_map {
						[0 mycells(Pat1,<1,1,1>)]
						[1 mycells(Pat1,<1,1,0>)]
					}
				]
				[1
					blend(z)
					pigment_map {
						[0 mycells(Pat1,<1,0,1>)]
						[1 mycells(Pat1,<1,0,0>)]
					}
				]
			}
		]
		[1
			blend(y)
			pigment_map {
				[0
					blend(z)
					pigment_map {
						[0 mycells(Pat1,<0,1,1>)]
						[1 mycells(Pat1,<0,1,0>)]
					}
				]
				[1
					blend(z)
					pigment_map {
						[0 mycells(Pat1,<0,0,1>)]
						[1 mycells(Pat1,<0,0,0>)]
					}
				]
			}
		]
	}
}
	
/*== (4) =============================================================================================*/
// The pigment for the veins crossing the Dakota Red Granite  [EXPERIMENTAL!]

#local P_DakotaRed_veins = //quartz veins through the granite
pigment {
  marble
  frequency 0.25
  color_map {C_DakotaRed_map2}
  scale <0.15, 1.0, 1.0>
  warp {turbulence <0.35, 0.05, 0.30>}
  translate <20.0, 20.0, 33.0>
  rotate <0.3, 0.2, -25.0>
}

/*== (5) =============================================================================================*/
// Texture code - Polished or Frosted Dakota Red Granite

#if (Pol)
  #local T1_DakotaRedPol =
  texture {
#else
  #local T1_DakotaRedFro =
  texture {
#end

    pigment {
      #if (Pat2 = 1)
        pigment_pattern {P_DakotaRed_mask scale 0.3}
      #elseif (Pat2 = 2)
        pigment_pattern {P_DakotaRed_mask_SN scale 0.3}
      #elseif (Pat2 = 3)
        pigment_pattern {CrackleMask scale 0.3}
      #else
        #debug "\nAttention! Pat2 should be 1, 2 or 3! 3 is used instead.\n"
        pigment_pattern {CrackleMask scale 0.3}
      #end
      pigment_map {
        #if (Blend)
          [0.20 P_DakotaRed_blend scale 0.15]
          [0.25 P_DakotaRed_blend scale 0.18]
          [0.35 P_DakotaRed_blend scale 0.18]
          [0.40 P_DakotaRed_blend scale 0.15]
          [0.60 P_DakotaRed_blend scale 0.15]
          [0.65 P_DakotaRed_blend scale 0.18]
          [0.75 P_DakotaRed_blend scale 0.18]
          [0.80 P_DakotaRed_blend scale 0.15]
        #else
          #if (Pat1 = 1)
            [0.20 P_DakotaRed scale 0.15]
            [0.25 P_DakotaRed scale 0.18]
            [0.35 P_DakotaRed scale 0.18]
            [0.40 P_DakotaRed scale 0.15]
            [0.60 P_DakotaRed scale 0.15]
            [0.65 P_DakotaRed scale 0.18]
            [0.75 P_DakotaRed scale 0.18]
            [0.80 P_DakotaRed scale 0.15]
          #elseif (Pat1 = 2)
            [0.20 P_DakotaRed_SN scale 0.15]
            [0.25 P_DakotaRed_SN scale 0.18]
            [0.35 P_DakotaRed_SN scale 0.18]
            [0.40 P_DakotaRed_SN scale 0.15]
            [0.60 P_DakotaRed_SN scale 0.15]
            [0.65 P_DakotaRed_SN scale 0.18]
            [0.75 P_DakotaRed_SN scale 0.18]
            [0.80 P_DakotaRed_SN scale 0.15]
          #elseif (Pat1 = 3)
            [0.20 P_DakotaRed_crackle scale 0.15]
            [0.25 P_DakotaRed_crackle scale 0.18]
            [0.35 P_DakotaRed_crackle scale 0.18]
            [0.40 P_DakotaRed_crackle scale 0.15]
            [0.60 P_DakotaRed_crackle scale 0.15]
            [0.65 P_DakotaRed_crackle scale 0.18]
            [0.75 P_DakotaRed_crackle scale 0.18]
            [0.80 P_DakotaRed_crackle scale 0.15]
          #else
            #debug "\nAttention! Pat1 should be 1, 2 or 3! 3 is used instead.\n"
            [0.20 P_DakotaRed_crackle scale 0.15]
            [0.25 P_DakotaRed_crackle scale 0.18]
            [0.35 P_DakotaRed_crackle scale 0.18]
            [0.40 P_DakotaRed_crackle scale 0.15]
            [0.60 P_DakotaRed_crackle scale 0.15]
            [0.65 P_DakotaRed_crackle scale 0.18]
            [0.75 P_DakotaRed_crackle scale 0.18]
            [0.80 P_DakotaRed_crackle scale 0.15]
          #end
        #end
      }
    } //pigment

    #if (Pol) //polished
      #if (Typ=1)
        finish {
          diffuse albedo 0.6 brilliance 1.5
          specular albedo 0.9*Granite_Specular_strength roughness 0.0025  //roughness 0.005 = less proeminent
          fresnel on
          #if (SS)
            subsurface {translucency Translucency}
          #end
          reflection {0 Granite_Reflection_strength fresnel on}
          conserve_energy
        }
      #else
        finish {
          diffuse albedo 0.6 brilliance 1.5
        }
      #end
    #else //frosted
      normal {
        #if (Pat2 = 1)
          pigment_pattern {P_DakotaRed_mask scale 0.3}
        #elseif (Pat2 = 2)
          pigment_pattern {P_DakotaRed_mask_SN scale 0.3}
        #elseif (Pat2 = 3)
          pigment_pattern {CrackleMask scale 0.3}
        #else
          #debug "\nAttention! Pat2 should be 1, 2 or 3! 3 is used instead.\n"
          pigment_pattern {CrackleMask scale 0.3}
        #end
        normal_map {
          [0.20 granite 0.50 scale 0.15]
          [0.25 granite 1.00 scale 0.18]
          [0.35 granite 1.00 scale 0.18]
          [0.40 granite 0.50 scale 0.15]
          [0.50 granite 1.00 scale 0.15]
          [0.60 granite 0.50 scale 0.15]
          [0.65 granite 1.00 scale 0.18]
          [0.75 granite 1.00 scale 0.18]
          [0.80 granite 0.50 scale 0.15]
        }
      } //normal
      #if (Typ=1)
        finish {
          diffuse albedo 0.6 brilliance 1.5
          Dull_Highlights()
          #if (SS)
            subsurface {translucency Translucency}
          #end
        }
      #else
        finish {
          diffuse albedo 0.6 brilliance 1.5
        }
      #end
    #end  //Pol
  } //texture T1

#if (Typ=2)
  #if (Pol) //polished
    #local T2_DakotaRedPol =
    texture {
      pigment {P_DakotaRed_veins}
      finish {
        diffuse albedo 0.6 brilliance 1.5
        specular albedo 0.9*Granite_Specular_strength roughness 0.0025  //roughness 0.005 = less proeminent
        fresnel on
        #if (SS)
          subsurface {translucency Translucency}
        #end
        reflection {0 Granite_Reflection_strength fresnel on} 
        conserve_energy
      }
    } //texture T2 polished
  #else //frosted
    #local T2_DakotaRedFro =
    texture {
      pigment {P_DakotaRed_veins}
      finish {
        diffuse albedo 0.6 brilliance 1.5
        Dull_Highlights()
        #if (SS)
          subsurface {translucency Translucency}
        #end
      }
      normal {
        pigment_pattern {P_DakotaRed_veins}
        normal_map {
          [0.50 granite 0.25 scale 0.4]
          [0.50 granite 0.00 scale 0.4]
        }
      }
    } //texture T2 frosted
  #end  //Pol
#end  //Typ

/*== (6) =============================================================================================*/
// material code - Polished or Frosted Dakota Red Granite

#ifndef (M_scale)  #local M_scale = <1.0, 1.0, 1.0>;  #end
#ifndef (M_rotat)  #local M_rotat = <0.0, 0.0, 0.0>;  #end
#ifndef (M_trans)  #local M_trans = <0.0, 0.0, 0.0>;  #end

#declare M_DakotaRed =
material {
  interior {ior 1.6}
  #if (Pol) //polished
    #if (Typ=1)
      texture {T1_DakotaRedPol}
    #else
      texture {T1_DakotaRedPol}
      texture {T2_DakotaRedPol}
    #end  //Typ
  #else //frosted
    #if (Typ=1)
      texture {T1_DakotaRedFro}
      Crand(0.25)
    #else  
      texture {T1_DakotaRedFro}
      texture {T2_DakotaRedFro}
      Crand(0.25)
    #end  //Typ
  #end  //Pol
  scale M_scale
  rotate M_rotat
  translate M_trans
} //material

M_DakotaRed

/*== (7) =============================================================================================*/
#end  //Dakota Red Granite macro

/*== (8) =============================================================================================*/
// Application to an object
/*
union {
  ovus {1.00, 0.65 
    scale 0.5
    translate <0, 0.45, 0> 
  }
  superellipsoid { <0.1, 0.1>
    scale 0.5
    translate -0.5*y
  }
  
  material { DakotaRedGranite (CSC, Pol, Typ, Pat1, Pat2, Blend, SS) }
  
  //transforms for the object here
}
*/

/*===============================================================================================*/