Custom Post-process


Contents
Related Links

Overview

Prepar3D supports adding user defined Post-processing. This enables developers to create Post-process effects to simulate sensors, as well as to create custom visual effects. Creating and using a new Post-process effect is a four step process:

  1. Create a custom pixel shader
  2. Create a Post-process description .XML
  3. Add the Post-process to a camera definition in the cameras.cfg

About Custom Post-processes

The custom Post-process framework is geared towards allowing developers to create and add custom effects to cameras. It can expose both the color and depth textures produced by the rendering system, allowing for the creation of effects such as colorization, distortion, custom fog, etc. This document includes code for an example grayscale Post-process as well as a slightly more advanced fisheye distortion example.

Example of Fisheye Distortion Post-process

Fisheye Distortion Sample Image

The Fisheye Post-process Sample consists of two files:


Creating a Custom Post-process for Prepar3D

Pixel Shader Creation

The first and largest step in creating a custom Post-process is to write the pixel shader that defines the behavior the Post-process will have on each pixel of the output. Shaders are written in HLSL (High Level Shader Language), a language based closely on C, but with features and limitations specific to programming graphics hardware. More information can be found here.

To begin, create a text file in the <Prepar3D Path>\ShadersHLSL\Post-process folder with a .psh file extension. Copy the example from the Example.psh Post-process into the file to ensure that the structure and includes are correct.

Determining Inputs

The first line of code must always be:

#include "Quad.sh"

Next, declare the input resources required by the shader. Custom Post-processes can request the output color, or depth, or both. They are requested as follows:

For the color output: Texture2D<float4> srcTex;

For the depth output: Texture2D<Float> srcDepth;

It is important that the texture declarations match exactly, because the names must match the values expected by the application. Only request the inputs that are needed by the post-process.

Writing the Pixel Shader function

Below is an example of an extremely simple pixel shader. Pixel shaders are custom programs that operate once for each pixel in a rendered image. The following shader finds the location of the pixel it is operating on, loads the corresponding value from the input texture, averages the color channels, and passes that value on as the output. Running this Post-process will result in a grayscale image being passed to the output. The Fisheye Effect demonstrates a slightly more complex pixel shader, calculating a distortion value for each pixel. This creates a non-uniform mapping from the input image to the output, which results in the distortion.

float4 PsMain(PsQuad vert) : SV_Target
{
    //Get the UV coordinates of the input
    float X = vert.texcoord.x;
    float Y = vert.texcoord.y;

    // Get the texture dimensions of the input texture.
    uint2 uTDim;
    srcTex.GetDimensions(uTDim.x,uTDim.y);

    //Multiply the UV coordinates( 0.0 - 1.0 ) by the size of the input texture to find the
    //corresponding input pixel
    int3 iTexCoord = int3(uTDim.x * X, uTDim.y * Y, 0);

    // Use these new coordinates to look up the color in the texture
    float4 color = srcTex.Load( iTexCoord );

    //Average the RGB channels to get a grayscale output
    color = ( color.x + color.y + color.z ) / 3;

    return color;
}

The ability to write custom pixel shaders provides a great amount of flexibility to developers. It opens the door to a wide range of effects using the color and depth channels. The only hard requirements for the pixel shader function are that the arguments and return value types remain unchanged. The function name and body may be changed as desired.


Adding the Post-process to Prepar3D

With the custom shader written, adding the Post-process to the shader library is a simple process.

Creating the Post-process Definition .XML

Create another text file, again in the <Prepar3D Path>\ShadersHLSL\Post-process folder with a .XML file extension. Copy in the contents of the Example.XML file. Replace the example effect name, file name, and pixel shader function name with names corresponding to the custom shader. Set the input requests to match the declarations in the shader. Below is the definition for the example post-process:

<?xml version="1.0" encoding="UTF-8"?>

<SimBase.Document Type="AceXML" version="1,0">

    <Post-processEffects.Post-processDefinition>
        <EffectName>Example</EffectName>
        <ShaderFileName>Example.psh</ShaderFileName>
        <ShaderEntryPoint>PsMain</ShaderEntryPoint>
        <ColorRequest>TRUE</ColorRequest>
        <DepthRequest>FALSE</DepthRequest>
        <PreVC>FALSE</PreVC>
    </Post-processEffects.Post-processDefinition>

</SimBase.Document>

Where:

EffectName is the name of the post-process effect. This should match the .xml file name without the .xml extension.
ShaderFileName is the name of the .psh file. This needs to include the .psh extension.
ShaderEntryPoint is the name of the function in the pixel shader (.psh) file that applies the effect.
ColorRequest specifies whether or not the pixel shader needs to color of each pixel. This will most likely always be set to true for most effects.
DepthRequest specifies whether or not the pixel shader needs the depth of each pixel. This is used for more advanced effects such as depth based fog.
PreVC specifies whether or not the pixel shader should be applied before or after panels are drawn in the virtual cockpit. Along with this flag the entire virtual cockpit can be excluded from a post-process. To enable this the ExcludeVcPostProcess must be set to true in the Cameras.cfg file located in the %APPDATA%\Lockheed Martin\Prepar3D v4 directory.

Note that formatting in the .XML file is very important. Do not include any whitespace or carriage returns between the entry tags.

Adding the Post-process to a Camera Definition

The final step in displaying the new Post-process within Prepar3D is to add the Post-process to one or more cameras in the Cameras.cfg file in the %APPDATA%\Lockheed Martin\Prepar3D v4 directory. Up to 16 post-process effects can be applied to a single camera, however to achieve the best performance, limit the number used to as few as possible. Add the following line to the camera config: PostProcess00="PostProcessName" where "PostProcessName" is the name of the .xml file without the .xml extension. Subsequent post-processes can be added by setting PostProcess01 - PostProcess15 in the camera config. Note also that these are applied to the rendered image in the order specified. Refer to the

  • Camera Configuration
  • section for more info on setting up cameras.


    Troubleshooting Custom Post-processes

    Shader Compilation / Initialization

    If the custom post-process effect is not being displayed it most likely due to the shader not compiling. To see compilation errors Content Error Reporting must be enabled. To turn this on set ContentErrorLogging=1 in the [MAIN] section of the Prepar3D.cfg located in the %APPDATA%\Lockheed Martin\Prepar3D v4 directory. Prepar3D must be restarted with this flag enabled and then shut down to have the errors logged. These are logged to the ContentErrorLog.txt located in the %USERPROFILE%\Documents\Prepar3D v4 Files directory.

    .XML Troubleshooting

    Note that formatting in the .XML file is very important. Do not include any whitespace or carriage returns between the entry tags. Also double check that all names match the entries in the PostProcess directory. Base the .xml off of the example listed here to help prevent typos and other errors. All boolean values (ColorRequest, DepthRequest, PreVC) are defaulted to false unless specified otherwise.