4

我正在尝试对我的 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)

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

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

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

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

   ComparisonFunc = LESS;
};

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

xTextureSh.SampleCmpLevelZero( cmpSampler, ShTex.xy, realDistance - xShBias );

可悲的是,我找到了一个有同样问题的人,但他通过将过滤器重写为我已经应用的模式来修复它。

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

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

4

2 回答 2

6

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

SamplerComparisonState compSampler:register(s2);

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

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

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

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

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

于 2013-06-17T13:30:35.227 回答
2

来自http://msdn.microsoft.com/en-us/library/windows/desktop/bb205073(v=vs.85).aspx#Mapping_Texels_to_Pixels_DX10

D3D10中的纹理坐标发生了变化,你考虑过这个吗?它们现在是半个单位,就像像素一样(以及在 D3D9 中的位置)。

如果您在移植时没有考虑到这一点,那么您现在正在精确的纹素位置进行采样,我认为这不会以您想要的着色器方式导致双线性插值。

编辑:因为你这样做正确:)我可能有另一个解决方案:

如果 GenerateMips 无法生成,它会静默失败。
我认为不可能为 DXGI_FORMAT_R24_UNORM_X8_TYPELESS 生成 mipmap。您可以在此处查看支持的格式列表:http: //msdn.microsoft.com/en-us/library/windows/desktop/bb173569 (v=vs.85).aspx 。

于 2013-06-15T19:27:36.763 回答