API Guide > Viewport 2.0 API > Maya Viewport 2.0 API Guide > 4. Advanced Topics >

# 4.4 Effects interfaces

## 4.4.1 SSAO (Screen-space ambient occlusion) control

The information in MPassContext provides sufficient information to indicate when a plug-in is being invoked for rendering certain passes required to support SSAO (screen-space ambient occlusion).

The internal algorithm for SSAO requires a specific normal-depth pass to produce intermediate results. By default, the renderer sets up a specific shader to be used in this pass. In the case where a plug-in shader causes geometry to be displaced or normal to be modified, it is possible to override this default shader.

This normal-depth pass can be detected by querying MPassContext information in a similar fashion to how shadow map passes can be detected (see Section 4.2.1 Shadowing control). For this pass, the pass identifier is: MPassContext::kNormalDepthPassSemantic.

If any tessellation shaders are required, then the override should be added to an MPxShaderOverride instead of an MShaderInstance.

To add support, any custom shader should take into account the following conditions.

- Two color targets are bound during the normal-depth pass:
  - Color target 0 has an unsigned fixed-point RGB format
  - Color target 1 has a floating point single channel (R) format
  - The current target information should be available from MFrameContext when this is available to the plug-in.
- Geometry Requirements:
  - Object space normal stream.
  - Object space position stream.
- Required output values:
  - Normalized normal values (unsigned and in world space) written to color target 0.
  - Depth values (in world space) written to color target 1.

The following is a sample of the shader used for this pass, written in HLSL:

    // Vertex shader input structure.
    struct VS_INPUT_NormalDepth
    {
        float3 Pos : POSITION;
        float3 Normal: NORMAL;
    };

    // Vertex shader output structure.
    struct VS_TO_PS_NormalDepth
    {
        float4 HPos : SV_Position;
        float4 NormalDepth : TEXCOORD0;
    };

    // Vertex shader.
    VS_TO_PS_NormalDepth VS_NormalDepth(VS_INPUT_NormalDepth In)
    {
        VS_TO_PS_NormalDepth Out;

        // Transform the vertex from object space to clip space.
        Out.HPos = mul(float4(In.Pos, 1.0f), gWVPXf);

        // Record the normal and depth components for the pixel shader.
        Out.NormalDepth.xyz = mul(In.Normal, gWVITXf);
        Out.NormalDepth.w = mul(float4(In.Pos, 1.0f), gWVXf).z;

        return Out;
    }

    // Pixel shader output structure.
    struct PS_OUT
    {
        float4 Normal : SV_Target0;
        float4 Depth : SV_Target1;
    };

    // Pixel shader.
    PS_OUT PS_NormalDepth(VS_TO_PS_NormalDepth In)
    {
        PS_OUT Out;

        // Set the normal for an unsigned normalized integer target, and depth for a floating-point
        // target.
        Out.Normal = float4((normalize(In.NormalDepth.xyz) + 1.0f) * 0.5f, 0.0f);
        Out.Depth  = In.NormalDepth.wwww;

        return Out;
    }

NoteDescribed above is the behavior of the internal pass for Maya 2014.
ImportantFor geometry requirements on a custom shader, if the appropriate input streams are not provided, then the renderer internally attempts to create them. This may occur per frame and thus affect performance. As an example, if an MPxGeometryOverride were written to provide the geometry for the custom shader, and the code only returns position but not normal streams, then an attempt to internally derive normal values occurs.