Renderman -Physically Plausible Shading.

The most important things about pnysicallu plausible shading from Renderman docs

Integrators first request samples from light shaders and it is this collection of samples that are delivered to your material's evaluateSamples method

It is the responsibility of the material to compute the materialResponse for each incoming sample according to the integrators' distribution requests. These samples may arrive from any source of radiance, along direct or indirect light paths.

Using the indirectspecular Integrator

Samples for indirectspecular integrator  are generated  by   generateSamples

Writing an MIS-aware Material

The new directlighting integrator uses a technique called Multiple Importance Sampling (MIS).

Finally, to support the full MIS framework, a light must implement the evaluateSamples method. In this context the material has identified important directions and the light must now write to the radiance and lightPdf fields. Typically, the light must determine whether a ray from the surface point along the provided direction would intersect the geometry of the light. For simple area light shapes, this is a simple computation. If the intersection point is at a distance farther than the current value of the distance field, a light should leave the sample untouched. To handle arbitrary shapes for area lights, a future release of PRMan will offer facilities to automatically compute the intersection.

It is also important to remember, as pointed out in the previous section, that the light must produce the same radiance and lightPdfvalues whether from generateSample or evaluateSample. Assymetries will produce unbalanced results.

Porting RSL to C++

In RSL many shading points are run in parallel and thus this cost has always been assumed to be leveraged.

Unfortunately, with the introduction of ray tracing, it is getting more and more difficult to shade multiple points at once, since divergent rays are likely to hit completely different objects and shaders. In practice, for an indoor scene, where almost every ray hits something, we found that 80% of the shaders can't be combined.

RSL to C++

 The shader only have to differentiate, per grid operation and per shading point operation by using the 2 keywords uniform and varying in front of each variable.

Optimizing C++

Changing the loop order gives us an additional 20% speedup for large grids and 10% for small grids.

C++ to ispc

ispc is the new Intel spmd program compiler. It uses a C-like syntax and generates a .o file that we can link as usual into a DSO. The difference between ispc and other parallel programming librairies is that ispc operates on SIMD lanes, while others are focusing on utilizing multicores. ispc performs optimizations and tranforms the program in a vector intermediate representation of LLVM. Then the final compilation is handled by LLVM.

Optimizing ispc

uniform conditionals are optimized in ispc, but ispc also provides an improved if for varying conditionals. These are called consistent branchings (cif, cwhile) and hint to the compiler that the result is likely going to be the same for all the points. This will create a special optimized code path for this branching.

Changing the array memory layout is going to have an impact on the whole shader system, so this time we only modified the layout of local arrays.

Results

Using RSL pipeline Methods

diffuselighting()  - compute view-independent shading which may be cached, method may be skipped if a value for its result is available in the cache. The pipeline will resume at specularlighting() with the Ci that was read from the cache. When caching occurs, the pipeline is run up to diffuselighting() on a different shading manifold or grid than that which will be shaded upon for later specular contributions.

diffuselighting() Only.

 run for diffuse rays and is cached. It is also run for raytrace hider camera rays and is cached. Specular rays obtain this cached result - if it exists - and invoke the pipeline while skipping over thediffuselighting() method (whose results are known). If no cached result exists, the pipeline is run up to the diffuselighting() method, and a result inserted into the cache. Shading then proceeds as if the result already existed (see above). In other words, shading does occur on specular rays, but is seeded with the diffuselighting() cached result.

specularlighting()  -  compute view-dependent shading which is not cached, but builds upon an input value which may have resulted from a cache lookup of view-independent results.

 specularlighting() Only. No diffuse component and diffuse rays trivially return black. specularlighting() is invoked in all other circumstances. Conductors are one class of material that are efficiently expressed with only a specularlighting() method. No results are inserted into the radiosity cache; none are looked up.

lighting() -  produce a full computation of all lighting interaction when the renderer knows it will require a full result.

lighting() + diffuselighting(). This combination signals the intent that specular and camera rays contain a view-dependent diffuse term. The lighting() method is utilized for REYES hider shading and ray-traced shading (specular and camera rays). The diffuselighting() method is invoked for diffuse rays - Its result is cached. For diffuse rays if a value exists in the cache, no further shading evaluation occurs.

The lighting() method is free to be view-dependent in both its specular term (which is always view-dependent) and in its diffuse term.

lighting() + diffuselighting() + specularlighting(). When the fully shaded result with both specular and diffuse contributions is required, it is typically more efficient to evaluate both at once, cause the light samples - those dictated by the light rather than the BRDF for Multiple Importance Sampling purposes - may be shared between both the specular and diffuse computations - single set of transmission rays is required rather than two - one for the diffuse and one for the specular. When only the diffuselighting() and specularlighting() methods exist, each is responsible for its own integration. Each would typically ask the lights for their samples and evaluate and shadow them.

For camera rays, the diffuse result is found in the cache (or evaluated and cached if it does not exist). The pipeline is run and diffuselighting() is skipped - its result is known from the cache. The input Ci to specularlighting() is the value resulting from the cache.

For REYES shading, the lighting() method is run.

The diffuselighting() and lighting() methods should generally agree with each other with respect to the view-independent nature of the diffuse term. If a view-dependent diffuse is absolutely required, the REYES shading may have a view-dependent diffuse term via the lighting()method. Be aware that this will create look differences between the raytrace and REYES hiders.

The caching opportunities are outlined below:

caching mechanism

meaning

REYES

Caching of results from an extended lighting() method may be shared with diffuse-depth 0 rays.

specular ray

Specular rays will invoke diffuselighting(), which is cached. In combination with REYES caching, this cached result may be used in REYES shading, where available. In such cases the diffuselighting() method may be invoked for REYES shading as well as for ray-traced shading.

Specular rays may reuse the cached diffuselighting() results, and may thereby reduce the shading workload. However, the benefits of doing so are scene-dependent as there is also a cost to the separate computation (and shadowing of) the diffuse and specular results.

raytrace hider camera ray

Camera rays in the raytrace hider will invoke separate diffuselighting() andspecularlighting() methods. The diffuselighting() results may be cached. Note that the coherency of rays generated by the raytrace hider lead to a cost-benefit tradeoff which differs from what is typical for specular rays. In particular, with pixel samples > 1x1, caching of the radiosity via thediffuselighting() method is generally very beneficial.

diffuse ray

Diffuse rays cache the radiosity via diffuselighting(). Note: modes that disable this will lead to a significant increase in the cost of computingindirectdiffuse()

subsurface ray

Irradiance results provided by diffuselighting() will be cached and reused by the subsurface() shadeop. Note that there is currently no way to turn off this caching independently of the other caching opportunities.

transmission ray

Opacity may be cached and reused by the transmission() andareashadow(). Note that under __computesOpacity == 2, the opacity is not cached. Opacity is also cached to determine ray continuation for all other ray types. This is not disabled under __computesOpacity == 2.