utkutuzcu/tst / Engine /Shaders /ShadowProjectionCommon.usf
utkutuzcu's picture
download
raw
5.75 kB
/*=============================================================================
ShadowProjectionCommon.usf: Contains functions that uniformly filter a depth buffer.
Copyright 1998-2008 Epic Games, Inc. All Rights Reserved.
=============================================================================*/
sampler2D ShadowDepthTexture;
float4 SampleOffsets[NUM_SAMPLE_CHUNKS * 2];
float2 ShadowBufferSize;
/**
* Takes samples and compares and averages manually.
*
* @return a PCF value between 0 and 1
*/
half ManualPCF(float4 ShadowPosition)
{
half Shadow = 0;
half SampleWeight = .25 / NUM_SAMPLE_CHUNKS;
UNROLL
for(int ChunkIndex = 0;ChunkIndex < NUM_SAMPLE_CHUNKS;ChunkIndex++)
{
float4 ShadowDepths;
ShadowDepths.r = texDepth2D(ShadowDepthTexture,ShadowPosition.xy + SampleOffsets[ChunkIndex * 2 + 0].xy).r;
ShadowDepths.g = texDepth2D(ShadowDepthTexture,ShadowPosition.xy + SampleOffsets[ChunkIndex * 2 + 0].zw).r;
ShadowDepths.b = texDepth2D(ShadowDepthTexture,ShadowPosition.xy + SampleOffsets[ChunkIndex * 2 + 1].xy).r;
ShadowDepths.a = texDepth2D(ShadowDepthTexture,ShadowPosition.xy + SampleOffsets[ChunkIndex * 2 + 1].zw).r;
Shadow += dot(ShadowPosition.z < ShadowDepths ? half4(1,1,1,1) : half4(0,0,0,0), SampleWeight.xxxx);
}
return Shadow;
}
/**
* Takes samples, compares and billinear filtering are done by hardware.
*
* @return a PCF value between 0 and 1
*/
half HardwarePCF(float4 ShadowPosition)
{
half Shadow = 0;
UNROLL
for(int ChunkIndex = 0;ChunkIndex < NUM_SAMPLE_CHUNKS;ChunkIndex++)
{
half4 FinalOffset = ShadowPosition.xyxy + SampleOffsets[ChunkIndex * 2].xyzw;
Shadow += texDepth2Dproj(ShadowDepthTexture,half4(FinalOffset.xy, ShadowPosition.z, 1)).r;
Shadow += texDepth2Dproj(ShadowDepthTexture,half4(FinalOffset.zw, ShadowPosition.z, 1)).r;
FinalOffset = ShadowPosition.xyxy + SampleOffsets[ChunkIndex * 2 + 1].xyzw;
Shadow += texDepth2Dproj(ShadowDepthTexture,half4(FinalOffset.xy, ShadowPosition.z, 1)).r;
Shadow += texDepth2Dproj(ShadowDepthTexture,half4(FinalOffset.zw, ShadowPosition.z, 1)).r;
}
return Shadow * .25 / NUM_SAMPLE_CHUNKS;
}
/**
* Takes refining samples, retrieving 4 neighboring values in every texture lookup using Fetch4.
* The neighboring values are then bilinearly filtered in the shader.
*
* @return a PCF value between 0 and 1
*/
half Fetch4PCF(float4 ShadowPosition)
{
half Shadow = 0;
//used to normalize accumulated coverage, since there are 4 bilinearly filtered samples per chunk
half SampleWeight = .25 / NUM_SAMPLE_CHUNKS;
//Go through each chunk and take samples
UNROLL
for(int ChunkIndex = 0;ChunkIndex < NUM_SAMPLE_CHUNKS;ChunkIndex++)
{
/* first two bilinearly filtered lookups in this chunk */
//offset this pixel's position in lightspace
half4 FinalOffset = ShadowPosition.xyxy + SampleOffsets[ChunkIndex * 2].xyzw;
//lookup 4 neighboring depth values using Fetch4 in each texDepth2Dlod
float4 ShadowDepthsOne = texDepth2D(ShadowDepthTexture,FinalOffset.xy);
float4 ShadowDepthsTwo = texDepth2D(ShadowDepthTexture,FinalOffset.zw);
half4 TopCoverageValues;
half4 BottomCoverageValues;
//Compare this pixel's depth, projected into lightspace, with the depths from the light's POV.
TopCoverageValues.xy = ShadowPosition.z < ShadowDepthsOne.wx;
TopCoverageValues.zw = ShadowPosition.z < ShadowDepthsTwo.wx;
BottomCoverageValues.xy = ShadowPosition.z < ShadowDepthsOne.yz;
BottomCoverageValues.zw = ShadowPosition.z < ShadowDepthsTwo.yz;
//calculate the fraction this pixel is between neighboring texels in the shadowmap
half4 fracCoordOne = frac(FinalOffset.xyzw * ShadowBufferSize.xyxy);
//linearly interpolate between the top four samples and the bottom four using the appropriate vertical fraction as a weight
half4 VerticalShadowPercentOne = lerp(TopCoverageValues, BottomCoverageValues, fracCoordOne.yyww);
/* second two bilinearly filtered lookups in this chunk */
FinalOffset = ShadowPosition.xyxy + SampleOffsets[ChunkIndex * 2 + 1].xyzw;
//lookup 4 neighboring depth values using Fetch4 in each texDepth2Dlod
ShadowDepthsOne = texDepth2D(ShadowDepthTexture,FinalOffset.xy);
ShadowDepthsTwo = texDepth2D(ShadowDepthTexture,FinalOffset.zw);
//Compare this pixel's depth, projected into lightspace, with the depths from the light's POV.
TopCoverageValues.xy = ShadowPosition.z < ShadowDepthsOne.wx;
TopCoverageValues.zw = ShadowPosition.z < ShadowDepthsTwo.wx;
BottomCoverageValues.xy = ShadowPosition.z < ShadowDepthsOne.yz;
BottomCoverageValues.zw = ShadowPosition.z < ShadowDepthsTwo.yz;
//calculate the fraction this pixel is between neighboring texels in the shadowmap
half4 fracCoordTwo = frac(FinalOffset.xyzw * ShadowBufferSize.xyxy);
//linearly interpolate between the top four samples and the bottom four using the appropriate vertical fraction as a weight
half4 VerticalShadowPercentTwo = lerp(TopCoverageValues, BottomCoverageValues, fracCoordTwo.yyww);
half4 BillinearShadowPercent;
//linearly interpolate between the first two vertical results weighted with the appropriate horizontal fraction
BillinearShadowPercent.xy = lerp(VerticalShadowPercentOne.xz, VerticalShadowPercentOne.yw, fracCoordOne.xz);
//linearly interpolate between the second two vertical results weighted with the appropriate horizontal fraction
BillinearShadowPercent.zw = lerp(VerticalShadowPercentTwo.xz, VerticalShadowPercentTwo.yw, fracCoordTwo.xz);
//weight the 4 bilinearly filtered samples and accumulate
Shadow = Shadow + dot(BillinearShadowPercent, SampleWeight.xxxx);
}
return Shadow;
}

Xet Storage Details

Size:
5.75 kB
·
Xet hash:
108e33c41ee9c7c037548f2bbda8350587d92939e2ca2cf61a22d4a7d99191bf

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.