如何启用硬件百分比更接近过滤?

Ján*_*zki 4 c++ directx hlsl directx-11

我正在尝试对我的 shaow 贴图实施 PCF 过滤,因此修改了 GPU Gems 文章(http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html),以便它可以在当前着色器上运行。修改包括用 Texture2D.Sample() 函数替换 tex2Dproj 函数,以便它接受在 DirectX11 中创建的采样器状态。然后我将偏移值与普通阴影贴图比较进行了比较:

float2 ShTex;
ShTex.x = PSIn.ShadowMapSamplingPos.x/PSIn.ShadowMapSamplingPos.w/2.0f +0.5f;
ShTex.y = -PSIn.ShadowMapSamplingPos.y/PSIn.ShadowMapSamplingPos.w/2.0f +0.5f;
float realDistance = PSIn.ShadowMapSamplingPos.z/PSIn.ShadowMapSamplingPos.w;


(realDistance - xShBias) <= offset_lookup(xTextureSh, texSampler, ShTex, float2(x, y), scale); //Blocker-receiver comparison (the usual stuff, only that it gets 4*4 samples from near offsets then divides the final value with 16)
Run Code Online (Sandbox Code Playgroud)

现在我得到的回报是这样的: 楼梯效果

在文章中,它说并表明硬件应该神奇地插入结果。我猜 tex2Dproj 可能会这样做,但没有成功让它工作。

最近我遇到了 SampleCmpLevelZero 函数,我用这个采样器状态尝试了它:

SamplerComparisonState cmpSampler
{
   Filter = COMPARISON_MIN_MAG_MIP_LINEAR;
   AddressU = Clamp;
   AddressV = Clamp;

   ComparisonFunc = LESS;
};
Run Code Online (Sandbox Code Playgroud)

当我让它工作时,整个场景从阴影到无阴影和部分阴影(这似乎是正确的阴影)随机闪烁。

xTextureSh.SampleCmpLevelZero( cmpSampler, ShTex.xy, realDistance - xShBias );
Run Code Online (Sandbox Code Playgroud)

可悲的是,我发现有人有同样的问题,但他设法通过将过滤器重写为我已经应用的模式来修复它。

我的深度纹理采用以下格式:DXGI_FORMAT_R24_UNORM_X8_TYPELESS

我现在对这个关于正确 PCF 过滤的谜感到非常困惑,有没有人可以提出任何建议?提前感谢您并阅读最后。

Ján*_*zki 6

好的,所以我已经完成了。通过使用SampleCmpLevelZero,我尝试SamplerComparisonState在 HLSL 代码中声明 a ,但结果出现故障。阴影贴图双线性过滤不起作用。然后我尝试在 D3D11 API 内部创建一个 Sampler 状态,设置D3D11_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT为描述的过滤器,D3D11_COMPARISON_LESS用于描述的比较函数。在着色器中,我声明了 aSamplerComparisonState而不是通常的SamplerState,并且没有在那里填写描述,而是从 api 中注册了它:

SamplerComparisonState compSampler:register(s2);
Run Code Online (Sandbox Code Playgroud)

然后魔术终于开始了: 手动采样 4*4 纹素网格的双线性过滤

如您所见,结果是阴影周围的无缝半影而不是楼梯。即使没有对上一张图片进行手动采样,我们也可以通过一个手动采样(以及由 完成的更多自动采样SampleCmpLevelZero)获得相当可以接受的结果:一份手工样品

可悲的是,我不知道是什么导致了着色器内的采样器声明出现故障,我不喜欢这样。如果有人经历过这样的事情,如果他/她和我一起着色,我会很高兴。

还要感谢MHGameWork试图帮助我解决这个问题。

更新:自从提出这个问题以来已经过去了很多时间,在此期间我已经知道在着色器中声明采样器的问题,所以我把它放在这里:如果您正在使用,则只能在着色器中声明采样器对象效果框架。使用准系统着色器时,它们需要通过 API 调用上传。