The image above was created using Renderman Python using a simple Fractional Brownian motion (fBM) displacement shader
displacement fbmDisp
(
float Km=0.1;
float Layers=6;
output varying float Freq=1;
)
{
/* init the shader values */
vector NN=normalize(N);
float i;
float mag=0;
point Pt=transform("shader",P);
for(i=0; i<Layers; i+=1)
{
mag+=(float noise(Pt*Freq)-0.5)*2/Freq;
Freq*=2;
}
mag /=length(vtransform("object",NN));
P=P+mag*NN*Km;
N=calculatenormal(P);
}
The basic scene was created using a Python for Renderman script below, this script is a two stage script which generates shadow maps by moving the camera to the position of each of the lights and rendering a Z depth map which the special shadowspot shader uses to calculate the occlusion.
Once these maps are generated the final scene is rendered using these maps.
#!/usr/bin/python
# for bash we need to add the following to our .bashrc
# export PYTHONPATH=$PYTHONPATH:$RMANTREE/bin
import getpass
import time,random,math
# import the python renderman library
import prman
# Modified from Renderman Examples in The renderman Companion
# AimZ(): rotate the world so the direction vector points in
# positive z by rotating about the y axis, then x. The cosine
# of each rotation is given by components of the normalized
# direction vector. Before the y rotation the direction vector
# might be in negative z, but not afterward.
def AimZ(ri,direction) :
if (direction[0]==0 and direction[1]==0 and direction[2]==0) :
return
#
# The initial rotation about the y axis is given by the projection of
# the direction vector onto the x,z plane: the x and z components
# of the direction.
xzlen = math.sqrt(direction[0]*direction[0]+direction[2]*direction[2])
if (xzlen == 0) :
if(direction[1] <0) :
yrot = 0
else :
yrot =180
# yrot = (direction[1] < 0) ? 180 : 0
else :
yrot = 180*math.acos(direction[2]/xzlen)/math.pi;
# The second rotation, about the x axis, is given by the projection on
# the y,z plane of the y-rotated direction vector: the original y
# component, and the rotated x,z vector from above.
yzlen = math.sqrt(direction[1]*direction[1]+xzlen*xzlen)
xrot = 180*math.acos(xzlen/yzlen)/math.pi # yzlen should never be 0
if (direction[1] > 0) :
ri.Rotate(xrot, 1.0, 0.0, 0.0)
else :
ri.Rotate(-xrot, 1.0, 0.0, 0.0)
#The last rotation declared gets performed first
if (direction[0] > 0) :
ri.Rotate(-yrot, 0.0, 1.0, 0.0)
else :
ri.Rotate(yrot, 0.0, 1.0, 0.0)
def ShadowPass(ri,Name,From,To,coneAngle,SceneFunc) :
#
print "Rendering Shadow pass %s.z" %(Name)
ri.Begin("__render")
ri.Display(Name+".z", "zfile", "z")
ri.Clipping(1,10)
# Specify PAL resolution 1:1 pixel Aspect ratio
ri.Format(512,512,1)
# now set the projection to perspective
ri.Projection(ri.PERSPECTIVE,{ri.FOV:coneAngle*(360/math.pi)})
#now move to light position
# create a vector for the Spotlight to and from values
# to do this we subtract each of thelist elements using a lambda function
# this is the same as doing the code below I will leave it to you as to which you
# find more readable
#direction =[To[0]-From[0],To[1]-From[1],To[2]-From[2]]
direction = map(lambda x,y : x-y , To,From)
AimZ(ri,direction)
ri.Translate(-From[0],-From[1],-From[2])
# now draw the Scene
ri.WorldBegin()
SceneFunc(ri)
ri.WorldEnd()
ri.MakeShadow(Name+".z",Name+".shad")
ri.End()
print " Done MakeShadow %s.shad" %(Name)
def Scene(ri) :
random.seed(25)
ri.TransformBegin()
ri.AttributeBegin()
ri.Color([1,1,1])
ri.Translate( 0,-1.0,0)
ri.Rotate(-90,1,0,0)
ri.Rotate(36,0,0,1)
ri.Scale(0.4,0.4,0.4)
ri.Surface("plastic")
ri.Displacement("fbmDisp",{"float Km":[0.2]})
ri.Geometry("teapot")
ri.AttributeEnd()
ri.TransformEnd()
face=[-0.1,-1,-3, 0.1,-1,-3,-0.1,-1,3, 0.1,-1,3]
plank=-5.0
ri.AttributeBegin()
while (plank <=5.0) :
ri.TransformBegin()
ri.Color([random.uniform(0.35,0.4),random.uniform(0.1,0.025),0])
c0=[random.uniform(-10,10),random.uniform(-10,10),random.uniform(-10,10)]
c1=[random.uniform(-10,10),random.uniform(-10,10),random.uniform(-10,10)]
ri.Surface("wood",{"Ks":[0.1],"point c0":c0,"point c1":c1,"float grain":random.randint(2,20)})
ri.Translate(plank,0,0)
ri.Patch("bilinear",{'P':face})
ri.TransformEnd()
plank=plank+0.206
ri.AttributeEnd()
ri = prman.Ri() # create an instance of the RenderMan interface
ri.Option("rib", {"string asciistyle": "indented"})
SpotFrom=[2,4,3]
SpotTo=[0,0,0]
SpotName="Spot1"
coneAngle=0.4
ShadowPass(ri,SpotName,SpotFrom,SpotTo,coneAngle,Scene)
Spot2From=[2,4,-3]
Spot2To=[0,0,0]
Spot2Name="Spot2"
coneAngle2=0.3
ShadowPass(ri,Spot2Name,Spot2From,Spot2To,coneAngle2,Scene)
filename = "__render" #ShadowSpot.rib"
# this is the begining of the rib archive generation we can only
# make RI calls after this function else we get a core dump
ri.Begin(filename)
ri.Clipping(1,10)
# ArchiveRecord is used to add elements to the rib stream in this case comments
# note the function is overloaded so we can concatinate output
ri.ArchiveRecord(ri.COMMENT, 'File ' +filename)
ri.ArchiveRecord(ri.COMMENT, "Created by " + getpass.getuser())
ri.ArchiveRecord(ri.COMMENT, "Creation Date: " +time.ctime(time.time()))
ri.Declare(SpotName ,"string")
ri.Declare("Ambient" ,"string")
ri.Attribute("displacementbound",{ri.COORDINATESYSTEM:["world"],"uniform float sphere":[10.8]})
# now we add the display element using the usual elements
# FILENAME DISPLAY Type Output format
ri.Display("Teapot.png", "file", "rgb")
# Specify PAL resolution 1:1 pixel Aspect ratio
ri.Format(720,576,1)
# now set the projection to perspective
ri.Projection(ri.PERSPECTIVE,{ri.FOV:50})
ri.ShadingRate(0.1)
ri.Translate(0,0,3)
# now we start our world
ri.WorldBegin()
ri.LightSource ("ambientlight",{ri.HANDLEID: "Ambient","intensity" :[0.05]})
ri.LightSource( "shadowspot", {ri.HANDLEID:SpotName,
"point from" : SpotFrom,
"point to" : SpotTo,
"float intensity" : [30],
"string shadowname" :SpotName+".shad",
"float coneangle" : coneAngle,
"float conedeltaangle" : [0.05]})
ri.LightSource( "shadowspot", {ri.HANDLEID:Spot2Name,
"point from" : Spot2From,
"point to" : Spot2To,
"float intensity" : [30],
"string shadowname" :Spot2Name+".shad",
"float coneangle" : coneAngle2,
"float conedeltaangle" : [0.05]})
ri.Illuminate(SpotName,1)
ri.Illuminate(Spot2Name,1)
Scene(ri)
ri.WorldEnd()
# and finally end the rib file
ri.End()

No comments:
Post a Comment