Joshua Barczak* CMSC 435 UMBC Renderman Joshua Barczak* CMSC 435 UMBC * Sample code stolen verbatim from Dr. Marc Olano
Project Goals Introduce some concepts Develop spatial reasoning skills Lights,Models,Materials,Transforms Common themes in graphics systems Some context for what’s ahead Develop spatial reasoning skills Feel the pain of artists
What RenderMan Is RenderMan Open Interface specification for renderers Renderman Interface Bytestream (RIB) C Binding Programmable shader language
RenderMan C Interface used to describe scene Light Sources Camera Parameters Objects Geometric Shape Visual Appearance Transformations
Transformations RiTranslate RiRotate RiScale Move Stuff Rotate the world RiScale Make the world bigger or smaller
Project 1 Dev Cycle Do: Until 11:59PM on due date Write C code Compile, linking with libri executable run program RIB rndr TIFF file Display image Contemplate ramifications of image Until 11:59PM on due date Check your code in! (see website)
The Universe According to RenderMan You need to tell it where all this stuff is Y Axis Z Axis 0,0,0 You are here… X Axis
Minimal RenderMan Program #include "ri.h" RtPoint Square[4]={{.5,.5,.5},{.5,-.5,.5},{-.5,.5,.5},{-.5,-.5,.5}}; static RtColor Color = {.2, .4, .6}; int main () { RiBegin("square.rib"); /* start the renderer */ RiDisplay("square.tif","file","rgb",RI_NULL); RiWorldBegin(); RiSurface ("constant", RI_NULL); RiColor (Color); /* declare color */ RiPatch (RI_BILINEAR, /* declare the square */ RI_P, (RtPointer) Square, RI_NULL); RiWorldEnd(); RiEnd(); return 0; } NOTE: Variable arguments…
square.rib ## Pixie 2.2.4 ## Generated Sat Jan 26 14:11:14 2013 Display "square.tif" "file" "rgb" WorldBegin Surface "constant" Color [0.2 0.4 0.6] Patch "bilinear" "P" [0.5 0.5 0.5 0.5 -0.5 0.5 -0.5 0.5 0.5 -0.5 -0.5 0.5 ] WorldEnd
square.tif
Refined Program Add a light… #include "ri.h" RtPoint Square[4]={{.5,.5,.5},{.5,-.5,.5},{-.5,.5,.5},{-.5,-.5,.5}}; static RtColor Color = {.2, .4, .6}; int main () { RiBegin("persp.rib"); /* start the renderer */ RiDisplay("persp.tif","file","rgb",RI_NULL); RiLightSource ("distantlight", RI_NULL); RiProjection("perspective", RI_NULL); RiTranslate(0.0,0.0,1.0); RiRotate (40.0, -1.0, 1.0, 0.0); RiWorldBegin(); RiSurface ("matte", RI_NULL); RiColor (Color); /* declare color */ RiPatch (RI_BILINEAR, /* declare the square */ RI_P, (RtPointer) Square, RI_NULL); RiWorldEnd(); RiEnd(); return 0; } Add a light…
Refined Program Tell it to shrink stuff with distance… #include "ri.h" RtPoint Square[4]={{.5,.5,.5},{.5,-.5,.5},{-.5,.5,.5},{-.5,-.5,.5}}; static RtColor Color = {.2, .4, .6}; int main () { RiBegin("persp.rib"); /* start the renderer */ RiDisplay("persp.tif","file","rgb",RI_NULL); RiLightSource ("distantlight", RI_NULL); RiProjection("perspective", RI_NULL); RiTranslate(0.0,0.0,1.0); RiRotate (40.0, -1.0, 1.0, 0.0); RiWorldBegin(); RiSurface ("matte", RI_NULL); RiColor (Color); /* declare color */ RiPatch (RI_BILINEAR, /* declare the square */ RI_P, (RtPointer) Square, RI_NULL); RiWorldEnd(); RiEnd(); return 0; } Tell it to shrink stuff with distance…
Refined Program #include "ri.h" RtPoint Square[4]={{.5,.5,.5},{.5,-.5,.5},{-.5,.5,.5},{-.5,-.5,.5}}; static RtColor Color = {.2, .4, .6}; int main () { RiBegin("persp.rib"); /* start the renderer */ RiDisplay("persp.tif","file","rgb",RI_NULL); RiLightSource ("distantlight", RI_NULL); RiProjection("perspective", RI_NULL); RiTranslate(0.0,0.0,1.0); RiRotate (40.0, -1.0, 1.0, 0.0); RiWorldBegin(); RiSurface ("matte", RI_NULL); RiColor (Color); /* declare color */ RiPatch (RI_BILINEAR, /* declare the square */ RI_P, (RtPointer) Square, RI_NULL); RiWorldEnd(); RiEnd(); return 0; } Tell it what to do to the world so it lines up to the camera…
The Universe According to RenderMan RenderMan’s coordinates… X Axis Y Axis Z Axis “World” Coordinates
Refined Program This means: #include "ri.h" RtPoint Square[4]={{.5,.5,.5},{.5,-.5,.5},{-.5,.5,.5},{-.5,-.5,.5}}; static RtColor Color = {.2, .4, .6}; int main () { RiBegin("persp.rib"); /* start the renderer */ RiDisplay("persp.tif","file","rgb",RI_NULL); RiLightSource ("distantlight", RI_NULL); RiProjection("perspective", RI_NULL); RiTranslate(0.0,0.0,1.0); RiRotate (40.0, -1.0, 1.0, 0.0); RiWorldBegin(); RiSurface ("matte", RI_NULL); RiColor (Color); /* declare color */ RiPatch (RI_BILINEAR, /* declare the square */ RI_P, (RtPointer) Square, RI_NULL); RiWorldEnd(); RiEnd(); return 0; } This means: Rotate THEN translate. (It’s like a stack) This will be extremely confusing…. There are reasons for this, but they are still many lectures out…
Refined Program RiWorldBegin resets the stack… #include "ri.h" RtPoint Square[4]={{.5,.5,.5},{.5,-.5,.5},{-.5,.5,.5},{-.5,-.5,.5}}; static RtColor Color = {.2, .4, .6}; int main () { RiBegin("persp.rib"); /* start the renderer */ RiDisplay("persp.tif","file","rgb",RI_NULL); RiLightSource ("distantlight", RI_NULL); RiProjection("perspective", RI_NULL); RiTranslate(0.0,0.0,1.0); RiRotate (40.0, -1.0, 1.0, 0.0); RiWorldBegin(); RiSurface ("matte", RI_NULL); RiColor (Color); /* declare color */ RiPatch (RI_BILINEAR, /* declare the square */ RI_P, (RtPointer) Square, RI_NULL); RiWorldEnd(); RiEnd(); return 0; } RiWorldBegin resets the stack… There are reasons for this, but they are still many lectures out…
Spheres Fiddle with these and watch what happens… #include "ri.h" RtFloat radius=1.0, zmin=-1.0, zmax=1.0, thetamax=360; int main () { RiBegin("sphere.rib"); /* start the renderer */ //… RiWorldBegin(); // … RiSphere (radius, zmin, zmax, thetamax, RI_NULL); RiWorldEnd(); RiEnd(); return 0; }
Other Stuff That’s in There RiCylinder RiParaboloid RiCone RiHyperboloid RiSphere RiTorus And much MUCH more I don’t have time for. RiRTM()
Unit Cube #include "ri.h" static RtColor Color = {.2, .4, .6}; void UnitCube() { /* ???? */ } int main () RiBegin("cube.rib"); /* start the renderer */ // … RiWorldBegin(); UnitCube(); RiWorldEnd(); RiEnd(); return 0;
Unit Cube #define L -.5 #define D -.5 #define N -.5 #define R .5 #define U .5 #define F .5 void UnitCube () { static RtPoint Cube[6][4] = { {{L,D,F}, {R,D,F}, {R,D,N}, {L,D,N}}, // bottom {{L,D,F}, {L,U,F}, {L,U,N}, {L,D,N}}, // left {{R,U,N}, {L,U,N}, {L,U,F}, {R,U,F}}, // top {{R,U,N}, {R,U,F}, {R,D,F}, {R,D,N}}, // right {{R,D,F}, {R,U,F}, {L,U,F}, {L,D,F}}, // far {{L,U,N}, {R,U,N}, {R,D,N}, {L,D,N}}};//near int i; for (i = 0; i < 6; i++) { RiPolygon(4,RI_P,(RtPointer)Cube[i],RI_NULL); }} 1 RiPolygon Vertices in this order… 3 2
Transforming Objects RiColor (Blue); UnitCube(); RiColor(Yellow); RiTransformBegin(); RiTranslate( 2, 0, 0 ); RiRotate( 30.0, 0, -1, 0 ); RiTransformEnd(); RiColor(Red); RiTranslate( -2, 1, 0 ); RiRotate(-60,0,1,0); RiScale( 2, 0.5, 1 ); Push current transformation state…. Return to state at last TransformBegin() You can nest these things if you want, consider the implications…
Transforming Objects RiColor (Blue); UnitCube(); RiColor(Yellow); RiTransformBegin(); RiTranslate( 2, 0, 0 ); RiRotate( 30.0, 0, -1, 0 ); RiTransformEnd(); RiColor(Red); RiTranslate( -2, 1, 0 ); RiRotate(-60,0,1,0); RiScale( 2, 0.5, 1 ); Save state Move the origin by that much Rotate the coordinate system Put axis-aligned unit cube at the origin Go back The transform calls are interpretted differently during WorldBegin/End than they are outside of it. This can be extremely confusing…
Transforming Objects RiColor (Blue); UnitCube(); RiColor(Yellow); RiTransformBegin(); RiTranslate( 2, 0, 0 ); RiRotate( 30.0, 0, -1, 0 ); RiTransformEnd(); RiColor(Red); RiTranslate( -2, 1, 0 ); RiRotate(-60,0,1,0); RiScale( 2, 0.5, 1 ); RiScale means: Change size by this much on each axis… Try reversing the order and watch what happens…
Transforms
Another Cube RiPatch Vertices in this order… 2 1 3 RtPoint Square[4]={{.5,.5,.5},{.5,-.5,.5},{-.5,.5,.5},{-.5,-.5,.5}}; static RtColor Color = {.2, .4, .6}; void UnitCube () { RiTransformBegin(); RiPatch(RI_BILINEAR,RI_P,(RtPointer)Square, RI_NULL); RiRotate(90.0, 0.0, 1.0, 0.0); // right face RiRotate(90.0, 0.0, 1.0, 0.0); // near face RiRotate(90.0, 0.0, 1.0, 0.0); // left face RiTransformEnd(); RiTransformBegin(); // bottom face RiRotate(90.0, 1.0, 0.0, 0.0); RiTransformBegin(); // top face RiRotate(-90.0, 1.0, 0.0, 0.0); } RiPatch Vertices in this order… 2 1 3
Light Sources DistantLight Like the sun Parameters From/To LightColor Intensity
DistantLight
DistantLight RtFloat from[] = { -1,1,0.2}; RtFloat to[] = { 0,0,0 }; RiLightSource ("distantlight", "from", from, "to", to, RI_NULL);
DistantLight RtFloat from[] = { 1,1,0.2}; RtFloat to[] = { 0,0,0 }; RiLightSource ("distantlight", "from", from, "to", to, RI_NULL);
DistantLight RtFloat from[] = {1,1,0.2}; RtFloat inten = 5; RiLightSource ("distantlight", "from", from, "intensity", &inten, RI_NULL);
DistantLight RtFloat from[] = {1,1,0.2}; RtFloat inten = 5; RiLightSource ("distantlight", "from", from, "intensity", &inten, RI_NULL);
PointLight Like a light bulb lightcolor intensity “from” (where is it) Brightness radiates outwards, falls off with distance Should always set intensity
PointLight RtFloat from[] = { 0,0,3 }; RtFloat intensity=5; RiLightSource( "pointlight", "from", from, "intensity", &intensity, RI_NULL );
PointLight RtFloat from[] = { 0,0,3 }; RtFloat intensity=10; RiLightSource( "pointlight", "from", from, "intensity", &intensity, RI_NULL );
PointLight RtFloat from[] = { 0,1,3 }; RtFloat intensity=10; RiLightSource( "pointlight", "from", from, "intensity", &intensity, RI_NULL );
Materials Matte Plastic Things that aren’t too shiny Kd: How bright it looks (0-1) Plastic Shiny coating with matte underneath Kd: Same as matte Ks: How bright the shine is roughness: How shiny it looks 1 Looks like matte 0.000..1 Mirror
Materials Plastic Spheres Roughness 0.01, 0.1, 0.5 RtFloat Kd = 0.8f; RtFloat rough = 0.01f; RiSurface ("plastic", "Kd", &Kd, "roughness",&rough, RI_NULL);
Materials Metal PaintedPlastic/PaintedMatte Raytraced surfaces Basically plastic, without the matte underneath PaintedPlastic/PaintedMatte Use an image texture for color Raytraced surfaces Glass, Mirror CD to $PIXIEHOME/shaders and look around…