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