Render Pass Merge Shaders

Pass merge shaders combine multiple pass files to a single pass file or image. They have access to all pass files, but only a single sample location at a time. One of the input file may be the currently rendered scene instead of a pass file on disk; in this case the merge shader is called every time the renderer has completed one sample, such as when a lens shader or primary material shader returns.

Here is an example of a simple merge shader that loops over all samples and selects the frontmost, based on its Z depth:

DLLEXPORT int passmerge_version(void) {return(1);}

DLLEXPORT miBoolean passmerge(
    miColor         *dummy,
    miState         *state,
    void            *paras)
    int             best_p = -1, p;
    miScalar        best_z = 1e10, *zp;
    miColor         *src, *tar;

    for (p=0;; p++) {
        zp = mi_renderpass_access(state, p, miRC_IMAGE_Z);
        if (!zp) break;
        if (*zp > 0 && *zp < best_z) {
            best_z = *zp;
            best_p = p;
    if (best_p >= 0) {
        tar = mi_renderpass_access(state, -1,     miRC_IMAGE_RGBA);
        src = mi_renderpass_access(state, best_p, miRC_IMAGE_RGBA);
        *tar = *src;
        if ((int)state->raster_x/3%5 == (int)state->raster_y/3%5)
            switch(best_p) {
              case 0:  tar->a = tar->r = 1; break;
              case 1:  tar->a = tar->g = 1; break;
              case 2:  tar->a = tar->b = 1; break;
              default: tar->a = tar->r = tar->g = tar->b = 1;

The shader first loops over all passes, reading the Z distance from the depth frame buffer ( miRC_IMAGE_RGBA). In pass rendering mode, the color and depth frame buffers always exist. When the lookup fails, the end of the pass list was reached and the loop terminates. Otherwise, for non-infinite depths (*zp = 0), the one closest to the camera is saved in the best_ variables.

When the closest sample was found, assuming one non-infinite distance was found, its color value is copied to the output ( tar), and diagonal white stripes are painted on top. Only the color frame buffer is written to. A better merge shader would write the entire sample, and perform a correct depth-sorted alpha blending loop. This is what the built-in default merge function does. It is very rarely necessary to override the built-in merge function with a custom one like this.

Copyright © 1986, 2013 NVIDIA Corporation