Deferred shading using normal map at Direct3D11 (2)

I modified my program to use normal map for deferred shading at Direct3D11.


When the material doesn't have the normal map, the program doesn't refer the normal map and use the vertex normal.
The following image is the normal component of the GBuffer.
Almost of the sponza model has a normal map, but other rigid models like stanford bunny and AT-AT don't have the normal maps.



Images below are the result of deferred shading using point lights.

In the following cases, I explicitly rendered only the sponza model for visual clearness.




I haved pasted my code which generates the GBuffer at Direct3D11. To enable the macros, I used the D3D_SHADER_MACRO structure ( http://d.hatena.ne.jp/hanecci/20120110 ).

static const D3D_SHADER_MACRO shaderMacroArray[ 2 ] = 
  { "DX11_ENABLE_NORMAL_MAP", "1",
    NULL, NULL                     };                                                      
//--------------------------------------------------------------------------------------
//
// Dx11GBuffer.hlsl                  ( hanecci 2012/01/12 )
//
//--------------------------------------------------------------------------------------

#include "Dx11Common.h"

struct VS_INPUT
{
    float4 vPosition    : POSITION;
    float3 vNormal      : NORMAL;
    float2 vTexcoord0   : TEXCOORD0;

#ifdef DX11_ENABLE_NORMAL_MAP
    float3 vTangent     : TANGENT;

  #ifdef DX11_ENABLE_BITANGENT
      float3 vBitangent   : BITANGENT;
  #endif

#endif

};

//--------------------------------------------------------------------------------------

struct VS_OUTPUT
{
    float4 vPositionCS  : SV_Position;
    float2 vTexcoord0   : TEXCOORD;
    float3 vNormalWS    : NORMALWS;
    float3 vPositionWS  : POSITIONWS;

#ifdef DX11_ENABLE_NORMAL_MAP
    float3 vTangentWS   : TANGENTWS;
    float3 vBitangentWS : BITANGENTWS;
#endif

};

//--------------------------------------------------------------------------------------

struct PS_INPUT
{
    float4 vPositionSS : SV_Position;
    float2 vTexcoord0  : TEXCOORD;
    float3 vNormalWS   : NORMALWS;
    float3 vPositionWS : POSITIONWS;

#ifdef DX11_ENABLE_NORMAL_MAP
    float3 vTangentWS   : TANGENTWS;
    float3 vBitangentWS : BITANGENTWS;
#endif

};

//--------------------------------------------------------------------------------------

struct PS_OUTPUT
{
    float4 vNormal         : SV_Target0;
    float4 vPosition       : SV_Target1;
    float4 vDiffuseAlbedo  : SV_Target2;
    float4 vSpecularAlbedo : SV_Target3;
};

//--------------------------------------------------------------------------------------

VS_OUTPUT MainVS( VS_INPUT input )
{
    VS_OUTPUT output;

    output.vPositionWS = mul( input.vPosition, mWorldMatrix ).xyz;
    output.vNormalWS   = normalize( mul( input.vNormal, ( float3x3 ) mWorldMatrix ) );
    output.vPositionCS = mul( input.vPosition, mWorldViewProjectionMatrix );

    output.vTexcoord0  = input.vTexcoord0;

#ifdef DX11_ENABLE_NORMAL_MAP
    float3 tangentWS    = normalize( mul ( input.vTangent.xyz,
                                         ( float3x3 ) mWorldMatrix ) );
    output.vTangentWS   = tangentWS;

    #ifdef DX11_ENABLE_BITANGENT
      float3 bitangentWS  = normalize( mul ( input.vBitangent.xyz,
                                           ( float3x3 ) mWorldMatrix ) );

    #else
      float3 bitangentWS  = normalize( cross( output.vNormalWS, tangentWS ) );
    #endif

    output.vBitangentWS = bitangentWS;
#endif

    return output;
}

//--------------------------------------------------------------------------------------

PS_OUTPUT MainPS( PS_INPUT input )
{
    PS_OUTPUT output;

    output.vPosition       = float4( input.vPositionWS, 1.0f );

    float4 diffuseAlbedo   = float4( 1.0f, 1.0f, 1.0f, 1.0f );
    if ( mEnableDiffuseTexture == 1.0f )
    {
        diffuseAlbedo = mDiffuseTexture.Sample( mLinearSampler, input.vTexcoord0 );
    }
    output.vDiffuseAlbedo = diffuseAlbedo;


#ifdef DX11_ENABLE_NORMAL_MAP
    if ( mEnableNormalTexture == 1.0f )
    {
        float3x3 tangentFrameWS = float3x3( normalize( input.vTangentWS   ),
                                            normalize( input.vBitangentWS ),
                                            normalize( input.vNormalWS ) );
        float3 normalTS = mNormalTexture.Sample( mLinearSampler, input.vTexcoord0 ).rgb;
        normalTS        = normalize( normalTS * 2.0f - 1.0f );

        float3 normalWS = mul( normalTS, tangentFrameWS );
        output.vNormal  = float4( normalWS, 1.0f );
    }
    else
    {
#endif

    float3 normalWS = normalize( input.vNormalWS );
    output.vNormal  = float4( normalWS, normalAlpha );

#ifdef DX11_ENABLE_NORMAL_MAP
    }
#endif

    float4 specularAlbedo = float4( 1.0f, 1.0f, 1.0f, 1.0f );
    if ( mEnableSpecularTexture == 1.0f )
    {
        specularAlbedo = mSpecularTexture.Sample( mLinearSampler, input.vTexcoord0 );
    }
    output.vSpecularAlbedo = specularAlbedo;

    return output;
}

//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
//
// Dx11Common.hlsl                  ( hanecci 2012/01/12 )
//
//--------------------------------------------------------------------------------------

cbuffer cbTransformMatrix : register( b0 )
{
    float4x4        mWorldViewProjectionMatrix : packoffset( c0 );
    float4x4        mWorldViewMatrix           : packoffset( c4 );
    float4x4        mProjectionMatrix          : packoffset( c8 );
    float4x4        mWorldMatrix               : packoffset( c12 );
    float4x4        mViewProjectionMatrix      : packoffset( c16 );
};

cbuffer cbPerMaterial : register( b1 )
{
    float             mEnableTexture        ;
    float             mEnableDiffuseTexture ;
    float             mEnableNormalTexture  ;
    float             mEnableSpecularTexture;
};

//--------------------------------------------------------------------------------------
// Textures and Samplers
//--------------------------------------------------------------------------------------

SamplerState mLinearSampler  : register( s0 );

Texture2D    mDiffuseTexture  : register( t0 );
Texture2D    mNormalTexture   : register( t1 );
Texture2D    mPositionTexture : register( t2 );
Texture2D    mSpecularTexture : register( t3 );

//--------------------------------------------------------------------------------------

struct PointLight
{
    float  mEnable;
    float3 mPosition;

    float4 mColor;

    float  mRadius;
    float3 mAttenuation;
};

StructuredBuffer<PointLight> mPointLightBuffer : register( t5 );

//--------------------------------------------------------------------------------------

void
getGBufferSurfaceAttributes( in  float2 screenPos,
                             out float3 normal,
                             out float3 position )
{
    int3 sampleIndices = int3( screenPos.xy, 0 );

    normal   = mNormalTexture.Load( sampleIndices ).xyz;
    position = mPositionTexture.Load( sampleIndices ).xyz;
}

//--------------------------------------------------------------------------------------

void
getGBufferMaterialAttributes( in  float2 screenPos,
                              out float4 diffuseAlbedo,
                              out float4 specularAlbedo )
{
    int3 sampleIndices = int3( screenPos.xy, 0 );

    diffuseAlbedo  = mDiffuseTexture.Load( sampleIndices ).xyzw;
    specularAlbedo = mSpecularTexture.Load( sampleIndices ).xyzw;
}

//--------------------------------------------------------------------------------------