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
Shader Model 2 vertex shaders have a certain number of output registers for each type of data.
- oPos:
1 position
- oFog:
1 fog
- oPts:
1 point-size
- oD#:
2 vertex color
- oT#:
8 texture coordinate
In Shader Model 3, you have 12 output registers available for any type of data.
Input Register Format
In Shader Model 2, output registers have different levels of precision.
When you port vertex colors
oD#
from Shader Model 2 to 3, you must applysaturate()
to the vertex color output.
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;
}