// Persistence of Vision Ray Tracer Scene Description File // File: warp_shaded_clouds.pov // Vers: MegaPov 0.5a // Desc: An Excercise in simulated light-sourcing of clouds using a black hole warp to displace shadows. // Date: Aug. 1, 2000 // Auth: Abe Madey (bullfrog@taconic.net) // Comments: This method seems fairly robust given the recognition of several limiting factors. // One limitation is the distortion of the displacement at low sun angles. I think this has to do with // the curved cloud plane. The other limitation is the degree of shadow displacement. Technically this // should be limited by the highest frequency feature in the cloud pattern (ie .5*1/f). Realistically // you can get away with alot more in most cases. // // Conventions: For sun and camera, z is the initial direction. Both are controlled by azimuth (horizontal) // and pitch or height (vertical) in degrees. //****************************** // VARIABLES //****************************** // ----------CAMERA #declare cam_loc=<0, .1, 0>; #declare cam_az=20; #declare cam_pitch=5; #declare cam_ang=50; // ----------SUN #declare sun_az = 25; #declare sun_ht=20; #declare sun_dist = 10000; #declare sun_corona_size = .5; #declare sun_col= <0.98047, 0.89844, 0.74609>; #declare sun_col = <1,.85, .5>; // ----------CLOUDS #declare cloud_height = 2 #declare cloud_scale = 5; #declare cloud_cover = .5; #declare shadow_displacement = .02; // ----------HEADERS #version unofficial MegaPov 0.5; #global_settings{max_trace_level 15} // convert sun angles to radians #declare sun_raz = radians(sun_az); // The following is used to clamp the sun_ht for calculating the warp center at low sun angles. // Adjust this if the shadow displacement gets out of hand at low sun elevations. #if(sun_ht<4) #declare sun_rht=radians(4); #else #declare sun_rht = radians(sun_ht); #end #declare light_dir = -cam_loc; #debug concat("light_dir = <", str(light_dir.x,0,2),", ",str(light_dir.y,0,2),", ",str(light_dir.z,0,2),">\n") //This is a multiplier for the sun changing the sun color as it nears the horizon. Twiddle this to //get the reddening effect at higher or lower sun elevations. #declare ht_factor=max((1-(5*sun_ht/90))^1.5,0); #debug concat(" ht_factor = ", str(ht_factor,0,5)) // -------- SUN CODE light_source{z*sun_dist, color rgb 1.5*(sun_col*ht_factor+(1-ht_factor))rotate -x*sun_ht rotate y*sun_az} //sun disc and corona. Very basic. I actuall have a better implementation of this in another excercise. disc{ 0, z, 1 no_shadow pigment {spherical color_map{[0 rgbt 1][.9 rgb (2*sun_col*ht_factor+(1-ht_factor)*1.0)][.95 rgb 7]} poly_wave 2} finish{ambient 1} scale sun_dist*sun_corona_size translate z*sun_dist rotate -x*sun_ht rotate y*sun_az } // -------- SKY AND ATMOSPHERICS fog{fog_type 2 fog_alt .5 distance 15 color rgb .8 transmit .2} sky_sphere{ pigment{ gradient y color_map{ [.5 rgb ht_factor*<.9, .7, .5>+(1-ht_factor)*1.1] [.7 rgb <0.58203, 0.70906, 0.99609>*.75] } scale 2 translate -y } } // ------- CLOUDS #declare cloud_plane = sphere{-y*5000, 5000+cloud_height hollow} // The cloud pattern #macro Perlin_func (P, Oct) //P=persistance and Oct=octaves #local N=0; #local norm_cnt=0; #local S=seed(2); #local Rdisp=100; #local func_buff=0; #while(N<(Oct+1)) #local Frq=pow(2,N); #local Amp=1/pow(P,N); #local Rx=(2*rand(S)-1)*Rdisp; #local Ry=(2*rand(S)-1)*Rdisp; #local Rz=(2*rand(S)-1)*Rdisp; #declare func_buff=function(func_buff+(noise3d((x+Rx)*Frq,(y+Ry)*Frq,(z+Rz)*Frq)*Amp)) #declare norm_cnt=norm_cnt+Amp; #local N=N+1; #end function(func_buff/norm_cnt) #end // Unfortunately I don't have any good color controls yet for the clouds #declare cloud_shade= pigment{ Perlin_func(2, 6) color_map{ [cloud_cover-.07 rgb ht_factor*<.9, .85, .75>*1.2+(1-ht_factor)*1.2 transmit .05] [cloud_cover rgb ht_factor*<.92, .9, .92>+(1-ht_factor)*1.2 transmit .05] [cloud_cover+.07 rgb <.8, .8, 1>] [cloud_cover+.14 rgb <.8, .8, 1>*.85] } #declare warp_loc = trace(cloud_plane, cam_loc, light_dir); warp{black_hole warp_loc, 100000000 falloff 0 strength shadow_displacement inverse} } //this provides the actual outline or mask for the clouds #declare cloud_mask = pigment{ Perlin_func(1.8, 6) pigment_map{ [cloud_cover color rgb 1 transmit 1] [cloud_cover+(1-cloud_cover)*.07 cloud_shade] } scale cloud_scale } object{ cloud_plane //double_illuminate pigment{cloud_mask} finish{ambient ((.7+sun_col*.3)*1.1)*ht_factor+(1-ht_factor)} } // ------- WATER // The reflection here is really what slows the whole thing down. sphere{ -y*5000, 5000 pigment{color rgb <0.48828, 0.50391, 0.72266>} normal{ #declare F=function{"ridgedMF",<1,2.25,7,-1,1>} function{F*.2} // this is an attempt to nomalize the function somewhat. bump_size .8 scale .50 } finish{reflection_type 0 reflection_min .1 reflection_max .5 reflection_falloff 1.5} } camera{ location 0 direction z rotate -x*cam_pitch rotate y*cam_az translate cam_loc angle cam_ang }