Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion Engine/source/lighting/shadowMap/pssmLightShadowMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,16 @@ void PSSMLightShadowMap::_roundProjection(const MatrixF& lightMat, const MatrixF
}

void PSSMLightShadowMap::_adjustScaleAndOffset(Box3F& clipAABB, Point3F& scale, Point3F& offset) {

const ShadowMapParams* params = mLight->getExtended<ShadowMapParams>();

F32 padding = params->shadowSoftness * (2.0f / (F32)mTexSize);

clipAABB.minExtents.x -= padding;
clipAABB.minExtents.y -= padding;
clipAABB.maxExtents.x += padding;
clipAABB.maxExtents.y += padding;

scale.x = 2.0f / (clipAABB.maxExtents.x - clipAABB.minExtents.x);
scale.y = 2.0f / (clipAABB.maxExtents.y - clipAABB.minExtents.y);
scale.z = 1.0f;
Expand Down Expand Up @@ -469,7 +479,7 @@ void PSSMLightShadowMap::setShaderParameters(GFXShaderConstBuffer* params, Light
params->setSafe( lsc->mOverDarkFactorPSSM, p->overDarkFactor);

// The softness is a factor of the texel size.
params->setSafe( lsc->mShadowSoftnessConst, p->shadowSoftness * ( 1.0f / mTexSize ) );
params->setSafe( lsc->mShadowSoftnessConst, p->shadowSoftness * ( 2.0f / mTexSize ) );
}

void PSSMLightShadowMap::_calcPlanesCullForShadowCasters(Vector< Vector<PlaneF> > &out, const Frustum &viewFrustum, const Point3F &_ligthDir)
Expand Down
18 changes: 12 additions & 6 deletions Engine/source/lighting/shadowMap/shadowMatHook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,18 @@ void ShadowMaterialHook::init( BaseMatInstance *inMat )

mShadowMat[ShadowType_Spot] = newMat;

newMat = new ShadowMatInstance(shadowMat);
newMat->setUserObject(inMat->getUserObject());
newMat->getFeaturesDelegate().bind(&ShadowMaterialHook::_overrideFeatures);
forced.setCullMode(GFXCullCW);
forced.zBias = 1000.0f;
forced.zSlopeBias = 1.0f;
forced.setFillModeSolid();
newMat->addStateBlockDesc(forced);
forced.cullDefined = true;
newMat->init(features, inMat->getVertexFormat());
mShadowMat[ShadowType_PSSM] = newMat;

newMat = new ShadowMatInstance( shadowMat );
newMat->setUserObject( inMat->getUserObject() );
newMat->getFeaturesDelegate().bind( &ShadowMaterialHook::_overrideFeatures );
Expand Down Expand Up @@ -162,12 +174,6 @@ BaseMatInstance* ShadowMaterialHook::getShadowMat( ShadowType type ) const
{
AssertFatal( type < ShadowType_Count, "ShadowMaterialHook::getShadowMat() - Bad light type!" );

// The cubemap and pssm shadows use the same
// spotlight material for shadows.
if ( type == ShadowType_Spot ||
type == ShadowType_PSSM )
return mShadowMat[ShadowType_Spot];

// Get the specialized shadow material.
return mShadowMat[type];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,37 @@ static float2 sNonUniformTaps[NUM_PRE_TAPS] =
/// rotations of the filter taps.
TORQUE_UNIFORM_SAMPLER2D(gTapRotationTex, 2);

float shadowCompare(float occluderDepth, float receiverDepth)
{
return receiverDepth > occluderDepth ? 0.0 : 1.0;
}

float pcf_sampleTaps(
TORQUE_SAMPLER2D(shadowMap),
float2 sinCos,
float2 shadowPos,
float filterRadius,
float receiverDepth,
float factor_bias,
int startTap,
int endTap )
{
float result = 0;

float2 tap;
for(int t = startTap; t < endTap; t++)
{
tap.x = (sNonUniformTaps[t].x * sinCos.y - sNonUniformTaps[t].y * sinCos.x) * filterRadius;
tap.y = (sNonUniformTaps[t].y * sinCos.y + sNonUniformTaps[t].x * sinCos.x) * filterRadius;

float occluder = TORQUE_TEX2DLOD(shadowMap, float4(shadowPos + tap,0,0)).r;

result += shadowCompare(occluder, receiverDepth);
}

return result / float(endTap - startTap);
}

float softShadow_sampleTaps( TORQUE_SAMPLER2D(shadowMap1),
float2 sinCos,
float2 shadowPos,
Expand All @@ -81,78 +112,65 @@ float softShadow_sampleTaps( TORQUE_SAMPLER2D(shadowMap1),
int startTap,
int endTap )
{

float shadow = 0;

float2 tap = 0;
for ( int t = startTap; t < endTap; t++ )
{
tap.x = ( sNonUniformTaps[t].x * sinCos.y - sNonUniformTaps[t].y * sinCos.x ) * filterRadius;
tap.y = ( sNonUniformTaps[t].y * sinCos.y + sNonUniformTaps[t].x * sinCos.x ) * filterRadius;

float occluder = TORQUE_TEX2DLOD( shadowMap1, float4( shadowPos + tap, 0, 0 ) ).r;

float esm = saturate( exp( esmFactor * ( occluder - distToLight ) ) );
float esm = exp( clamp(esmFactor * (occluder - distToLight), -80.0, 0.0) );
esm = saturate(esm);
shadow += esm / float( endTap - startTap );
}

return shadow;
}


float softShadow_filter( TORQUE_SAMPLER2D(shadowMap),
float2 vpos,
float2 shadowPos,
float filterRadius,
float distToLight,
float dotNL,
float esmFactor )
float softShadow_filter(
TORQUE_SAMPLER2D(shadowMap),
float2 vpos,
float2 shadowPos,
float filterRadius,
float distToLight,
float dotNL,
float esmFactor)
{
#ifndef SOFTSHADOW

// If softshadow is undefined then we skip any complex
// filtering... just do a single sample ESM.

float occluder = TORQUE_TEX2DLOD(shadowMap, float4(shadowPos, 0, 0)).r;
float shadow = saturate( exp( esmFactor * ( occluder - distToLight ) ) );

#else
// Lookup the random rotation for this screen pixel.
float2 sinCos = ( TORQUE_TEX2DLOD(gTapRotationTex, float4(vpos * 16, 0, 0)).rg - 0.5) * 2;

// Do the prediction taps first.
float shadow = softShadow_sampleTaps( TORQUE_SAMPLER2D_MAKEARG(shadowMap),
sinCos,
shadowPos,
filterRadius,
distToLight,
esmFactor,
0,
NUM_PRE_TAPS );

// We live with only the pretap results if we don't
// have high quality shadow filtering enabled.
#ifdef SOFTSHADOW_HIGH_QUALITY

// Only do the expensive filtering if we're really
// in a partially shadowed area.
if ( shadow * ( 1.0 - shadow ) * max( dotNL, 0 ) > 0.06 )
{
shadow += softShadow_sampleTaps( TORQUE_SAMPLER2D_MAKEARG(shadowMap),
sinCos,
shadowPos,
filterRadius,
distToLight,
esmFactor,
NUM_PRE_TAPS,
NUM_TAPS );

// This averages the taps above with the results
// of the prediction samples.
shadow *= 0.5;
}

#endif // SOFTSHADOW_HIGH_QUALITY

#endif // SOFTSHADOW
float2 sinCos = (TORQUE_TEX2DLOD(gTapRotationTex, float4(vpos * 16,0,0)).rg - 0.5) * 2;

float shadow = pcf_sampleTaps(
TORQUE_SAMPLER2D_MAKEARG(shadowMap),
sinCos,
shadowPos,
filterRadius,
distToLight,
esmFactor,
0,
NUM_PRE_TAPS);

#ifdef SOFTSHADOW_HIGH_QUALITY

if(shadow * (1.0-shadow) * max(dotNL,0) > 0.06)
{
shadow += pcf_sampleTaps(
TORQUE_SAMPLER2D_MAKEARG(shadowMap),
sinCos,
shadowPos,
filterRadius,
distToLight,
esmFactor,
NUM_PRE_TAPS,
NUM_TAPS);

shadow *= 0.5;
}

return shadow;
#endif

return shadow;
}
Loading
Loading