Light Prepass test in Direct3D11 (2)
I have implemented light prepass in Direct3D11. Here are some screenshots.
Diffuse light component in Light buffer

Specular light component in Light buffer

And I have pasted the D3D11 HLSL shader codes below.
//--------------------------------------------------------------------------------------
//
// Dx11Common.hlsl ( hanecci 2012/02/28 )
//
//--------------------------------------------------------------------------------------
#define DX11_MAX_POINT_LIGHT_NUM 16
//--------------------------------------------------------------------------------------
cbuffer cbTransformMatrix : register( b0 )
{
float4x4 mWorldViewProjectionMatrix : packoffset( c0 );
float4x4 mWorldViewMatrix : packoffset( c4 );
float4x4 mProjectionMatrix : packoffset( c8 );
float4x4 mWorldMatrix : packoffset( c12 );
float4x4 mViewProjectionMatrix : packoffset( c16 );
float4 mCameraWorldPos : packoffset( c20 );
};
static float cMaterialSpecularExponent = 10;
cbuffer cbPerMaterial : register( b1 )
{
float mEnableTexture ;
float mEnableDiffuseTexture ;
float mEnableNormalTexture ;
float mEnableSpecularTexture;
float mEnableDirectionalLight;
float mEnablePointLight;
float mEnableDiffuseLighting;
float mEnableSpecularLighting;
};
//--------------------------------------------------------------------------------------
static const float3 cAmbientLightColor = float3( 0.05f, 0.05f, 0.05f );
static const float3 cDirectionalLightWorldDir = float3( 0.0f, -1.0f, 0.0f );
static const float3 cDirectionalLightDiffuseColor = float3( 1.0f, 1.0f, 1.0f );
static const float3 cDirectionalLightSpecularColor = float3( 1.0f, 1.0f, 1.0f );
static const float cDirectionalLightDiffuseScale = 0.5f;
static const float cDirectionalLightSpecularScale = 0.5f;
//--------------------------------------------------------------------------------------
// Textures and Samplers
//--------------------------------------------------------------------------------------
SamplerState mLinearSampler0 : register( s0 );
SamplerState mLinearSampler1 : register( s1 );
Texture2D mDiffuseTexture : register( t0 );
Texture2D mNormalTexture : register( t1 );
Texture2D mPositionTexture : register( t2 );
Texture2D mSpecularTexture : register( t3 );
Texture2D mLightTexture : register( t4 );
//--------------------------------------------------------------------------------------
struct PointLight
{
float mEnable;
float3 mPosition;
float4 mDiffuseColor;
float4 mSpecularColor;
float mRadius;
float3 mAttenuation;
};
static const int cMaxPointLightNum = DX11_MAX_POINT_LIGHT_NUM ;
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;
}
//--------------------------------------------------------------------------------------
float4
getLightTextureAttributes( in float2 screenPos )
{
int3 sampleIndices = int3( screenPos.xy, 0 );
return mLightTexture.Load( sampleIndices );
}
//--------------------------------------------------------------------------------------//--------------------------------------------------------------------------------------
//
// GBufferDx11.hlsl ( hanecci 2012/02/28 )
//
//--------------------------------------------------------------------------------------
#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;
#ifdef DX11_ENABLE_MATERIAL_GBUFFER
float4 vDiffuseAlbedo : SV_Target2;
float4 vSpecularAlbedo : SV_Target3;
#endif
};
//--------------------------------------------------------------------------------------
VS_OUTPUT MainVS( VS_INPUT vs_input )
{
VS_OUTPUT vs_output;
vs_output.vPositionWS = mul( vs_input.vPosition, mWorldMatrix ).xyz;
vs_output.vNormalWS = normalize( mul( vs_input.vNormal, ( float3x3 ) mWorldMatrix ) );
vs_output.vPositionCS = mul( vs_input.vPosition, mWorldViewProjectionMatrix );
vs_output.vTexcoord0 = vs_input.vTexcoord0;
#ifdef DX11_ENABLE_NORMAL_MAP
float3 tangentWS = normalize( mul ( vs_input.vTangent.xyz,
( float3x3 ) mWorldMatrix ) );
vs_output.vTangentWS = tangentWS;
#ifdef DX11_ENABLE_BITANGENT
float3 bitangentWS = normalize( mul ( vs_input.vBitangent.xyz,
( float3x3 ) mWorldMatrix ) );
#else
float3 bitangentWS = normalize( cross( vs_output.vNormalWS, tangentWS ) );
#endif
vs_output.vBitangentWS = bitangentWS;
#endif
return vs_output;
}
//--------------------------------------------------------------------------------------
PS_OUTPUT MainPS( PS_INPUT ps_input )
{
PS_OUTPUT ps_output;
ps_output.vPosition = float4( ps_input.vPositionWS, posAlpha );
#ifdef DX11_ENABLE_NORMAL_MAP
if ( mEnableNormalTexture == 1.0f )
{
float3x3 tangentFrameWS = float3x3( normalize( ps_input.vTangentWS ),
normalize( ps_input.vBitangentWS ),
normalize( ps_input.vNormalWS ) );
float3 normalTS = mNormalTexture.Sample( mLinearSampler0, ps_input.vTexcoord0 ).rgb;
normalTS = normalize( normalTS * 2.0f - 1.0f );
float3 normalWS = mul( normalTS, tangentFrameWS );
ps_output.vNormal = float4( normalWS, normalAlpha );
}
else
{
#endif
float3 normalWS = normalize( ps_input.vNormalWS );
ps_output.vNormal = float4( normalWS, normalAlpha );
#ifdef DX11_ENABLE_NORMAL_MAP
}
#endif
#ifdef DX11_ENABLE_MATERIAL_GBUFFER
float4 diffuseAlbedo = float4( 1.0f, 1.0f, 1.0f, 1.0f );
if ( mEnableDiffuseTexture == 1.0f )
{
diffuseAlbedo =
mDiffuseTexture.Sample( mLinearSampler0,
ps_input.vTexcoord0 );
}
ps_output.vDiffuseAlbedo = diffuseAlbedo;
float4 specularAlbedo = float4( 1.0f, 1.0f, 1.0f, 1.0f );
if ( mEnableSpecularTexture == 1.0f )
{
specularAlbedo =
mSpecularTexture.Sample( mLinearSampler0, ps_input.vTexcoord0 );
}
specularAlbedo.w = cMaterialSpecularExponent;
ps_output.vSpecularAlbedo = specularAlbedo;
#endif
return ps_output;
}
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
//
// Dx11LightBuffer.hlsl ( hanecci 2012/02/28 )
//
//--------------------------------------------------------------------------------------
#include "Dx11Common.h"
//--------------------------------------------------------------------------------------
struct VS_Input
{
float4 vPosition : POSITION;
};
//--------------------------------------------------------------------------------------
struct PS_Input
{
float4 vPosition : SV_Position;
};
//--------------------------------------------------------------------------------------
PS_Input MainVS( VS_Input vs_input )
{
PS_Input ps_input = ( PS_Input ) 0;
ps_input.vPosition = vs_input.vPosition;
return ps_input;
}
//--------------------------------------------------------------------------------------
float4
calcDirectionalLighting( float3 surfaceWorldPos,
float3 surfaceWorldNormal,
float3 lightWorldDir,
float3 lightDiffuseColor,
float lightDiffuseScale,
float lightSpecularScale,
float specularExponent )
{
float4 color = float4( 0.0f, 0.0f, 0.0f, 0.0f );
float3 lightDir = - lightWorldDir;
float dotValue = saturate( dot( lightDir, surfaceWorldNormal ) );
// Diffuse lighting
float3 diffuseColor = float3( 0.0f, 0.0f, 0.0f );
float specularValue = 0.0f;
if ( mEnableDiffuseLighting )
{
diffuseColor = dotValue * lightDiffuseScale * lightDiffuseColor;
}
// Specular lighting
if ( mEnableSpecularLighting )
{
float3 eyeWorldDir =
normalize( mCameraWorldPos.xyz - surfaceWorldPos );
float3 halfDir =
normalize( ( eyeWorldDir + lightDir ) );
float dotValue =
max( dot( surfaceWorldNormal, halfDir ), 0.0f );
specularValue =
lightSpecularScale * pow( dotValue, specularExponent );
}
color.xyz = diffuseColor;
color.w = specularValue;
return color;
}
//--------------------------------------------------------------------------------------
// Blinn-Phong
float4
calcPointLighting( float3 surfaceWorldPos,
float3 surfaceWorldNormal,
float specularExponent )
{
float4 color = float4( 0.0f, 0.0f, 0.0f, 0.0f );
// Specular lighting
float3 eyeWorldDir = float3( 0.0f, 0.0f, 0.0f );
if ( mEnableSpecularLighting )
{
eyeWorldDir = normalize( mCameraWorldPos.xyz - surfaceWorldPos );
}
for ( int index = 0; index < cMaxPointLightNum; index++ )
{
float enableLight = mPointLightBuffer[ index ].mEnable;
float3 lightWorldPos = mPointLightBuffer[ index ].mPosition;
float3 lightDiffuseColor = mPointLightBuffer[ index ].mDiffuseColor.xyz;
float3 lightSpecularColor = mPointLightBuffer[ index ].mSpecularColor.xyz;
float lightRadius = mPointLightBuffer[ index ].mRadius;
float3 lightAttenuation = mPointLightBuffer[ index ].mAttenuation.xyz;
float3 lightWorldPosVec = lightWorldPos - surfaceWorldPos;
float3 lightWorldDir = normalize( lightWorldPosVec );
float dotValue = max( dot( lightWorldDir, surfaceWorldNormal ), 0.0f );
float3 diffuseColor = float3( 0.0f, 0.0f, 0.0f );
float specularValue = 0.0f;
// dist
float lightWorldDist = length( lightWorldPosVec );
float attenuation = 1.0f / (
lightAttenuation.z * lightWorldDist * lightWorldDist
);
attenuation *= saturate( sign( lightRadius - lightWorldDist ) );
float lightScale = ( enableLight * dotValue * attenuation );
if ( mEnableDiffuseLighting )
{
diffuseColor = lightDiffuseColor;
}
if ( mEnableSpecularLighting )
{
float3 halfDir =
normalize( ( eyeWorldDir + lightWorldDir ) );
float specularDotValue =
max( dot( surfaceWorldNormal, halfDir ), 0 );
specularValue =
lightScale * pow( specularDotValue,
specularExponent );
}
color.xyz += lightScale * diffuseColor;
color.w += specularValue;
}
return color;
}
//--------------------------------------------------------------------------------------
float4
MainPS( PS_Input ps_input ) : SV_Target
{
float3 worldNormal;
float3 worldPosition;
getGBufferSurfaceAttributes( ps_input.vPosition.xy,
worldNormal,
worldPosition );
float4 color = float4( 0.0f, 0.0f, 0.0f, 0.0f );
float specularExponent = cMaterialSpecularExponent;
if ( mEnableDirectionalLight )
{
color.xyzw += calcDirectionalLighting( worldPosition,
worldNormal,
cDirectionalLightWorldDir,
cDirectionalLightDiffuseColor,
cDirectionalLightDiffuseScale,
cDirectionalLightSpecularScale,
specularExponent );
}
if ( mEnablePointLight )
{
color.xyzw += calcPointLighting( worldPosition,
worldNormal,
specularExponent );
}
color = saturate( color );
return color;
}
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
//
// Dx11LightPrepass.hlsl ( hanecci 2012/02/28 )
//
//--------------------------------------------------------------------------------------
#include "Dx11Common.h"
//--------------------------------------------------------------------------------------
struct VS_Input
{
float3 vPosition : POSITION;
float3 vNormal : NORMAL;
float2 vTexcoord0 : TEXCOORD0;
};
//--------------------------------------------------------------------------------------
struct VS_Output
{
float4 vPosition : SV_POSITION;
float2 vTexcoord0 : TEXCOORD0;
};
//--------------------------------------------------------------------------------------
struct PS_Input
{
float4 vScreenPos : SV_POSITION;
float2 vTexcoord0 : TEXCOORD0;
};
//--------------------------------------------------------------------------------------
struct PS_Output
{
float4 vColor : SV_Target0;
};
//--------------------------------------------------------------------------------------
// Vertex Shader
//--------------------------------------------------------------------------------------
VS_Output
MainVS( VS_Input vs_input )
{
VS_Output vs_output;
float4 pos = float4( vs_input.vPosition.xyz, 1.0f );
vs_output.vPosition = mul( pos,
mWorldViewProjectionMatrix );
vs_output.vTexcoord0 = vs_input.vTexcoord0;
return vs_output;
}
//--------------------------------------------------------------------------------------
// Pixel Shader
//--------------------------------------------------------------------------------------
PS_Output
MainPS( PS_Input ps_input )
{
PS_Output ps_output;
float4 lightVec4 = getLightTextureAttributes( ps_input.vScreenPos.xy );
float4 diffuseAlbedo = float4( 1.0f, 1.0f, 1.0f, 1.0f );
if ( mEnableDiffuseTexture == 1.0f )
{
diffuseAlbedo.rgb =
mDiffuseTexture.Sample( mLinearSampler0,
ps_input.vTexcoord0 ).rgb;
}
float4 specularAlbedo = float4( 1.0f, 1.0f, 1.0f, 1.0f );
if ( mEnableSpecularTexture == 1.0f )
{
specularAlbedo =
mSpecularTexture.Sample( mLinearSampler0,
ps_input.vTexcoord0 );
}
float4 color = float4( 0.0f, 0.0f, 0.0f, 1.0f );
float3 diffuseLight = lightVec4.xyz * diffuseAlbedo.xyz;
float3 specularLight = lightVec4.w * specularAlbedo.xyz;
color.rgb = saturate( diffuseLight + specularLight );
ps_output.vColor = color;
return ps_output;
}
//--------------------------------------------------------------------------------------

