Keywords: main

Next: 3.12 Light Shaders Up: 3. Using and Writing Previous: 3.10 Volume Shaders

# 3.11 Environment Shaders

Environment shaders provide a color for rays that leave the scene entirely, and for rays that would exceed the trace depth limit. Environment shaders are called automatically by mental ray if a ray leaves the scene, or when a ray exceeds the trace depth. It can also be done explicitly by shaders using the mi_trace_environment function:

         mi_reflection_dir(&dir, state);
         if (/* do ray tracing? */)
             mi_trace_reflection (&color, state, &dir);
         else
             mi_trace_environment(&color, state, &dir);
          /* use the returned color */

Environment shaders, like any other shader, may return `miFALSE` to inform the caller that the environment lookup failed. If mental ray falls back on calling the environment shader, it returns the value returned by the environment shader, not necessarily `miFALSE`.

In both the explicit case and the automatic case (when a ray cast by a function call such as mi_trace_reflection leaves the scene without intersecting with any object) mental ray calls the environment shader found in state- >environment. In primary rays, this variable is initialized with the global environment shader in the camera (also found in state- >camera- >environment). Subsequent material shaders get the environment defined in the material if present, or the camera environment otherwise. Material shaders never inherit the environment from the parent shader, they always use the environment in the material or the camera. All other types of shaders inherit the environment from the parent shader.

Here is an example environment shader that uses a texture that covers an infinite sphere around the scene:

         #include <stdio.h>
         #include <mi/shader.h>

         int myenv_version(void) {return(1);}

         miBoolean myenv(
            register miColor      *result,
            register miState      *state,
            register struct myenv *paras)
         {
            register miScalar     theta;
            miVector              coord;

            theta = fabs(state->dir.z)*HUGE < fabs(state->dir.x)
                    ? state->dir.x > 0
                            ? 1.5*M_PI
                            : 0.5*M_PI
                    : state->dir.z > 0
                            ? 1.0*M_PI + atan(state->dir.x /
                                              state->dir.z)
                            : 2.0*M_PI + atan(state->dir.x /
                                              state->dir.z);
            if (theta > 2 * M_PI)
                 theta -= 2 * M_PI;

            coord.x = 1 - theta / (2 * M_PI);
            coord.y = 0.5 * (state->dir.y + 1.0);
            coord.z = 0;

            state->tex = coord;
            return(mi_call_shader(result, miSHADER_TEXTURE,
                                  state, *mi_eval_tag(
                                             &paras->texture)));
         }

This shader gets a single parameter in its shader parameter structure, a `miTag` for a texture shader. The texture is evaluated by storing the texture coordinate in state- >tex and calling the texture shader with mi_call_shader. For a description of texture shaders and how to call them, see the Texture section above.

Next: 3.12 Light Shaders Up: 3. Using and Writing Previous: 3.10 Volume Shaders