/* fast_prox.inc version 0.2 introduces a tighter sampling type for fastSSS2 called fastSS2b 2008 Samuel Benge Distribute freely~ Works with POV-Ray version 3.6 and 3.7b. All macros return pigment_patterns which can be used in any pigment, normal, texture and density blocks. You can apply different wave types to the patterns. I recommend cubic_wave and poly_wave 2 and higher for the proximity macros, and cubic_wave for the fastSSS2() macro. You must manually specify bounding boxes for the macros, as POV's handing of bounding boxes is not always perfect. Make the bounding box slightly larger than the object itself to make sure the effect covers the whole object. Optionally, you can select only a small region inside the object if desired. This is especially handy with the proximity macros. Use only vectors where vectors are specified in the macro definition, as I have not implemented vector-float conversion yet. Contents: fastProx() fastProx2() fastProx3() fastSSS() fastSSS2() ******************************************************************* The proximity macros -these can only be used with objects suporting inside() testing (ie. unions of csg objects. No meshes, sorry!) -they create an edge pattern allowing you to assign different pigments and textures for the inside and outside edges of an object -higher (fPincre) samples means tighter edges, and longer parsing times -higher (fpSamples) samples means longer parse and render times, but with a higher degree of accuracy ___________________________________________________________________ fastProx(fPobj, Min, Max, fPincre) -starting point for the proximity macros -only useful for square objects such as unions of boxes fPobj: the predeclared object Min: vector. minimum extent of the the object's bound box Max: vector. maximum extent of the the object's bound box fPincre: vector representing number of xyz samples usage: object{ myObj pigment{fastProx(myObj,<-4,-4,-4>,<4,4,4>,<5,5,5>)} } ___________________________________________________________________ fastProx2(fpobj, Min, Max, fPincre, upper, fpSamples) -creates an averaged pattern of several instances of fastProx() fPobj: the predeclared object Min: vector. minimum extent of the the object's bound box Max: vector. maximum extent of the the object's bound box fPincre: vector representing number of xyz samples upper: float. "fPincre" will be multiplied incrementally by this value. fpIncre*upper must not exceed 253! fpSamples: float. The total number of averaged instances of fastProx(). "fPincre" will be multiplied by a fraction of "upper" until it reaches the value of "fpSamples", thus ending at the value of "upper." "fPincre", "upper" and "fpSamples" all determine the quality and speed of this macro. Must not exceed 255. usage: object{ myObj pigment{ fastProx2(myObj,<-4,-4,-4>,<4,4,4>,<5,5,5>,2,20) cubic_wave } } ___________________________________________________________________ fastProx3(fpobj, Min, Max, fPincre, upper, fpSamples, fpmult) -same as fastProx2(). It resamples the pattern for faster rendering, but with higher parse times. There can be a loss of quality, but it is not always noticable. -it returns a single pigment_pattern, not several averaged instances fPobj: the predeclared object Min: vector. minimum extent of the the object's bound box Max: vector. maximum extent of the the object's bound box fPincre: vector representing number of xyz samples upper: float. "fPincre" will be multiplied incrementally by this value. fpIncre*upper must not exceed 253! fpSamples: float. The total number of averaged instances of fastProx(). "fPincre" will be multiplied by a fraction of "upper" until it reaches the value of "fpSamples", thus ending at the value of "upper." "fPincre", "upper" and "fpSamples" all determine the quality and speed of this macro. Must not exceed 255. fpMult: vector. Number of oversamples. To see any benefit from this macro, make sure this vector exceeds <1,1,1>. usage: object{ myObj pigment{ fastProx3(myObj,<-4,-4,-4>,<4,4,4>,<5,5,5>,2,20,<2,2,2>) poly_wave 2 } } ******************************************************************* The subsurface scattering macros -these can only be used with any objects suporting the trace() command. This means *any* object, as far as I know, meshes included. -they create a subsurface scattering pattern allowing you to assign different pigments and textures for the lit and unlit portions of an object -higher (fPincre) samples means less light penetration, and longer parsing times -higher (fpSamples) samples means longer parse and render times, but with a higher degree of accuracy ___________________________________________________________________ fastSSS(fPobj, fPlightPos, Min, Max, fPincre) -starting point for the fastSSS2() macro -may be useful for square objects such as unions of boxes -I don't recommend using this macro fPobj: the predeclared object fPlightPos: vector. The position of the virtual light_source. Min: vector. minimum extent of the the object's bound box Max: vector. maximum extent of the the object's bound box fPincre: vector representing number of xyz samples usage: Don't use this macro :) ___________________________________________________________________ fastSSS2(fpobj, fPlightPos, Min, Max, fPincre, upper, fpSamples) fPobj: the predeclared object fPlightPos: vector. The position of the virtual light_source. Min: vector. minimum extent of the the object's bound box Max: vector. maximum extent of the the object's bound box fPincre: vector representing number of xyz samples upper: float. "fPincre" will be multiplied incrementally by this value. fpIncre*upper must not exceed 253! fpSamples: float. The total number of averaged instances of fastProx(). "fPincre" will be multiplied by a fraction of "upper" until it reaches the value of "fpSamples", thus ending at the value of "upper." "fPincre", "upper" and "fpSamples" all determine the quality and speed of this macro. Must not exceed 255. usage: object{ myObj pigment{ fastSSS2(myObj,lpos,<-4,-4,-4>,<4,4,4>,<5,5,5>,2,20) cubic_wave } finish{ambient .5 diffuse .5} } ******************************************************************* */ #macro fastProx(fPobj, Min, Max, fPincre) #local increX=1/fPincre.x; #local increY=1/fPincre.y; #local increZ=1/fPincre.z; #local fpt= pigment{ pigment_pattern{planar scale (Max.z-Min.z) rotate x*90 translate Max.z} pigment_map{ [0 rgb 1] #local Z=increZ; #while(Z<=1-increZ) #local Zv=Min.z+Z*(Max.z-Min.z); [Z pigment_pattern{planar scale (Max.y-Min.y) translate Max.y} pigment_map{ [0 rgb 1] #local Y=increY; #while(Y<=1-increY) #local Yv=Min.y+Y*(Max.y-Min.y); [Y pigment_pattern{planar scale (Max.x-Min.x) rotate z*90 translate Max.x} pigment_map{ [0 rgb 1] #local X=increX; #while(X<=1-increX) #local Xv=Min.x+X*(Max.x-Min.x); #local av=1; #if(inside(fPobj,)) #local av=0; #end [X rgb av ] #local X=X+increX; #end [1 rgb 1] } ] #local Y=Y+increY; #end [1 rgb 1] } ] #local Z=Z+increZ; #end [1 rgb 1] } } pigment_pattern{ pigment_pattern{ boxed scale .5 translate .5 scale (Max-Min) translate Min } pigment_map{ [0 rgb 1] [1/256 fpt ] } } #end #macro fastProx2(fpobj, Min, Max, fps, upper, fpSamples) pigment_pattern{ average pigment_map{ #local V=0; #while(V<=1) [1 fastProx(fpobj,Min,Max,fps*(1+(upper-1)*V))] #local V=V+1/fpSamples; #end } } #end #macro resample(fpobj, lPos, Min, Max, fps, upper, fpSamples, fpmult, resampleType) #local fPincre=fps*fpmult; #if(resampleType=1) #local fpt=pigment{fastProx2(fpobj, Min, Max, fps, upper, fpSamples) } #end #if(resampleType=2) #local fpt=pigment{fastSSS2(fpobj, lPos, Min, Max, fps, upper, fpSamples) } #end #if(resampleType=3) #local fpt=pigment{fastSSS2b(fpobj, lPos, Min, Max, fps, upper, fpSamples) } #end #local increX=1/fPincre.x; #local increY=1/fPincre.y; #local increZ=1/fPincre.z; #local fpt= pigment{ pigment_pattern{planar scale (Max.z-Min.z) rotate x*90 translate Max.z} pigment_map{ [0 rgb 1] #local Z=increZ; #while(Z<=1-increZ) #local Zv=Min.z+Z*(Max.z-Min.z); [Z pigment_pattern{planar scale (Max.y-Min.y) translate Max.y} pigment_map{ [0 rgb 1] #local Y=increY; #while(Y<=1-increY) #local Yv=Min.y+Y*(Max.y-Min.y); [Y pigment_pattern{planar scale (Max.x-Min.x) rotate z*90 translate Max.x} pigment_map{ [0 rgb 1] #local X=increX; #while(X<=1-increX) #local Xv=Min.x+X*(Max.x-Min.x); #local av=1; #local pf=eval_pigment(fpt,); [X rgb pf.x ] #local X=X+increX; #end [1 rgb 1] } ] #local Y=Y+increY; #end [1 rgb 1] } ] #local Z=Z+increZ; #end [1 rgb 1] } } pigment_pattern{ pigment_pattern{ boxed scale .5 translate .5 scale (Max-Min) translate Min } pigment_map{ [0 rgb 1] [1/256 fpt ] } } #end #macro fastProx3(fpobj, Min, Max, fps, upper, fpSamples, fpmult) #local prox=1; resample(fpobj, <0,0,0>, Min, Max, fps, upper, fpSamples, fpmult, prox) #end #macro fastSSS(fPobj, fPlightPos, Min, Max, fPincre, typeFlag) #local increX=1/fPincre.x; #local increY=1/fPincre.y; #local increZ=1/fPincre.z; #local fpt= pigment{ pigment_pattern{planar scale (Max.z-Min.z) rotate x*90 translate Max.z} pigment_map{ [0 rgb 0] #local Z=increZ; #while(Z<=1-increZ) #local Zv=Min.z+Z*(Max.z-Min.z); [Z pigment_pattern{planar scale (Max.y-Min.y) translate Max.y} pigment_map{ [0 rgb 0] #local Y=increY; #while(Y<=1-increY) #local Yv=Min.y+Y*(Max.y-Min.y); [Y pigment_pattern{planar scale (Max.x-Min.x) rotate z*90 translate Max.x} pigment_map{ [0 rgb 0] #local X=increX; #while(X<=1-increX) #local Xv=Min.x+X*(Max.x-Min.x); #local av=0; //#local norm=<0,0,0>; #local tv=trace(fPobj,fPlightPos,-fPlightPos); #if(typeFlag=0) #if( ( tv.x>Xv-(Max.x-Min.x)/fPincre.x & tv.y>Yv-(Max.y-Min.y)/fPincre.y & tv.z>Zv-(Max.z-Min.z)/fPincre.z )& ( tv.xXv-(Max.x-Min.x)/fPincre.x/2 & tv.y>Yv-(Max.y-Min.y)/fPincre.y/2 & tv.z>Zv-(Max.z-Min.z)/fPincre.z/2 )& ( tv.x