Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // START UNIFORM DECLARATION
- struct ShadowReceiverData
- {
- float4x4 texViewProj;
- float2 shadowDepthRange;
- float2 padding;
- float4 invShadowMapSize;
- };
- struct Light
- {
- float3 position;
- float3 diffuse;
- float3 specular;
- float3 attenuation;
- float3 spotDirection;
- float3 spotParams;
- };
- //Uniforms that change per pass
- cbuffer PassBuffer : register(b0)
- {
- struct PassData
- {
- //Vertex shader (common to both receiver and casters)
- float4x4 viewProj;
- //Vertex shader
- float4x4 view;
- ShadowReceiverData shadowRcv[5];
- //-------------------------------------------------------------------------
- //Pixel shader
- float3x3 invViewMatCubemap;
- float padding; //Compatibility with GLSL.
- float pssmSplitPoints0;
- float pssmSplitPoints1;
- float pssmSplitPoints2; Light lights[3];
- } passBuf;
- };
- //Uniforms that change per Item/Entity, but change very infrequently
- struct Material
- {
- /* kD is already divided by PI to make it energy conserving.
- (formula is finalDiffuse = NdotL * surfaceDiffuse / PI)
- */
- float4 kD; //kD.w is alpha_test_threshold
- float4 kS; //kS.w is roughness
- //Fresnel coefficient, may be per colour component (float3) or scalar (float)
- //F0.w is mNormalMapWeight
- float4 F0;
- float4 normalWeights;
- float4 cDetailWeights;
- float4 detailOffsetScaleD[4];
- float4 detailOffsetScaleN[4];
- uint4 indices0_3;
- uint4 indices4_7;
- };
- cbuffer MaterialBuf : register(b1)
- {
- Material materialArray[273];
- };
- //Uniforms that change per Item/Entity
- cbuffer InstanceBuffer : register(b2)
- {
- //.x =
- //The lower 9 bits contain the material's start index.
- //The higher 23 bits contain the world matrix start index.
- //
- //.y =
- //shadowConstantBias. Send the bias directly to avoid an
- //unnecessary indirection during the shadow mapping pass.
- //Must be loaded with uintBitsToFloat
- uint4 worldMaterialIdx[4096];
- };
- // END UNIFORM DECLARATION
- struct PS_INPUT
- {
- nointerpolation uint drawId : TEXCOORD0;
- float3 pos : TEXCOORD1;
- float3 normal : TEXCOORD2;
- float2 uv0 : TEXCOORD3;
- float4 posL0 : TEXCOORD4;
- float4 posL1 : TEXCOORD5;
- float4 posL2 : TEXCOORD6;
- float4 posL3 : TEXCOORD7;
- float4 posL4 : TEXCOORD8; float depth : TEXCOORD9;
- };
- Texture2DArray textureMaps[2] : register(t6);
- SamplerState samplerStates[2] : register(s6);
- Texture2D texShadowMap[5] : register(t1);
- SamplerComparisonState shadowSampler : register(s1);
- float getShadow( Texture2D shadowMap, float4 psPosLN, float4 invShadowMapSize )
- {
- float fDepth = psPosLN.z;
- float2 uv = psPosLN.xy / psPosLN.w;
- /*float c = shadowMap.SampleCmpLevelZero( shadowSampler, uv.xy, fDepth );
- return c;*/
- float retVal = 0;
- float2 offsets[4] =
- {
- float2( 0, 0 ), //0, 0
- float2( 1, 0 ), //1, 0
- float2( 0, 1 ), //1, 1
- float2( 0, 0 ) //1, 1
- };
- uv += offsets[0] * invShadowMapSize.xy;
- // 2x2 PCF
- retVal += shadowMap.SampleCmpLevelZero( shadowSampler, uv.xy, fDepth );
- uv += offsets[1] * invShadowMapSize.xy;
- // 2x2 PCF
- retVal += shadowMap.SampleCmpLevelZero( shadowSampler, uv.xy, fDepth );
- uv += offsets[2] * invShadowMapSize.xy;
- // 2x2 PCF
- retVal += shadowMap.SampleCmpLevelZero( shadowSampler, uv.xy, fDepth );
- uv += offsets[3] * invShadowMapSize.xy;
- // 2x2 PCF
- retVal += shadowMap.SampleCmpLevelZero( shadowSampler, uv.xy, fDepth );
- retVal *= 0.25;
- return retVal;
- }
- //Default BRDF
- float3 BRDF( float3 lightDir, float3 viewDir, float NdotV, float3 lightDiffuse, float3 lightSpecular, Material material, float3 nNormal , float3 diffuseCol, float ROUGHNESS )
- {
- float3 halfWay= normalize( lightDir + viewDir );
- float NdotL = saturate( dot( nNormal, lightDir ) );
- float NdotH = saturate( dot( nNormal, halfWay ) );
- float VdotH = saturate( dot( viewDir, halfWay ) );
- float sqR = ROUGHNESS * ROUGHNESS * ROUGHNESS * 0.2;
- //Roughness/Distribution/NDF term (GGX)
- //Formula:
- // Where alpha = roughness
- // R = alpha^2 / [ PI * [ ( NdotH^2 * (alpha^2 - 1) ) + 1 ]^2 ]
- float f = ( NdotH * sqR - NdotH ) * NdotH + 1.0;
- float R = sqR / (f * f + 1e-6f);
- //Geometric/Visibility term (Smith GGX Height-Correlated)
- float Lambda_GGXV = NdotL * sqrt( (-NdotV * sqR + NdotV) * NdotV + sqR );
- float Lambda_GGXL = NdotV * sqrt( (-NdotL * sqR + NdotL) * NdotL + sqR );
- float G = 0.5 / (( Lambda_GGXV + Lambda_GGXL + 1e-6f ) * 3.141592654);
- //Formula:
- // fresnelS = lerp( (1 - V*H)^5, 1, F0 )
- float3 fresnelS = material.kS.xyz.xyz + pow( 1.0 - VdotH, 5.0 ) * (1.0 - material.kS.xyz.xyz);
- //We should divide Rs by PI, but it was done inside G for performance
- float3 Rs = ( fresnelS * (R * G) ) * float3(1,1,1) * lightSpecular;
- //Diffuse BRDF (*Normalized* Disney, see course_notes_moving_frostbite_to_pbr.pdf
- //"Moving Frostbite to Physically Based Rendering" Sebastien Lagarde & Charles de Rousiers)
- float energyBias = ROUGHNESS * 0.5;
- float energyFactor = lerp( 1.0, 1.0 / 1.51, ROUGHNESS );
- float fd90 = energyBias + 2.0 * VdotH * VdotH * ROUGHNESS;
- float lightScatter = 1.0 + (fd90 - 1.0) * pow( 1.0 - NdotL, 5.0 );
- float viewScatter = 1.0 + (fd90 - 1.0) * pow( 1.0 - NdotV, 5.0 );
- float3 fresnelD = 1.0 - fresnelS;
- //We should divide Rd by PI, but it is already included in kD
- float3 Rd = (lightScatter * viewScatter * fresnelD) * diffuseCol.xyz * lightDiffuse;
- return NdotL * (Rs + Rd);
- }
- float4 main( PS_INPUT inPs
- ) : SV_Target0
- {
- Material material;
- float4 outColour;
- uint roughnessIdx;
- uint detailMapIdx0;
- float4 diffuseCol;
- float ROUGHNESS;
- float3 nNormal;
- uint materialId = worldMaterialIdx[inPs.drawId].x & 0x1FFu;
- material = materialArray[materialId];
- roughnessIdx = material.indices0_3.y >> 16u;
- detailMapIdx0 = material.indices0_3.z >> 16u;
- float4 detailWeights = float4( 1.0, 1.0, 1.0, 1.0 );
- float4 detailCol0 = textureMaps[1].Sample( samplerStates[1], float3( inPs.uv0.xy * material.detailOffsetScaleD[0].zw + material.detailOffsetScaleD[0].xy, detailMapIdx0 ) );
- detailWeights.x *= detailCol0.w;
- detailCol0.w = detailWeights.x;
- nNormal = normalize( inPs.normal );
- float fShadow = 1.0;
- if( inPs.depth <= passBuf.pssmSplitPoints0 )
- fShadow = getShadow( texShadowMap[0], inPs.posL0, passBuf.shadowRcv[0].invShadowMapSize );
- else if( inPs.depth <= passBuf.pssmSplitPoints1 )
- fShadow = getShadow( texShadowMap[1], inPs.posL1, passBuf.shadowRcv[1].invShadowMapSize );
- else if( inPs.depth <= passBuf.pssmSplitPoints2 )
- fShadow = getShadow( texShadowMap[2], inPs.posL2, passBuf.shadowRcv[2].invShadowMapSize );
- ROUGHNESS = material.kS.w * textureMaps[0].Sample( samplerStates[0], float3(inPs.uv0.xy, roughnessIdx) ).x;
- ROUGHNESS = max( ROUGHNESS, 0.001f );
- diffuseCol = float4( 0.0, 0.0, 0.0, 0.0 );
- //Normal Non Premultiplied 0
- diffuseCol.xyz = lerp( diffuseCol.xyz, detailCol0.xyz, detailCol0.a );
- diffuseCol.xyz *= material.kD.xyz;
- //Everything's in Camera space
- float3 viewDir = normalize( -inPs.pos );
- float NdotV = saturate( dot( nNormal, viewDir ) );
- float3 finalColour = float3(0, 0, 0);
- finalColour += BRDF( passBuf.lights[0].position, viewDir, NdotV, passBuf.lights[0].diffuse, passBuf.lights[0].specular, material, nNormal , diffuseCol.xyz, ROUGHNESS );
- finalColour *= fShadow; //1st directional light's shadow
- float3 lightDir;
- float fDistance;
- float3 tmpColour;
- float spotCosAngle;
- //Point lights
- //Spot lights
- //spotParams[0].x = 1.0 / cos( InnerAngle ) - cos( OuterAngle )
- //spotParams[0].y = cos( OuterAngle / 2 )
- //spotParams[0].z = falloff
- lightDir = passBuf.lights[1].position - inPs.pos;
- fDistance= length( lightDir );
- spotCosAngle = dot( normalize( inPs.pos - passBuf.lights[1].position ), passBuf.lights[1].spotDirection );
- if( fDistance <= passBuf.lights[1].attenuation.x && spotCosAngle >= passBuf.lights[1].spotParams.y )
- {
- lightDir *= 1.0 / fDistance;
- float spotAtten = saturate( (spotCosAngle - passBuf.lights[1].spotParams.y) * passBuf.lights[1].spotParams.x );
- spotAtten = pow( spotAtten, passBuf.lights[1].spotParams.z );
- tmpColour = BRDF( lightDir, viewDir, NdotV, passBuf.lights[1].diffuse, passBuf.lights[1].specular, material, nNormal , diffuseCol.xyz, ROUGHNESS ) * getShadow( texShadowMap[3], inPs.posL3, passBuf.shadowRcv[3].invShadowMapSize );
- float atten = 1.0 / (1.0 + (passBuf.lights[1].attenuation.y + passBuf.lights[1].attenuation.z * fDistance) * fDistance );
- finalColour += tmpColour * (atten * spotAtten);
- }
- lightDir = passBuf.lights[2].position - inPs.pos;
- fDistance= length( lightDir );
- spotCosAngle = dot( normalize( inPs.pos - passBuf.lights[2].position ), passBuf.lights[2].spotDirection );
- if( fDistance <= passBuf.lights[2].attenuation.x && spotCosAngle >= passBuf.lights[2].spotParams.y )
- {
- lightDir *= 1.0 / fDistance;
- float spotAtten = saturate( (spotCosAngle - passBuf.lights[2].spotParams.y) * passBuf.lights[2].spotParams.x );
- spotAtten = pow( spotAtten, passBuf.lights[2].spotParams.z );
- tmpColour = BRDF( lightDir, viewDir, NdotV, passBuf.lights[2].diffuse, passBuf.lights[2].specular, material, nNormal , diffuseCol.xyz, ROUGHNESS ) * getShadow( texShadowMap[4], inPs.posL4, passBuf.shadowRcv[4].invShadowMapSize );
- float atten = 1.0 / (1.0 + (passBuf.lights[2].attenuation.y + passBuf.lights[2].attenuation.z * fDistance) * fDistance );
- finalColour += tmpColour * (atten * spotAtten);
- }
- outColour.xyz = finalColour;
- //outColour.w = 1.0;
- outColour.w = material.kD.w;
- return outColour;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement