11.1. RenderMan RIB export
The module cgkit.ribexport contains the class RIBExporter that
exports the current scene as RIB and creates shaders from the materials and
light sources used in the scene.
To use the exporter you can simply use the save()
command and pass a file name with suffix .rib. The plugin supports the
following options that can be passed to the save() command:
| Option |
Default |
Description |
| camera |
None |
Camera object to be used |
| output |
None |
Output image file name or
output specs |
| output_framebuffer |
True |
Framebuffer output? |
| bake |
False |
Activate texture baking mode |
| bakemodel |
None |
Determines the model to bake |
| bakestvar |
"st" |
Variable name of the bake
texture coordinates |
camera specifies the camera object to be used for rendering the scene. If
None is specified the first camera found in the scene is used.
output is the output image file name or a list of output specifiers. Each
specifier is a 4-tuple (filename, type, mode, params) containing the
parameters for a RiDisplay() call. The additional parameters must be given
as a dictionary. output can also be None in which case no
RiDisplay() call is made.
output_framebuffer is a flag that specifies if a framebuffer display should be
opened in addition to writing the output image file to disk. This flag is only
used when output is a string.
If bake is True the exported scene will bake a texture map instead of
producing a final image.
bakemodel is either the name of a WorldObject or a WorldObject itself. The
texture will be baked for the specified model. This parameter doesn’t have to be
specified if there is only one mesh in the scene.
bakestvar is the name of the primitive variable that holds the texture
coordinates that should be used for baking.
The plugin uses the following global options:
| Option |
Default |
Description |
| displaymode |
"rgb" |
Display mode |
| displaytype |
"file" |
Display type |
| output |
None |
Output image file name or
output specs (see above) |
| resolution |
(640,480) |
Output image resolution |
| pixelsamples |
(2,2) |
Number of pixel samples |
| shadingrate |
1.0 |
Shading rate |
| pixelfilter |
None |
Pixel filter setting |
| tiles |
None |
Render the image in tiles |
| rib |
None |
Additional global RIB requests |
displaymode is the mode string for the RiDisplay() call and determines
what data is written to the output. Usually you might want to switch between
“rgb” (default) and “rgba”.
output is the image output name or a list of output specifiers (see above).
resolution is either a 2-tuple (width, height) or a 3-tuple (width,
height, pixel aspect) specifying the outpout image resolution.
pixelsamples is a 2-tuple containing the pixel samples setting.
shadingrate contains the shading rate setting.
pixelfilter is a 2-tuple (filter, (xwidth, ywidth)) that sets the pixel
filter to use. If None is passed the default pixel filter of the renderer is
used. Example: (“gaussian”, (2,2))
tiles contains two sequences that defines the positions where the image is
split. The first sequence contains the x positions and the second sequence the y
positions where a split should occur. Each value lies between 0 and 1, so for
example tiles=((0.5,), (0.5,)) will render the image in four equal tiles. The
tiles can than be stitched together using the stitch module.
rib is a string containing additional RIB requests that are written in front
of the frames.
It is possible to attach user RIB requests to an object simply by adding a
string attribute called rib. When present this string will be written right
before the geometry calls. For example, this can be used to set attributes that
are specific to a particular renderer:
s = Sphere(...)
s.rib = 'Attribute "visibility" "transmission" "opaque"'
For an object to be exported as RIB it has to use a geometry that supports the
IGeometry protocol. Materials must support the IMaterial
protocol and light sources the ILightSource protocol. For details on
these protocols see the sub sections below. If there is an object that does not
support one of these protocols an adapter can be written that implements the
protocol on behalf of the original object.
The remainder of this section is meant to be read by developers who want to
extend the functionality of the exporter either by implementing adapter classes
for existing classes or by implementing new geometries, materials or light
sources that natively support the respective protocol.
11.1.1. The IGeometry protocol
Every GeomObject that supports the IGeometry protocol can be
exported as RIB. If the geometry does not support the protocol it will be
ignored.
The IGeometry protocol only specifies the presence of one method:
-
IGeometry.render(matid)
- Creates Ri geometry requests for the geometry that has the material with id
matid assigned to it. The geometry should be created in the local coordinate
system of the GeomObject. The primitive variables should also be
exported. The method can assume that there is already an enclosing
RiAttributeBegin()/RiAttributeEnd() block around the call.
Here is an example of an adapter class that implements the IGeometry
protocol for the SphereGeom (which knows nothing about RenderMan):
import protocols
from ri import *
# Adapter class that implements the IGeometry protocol on behalf of the SphereGeom class
class SphereAdapter:
protocols.advise(instancesProvide=[IGeometry], asAdapterForTypes=[SphereGeom])
def __init__(self, spheregeom, proto):
self.geom = spheregeom
def render(self, matid):
# A sphere can only have one single material
if matid==0:
r = self.geom.radius
RiSphere(r, -r, r, 360)
11.1.2. The IMaterial protocol
A material that supports the IMaterial protocol will be mapped to a
surface shader, displacement shader and interior shader. To support the
IMaterial protocol the following methods have to be implemented:
-
IMaterial.createPasses()
- Returns a list of RenderPass objects necessary for this material
instance. These passes may be used to create environment maps, for example. If
no extra passes are required an empty list has to be returned.
-
IMaterial.preProcess(exporter)
- This method is called before the image is rendered and can be used to create or
copy image maps or do other initializations that have to be done before the
actual rendering starts. The exporter instance is provided as argument to the
method (for example, to find out where image maps are stored).
-
IMaterial.color()
- Return the color (as a 3-sequence of floats) for the RiColor() call. If no
color is required the method may return None in which case no Color call
is made.
-
IMaterial.opacity()
- Return the opacity (as a 3-sequence of floats) for the RiOpacity() call.
If no opacity is required the method may return None in which case no
Opacity call is made.
-
IMaterial.surfaceShaderName()
- Return the name of the surface shader for this material. The exporter may still
modify this name to make it unique among all generated shaders.
-
IMaterial.surfaceShaderSource()
- Return the RenderMan Shading Language source code for the surface shader.
Instead of the shader name the generated source code should contain the variable
$SHADERNAME that will be substituted with the actual name of the shader. The
method may also return None if no shader should be created. In this case,
the name returned by surfaceShaderName() is assumed to be the name of an
existing shader.
-
IMaterial.surfaceShaderParams(passes)
- Returns a dictionary that contains the shader parameters that should be used for
the surface shader. The key is the name of the parameter (including inline
declarations) and the value is the actual parameter value at the current time.
The passes argument contains the list of passes as generated by
createPasses(). This list can be used to obtain the actual name of an
environment map, for example.
-
IMaterial.surfaceShaderTransform()
- Return a mat4 containing the transformation that should be applied to the
shader.
-
IMaterial.displacementShaderName()
- Return the name of the displacement shader for this material. The exporter may
still modify this name to make it unique among all generated shaders. You can
also return None if no displacement shader is required.
-
IMaterial.displacementShaderSource()
- Return the RenderMan Shading Language source code for the displacement shader.
Instead of the shader name the generated source code should contain the variable
$SHADERNAME that will be substituted with the actual name of the shader. The
method may also return None if no shader should be created. In this case,
the name returned by displacementShaderName() is assumed to be the name of
an existing shader.
-
IMaterial.displacementShaderParams(passes)
- Returns a dictionary that contains the shader parameters that should be used for
the displacement shader. The key is the name of the parameter (including inline
declarations) and the value is the actual parameter value at the current time.
The passes argument contains the list of passes as generated by
createPasses().
-
IMaterial.displacementShaderTransform()
- Return a mat4 containing the transformation that should be applied to the
shader.
-
IMaterial.displacementBound()
- Returns a tuple (coordinate system, distance) that specifies the maximum
displacement. The distance is the maximum amount that a surface point is
displaced and is given in the specified coordinate system.
-
IMaterial.interiorShaderName()
- Return the name of the interior shader for this material. The exporter may still
modify this name to make it unique among all generated shaders. You can also
return None if no interior shader is required.
-
IMaterial.interiorShaderSource()
- Return the RenderMan Shading Language source code for the interior shader.
Instead of the shader name the generated source code should contain the variable
$SHADERNAME that will be substituted with the actual name of the shader. The
method may also return None if no shader should be created. In this case,
the name returned by displacementShaderName() is assumed to be the name of
an existing shader.
-
IMaterial.interiorShaderParams(passes)
- Returns a dictionary that contains the shader parameters that should be used for
the interior shader. The key is the name of the parameter (including inline
declarations) and the value is the actual parameter value at the current time.
The passes argument contains the list of passes as generated by
createPasses().
-
IMaterial.interiorShaderTransform()
- Return a mat4 containing the transformation that should be applied to the
shader.
11.1.3. The ILightSource protocol
Every world object that supports the ILightSource protocol will be used
as light source to illuminate the scene. In order to support the
ILightSource protocol the following four methods have to be
implemented:
-
ILightSource.createPasses()
- Returns a list of RenderPass objects necessary for this light source
instance. Usually the light sources will make use of the ShadowPass
pass. If no extra passes are required an empty list has to be returned.
-
ILightSource.shaderName()
- Return the name of the light source shader for this light source. The exporter
may still modify this name to make it unique among all generated shaders.
-
ILightSource.shaderSource()
- Return the RenderMan Shading Language source code for this light source. Instead
of the shader name the generated source code should contain the variable
$SHADERNAME that will be substituted with the actual name of the shader. The
method may also return None if no shader should be created. In this case,
the name returned by shaderName() is assumed to be the name of an existing
shader.
-
ILightSource.shaderParams(passes)
- Returns a dictionary that contains the shader parameters that should be used for
this light source instance. The key is the name of the parameter (including
inline declarations) and the value is the actual parameter value at the current
time. The passes argument contains the list of passes as generated by
createPasses(). This list can be used to obtain the actual name of a
shadow map, for example.
11.1.4. RenderPass — Base class for all passes
The creation of an image may take several render passes where shadow maps,
environment maps and eventually the final image are created. The number of
passes is dependent on the number and types of light sources and the materials
used in the scene. Every render pass is represented by a class that is derived
from the RenderPass class.
An actual pass has to implement the doPass() method where it has to
output a frame block that generates one or more output files. To do the scene
export it can use the methods from the exporter.
-
class RenderPass(output, owner=None)
output is a list of tuples (name, type, mode, params) that each
defines the output to create in this pass. Each tuple contains the parameters
necessary for a RiDisplay() call. name is the name of the output file,
type is the output type (such as “file” or “zfile”), mode specifies what
information will be stored in the file (RI_RGB, RI_RGBA, ...) and
params is a dictionary with extra parameters.
Every RenderPass instance has an attribute exporter that will contain
a reference to the exporter. So the pass object may use the exporter methods to
output the scene.
-
RenderPass.done()
- Check if this pass is already done or not. This method is used when shader
parameters have to be determined. The output of a pass may only be used once the
pass is done and the output really exists (for example, you cannot use a shadow
map until it was created).
-
RenderPass.doPass(framenr)
- This method has to be overwritten in derived classes where the actual frame
block is generated. framenr is the frame number to use for the
RiFrameBegin() call.
-
RenderPass.realFilename(filename)
- Translate the logical file name filename into a real file name. A
ValueError exception is generated if filename is not a logical file
name of this pass.
-
RenderPass.getFilenameTable()
- Return the filename translation table. The return value is a dictionary that
maps logical file names to real file names.
-
RenderPass.setFilenameTable(tab)
- Set an updated filename table. This method is used to set the updated file name
table where no name clashes occur with other passes.
-
RenderPass.initDisplays()
- This method calls RiDisplay() for all specified outputs. This is a helper
method that can be used in doPass().
11.1.5. ImagePass — Creates the final image pass
-
class ImagePass(output, cam)
11.1.6. ShadowPass — Creates a shadow map
-
class ShadowPass(output, light, fov, resolution)
11.1.7. RIBExporter — The exporter class
Besides the usual methods that every exporter must implement this exporter has
the following helper methods that have to be used by RenderPass
objects:
-
RIBExporter.isExportable(wobj)
-
RIBExporter.applyViewTransform(V)
- Applies the view transformation V (given as a mat4). This method corresponds
to a RiConcatTransform() call. It outputs the view transformation V
(which transforms from world to camera coordinates) as a RenderMan
transformation. The handedness of the scene is taken into account.
-
RIBExporter.applyLightSource(lgt)
- Apply the light source lgt which must be a light source world object. This
method corresponds to a RiLightSource() call.
-
RIBExporter.applyTransformation(T, linearvel=None, angularvel=None)
- Apply the transformation T (given as a mat4). This method corresponds to a
RiConcatTransform() call. It outputs T as a RenderMan transformation.
If a linear or angular velocity is given an motion block is written to enable
motion blur.
-
RIBExporter.applyMaterial(mat)
- Apply the material mat which must be a Material object. This method
corresponds to the calls RiColor(), RiOpacity(), RiSurface(),
RiDisplacement() and RiInterior().
-
RIBExporter.applyGeometry(geom)
- Apply the geometry geom which must be a GeomObject.
-
RIBExporter.writeShader(name, source)
- Write a shader source file and return the name of the shader. Usually, you
don’t have to call this method yourself as it is called by the above
applyXyz()-methods.