XNA Code Snippet: My HLSL (*.fx file) for rendering the Aircraft

October 24th, 2006 by Sharky

kick it on GameDevKicks.com 

 

I promised I’d start sharing some snippets of source, so here’s the HLSL Shader code (an *.fx file) I use for rendering my Aircraft.  (as requested by Omegaman)

Those familiar with the XNA “Spacewars” sample will see an uncanny the resemblance to the sample’s Ship.fx file.  In fact it’s probably barely changed. Perhaps some trimming here and there, but I really can’t remember.

It’s pretty scary HLSL for a beginner like me.  I’d love to be able to explain it to folk, but frankly I barely understand it myself!  ;)

(next time hopefully I’ll be posting some HLSL I can at least reasonably explain)

I will try and describe its characteristics though:

  • It lights & shades the model with a provided Ambient color, a Directional light and a Point light.  Directional light is a color of light cast in a particular direction, from no particular point in space.  In other words, its brightness is the same no matter where the model is in space.  Point light however is a color radiating out from a point in space, so the closer the model is to it, the stronger the effect.
  • SkinTexture is the painted skin of the model…duh!
  • ReflectionTexture is special kind of texture – a TextureCube.  I haven’t really experimented with it but I believe the texture passed would be a mock up of the typical world around the model, and it would be rendered as ‘good enough’ reflections on the model.  I say ‘good enough’ because you’d probably have a static TextureCube of a typical sky, clouds and ground, rather than dynamically create one with the exact rendered background and moving clouds.  To do so, might be possible, but I imagine a performance killer if you had to do it on every frame.
  • I think the NormalMap stuff might be redundant actually.
//Input variables
float4x4 world;
float4x4 inverseWorld;
float4x4 worldViewProjection;
float4 viewPosition;
float4 Ambient;
float4 DirectionalDirection;
float4 DirectionalColor;
float4 PointPosition;
float4 PointColor;
float PointFactor;
float4 Material;
texture SkinTexture;
sampler Skin = sampler_state
{
Texture = (SkinTexture);
ADDRESSU = CLAMP;
ADDRESSV = CLAMP;
MAGFILTER = LINEAR;
MINFILTER = LINEAR;
MIPFILTER = LINEAR;
};
texture NormalMapTexture;
sampler NormalMap = sampler_state
{
Texture = (NormalMapTexture);
ADDRESSU = CLAMP;
ADDRESSV = CLAMP;
MAGFILTER = LINEAR;
MINFILTER = LINEAR;
MIPFILTER = LINEAR;
};
texture ReflectionTexture;
sampler Reflection = sampler_state
{
Texture = (ReflectionTexture);
ADDRESSU = CLAMP;
ADDRESSV = CLAMP;
MAGFILTER = LINEAR;
MINFILTER = LINEAR;
MIPFILTER = LINEAR;
};
struct VS_INPUT
{
    float4 ObjectPos: POSITION;
    float2 Tex : TEXCOORD0;
    float3 ObjectNormal : NORMAL;
};
struct VS_OUTPUT
{
float4 ScreenPos: POSITION;
float2 Tex: TEXCOORD0;
float3 WorldNormal: TEXCOORD1;
float4 PointDirection: TEXCOORD2;
};
VS_OUTPUT AircraftVS(VS_INPUT In)
{
VS_OUTPUT Out;
    //Move to screen space
    Out.ScreenPos = mul(In.ObjectPos, worldViewProjection);
    
    float4 WorldPos = mul(In.ObjectPos, world);
    float4 WorldNormal = mul(In.ObjectNormal, world);
    
    //Pass on texture coordinates and normal
    Out.Tex = In.Tex;
    Out.WorldNormal = WorldNormal;
    //Direction of point light to this vertex
    float4 lightDir;
    lightDir= PointPosition - WorldPos;
    float dist = length(lightDir);
    lightDir = lightDir/dist;
    
    //Store attenuation in w
    lightDir.w = saturate(1/(PointFactor * dist));
    Out.PointDirection = lightDir;
return Out;
}
float4 DirectionalLight(float3 WorldNormal)
{
    return DirectionalColor * saturate(dot(WorldNormal, normalize(DirectionalDirection)));
}
float4 PointLight(float3 Normal, float4 PointDirection)
{
    return PointColor * saturate(PointDirection.w * dot(Normal, normalize(PointDirection.xyz)));
}
float4 AircraftPS( float2 tex: TEXCOORD0, float3 WorldNormal : TEXCOORD1, float4 PointDirection : TEXCOORD2) : COLOR
{
    WorldNormal = normalize(WorldNormal);
    
    float4 Directional = DirectionalLight(WorldNormal);
    float4 Point = PointLight(WorldNormal, PointDirection);
    
    //Specular map is in alpha of diffusemap and material
    float MattFactor = Material.a * tex2D(Skin, tex).a;
    //Add it all up
    float4 retval;
    retval= saturate(
                Material *
                (                                        //Remove alpha channel from texture
                    ((Ambient + Directional + Point) * float4(tex2D(Skin, tex).rgb, 1)) +
                    (1-MattFactor) * texCUBE(Reflection, WorldNormal)
                )
            );
    
    
    return retval;
}
//--------------------------------------------------------------//
// Technique Section for Aircraft Effects
//--------------------------------------------------------------//
technique Aircraft
{
pass Single_Pass
{
        ZENABLE = TRUE;
        ZWRITEENABLE = TRUE;
        
        CULLMODE = CW;
        VertexShader = compile vs_1_1 AircraftVS();
        PixelShader = compile ps_2_0 AircraftPS();
}
}

Leave a Reply