Project Reality: Shader Model 3.0 Considerations

The Project Reality Team updated Project Reality to support Shader Model 3. The update gave Project Reality more graphical potential. This post considerations when porting shaders from Shader Model 2 to 3.

Fogging

From Shader Model 3, fogging is no longer fixed-function. You must implement your fogging method in the pixel shader.

Output Register Count

Input Register Format

Register Assignments and Declarations

If you encounter the following asm, with constants not declared in ASM.

VertexShader = asm
{
    vs.1.1

    dcl_position0 v0

    add r0.xyz, v0.xzw, -c[0].xyz
    mul r0.xyz, r0.xyz, c[1].xyw // z = 0, w = 1
    add oPos.x, r0.x, -c[1].w
    add oPos.y, r0.y, -c[1].w
    mov oPos.z, r0.z
    mov oPos.w, c[1].w // z = 0, w = 1
    add r1, v0.y, -c[2].x
    mul oD0, r1, c[2].y
    mov oD0.a, c[1].z // z = 0
};

PixelShader = asm
{
    ps.1.1
    mov r0, v0
};

The solution: use the : register() to a shader variable to a particular register. You can read more about it here.

// Assign variables to registers because DICE didn't do so in their ASM.
float4 Constant0 : register(c0); // c[0]
float4 Constant1 : register(c1); // c[1]
float4 Constant2 : register(c2); // c[2]

struct APP2PS_ProjectRoad
{
    float4 Pos : POSITION0;
};

struct VS2PS_ProjectRoad
{
    float4 HPos : POSITION;
    float4 Color : TEXCOORD0;
};

// VertexShader
VS2PS_ProjectRoad VS_ProjectRoad(APP2PS_ProjectRoad Input)
{
    VS2PS_ProjectRoad Output = (VS2PS_ProjectRoad)0.0;

    // add r0.xyz, v0.xzw, -c[0].xyz
    // mul r0.xyz, r0.xyz, c[1].xyw // z = 0, w = 1
    float3 ProjPos = Input.Pos.xzw - Constant0.xyz;
    ProjPos *= Constant1.xyw; // z = 0, w = 1

    // add oPos.x, r0.x, -c[1].w
    // add oPos.y, r0.y, -c[1].w
    // mov oPos.z, r0.z
    // mov oPos.w, c[1].w // z = 0, w = 1
    Output.HPos.x = ProjPos.x - Constant1.w;
    Output.HPos.y = ProjPos.y - Constant1.w;
    Output.HPos.z = ProjPos.z;
    Output.HPos.w = Constant1.w; // z = 0, w = 1

    // add r1, v0.y, -c[2].x
    // mul oD0, r1, c[2].y
    // mov oD0.a, c[1].z // z = 0
    float4 Color = Input.Pos.y - Constant2.x;
    Output.Color = Color * Constant2.y;
    Output.Color.a = Constant1.z; // z = 0
    Output.Color = saturate(Output.Color);

    return Output;
}

// PixelShader
float4 PS_ProjectRoad(VS2PS_ProjectRoad Input) : COLOR0
{
    // mov r0, v0
    return Input.Color;
}