summaryrefslogtreecommitdiff
path: root/tests/hlsl/dxsdk/VarianceShadows11
diff options
context:
space:
mode:
Diffstat (limited to 'tests/hlsl/dxsdk/VarianceShadows11')
-rw-r--r--tests/hlsl/dxsdk/VarianceShadows11/2DQuadShaders.hlsl211
-rw-r--r--tests/hlsl/dxsdk/VarianceShadows11/RenderVarianceScene.hlsl412
-rw-r--r--tests/hlsl/dxsdk/VarianceShadows11/RenderVarianceShadow.hlsl45
3 files changed, 668 insertions, 0 deletions
diff --git a/tests/hlsl/dxsdk/VarianceShadows11/2DQuadShaders.hlsl b/tests/hlsl/dxsdk/VarianceShadows11/2DQuadShaders.hlsl
new file mode 100644
index 000000000..c4401f010
--- /dev/null
+++ b/tests/hlsl/dxsdk/VarianceShadows11/2DQuadShaders.hlsl
@@ -0,0 +1,211 @@
+//TEST:COMPARE_HLSL: -target dxbc-assembly -profile vs_4_0 -entry VSMain -profile ps_4_0 -entry PSBlurX -entry PSBlurY
+//--------------------------------------------------------------------------------------
+// File: Skinning10.fx
+//
+// The effect file for the Skinning10 sample.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//--------------------------------------------------------------------------------------
+
+#ifndef SEPERABLE_BLUR_KERNEL_SIZE
+#define SEPERABLE_BLUR_KERNEL_SIZE 3
+#endif
+
+static const int BLUR_KERNEL_BEGIN = SEPERABLE_BLUR_KERNEL_SIZE / -2;
+static const int BLUR_KERNEL_END = SEPERABLE_BLUR_KERNEL_SIZE / 2 + 1;
+static const float FLOAT_BLUR_KERNEL_SIZE = (float)SEPERABLE_BLUR_KERNEL_SIZE;
+
+cbuffer cbblurVS : register( b2)
+{
+ int2 g_iWidthHeight : packoffset( c0 );
+ int g_iKernelStart : packoffset( c0.z );
+ int g_iKernelEnd : packoffset( c0.w );
+};
+
+//--------------------------------------------------------------------------------------
+// defines
+//--------------------------------------------------------------------------------------
+
+Texture2DArray g_txShadow : register( t5 );
+SamplerState g_samShadow : register( s5 );
+
+//--------------------------------------------------------------------------------------
+// Input/Output structures
+//--------------------------------------------------------------------------------------
+
+struct PSIn
+{
+ float4 Pos : SV_Position; //Position
+ float2 Tex : TEXCOORD; //Texture coordinate
+ float2 ITex : TEXCOORD2;
+};
+
+struct VSIn
+{
+ uint Pos : SV_VertexID ;
+};
+
+
+PSIn VSMain(VSIn inn)
+{
+ PSIn output;
+
+ output.Pos.y = -1.0f + (inn.Pos%2) * 2.0f ;
+ output.Pos.x = -1.0f + (inn.Pos/2) * 2.0f;
+ output.Pos.z = .5;
+ output.Pos.w = 1;
+ output.Tex.x = inn.Pos/2;
+ output.Tex.y = 1.0f - inn.Pos%2;
+ output.ITex.x = (float)(g_iWidthHeight.x * output.Tex.x);
+ output.ITex.y = (float)(g_iWidthHeight.y * output.Tex.y);
+ return output;
+}
+
+//float PSDepth
+
+//------------------------------------------------------------------------------
+// Logarithmic filtering
+//------------------------------------------------------------------------------
+
+float log_conv ( float x0, float X, float y0, float Y )
+{
+ return (X + log(x0 + (y0 * exp(Y - X))));
+}
+
+
+//--------------------------------------------------------------------------------------
+// Pixel shader that performs bump mapping on the final vertex
+//--------------------------------------------------------------------------------------
+float2 PSBlurX(PSIn input) : SV_Target
+{
+/*
+ float2 centerDistance;
+ if ( input.Tex.x < .5 ) centerDistance.x = (1.0 - input.Tex.x);
+ else centerDistance.x = input.Tex.x;
+ if ( input.Tex.y < .5 ) centerDistance.y = (1.0 - input.Tex.y);
+ else centerDistance.y = input.Tex.y;
+ if (centerDistance.x < centerDistance.y) centerDistance.x = centerDistance.y;
+ centerDistance.x -= .2;
+ centerDistance.x *= (1.0f / .8);
+
+ float store_samples[8];
+ int ind = 0;
+ for (int x = g_iKernelStart; x < g_iKernelEnd; ++x) {
+ store_samples[ind] = g_txShadow.Load( int3(input.ITex.x+(float)x * centerDistance.x , input.ITex.y, 0) ).r;
+ ind++;
+ }
+ const float c = (1.f/5.f);
+
+ float accum;
+ accum = log_conv( c, store_samples[0], c, store_samples[1] );
+
+ ind = 0;
+ for (x = g_iKernelStart - 2; x < g_iKernelEnd; ++x) {
+ ind++;
+ accum += log_conv( 1.0f, accum, c, store_samples[ind] );
+ }
+ float2 rt;
+ rt.x = accum;
+ return rt;
+ */
+ /*
+ float2 dep = 0;
+ float2 centerDistance;
+ if ( input.Tex.x < .5 ) centerDistance.x = (1.0 - input.Tex.x);
+ else centerDistance.x = input.Tex.x;
+ if ( input.Tex.y < .5 ) centerDistance.y = (1.0 - input.Tex.y);
+ else centerDistance.y = input.Tex.y;
+ if (centerDistance.x < centerDistance.y) centerDistance.x = centerDistance.y;
+ centerDistance.x -= .2;
+ centerDistance.x *= ( 1.0f / 0.8f );
+
+ for (int x = g_iKernelStart; x < g_iKernelEnd; ++x) {
+ dep += g_txShadow.Load( int3(input.ITex.x+(float)x * centerDistance.x , input.ITex.y, 0) ).rg;
+ }
+ dep /= (g_iKernelEnd - g_iKernelStart);
+ return dep;
+ */
+
+ float2 dep=0;
+ [unroll]for ( int x = BLUR_KERNEL_BEGIN; x < BLUR_KERNEL_END; ++x ) {
+ dep += g_txShadow.Sample( g_samShadow, float3( input.Tex.x, input.Tex.y, 0 ), int2( x,0 ) ).rg;
+ }
+ dep /= FLOAT_BLUR_KERNEL_SIZE;
+ return dep;
+
+// return g_txShadow.Sample(g_samShadow, float3(input.Tex.x, input.Tex.y, 0) ).rg;
+
+}
+
+//--------------------------------------------------------------------------------------
+// Pixel shader that performs bump mapping on the final vertex
+//--------------------------------------------------------------------------------------
+float2 PSBlurY(PSIn input) : SV_Target
+{
+/*
+ float2 centerDistance;
+ if ( input.Tex.x < .5 ) centerDistance.x = (1.0 - input.Tex.x);
+ else centerDistance.x = input.Tex.x;
+ if ( input.Tex.y < .5 ) centerDistance.y = (1.0 - input.Tex.y);
+ else centerDistance.y = input.Tex.y;
+ if (centerDistance.x < centerDistance.y) centerDistance.x = centerDistance.y;
+ centerDistance.x -= .2;
+ centerDistance.x *= (1.0f / .8);
+
+ float store_samples[8];
+ int ind = 0;
+ for (int y = g_iKernelStart; y < g_iKernelEnd; ++y) {
+ store_samples[ind] = g_txShadow.Load( int3(input.ITex.x, input.ITex.y+(float)y * centerDistance.x, 0) ).r;
+ }
+ const float c = (1.f/5.f);
+
+ float accum;
+ accum = log_conv( c, store_samples[0], c, store_samples[1] );
+
+ ind = 0;
+ for (y = g_iKernelStart; y < g_iKernelEnd; ++y) {
+ ind++;
+ accum += log_conv( 1.0f, accum, c, store_samples[ind] );
+ }
+ float2 rt;
+ rt.x = accum;
+ return rt;
+ */
+
+
+ /*
+ float2 dep = 0;
+
+ float2 centerDistance;
+ if ( input.Tex.x < .5 ) centerDistance.x = (1.0 - input.Tex.x);
+ else centerDistance.x = input.Tex.x;
+ if ( input.Tex.y < .5 ) centerDistance.y = (1.0 - input.Tex.y);
+ else centerDistance.y = input.Tex.y;
+ if (centerDistance.x < centerDistance.y) centerDistance.x = centerDistance.y;
+ centerDistance.x -= 0;
+ centerDistance.x *= (1.0f / 1.0f);
+
+ if (centerDistance.x < centerDistance.y) centerDistance.x = centerDistance.y;
+ for (int y = g_iKernelStart; y < g_iKernelEnd; ++y) {
+ dep += g_txShadow.Load( int3(input.ITex.x, input.ITex.y+(float)y * centerDistance.x, 0) ).rg;
+ }
+
+
+ dep /= (g_iKernelEnd - g_iKernelStart);
+ return dep;
+
+ */
+
+
+ float2 dep=0;
+ [unroll]for ( int y = BLUR_KERNEL_BEGIN; y < BLUR_KERNEL_END; ++y ) {
+ dep += g_txShadow.Sample( g_samShadow, float3( input.Tex.x, input.Tex.y, 0 ), int2( 0,y ) ).rg;
+ }
+ dep /= FLOAT_BLUR_KERNEL_SIZE;
+ return dep;
+
+ //return g_txShadow.Sample(g_samShadow, float3(input.Tex.x, input.Tex.y, 0) ).rg;
+}
+
+
+
diff --git a/tests/hlsl/dxsdk/VarianceShadows11/RenderVarianceScene.hlsl b/tests/hlsl/dxsdk/VarianceShadows11/RenderVarianceScene.hlsl
new file mode 100644
index 000000000..0b2e43b5c
--- /dev/null
+++ b/tests/hlsl/dxsdk/VarianceShadows11/RenderVarianceScene.hlsl
@@ -0,0 +1,412 @@
+//TEST_IGNORE_FILE: Currently failing due to Spire compiler issues.
+//TEST:COMPARE_HLSL: -target dxbc-assembly -profile vs_4_0 -entry VSMain -profile ps_4_0 -entry PSBlurX -entry PSBlurY
+//--------------------------------------------------------------------------------------
+// File: RenderCascadeScene.hlsl
+//
+// This is the main shader file. This shader is compiled with several different flags
+// to provide different customizations based on user controls.
+//
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//--------------------------------------------------------------------------------------
+
+//--------------------------------------------------------------------------------------
+// Globals
+//--------------------------------------------------------------------------------------
+
+// This flag enables the shadow to blend between cascades. This is most useful when the
+// the shadow maps are small and artifact can be seen between the various cascade layers.
+#ifndef BLEND_BETWEEN_CASCADE_LAYERS_FLAG
+#define BLEND_BETWEEN_CASCADE_LAYERS_FLAG 0
+#endif
+
+// There are two methods for selecting the proper cascade a fragment lies in. Interval selection
+// compares the depth of the fragment against the frustum's depth partition.
+// Map based selection compares the texture coordinates against the acutal cascade maps.
+// Map based selection gives better coverage.
+// Interval based selection is easier to extend and understand.
+#ifndef SELECT_CASCADE_BY_INTERVAL_FLAG
+#define SELECT_CASCADE_BY_INTERVAL_FLAG 0
+#endif
+
+// The number of cascades
+#ifndef CASCADE_COUNT_FLAG
+#define CASCADE_COUNT_FLAG 3
+#endif
+
+
+// Most titles will find that 3-4 cascades with
+// BLEND_BETWEEN_CASCADE_LAYERS_FLAG, is good for lower end PCs.
+
+cbuffer cbAllShadowData : register( b0 )
+{
+ matrix m_mWorldViewProjection;
+ matrix m_mWorld;
+ matrix m_mWorldView;
+ matrix m_mShadow;
+ float4 m_vCascadeOffset[8];
+ float4 m_vCascadeScale[8];
+ int m_nCascadeLevels; // Number of Cascades
+ int m_iVisualizeCascades; // 1 is to visualize the cascades in different colors. 0 is to just draw the scene
+
+ // For Map based selection scheme, this keeps the pixels inside of the the valid range.
+ // When there is no boarder, these values are 0 and 1 respectivley.
+ float m_fMinBorderPadding;
+ float m_fMaxBorderPadding;
+
+ float m_fCascadeBlendArea; // Amount to overlap when blending between cascades.
+ float m_fTexelSize; // Padding variables exist because CBs must be a multiple of 16 bytes.
+ float m_fNativeTexelSizeInX;
+ float4 m_fCascadeFrustumsEyeSpaceDepthsData[2]; // The values along Z that seperate the cascades.
+ // This code creates an array based pointer that points towards the vectorized input data.
+ // This is the only way to index arbitrary arrays of data.
+ // If the array is used at run time, the compiler will generate code that uses logic to index the correct component.
+
+ static float m_fCascadeFrustumsEyeSpaceDepths[8] = (float[8])m_fCascadeFrustumsEyeSpaceDepthsData;
+
+ float3 m_vLightDir;
+ float m_fPaddingCB4;
+
+};
+
+
+
+//--------------------------------------------------------------------------------------
+// Textures and Samplers
+//--------------------------------------------------------------------------------------
+Texture2D g_txDiffuse : register( t0 );
+Texture2DArray g_txShadow : register( t5 );
+
+SamplerState g_samLinear : register( s0 );
+SamplerState g_samShadow : register( s5 );
+
+//--------------------------------------------------------------------------------------
+// Input / Output structures
+//--------------------------------------------------------------------------------------
+struct VS_INPUT
+{
+ float4 vPosition : POSITION;
+ float3 vNormal : NORMAL;
+ float2 vTexcoord : TEXCOORD0;
+};
+
+struct VS_OUTPUT
+{
+ float3 vNormal : NORMAL;
+ float2 vTexcoord : COLOR0;
+ float4 vTexShadow : TEXCOORD1;
+ float4 vPosition : SV_POSITION;
+ float4 vInterpPos : TEXCOORD2;
+ float vDepth : TEXCOORD3;
+};
+
+//--------------------------------------------------------------------------------------
+// Vertex Shader
+//--------------------------------------------------------------------------------------
+VS_OUTPUT VSMain( VS_INPUT Input )
+{
+ VS_OUTPUT Output;
+
+ Output.vPosition = mul( Input.vPosition, m_mWorldViewProjection );
+ Output.vNormal = mul( Input.vNormal, (float3x3)m_mWorld );
+ Output.vTexcoord = Input.vTexcoord;
+ Output.vInterpPos = Input.vPosition;
+ Output.vDepth = mul( Input.vPosition, m_mWorldView ).z ;
+
+ // Transform the shadow texture coordinates for all the cascades.
+ Output.vTexShadow = mul( Input.vPosition, m_mShadow );
+
+ return Output;
+}
+
+
+
+static const float4 vCascadeColorsMultiplier[8] =
+{
+ float4 ( 1.5f, 0.0f, 0.0f, 1.0f ),
+ float4 ( 0.0f, 1.5f, 0.0f, 1.0f ),
+ float4 ( 0.0f, 0.0f, 5.5f, 1.0f ),
+ float4 ( 1.5f, 0.0f, 5.5f, 1.0f ),
+ float4 ( 1.5f, 1.5f, 0.0f, 1.0f ),
+ float4 ( 1.0f, 1.0f, 1.0f, 1.0f ),
+ float4 ( 0.0f, 1.0f, 5.5f, 1.0f ),
+ float4 ( 0.5f, 3.5f, 0.75f, 1.0f )
+};
+
+
+void ComputeCoordinatesTransform( in int iCascadeIndex,
+ in float4 InterpolatedPosition,
+ in out float4 vShadowTexCoord,
+ in out float4 vShadowTexCoordViewSpace )
+{
+ // Now that we know the correct map, we can transform the world space position of the current fragment
+ if( SELECT_CASCADE_BY_INTERVAL_FLAG )
+ {
+ vShadowTexCoord = vShadowTexCoordViewSpace * m_vCascadeScale[iCascadeIndex];
+ vShadowTexCoord += m_vCascadeOffset[iCascadeIndex];
+ }
+ vShadowTexCoord.w = vShadowTexCoord.z; // We put the z value in w so that we can index the texture array with Z.
+ vShadowTexCoord.z = iCascadeIndex;
+
+}
+
+//--------------------------------------------------------------------------------------
+// Use PCF to sample the depth map and return a percent lit value.
+//--------------------------------------------------------------------------------------
+void CalculateVarianceShadow ( in float4 vShadowTexCoord, in float4 vShadowMapTextureCoordViewSpace, int iCascade, out float fPercentLit )
+{
+ fPercentLit = 0.0f;
+ // This loop could be unrolled, and texture immediate offsets could be used if the kernel size were fixed.
+ // This would be a performance improvment.
+
+ float2 mapDepth = 0;
+
+
+ // In orderto pull the derivative out of divergent flow control we calculate the
+ // derivative off of the view space coordinates an then scale the deriviative.
+
+ float3 vShadowTexCoordDDX =
+ ddx(vShadowMapTextureCoordViewSpace );
+ vShadowTexCoordDDX *= m_vCascadeScale[iCascade].xyz;
+ float3 vShadowTexCoordDDY =
+ ddy(vShadowMapTextureCoordViewSpace );
+ vShadowTexCoordDDY *= m_vCascadeScale[iCascade].xyz;
+
+ mapDepth += g_txShadow.SampleGrad( g_samShadow, vShadowTexCoord.xyz,
+ vShadowTexCoordDDX,
+ vShadowTexCoordDDY);
+ // The sample instruction uses gradients for some filters.
+
+ float fAvgZ = mapDepth.x; // Filtered z
+ float fAvgZ2 = mapDepth.y; // Filtered z-squared
+
+ if ( vShadowTexCoord.w <= fAvgZ ) // We put the z value in w so that we can index the texture array with Z.
+ {
+ fPercentLit = 1;
+ }
+ else
+ {
+ float variance = ( fAvgZ2 ) - ( fAvgZ * fAvgZ );
+ variance = min( 1.0f, max( 0.0f, variance + 0.00001f ) );
+
+ float mean = fAvgZ;
+ float d = vShadowTexCoord.w - mean; // We put the z value in w so that we can index the texture array with Z.
+ float p_max = variance / ( variance + d*d );
+
+ // To combat light-bleeding, experiment with raising p_max to some power
+ // (Try values from 0.1 to 100.0, if you like.)
+ fPercentLit = pow( p_max, 4 );
+
+ }
+
+}
+
+//--------------------------------------------------------------------------------------
+// Calculate amount to blend between two cascades and the band where blending will occure.
+//--------------------------------------------------------------------------------------
+void CalculateBlendAmountForInterval ( in int iNextCascadeIndex,
+ in out float fPixelDepth,
+ in out float fCurrentPixelsBlendBandLocation,
+ out float fBlendBetweenCascadesAmount
+ )
+{
+
+ // We need to calculate the band of the current shadow map where it will fade into the next cascade.
+ // We can then early out of the expensive PCF for loop.
+ //
+ float fBlendInterval = m_fCascadeFrustumsEyeSpaceDepths[ iNextCascadeIndex - 1 ];
+ if( iNextCascadeIndex > 1 )
+ {
+ fPixelDepth -= m_fCascadeFrustumsEyeSpaceDepths[ iNextCascadeIndex-2 ];
+ fBlendInterval -= m_fCascadeFrustumsEyeSpaceDepths[ iNextCascadeIndex-2 ];
+ }
+ // The current pixel's blend band location will be used to determine when we need to blend and by how much.
+ fCurrentPixelsBlendBandLocation = fPixelDepth / fBlendInterval;
+ fCurrentPixelsBlendBandLocation = 1.0f - fCurrentPixelsBlendBandLocation;
+ // The fBlendBetweenCascadesAmount is our location in the blend band.
+ fBlendBetweenCascadesAmount = fCurrentPixelsBlendBandLocation / m_fCascadeBlendArea;
+}
+
+
+//--------------------------------------------------------------------------------------
+// Calculate amount to blend between two cascades and the band where blending will occure.
+//--------------------------------------------------------------------------------------
+void CalculateBlendAmountForMap ( in float4 vShadowMapTextureCoord,
+ in out float fCurrentPixelsBlendBandLocation,
+ out float fBlendBetweenCascadesAmount )
+{
+ // Calcaulte the blend band for the map based selection.
+ float2 distanceToOne = float2 ( 1.0f - vShadowMapTextureCoord.x, 1.0f - vShadowMapTextureCoord.y );
+ fCurrentPixelsBlendBandLocation = min( vShadowMapTextureCoord.x, vShadowMapTextureCoord.y );
+ float fCurrentPixelsBlendBandLocation2 = min( distanceToOne.x, distanceToOne.y );
+ fCurrentPixelsBlendBandLocation =
+ min( fCurrentPixelsBlendBandLocation, fCurrentPixelsBlendBandLocation2 );
+ fBlendBetweenCascadesAmount = fCurrentPixelsBlendBandLocation / m_fCascadeBlendArea;
+}
+
+//--------------------------------------------------------------------------------------
+// Calculate the shadow based on several options and rende the scene.
+//--------------------------------------------------------------------------------------
+
+float4 PSMain( VS_OUTPUT Input ) : SV_TARGET
+{
+ float4 vDiffuse = g_txDiffuse.Sample( g_samLinear, Input.vTexcoord );
+
+
+ float4 vShadowMapTextureCoordViewSpace = 0.0f;
+ float4 vShadowMapTextureCoord = 0.0f;
+ float4 vShadowMapTextureCoord_blend = 0.0f;
+
+ float4 vVisualizeCascadeColor = float4(0.0f,0.0f,0.0f,1.0f);
+
+ float fPercentLit = 0.0f;
+ float fPercentLit_blend = 0.0f;
+
+ int iCascadeFound = 0;
+ int iCurrentCascadeIndex=1;
+ int iNextCascadeIndex = 0;
+
+ float fCurrentPixelDepth;
+
+ // The interval based selection technique compares the pixel's depth against the frustum's cascade divisions.
+ fCurrentPixelDepth = Input.vDepth;
+
+ // This for loop is not necessary when the frustum is uniformaly divided and interval based selection is used.
+ // In this case fCurrentPixelDepth could be used as an array lookup into the correct frustum.
+ vShadowMapTextureCoordViewSpace = Input.vTexShadow;
+
+
+ if( SELECT_CASCADE_BY_INTERVAL_FLAG )
+ {
+ iCurrentCascadeIndex = 0;
+ if (CASCADE_COUNT_FLAG > 1 )
+ {
+ float4 vCurrentPixelDepth = Input.vDepth;
+ float4 fComparison = ( vCurrentPixelDepth > m_fCascadeFrustumsEyeSpaceDepthsData[0]);
+ float4 fComparison2 = ( vCurrentPixelDepth > m_fCascadeFrustumsEyeSpaceDepthsData[1]);
+ float fIndex = dot(
+ float4( CASCADE_COUNT_FLAG > 0,
+ CASCADE_COUNT_FLAG > 1,
+ CASCADE_COUNT_FLAG > 2,
+ CASCADE_COUNT_FLAG > 3)
+ , fComparison )
+ + dot(
+ float4(
+ CASCADE_COUNT_FLAG > 4,
+ CASCADE_COUNT_FLAG > 5,
+ CASCADE_COUNT_FLAG > 6,
+ CASCADE_COUNT_FLAG > 7)
+ , fComparison2 ) ;
+
+ fIndex = min( fIndex, CASCADE_COUNT_FLAG - 1 );
+ iCurrentCascadeIndex = (int)fIndex;
+ }
+ }
+
+ if ( !SELECT_CASCADE_BY_INTERVAL_FLAG )
+ {
+ iCurrentCascadeIndex = 0;
+ if ( CASCADE_COUNT_FLAG == 1 )
+ {
+ vShadowMapTextureCoord = vShadowMapTextureCoordViewSpace * m_vCascadeScale[0];
+ vShadowMapTextureCoord += m_vCascadeOffset[0];
+ }
+ if ( CASCADE_COUNT_FLAG > 1 ) {
+ for( int iCascadeIndex = 0; iCascadeIndex < CASCADE_COUNT_FLAG && iCascadeFound == 0; ++iCascadeIndex )
+ {
+ vShadowMapTextureCoord = vShadowMapTextureCoordViewSpace * m_vCascadeScale[iCascadeIndex];
+ vShadowMapTextureCoord += m_vCascadeOffset[iCascadeIndex];
+
+ if ( min( vShadowMapTextureCoord.x, vShadowMapTextureCoord.y ) > m_fMinBorderPadding
+ && max( vShadowMapTextureCoord.x, vShadowMapTextureCoord.y ) < m_fMaxBorderPadding )
+ {
+ iCurrentCascadeIndex = iCascadeIndex;
+ iCascadeFound = 1;
+ }
+ }
+ }
+ }
+ // Found the correct map.
+ vVisualizeCascadeColor = vCascadeColorsMultiplier[iCurrentCascadeIndex];
+
+ ComputeCoordinatesTransform( iCurrentCascadeIndex, Input.vInterpPos, vShadowMapTextureCoord, vShadowMapTextureCoordViewSpace );
+
+ if( BLEND_BETWEEN_CASCADE_LAYERS_FLAG && CASCADE_COUNT_FLAG > 1 )
+ {
+ // Repeat text coord calculations for the next cascade.
+ // The next cascade index is used for blurring between maps.
+ iNextCascadeIndex = min ( CASCADE_COUNT_FLAG - 1, iCurrentCascadeIndex + 1 );
+ if( !SELECT_CASCADE_BY_INTERVAL_FLAG )
+ {
+ vShadowMapTextureCoord_blend = vShadowMapTextureCoordViewSpace * m_vCascadeScale[iNextCascadeIndex];
+ vShadowMapTextureCoord_blend += m_vCascadeOffset[iNextCascadeIndex];
+ }
+ ComputeCoordinatesTransform( iNextCascadeIndex, Input.vInterpPos, vShadowMapTextureCoord_blend, vShadowMapTextureCoordViewSpace );
+ }
+ float fBlendBetweenCascadesAmount = 1.0f;
+ float fCurrentPixelsBlendBandLocation = 1.0f;
+
+ if( SELECT_CASCADE_BY_INTERVAL_FLAG )
+ {
+ if( CASCADE_COUNT_FLAG > 1 && BLEND_BETWEEN_CASCADE_LAYERS_FLAG )
+ {
+ CalculateBlendAmountForInterval ( iNextCascadeIndex, fCurrentPixelDepth,
+ fCurrentPixelsBlendBandLocation, fBlendBetweenCascadesAmount );
+
+ }
+ }
+ else
+ {
+ if( CASCADE_COUNT_FLAG > 1 && BLEND_BETWEEN_CASCADE_LAYERS_FLAG )
+ {
+ CalculateBlendAmountForMap ( vShadowMapTextureCoord,
+ fCurrentPixelsBlendBandLocation, fBlendBetweenCascadesAmount );
+ }
+ }
+
+ // Because the Z coordinate specifies the texture array,
+ // the derivative will be 0 when there is no divergence
+ //float fDivergence = abs( ddy( vShadowMapTextureCoord.z ) ) + abs( ddx( vShadowMapTextureCoord.z ) );
+ CalculateVarianceShadow ( vShadowMapTextureCoord, vShadowMapTextureCoordViewSpace,
+ iCurrentCascadeIndex, fPercentLit);
+
+ // We repeat the calcuation for the next cascade layer, when blending between maps.
+ if( BLEND_BETWEEN_CASCADE_LAYERS_FLAG && CASCADE_COUNT_FLAG > 1 )
+ {
+ if( fCurrentPixelsBlendBandLocation < m_fCascadeBlendArea )
+ { // the current pixel is within the blend band.
+
+ // Because the Z coordinate species the texture array,
+ // the derivative will be 0 when there is no divergence
+ float fDivergence = abs( ddy( vShadowMapTextureCoord_blend.z ) ) +
+ abs( ddx( vShadowMapTextureCoord_blend.z) );
+ CalculateVarianceShadow ( vShadowMapTextureCoord_blend, vShadowMapTextureCoordViewSpace,
+ iNextCascadeIndex, fPercentLit_blend );
+
+ // Blend the two calculated shadows by the blend amount.
+ fPercentLit = lerp( fPercentLit_blend, fPercentLit, fBlendBetweenCascadesAmount );
+
+ }
+ }
+
+ if( !m_iVisualizeCascades ) vVisualizeCascadeColor = float4( 1.0f, 1.0f, 1.0f, 1.0f );
+
+ float3 vLightDir1 = float3( -1.0f, 1.0f, -1.0f );
+ float3 vLightDir2 = float3( 1.0f, 1.0f, -1.0f );
+ float3 vLightDir3 = float3( 0.0f, -1.0f, 0.0f );
+ float3 vLightDir4 = float3( 1.0f, 1.0f, 1.0f );
+ // Some ambient-like lighting.
+ float fLighting =
+ saturate( dot( vLightDir1 , Input.vNormal ) )*0.05f +
+ saturate( dot( vLightDir2 , Input.vNormal ) )*0.05f +
+ saturate( dot( vLightDir3 , Input.vNormal ) )*0.05f +
+ saturate( dot( vLightDir4 , Input.vNormal ) )*0.05f ;
+
+ float4 vShadowLighting = fLighting * 0.5f;
+ fLighting += saturate( dot( m_vLightDir , Input.vNormal ) );
+ fLighting = lerp( vShadowLighting, fLighting, fPercentLit );
+
+ return fLighting * vVisualizeCascadeColor * vDiffuse;
+
+}
+
diff --git a/tests/hlsl/dxsdk/VarianceShadows11/RenderVarianceShadow.hlsl b/tests/hlsl/dxsdk/VarianceShadows11/RenderVarianceShadow.hlsl
new file mode 100644
index 000000000..9837bf299
--- /dev/null
+++ b/tests/hlsl/dxsdk/VarianceShadows11/RenderVarianceShadow.hlsl
@@ -0,0 +1,45 @@
+//TEST:COMPARE_HLSL: -target dxbc-assembly -profile vs_4_0 -entry VSMain -profile ps_4_0 -entry PSMain
+
+
+//--------------------------------------------------------------------------------------
+// Globals
+//--------------------------------------------------------------------------------------
+cbuffer cbPerObject : register( b0 )
+{
+ matrix g_mWorldViewProjection : packoffset( c0 );
+};
+
+//--------------------------------------------------------------------------------------
+// Input / Output structures
+//--------------------------------------------------------------------------------------
+struct VS_INPUT
+{
+ float4 vPosition : POSITION;
+};
+
+struct VS_OUTPUT
+{
+ float4 vPosition : SV_POSITION;
+};
+
+//--------------------------------------------------------------------------------------
+// Vertex Shader
+//--------------------------------------------------------------------------------------
+VS_OUTPUT VSMain( VS_INPUT Input )
+{
+ VS_OUTPUT Output;
+
+
+ Output.vPosition = mul( Input.vPosition, g_mWorldViewProjection );
+
+ return Output;
+}
+
+
+float2 PSMain (VS_OUTPUT Input) : SV_TARGET
+{
+ float2 rt;
+ rt.x = Input.vPosition.z;
+ rt.y = rt.x * rt.x;
+ return rt;
+} \ No newline at end of file