Sunteți pe pagina 1din 5

PRMan SDK

The RenderMan Software Developers Kit (SDK) is a collection of interfaces that allows users of RenderMan to extend the capabilities of the software in many varied and powerful ways There are two categories of interfaces in RenderMan : the first is plugins and the second is standalone applications. With plugins the interface can be bidirectional, meaning that the plugin will be expected to provide an entry point for the renderer to call into and the plugin can also make calls into entry points exposed by the renderer. Stand-alone programs will always simply make calls into entry points exposed by the renderer. This is why providing a shared library that supports all the needs of the plugin interfaces and the stand-alone applications has great appeal. With a shared library, the executable prman simply loads the shared library at runtime and all plugins resolve their exported entry points against the shared library. Stand-alone programs can also resolve against the same shared library and can even embed the RenderMan renderer themselves. (A good example of this is the prman_for_python extension.) The downside of this is that stand-alone programs will now have to load the dynamic runtime library; however, all operating systems provide many mechanisms to meet this requirement and it is a small price to pay for the added flexibility it affords.

Linking Plugins
On Unix-based platforms, plugins are linked such that symbols that resolve to entry points in libprman.so or libprman.dylib are left unresolved. An example of linking an RSL Plugin is provided below. Note that on Linux the use of -fPIC is important for code that will be used as a plugin and that there is no explicit linkage of libprman.so, even if the plugin makes reference to application interfaces, like deeptexture. On OS X, the linker must be explicitly told that the unresolved symbols will be resolved at run-time. On Windows, the libprman.lib must always be referenced to resolve the unresolved symbols in the plugin. Linux
g++ -c -fPIC -I$RMANTREE/include myplugin.cpp

g++ -shared myplugin.o -o myplugin.so

OS X
g++ -c -I$RMANTREE/include myplugin.cpp g++ -bundle -undefined dynamic_lookup myplugin.o -o myplugin.so

Windows
cl /c /nologo /MT /TP /DWIN32 /I"%RMANTREE%\include" myplugin.cpp link /nologo /out:myplugin.dll /dll /LIBPATH:"%RMANTREE%\lib" libprman.lib myplugin.obj

Linking Applications
For applications, on all platforms the libprman library will be linked against the application. Of course, the application will also need to be told where to find the library. This can be done at linktime or at runtime via various mechanisms on each platform. Linux
g++ -c -fPIC -I$RMANTREE/include myapp.cpp g++ myapp.o -L$RMANTREE/lib -lprman -o myapp

OS X
g++ -c -I$RMANTREE/include myapp.cpp g++ myapp.o -L$RMANTREE/lib -lprman -o myapp

Windows
cl /nologo /MT /TP /DWIN32 /I%RMANTREE%\include myapp.cpp link /nologo /out:myapp /L%RMANTREE%\lib libprman.lib myapp.o

PRMan for Python


RenderMan Pro Server 14 introduces prman_for_python, a Python plugin module that allows you to build Pixar's RenderMan into your Python applications. With the plugin module prman_for_python.so comes a simple Python wrapper module, prman.py. prman_for_python can be used to write RIB files and to render pixels directly from Python. You can even express RenderMan procedural primitive plugins (procprims) and Ri filters (rifs) directly in Python. Here's a simple example that can produce either a RIB file or final pixels:
% setenv PYTHONPATH $RMANTREE/bin # this is where prman.py lives % python import prman ri = prman.Ri() # create an instance of the RenderMan interface rendertarget = "helloworld.rib" ri.Begin(rendertarget) # set rendertarget to ri.RENDER to render pixels ri.Display("helloworld.exr", "openexr", "rgba") ri.Format(512,512,1) ri.Projection(ri.PERSPECTIVE, {ri.FOV: 45}) # standard Ri tokens are available ri.Translate(0,0,10) ri.WorldBegin() ri.Geometry("teapot") ri.WorldEnd() ri.End()

Re-Rendering
Note: Although there is currently no support in Renderman Studio 2 for re-rendering. There is (on certain platforms) support for Python within Maya. Therefore some access to prman for python can be obtained to implement your own custom re-rendering pipeline. But further description of this is out of the scope of this courseware. RenderMan Pro Server 14 introduces a new re-rendering mode that accelerates re-shading of production-quality scenes. The implementation employs a deep-framebuffer approach that requires an initial pre-rendering pass to bake subsample visibility results as well as partial results from shading calculations. Because visibility information is baked, re-rendering imposes several limitations on the kinds of edits that can be made during a re-rendering session. We disallow editing of scene elements that affect visibility including camera settings, displacements and geometric primitives. Re-rendering with prman is a three step process: Shader analysis Baking for rerendering Rerendering Shader Analysis First, surface shaders are analyzed to determine which parts of the shaders are lighting-independent. A special shadeop, _lightingstart(), is inserted into the shaders automatically by the shader compiler. During baking, _lightingstart() writes to disk the results of the lightingindependent calculations. During re-rendering, shader re-execution will begin with the _lightingstart() shadeop, loading the previously cached data from disk. Baking for re-rendering Simply add the two baking options given above to the top of your rib and render with prman as usual. In addition to rendering the scene, prman will create the directory specified by ''rerenderbakedir'' and write cached data into it. Re-rendering and editing The following Python script illustrates the major components of rerendering session in prman: the options to tell prman to bake a database for re-rendering, the APIs to launch a separate prman process and communicate with it, and the new Ri calls to load and edit a baked scene.
import time import prman arglist = [] prman.Init(arglist) ri = prman.Ri() # The light we will be editing def doLight1(ri, angle): ri.TransformBegin() ri.Rotate(angle, 0,1,0) ri.Rotate(45, 1,0,0) ri.Translate(0,0,-7) ri.LightSource("shadowspot", {ri.HANDLEID: "light1", "float coneangle": .7, "float intensity": 20, }) ri.TransformEnd() # Here's a simple scene description def doScene(ri): # Do not use the multires driver when baking. There is a known issue # (to be fixed) that prman will not exit while the multires driver window # stays open. This script would hang until the user closed the window. ri.Display("example.tif", "framebuffer", "rgba") ri.Format(512, 512, 1)

ri.ShadingRate(1) ri.Projection(ri.PERSPECTIVE, {ri.FOV: 35}) ri.Translate(0, 0, 20) ri.Rotate(-25, 1, 0, 0) ri.WorldBegin() ri.LightSource("ambientlight", {"float intensity": .1, ri.HANDLEID: "l1"}) # Issue the light we'll be editing doLight1(ri, 0) # The floor ri.Color([1, 1, 1]) ri.TransformBegin() ri.Scale(6, 1, 6) ri.Surface( "matte" ) ri.Patch( "bilinear", {"P": [-1, 0, -1, 1, 0, -1, ri.TransformEnd() # A teapot ri.Color([.2, .5, 1]) ri.Surface("rmarble") ri.Rotate(-90, 1, 0, 0) ri.Translate(0, 1, 0) ri.Geometry("teapot") ri.WorldEnd() # Step 1: Bake the scene for re-rendering print "perform pre-render bake...." # Launch a prman process with a control channel filename = "launch:prman? -t -ctrl $ctrlin $ctrlout" ri.Begin(filename) # The options to turn on baking for re-rendering. ri.Option("render", {"int rerenderbake": 1}) ri.Option("render", {"string rerenderbakedbdir": "bakedb"}) # Issue the scene to be baked doScene(ri) # RiEnd will block until the render is finished print "waiting for bake render to finish...." ri.End() # Step 2: Re-render and edit the baked scene max = 720 if max > 0: print "initializing re-rendering...." # Launch a prman process with a control channel filename = "launch:prman? -t -ctrl $ctrlin $ctrlout" ri.Begin(filename) # It's preferable not to use 'it', 'x11', or 'windows' as # your framebuffer. The higher performance option is 'multires'. ri.Display("teapot", "multires", "rgb") # Load the baked scene ri.EditWorldBegin("bakedb");

-1, 0, 1, 1, 0, 1]})

# Optional: Wait for the load and it's initial display before # issuing edits. This is here simply to illustrate the use of # a "finishing" flush. #print "waiting for initial display of editing session...." #ri.ArchiveRecord("structure", ri.STREAMMARKER + "_initial"); #prman.RicFlush("_initial", 1, ri.FINISHRENDERING) # Spin the light around the teapot print "now we're ready to send edits...." for i in range(0,max,10): # We can interrupt rendering by annotating the Ri # stream and flushing the renderer to the desired # point. # Mark a point in the stream with a special archive record. print "edit %d/%d" % (i,max) ri.ArchiveRecord("structure", ri.STREAMMARKER + `i` ); # Issue a non-blocking flush to the marked point. Tell the # renderer to skip any previous edits it's processing and # advance to this point in the Ri stream. prman.RicFlush( "%d" % i, 0, ri.SUSPENDRENDERING) # Issue the edit ri.EditBegin("relighting", {"string editlights": "light1"}) doLight1(ri,i) ri.EditEnd() # Optional: Give the renderer time to complete a few levels # of progressive refinement before we interrupt it with # a new edit. Uncomment this to slow down updates. Depending # on the speed of your system and the complexity of the scene, # these parameters may need adjusting. #while prman.RicGetProgress() < 15: # time.sleep(.05) print "waiting for last edit to finish...." ri.EditWorldEnd() print "editing done, goodbye" ri.End()

S-ar putea să vă placă și