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; } //--------------------------------------------------------------------------------------