I've implemented a cubic shadow map for dealing with omni-directional light sources in my scene. By defualt it produces hard shadows enter image description here

Obviously a shadow map with higher resolution (currently using 512x512) would produce a finer edge but that would also result in larger memory footprint for the application.

I'm currently using a very simple approach to sample the cubic shadow map using the TextureCube::SampleCmp method

float depthBias = 0.002f;
float shadowFactor = omniShadowMap.SampleCmp( omniShadowSampler, -lightVec, lightVecLength / pointLight.positionAndRadius.w - depthBias );  

if( shadowFactor == 0.0f )
    shadowFactor = 0.5f;

return float4( ( finalDiffuse + finalSpecular.xyz  ) * shadowFactor , 1.0f );

The SamplerComparisonState is configuered like this

D3D11_SAMPLER_DESC samplerDesc;

samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
samplerDesc.MipLODBias = 0;
samplerDesc.MaxAnisotropy = 1;
samplerDesc.ComparisonFunc = D3D11_COMPARISON_LESS_EQUAL;
samplerDesc.BorderColor[0] = 0.0f;
samplerDesc.BorderColor[1] = 0.0f;
samplerDesc.BorderColor[2] = 0.0f;
samplerDesc.BorderColor[3] = 0.0f;
samplerDesc.MinLOD = 0.0f;
samplerDesc.MaxLOD = 0.0f;

One approach would be to use Percentage-Closer Filtering but I don't know how to access the texels in a TextureCube.

Any suggestions? Thank you!

  • \$\begingroup\$ Cubic Shadow Map makes me think volumetric, by the way... this is just a Cubemap. You sample that using a direction vector. You should be able to get hardware softening of your shadows simply by using D3D11_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR. Now instead a binary 0.0 / 1.0 result, you'll get an average based on the number of samples taken (4, given MaxAnisotropy=1) that pass/fail. I'd hesitate to call this averaged value PCF, but it'll accomplish the same sort of thing. \$\endgroup\$ Aug 7 '15 at 3:02
  • \$\begingroup\$ If you use PCF, you should try and let the hardware do the work. This means you should use SamplerComparisonState as a sampler and use SampleCmpLevelZero on a texture object. This returns 0 if none of the pixel are in shadow 1 if all of them are in it. It also returns a fraction between 0 and 1 to represent shadows that are on the edge. \$\endgroup\$ Jul 28 '17 at 16:58
  • \$\begingroup\$ PCF works by you sampling multiple times around the target pixel and determine % of you in shadow vs not in shadow. So if you have the cubemap already working, you need to offset your sampling vector in a unit circle around the original vector. Typically people use a poisson disk to generated the "random" vector around the target. \$\endgroup\$ Jul 28 '17 at 16:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.