Render to G-Buffer shader

Language: HLSL

This shader render a mesh by writing to the G-Buffer using multiple render targets.

Code sample

//Matrix used by this shader pass
float4x4 World;
float4x4 View;
float4x4 Projection;
 
//The material properties
 
//The specular coeficients
float specularIntensity = 1.0f;
float specularPower = 32; 
 
//The used textures
bool useTexture = false;
bool useEmissive = false;
bool useNormal = false;
 
//The normal scale
float normalScale = 1.0f;
 
//The base diffuse color
float4 diffuseColor = {1.0f, 1.0f, 1.0f, 1.0f};
 
//The material textures
 
//Diffuse texture
texture diffuseTexture;
sampler diffuseSampler = sampler_state
{
    Texture = (diffuseTexture);
    MAGFILTER = Linear;
    MINFILTER = Linear;
    MIPFILTER = Linear;
    AddressU = Wrap;
    AddressV = Wrap;
};
 
//Normal map
texture normalTexture;
sampler normalSampler = sampler_state
{
    Texture = (normalTexture);
    MAGFILTER = Linear;
    MINFILTER = Linear;
    MIPFILTER = Linear;
    AddressU = Wrap;
    AddressV = Wrap;
};
 
//Emissive map
texture emissiveTexture;
sampler emissiveSampler = sampler_state
{
    Texture = (emissiveTexture);
    MAGFILTER = Linear;
    MINFILTER = Linear;
    MIPFILTER = Linear;
    AddressU = Wrap;
    AddressV = Wrap;
};
 
struct VertexShaderInput
{
    float4 Position : POSITION0;
    float3 Normal : NORMAL0;
    float2 TexCoord : TEXCOORD0;
    float3 Binormal : BINORMAL0;
    float3 Tangent : TANGENT0;
};
 
struct VertexShaderOutput
{
    float4 Position : POSITION0;
    float2 TexCoord : TEXCOORD0;
    float3 Normal : TEXCOORD1;
    float4 PointPosition : TEXCOORD2;
    float3x3 TangentToWorld : TEXCOORD3;
};
 
//A simple vertex shader
VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
    VertexShaderOutput output;
 
    float4x4 worldViewProjection = mul( mul(World, View), Projection);
    output.Position = mul(input.Position, worldViewProjection);
 
    output.TexCoord = input.TexCoord;
 
    //For normal mapping, we need to compute the tangent to world matrix
    output.Normal = mul(input.Normal,World);               
    output.PointPosition = mul(input.Position, World);
    output.TangentToWorld[0] = mul(input.Tangent, World);
    output.TangentToWorld[1] = mul(input.Binormal, World);
    output.TangentToWorld[2] = mul(input.Normal, World);
 
    return output;
}
 
struct PixelShaderOutput
{
    // Position
    float4 MRT1 : COLOR0;    
    // Color and Specular Power
    float4 MRT2 : COLOR1;    
    // Normal and Specular Intensity
    float4 MRT3 : COLOR2;    
    // Emissive light
    float4 MRT4 : COLOR3;
};
 
//This pixel shader write to the G-Buffer using MRT
PixelShaderOutput PixelShaderFunction(VertexShaderOutput input)
{
    PixelShaderOutput output;
 
    //The world position in the scene
    float3 position = input.PointPosition.xyz;
 
    //The diffuse color (albedo)
    float3 color;    
    if(useTexture)
        color = tex2D(diffuseSampler, input.TexCoord);
    else
        color = diffuseColor.rgb;
 
    //The emissive light color
    float3 emissive;    
    if(useEmissive)
        emissive = tex2D(emissiveSampler, input.TexCoord);
    else
        emissive = 0.0f;
 
    //The world space normal
    float3 normal;
    if(useNormal)
    {
        //We sample the normal map
        float3 normalMap = tex2D(normalSampler, input.TexCoord);
        normalMap = 2.0f * normalMap - 1.0f;
        normalMap.xy = normalMap.xy * normalScale;
        normalMap = normalize(normalMap);
 
        //And use the TangentToWorld matrix to transform the sample to world space
        normal = mul(normalMap, input.TangentToWorld);
    }
    else
        normal = input.Normal;
 
    normal = normalize(normal);
 
    //Finally, writing informations to the ouput
    output.MRT1.rgb = position;
    output.MRT1.a = 1.0f;    
 
    output.MRT2.rgb = color;
    output.MRT2.a = specularPower / 255.0f;
 
    output.MRT3.rgb = normal * 0.5f + 0.5f;
    output.MRT3.a = specularIntensity;
 
    output.MRT4.rgb = emissive;
    output.MRT4.a = 1.0f;
 
    return output;
}
 
technique Technique1
{
    pass Pass1
    {
        VertexShader = compile vs_3_0 VertexShaderFunction();
        PixelShader = compile ps_3_0 PixelShaderFunction();
    }
}
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License