www.pudn.com > GPUGeometryClipmaps.rar > ComputeNormals.fx


texture heightVals; 
texture coarserNormalsTexture; 
 
uniform float  OneOverSize; 
uniform float  Size; 
uniform float2 Viewport; 
uniform float2 ToroidalOrigin; 
uniform float2 TextureOffset; 
uniform float2 ScaleFac; 
 
uniform sampler ElevationSampler = sampler_state            
{ 
    Texture   = (heightVals); 
    MipFilter = None; 
    MinFilter = Point; 
    MagFilter = Point; 
    AddressU  = Wrap; 
    AddressV  = Wrap; 
}; 
 
uniform sampler CoarseLeveNormalSampler = sampler_state          
{ 
    Texture   = (coarserNormalsTexture); 
    MipFilter = None; 
    MinFilter = Linear; 
    MagFilter = Linear; 
    AddressU  = Wrap; 
    AddressV  = Wrap; 
}; 
 
struct OUTPUT 
{ 
    vector position   : POSITION; 
    float2 texcoords  : TEXCOORD0; 
}; 
 
OUTPUT ComputeNormalsVS(float3 position : POSITION, float2 texcoords : TEXCOORD0) 
{ 
    OUTPUT output; 
    output.position   = float4(float2(position.x,-position.y) + float2(-1.0, 1.0)/Viewport,0.0,1.0);  
    output.texcoords  = texcoords*Size; 
     
    return output; 
} 
 
float4 ComputeNormalsPS(OUTPUT input) : COLOR 
{    
    input.texcoords  = floor(input.texcoords); 
     
    // compute a local tangent vector along the X axis 
    float2 texcoord0 = float2(input.texcoords.x-1, input.texcoords.y)*OneOverSize; 
    float z1         = floor(tex2D(ElevationSampler, texcoord0+0.5*OneOverSize));   
    float2 texcoord1 = float2(input.texcoords.x+1, input.texcoords.y)*OneOverSize; 
    float z2         = floor(tex2D(ElevationSampler, texcoord1+0.5*OneOverSize)); 
    float zx         = z2-z1; 
     
    // compute a local tangent vector along the Y axis 
    texcoord0 = float2(input.texcoords.x, input.texcoords.y-1)*OneOverSize; 
    z1        = floor(tex2D(ElevationSampler, texcoord0+0.5*OneOverSize));  
    texcoord1 = float2(input.texcoords.x, input.texcoords.y+1)*OneOverSize; 
    z2        = floor(tex2D(ElevationSampler, texcoord1+0.5*OneOverSize)); 
    float zy = z2-z1; 
 
    // The normal is now the cross product of the two tangent vectors 
    // normal = (2*sx, 0, zx) x (0, 2*sy, zy), where sx, sy = gridspacing in x, y 
    // the normal below has n_z = 1 
    // ScaleFac = -0.5*ScaleFac.z/ScaleFac.x, -0.5*ScaleFac.z/ScaleFac.y 
    float2 normalf = float2(zx*ScaleFac.x, zy*ScaleFac.y); 
         
    // pack coordinates in [-1, +1] range to [0, 1] range 
    normalf = normalf/2 + 0.5; 
     
    // lookup the normals at the coarser level and pack it in normal map for current level 
    float2 texcoordc = frac(input.texcoords/Size-ToroidalOrigin+1)/2.0+TextureOffset; 
    float2 normalc = tex2D(CoarseLeveNormalSampler, texcoordc+0.5*OneOverSize); 
    return float4(normalf.xy, normalc.xy); 
} 
 
technique ComputeNormals 
{ 
    pass P0 
    { 
        VertexShader = compile vs_3_0 ComputeNormalsVS(); 
        PixelShader  = compile ps_2_a ComputeNormalsPS(); 
    } 
}