/********************************************************************************** Persistence of Vision Ray Tracer Scene Description File File: MH_CloudShell_v2_test.pov Vers: 3.7+ Desc: Media sky based on code by Juha Leppälä (as used originally by Mick Hazelgrove). upgrade by Thomas de Groot. Date: Original 2004; upgraded November 2020 Auth: Mick Hazelgrove + Thomas de Groot **********************************************************************************/ //+w350 +h450 +a0.3 +am2 +bm2 +bs8 +wt10 //+w700 +h900 +a0.3 +am2 +bm2 +bs8 +wt10 #version 3.8; global_settings { assumed_gamma 1.0 } #declare SunColor1 = rgb <0.98, 0.98, 0.95>*5; #declare SunColor2 = rgb <0.98, 0.98, 0.95>*2; //to be used in light_group with clouds #declare SunPosition = <0, 0, -2>*10e4; #declare SunDis = vlength(SunPosition)*2/215; //*1/215 #declare Sun1 = light_source { <0, 0, 0> // light's position (translated below) color SunColor1 // light's color translate SunPosition rotate 30*x rotate -140*y parallel point_at <0, 0, 0> } Sun1 #declare Sun2 = light_source { <0, 0, 0> // light's position (translated below) color SunColor2 // light's color translate SunPosition rotate 30*x rotate -140*y parallel point_at <0, 0, 0> } //Remainder of the scene code at the end of file. //=============================================================================================================== //=============================================================================================================== #debug "Using Mick Hazelgrove's Cloud Shell utility (version 2.0).\n" // ---------------------------------------------------------------------------------- // + Media sky based on code by Juha Leppälä (as used originally by Mick Hazelgrove). // + Three concentric cloud shells and an atmospheric haze. // + Upgraded by Thomas de Groot (2020) // ---------------------------------------------------------------------------------- // [0] Preliminaries: // ----------------- // Here starts the Cloud Shell utility by opening a light_group. light_group { object {Sun2} // Choose which cloud shells you want to use in your scene, top to bottom (on/off): #local hc = on; // [1] High Clouds #local ldc = on; // [2] Low Dark Clouds #local lsdc = on; // [3] Low Scudding Dark Clouds #local ah = on; // [4] Atmospheric Haze // Choose: // 1. whether to show cloud shell dimensions (on/off); // 2. whether to use test samples (on/off); // 3. When Test is 'off', Samp is used, degressively; // 4. Set the Cloud Shells' horizontal radius multiplicator. #local Debug = on; #local Test = off; #local Samp = 150; #local Radius = 10; //-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_- #macro SkyShellCalc(minAlt, maxAlt, Radius) #declare F1 = ((maxAlt*Radius)-(maxAlt-minAlt))/minAlt; #declare F2 = ((maxAlt*Radius)-(maxAlt-minAlt))/(maxAlt*Radius); #if (Debug) #debug concat("\n Scale Factor F1: ",str(F1, 4,3),"\n") #debug concat(" Scale Factor F2: ",str(F2, 4,3),"\n\n") #end #end //of macro //-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_- //================================================================================ // [1] high clouds, the outer shell of clouds: // ------------------------------------------ #if (hc) #declare minAltHC = 995; //Lowest altitude at zenith #declare maxAltHC = 2000; //highest altitude at zenith #declare ScaleHC = <0.5, 1.0, 0.3>; //scales the overall size of the clouds (can be vector); best to keep y-scale at 1.0 #declare RotHC = <90, 30, 10>; //rotates the clouds (can be vector) #declare ClearHor = off; //a cloud free horizon (on/off) SkyShellCalc (minAltHC, maxAltHC, Radius) #local DensityHC1 = density { wrinkles warp {turbulence <0.4, 2.0, 1.0> lambda 3 omega 0.6} //(1) the density value controls the size and crispness/fluffyness of the clouds. //(2) the multiplier controls the density of the clouds. // see also the multiplier used at the scattering media level. color_map { [0.000 rgb 0] [0.530 rgb 0] [0.550 rgb 0.5*0.35] [0.650 rgb 0.8*0.35] [0.800 rgb <0.85, 0.85, 0.90>*0.35] [0.850 rgb 0] } scale ScaleHC scale rotate RotHC.x*x rotate RotHC.z*z rotate RotHC.y*y } #local DensityHC2 = density { cylindrical density_map { [1-F2+0.05 rgb <0.0, 0, 0>] [1-F2+0.05 DensityHC1 scale <1/(maxAltHC*Radius), 1, 1/(maxAltHC*Radius)>] } scale scale 1/10 warp {turbulence <0.8, 0.0, 0.3> lambda 3 omega 0.6} scale 10 } #declare HC = difference { sphere {0.0, maxAltHC scale } sphere {0.0, minAltHC scale } plane {y, 0.01} pigment {rgbt <1,1,1, 1>} hollow interior { media { #if (Test) samples 25 #else samples Samp #end intervals 1 //absorption darkens the clouds; use with care or comment out. absorption rgb <0.30, 0.30, 0.30>*0.0010 //cloud colour; the multiplier controls darkness of the cloud base (smaller is lighter). scattering {1, rgb <0.95, 0.90, 0.85>*0.009} density { #if (ClearHor) DensityHC2 #else DensityHC1 #end } //density } //media } //interior } //difference #end //of hc //================================================================================ // [2] low, dark cloud, cloud shell just below the preceding one: // ------------------------------------------------------------- #if (ldc) #declare minAltLDC = 510; //Lowest altitude at zenith #declare maxAltLDC = 951; //highest altitude at zenith #declare ScaleLDC = <0.1, 1.0, 0.1>; //scales the overall size of the clouds (can be vector); best to keep y-scale at 1.0 #declare RotLDC = <90, -20, 0>; //rotates the clouds (can be vector) #declare ClearHor = off; //a cloud free horizon (on/off) SkyShellCalc (minAltLDC, maxAltLDC, Radius) #local DensityLDC1 = density { wrinkles warp {turbulence 0.5 lambda 2.3 omega 0.475} frequency 1 //(1) the density value controls the size and crispness/fluffyness of the clouds. //(2) the multiplier controls the density of the clouds. // see also the multiplier used at the scattering media level. color_map { [0.000 rgb 0] [0.550 rgb 0] [0.650 rgb 0.75*0.35] [0.950 rgb 1.5*0.35] [1.000 rgb <1.0, 1.0, 0.7>] } scale ScaleLDC scale rotate RotLDC.x*x rotate RotLDC.z*z rotate RotLDC.y*y } //density #local DensityLDC2 = density { cylindrical density_map { [1-F2+0.05 rgb <0.0, 0, 0>] [1-F2+0.05 DensityLDC1 scale <1/(maxAltLDC*Radius), 1, 1/(maxAltLDC*Radius)>] } scale scale 1/10 warp {turbulence <0.8, 0.0, 0.3> lambda 3 omega 0.6} scale 10 } #declare LDC = difference { sphere {0.0, maxAltLDC scale } sphere {0.0, minAltLDC scale } plane {y, 0.01} pigment {rgbt <1,1,1, 1>} hollow interior { media { #if (Test) samples 25 #else samples Samp/2 #end intervals 1 //absorption darkens the clouds; use with care or comment out. absorption rgb <0.30, 0.30, 0.30>*0.010 //cloud colour; the multiplier controls darkness of the cloud base (smaller is lighter). scattering {1, rgb <0.95, 0.90, 0.85>*0.0035} density { #if (ClearHor) DensityLDC2 #else DensityLDC1 #end } //density } //media } //int } //difference #end //of ldc //================================================================================ // [3] low scudding, dark clouds, the lowest cloud shell: // ----------------------------------------------------- #if (lsdc) #declare minAltLSDC = 280; //Lowest altitude at zenith #declare maxAltLSDC = 400; //highest altitude at zenith #declare ScaleLSDC = <0.25, 1.0, 0.08>; //scales the overall size of the clouds (can be vector); best to keep y-scale at 1.0 #declare RotLSDC = <0, -43, 0>; //rotates the clouds (can be vector) #declare ClearHor = off; //a cloud free horizon (on/off) SkyShellCalc (minAltLSDC, maxAltLSDC, Radius) #local DensityLSDC1 = density { wrinkles warp {turbulence 0.5 lambda 2.3 omega 0.475} //(1) the density value controls the size and crispness/fluffyness of the clouds. //(2) the multiplier controls the density of the clouds. // see also the multiplier used at the scattering media level. color_map { [0.00 rgb 0] [0.65 rgb 0] [0.75 rgb 0.75/3] [0.95 rgb 1.5/3] [1.00 rgb <1.0, 1.0, 0.7>] } scale ScaleLSDC scale rotate RotLSDC.x*x rotate RotLSDC.z*z rotate RotLSDC.y*y } //density #local DensityLSDC2 = density { cylindrical density_map { [1-F2+0.05 rgb <0.0, 0, 0>] [1-F2+0.05 DensityLSDC1 scale <1/(maxAltLSDC*Radius), 1, 1/(maxAltLSDC*Radius)>] } scale scale 1/10 warp {turbulence <0.8, 0.0, 0.3> lambda 3 omega 0.6} scale 10 } #declare LSDC = difference { sphere {0.0, maxAltLSDC scale } sphere {0.0, minAltLSDC scale } plane {y, 0.01} pigment {rgbt <1,1,1, 1>} hollow interior { media { #if (Test) samples 25 #else samples Samp/3 #end intervals 1 //absorption darkens the clouds; use with care or comment out. //absorption rgb <0.30, 0.30, 0.30>*0.010 //cloud colour; the multiplier controls darkness of the cloud base (smaller is lighter). scattering {1, rgb <0.95, 0.90, 0.85>*0.05} density { #if (ClearHor) DensityLSDC2 #else DensityLSDC1 #end } //density } //media } //int } //difference #end //of lsdc //================================================================================ // [4] Atmospheric haze below the clouds: // ------------------------------------- #if (ah) #declare minAltAH = 0.0; //Lowest altitude at zenith #declare maxAltAH = 100; //highest altitude at zenith #declare AH = difference { sphere {minAltAH, maxAltAH} plane {y, 0.0} pigment {rgbt 1} scale hollow interior { media { #if (Test) samples 25 #else samples Samp/2.5 #end intervals 1 //haze colour; the multiplier controls the density of the haze (smaller is more transparant) scattering {5, rgb <0.90, 0.90, 0.95>*0.00001 eccentricity 0.4 } density { spherical color_map { [0.00 rgb 0.1] [1.00 rgb 1.0] } scale *maxAltAH } //density } //media } //int } //difference #end //of ah //================================================================================ union { #if (Debug) #debug "\n Extensions of the cloud shells:\n" #end #if (hc) object {HC} //---------------------------------------- #if (Debug) #local MinHC = min_extent(HC); #local MaxHC = max_extent(HC); #debug concat("\n max_extent high clouds shell: ",vstr(3, MaxHC, ", ", 3, 3),"\n") #debug concat(" min_extent high clouds shell: ",vstr(3, MinHC, ", ", 3, 3),"\n") #debug concat(" min_extent high clouds level: ",str(minAltHC, 4,3)," at zenith\n") #end //---------------------------------------- #end #if (ldc) object {LDC} //---------------------------------------- #if (Debug) #local MinLDC = min_extent(LDC); #local MaxLDC = max_extent(LDC); #debug concat("\n max_extent low, dark clouds shell: ",vstr(3, MaxLDC, ", ", 3, 3),"\n") #debug concat(" min_extent low, dark clouds shell: ",vstr(3, MinLDC, ", ", 3, 3),"\n") #debug concat(" min_extent low, dark clouds level: ",str(minAltLDC, 4,3)," at zenith\n") #end //---------------------------------------- #end #if (lsdc) object {LSDC} //---------------------------------------- #if (Debug) #local MinLSDC = min_extent(LSDC); #local MaxLSDC = max_extent(LSDC); #debug concat("\n max_extent low, scudding clouds shell: ",vstr(3, MaxLSDC, ", ", 3, 3),"\n") #debug concat(" min_extent low, scudding clouds shell: ",vstr(3, MinLSDC, ", ", 3, 3),"\n") #debug concat(" min_extent low, scudding clouds level: ",str(minAltLSDC, 4,3)," at zenith\n") #end //---------------------------------------- #end #if(ah) object {AH} //---------------------------------------- #if (Debug) #local MinAH = min_extent(AH); #local MaxAH = max_extent(AH); #debug concat("\n max_extent atmospheric haze shell: ",vstr(3, MaxAH, ", ", 3, 3),"\n") #debug concat(" min_extent atmospheric haze shell: ",vstr(3, MinAH, ", ", 3, 3),"\n") #end //---------------------------------------- #end //translate the cloudshells to an appropriate location; e.g.: //translate } //union of cloud shells } //light_group //=============================================================================================================== //=============================================================================================================== global_settings { radiosity { pretrace_start 0.08 pretrace_end 0.04 count 50, 1000 nearest_count 10, 5 error_bound 1 recursion_limit 1 low_error_factor .3 gray_threshold 0.0 minimum_reuse 0.015 maximum_reuse 0.1 brightness 0.8 adc_bailout 0.01/2 normal off media off always_sample off //max_sample 1.0 } } //--------------------------------------------------------------------------------- //transformation functions by Ive: //from scRGB (linear color space) -> sRGB: #declare sRGB_Gamma = function(C) { select(C-0.0031308, C*12.92 , 1.055*pow(C,1/2.4)-0.055) } #macro scRGB_to_sRGB(Color) rgb #end //--------------------------------------------------------------------------------- //Colour saturation variation code by Clipka. //[povray.advanced-users 15-07-2016: Reverse engineering pigments and textures by BaldEagle]: #macro ColourSat(SatBoost, BrightBoost, Raw) #declare SB = SatBoost; // Saturation boost #declare VB = BrightBoost; // Brightness ("volume") boost #declare RawColour = srgb Raw; #declare SatColour = RawColour-SB; #declare MyColour = SatColour*(1+VB)*RawColour.gray/SatColour.gray; MyColour #end //--------------------------------------------------------------------------------- //Saturation and Brightness values for Clipka's saturation macro: #declare SatBoost = 0.01; #declare BrightBoost = -0.01; //0 = no brightness change; >0 = brighter; <0 = darker #local skyColor1 = <153, 178, 255>/255; #local skyColor2 = < 0, 45, 204>/255; //--------------------------------------------------------------------------------- // a sky sphere sphere { <0, 0, 0>, 1 pigment { gradient y color_map { [0.0 ColourSat(SatBoost, BrightBoost, scRGB_to_sRGB(skyColor1))] [0.7 ColourSat(SatBoost, BrightBoost, scRGB_to_sRGB(skyColor2))] } } finish {emission 1 diffuse 0} scale 5*10e4 inverse } //--------------------------------------------------------------------------------- camera { location <0, 2, -20> sky y up y direction z right x*image_width/image_height angle 50 look_at <0, 10, 0> } //--------------------------------------------------------------------------------- plane {y, 0.001 pigment {srgb 0.5} normal {granite 0.1 scale 0.001}} cylinder {<0,0,0>,<0,5,0>, 0.25 pigment {srgb <1,0,0>} normal {granite 1 scale 0.001} translate 10*z}