Export RIB (Renderman)

The RenderMan RIB Specification is an API developed by Pixar to describe three dimensional scenes. It includes the RenderMan Shading Language.

It is a technical specification for a standard communications protocol between modeling programs and rendering programs capable of producing photorealistic-quality images. In this way, it is similar to PostScript but for describing 3D scenes rather than 2D page layouts.

Selecting a RenderMan installation

Note:
CityEngine does not write the RIB files itself, but makes use of any installed Renderman package (examples are prman, air, 3delight, aqsis, pixie, etc.). Ensure you are using the 64bit version.

Please set the path to the corresponding shared library in Edit > Preferences > Export > RenderMan > RenderMan Library .

Examples for common RIB output libraries are listed in the following table (the library extensions are .so/.dylib/.dll for Linux/OS X/Windows). These libraries are usually found in the lib subdirectory:

RendererLibrary (w/o extension)

PRMan (>= 14)

libprman-xx.x

3Delight

lib3delight

Air

airdlink

Aqsis

libaqsis_ri2rib

Pixie

libri

Export settings

In addition to the general export options, RIB has the following options:

Include Camera Data

If enabled, CityEngine will export additional RIB statements to the primary rib file (current camera position of "Perspective" camera and default lights) to make the exported rib files directly renderable without the need for additional tools.

Write Compressed Files

If enabled, CityEngine will instruct the RIB library to write to compressed/binary rib files (not available with every renderman package).

CGA Mapping to RIB

This section explains the mapping of the CityEngine geometry and material data to the RIB elements.

The implementation of the RIB exporter in the CityEngine follows the RIB specification version 3.2. The specification is freely available at http://www.pixar.com.

Geometry

All meshes are translated using the RiPointsGeneralPolygons API call. All non-empty texture coordinate channels are appended using custom attributes and the numbering of the texture channel is preserved. For example, a single mesh translates into RIB like this:

PointsGeneralPolygons [ ... ] [ ... ] [ ... ] 
  "P" [ ... ] 
  "facevarying normal N" [ ... ]
  "st" [ ... ]
  "facevarying float [2] uv1" [ ... ]
  "facevarying float [2] uv2" [ ... ]
  "facevarying float [2] uv3" [ ... ]
  "facevarying float [2] uv4" [ ... ]
  "facevarying float [2] uv5" [ ... ]

Any of the N, st, uv1, .., uv6 attributes are optional, depending on the settings of the export options and presence of texture coordinates in the mesh.

Material/Shader

CityEngine includes a template RSL shader with a lighting model similar to phong. Upon export the shader is renamed and copied into the target folder, which is handy for quick visualisation tests. The following shader implementation is used:

surface DefaultCityEngineShader 
(
  color diffuseColor = color(1.0, 1.0, 1.0);
  color ambientColor = color(0.0, 0.0, 0.0);
  color specularColor = color(0.0, 0.0, 0.0);
  float shininess = 1.0;
  float reflectivity = 0.0;

  string diffuseMap = "";
  string diffuseMap1 = "";
  string specularMap = "";
  string opacityMap = "";
  string bumpMap = "";
  string normalMap = "";
  
  float diffuseMapScale[2] = { 1, 1 };
  float diffuseMap1Scale[2] = { 1, 1 };
  float specularMapScale[2] = { 1, 1 };
  float opacityMapScale[2] = { 1, 1 };
  float bumpMapScale[2] = { 1, 1 };
  float normalMapScale[2] = { 1, 1 };
  
  float diffuseMapTranslate[2] = { 0, 0 };
  float diffuseMap1Translate[2] = { 0, 0 };
  float specularMapTranslate[2] = { 0, 0 };
  float opacityMapTranslate[2] = { 0, 0 };
  float bumpMapTranslate[2] = { 0, 0 };
  float normalMapTranslate[2] = { 0, 0 };
  
  float diffuseMapRotate = 0.0;
  float diffuseMap1Rotate = 0.0;
  float specularMapRotate = 0.0;
  float opacityMapRotate = 0.0;
  float bumpMapRotate = 0.0;
  float normalMapRotate = 0.0;

  varying float uv1[2] = { 0, 0 };
  varying float uv2[2] = { 0, 0 };
  varying float uv3[2] = { 0, 0 };
  varying float uv4[2] = { 0, 0 };
  varying float uv5[2] = { 0, 0 };
)
{
    // helper variables for texture uv transformation
    float rotPivot[2] = { 0.5, -0.5 };
    point p1 = point(rotPivot[0], 0, rotPivot[1]);
    point p2 = point(rotPivot[0], 1, rotPivot[1]);

    // light independent color (useful to debug)
    float Kg = 0.0;
    color globalColor = color(1, 1, 1);

    // some magic intensity scalings to make it look good :)
    float Ka = 0.3;
    float Kd = 0.6;
    float Ks = 0.1;

    // initialize texture color
    color tex = color(1, 1, 1);

    // please note: 
    // this example shader only uses texture layer 0 and 2 and does not apply uv rotation

    if (diffuseMap != "")
    {
      float u = (s - diffuseMapTranslate[0]) * diffuseMapScale[0];
      float v = (t - diffuseMapTranslate[1]) * diffuseMapScale[1];
      tex *= color texture(diffuseMap, u, v);
    }

    if (diffuseMap1 != "")
    {
      float u = (uv2[0] - diffuseMap1Translate[0]) * diffuseMap1Scale[0];
      float v = (uv2[1] - diffuseMap1Translate[1]) * diffuseMap1Scale[1];
      tex *= color texture(diffuseMap1, u, v);
    }

    /* compute shading variables */
    normal Nf = faceforward(normalize(N), I);
    vector V = -normalize(I);

    /*
     * now add it all together
    */
    Oi = Os;
    Ci = Os * (Cs * tex * ( Kg * globalColor +
                            Ka * ambientColor * ambient() +
                            Kd * diffuseColor * diffuse(Nf) ) +
                            Ks * specularColor * phong(Nf, V, shininess) );
}