C++ 阴影贴图透视混叠

C++ 阴影贴图透视混叠,c++,opengl,shadow,shadow-mapping,C++,Opengl,Shadow,Shadow Mapping,当曲面几乎与灯光方向平行时,似乎不可能删除此类透视混叠 我已经测试了几种不同的暗影祛痘技术: 持续的偏见不起作用:介绍peter panning关于足够大的偏见,以消除问题 坡度比例偏差不能完全起作用,只会稍微减轻问题 法线偏移阴影不起作用,会引入额外的阴影变形 glPolygonOffset不起作用,我怀疑这和斜率刻度偏差是一样的 PCL只是稍微消除了模式的锯齿,实际上并不能解决问题。消除图案所需的过滤量会产生巨大的斑点阴影 VSM做的不多,只是稍微改变了模式 增加阴影贴图的分辨率和像素深

当曲面几乎与灯光方向平行时,似乎不可能删除此类透视混叠

我已经测试了几种不同的暗影祛痘技术:

  • 持续的偏见不起作用:介绍peter panning关于足够大的偏见,以消除问题
  • 坡度比例偏差不能完全起作用,只会稍微减轻问题
  • 法线偏移阴影不起作用,会引入额外的阴影变形
  • glPolygonOffset不起作用,我怀疑这和斜率刻度偏差是一样的
  • PCL只是稍微消除了模式的锯齿,实际上并不能解决问题。消除图案所需的过滤量会产生巨大的斑点阴影
  • VSM做的不多,只是稍微改变了模式
  • 增加阴影贴图的分辨率和像素深度可以减少问题,但是足够大的分辨率可以完全解决问题,这将大大降低帧速率
  • 扩展投影变换的近平面和远平面以创建阴影贴图也没有任何作用
从我在谷歌和我的书上所能找到的一切来看,这基本上是一个无法解决的问题。我知道一定有办法解决这个问题,因为即使是一些独立游戏也有完美平滑的阴影贴图


有人愿意分享这个秘密吗?

也许你已经找到了答案,因为这个问题已经三年了,但我仍然想说,平行于光方向的表面上的瑕疵必须用法线偏移固定。至少我用这种方法解决了同样的问题。是的

vec4 shadowPosition = lightMatrix * vec4(_position, 1.0);
float bias = 0.0002;
float visibility = (texture(shadow, shadowPosition.xy / 2. + .5).r - .5) * 2. < shadowPosition.z - bias ? 0.1: 1.0;
vec4 shadowPosition=lightMatrix*vec4(_位置,1.0);
浮动偏差=0.0002;
浮动可见性=(纹理(阴影,阴影位置.xy/2.+.5).r-.5)*2.<阴影位置,z偏移?0.1: 1.0;

现在是了

float bias = 0.02;
vec4 shadowPosition = lightMatrix * vec4(_position + _normal * bias, 1.);
float visibility = (texture(shadow, shadowPosition.xy / 2. + .5).r - .5) * 2. < shadowPosition.z ? 0.1: 1.0;
浮动偏差=0.02;
vec4阴影位置=光矩阵*vec4(_位置+_法线*偏差,1.);
浮动可见性=(纹理(阴影,阴影位置.xy/2.+.5).r-.5)*2.<阴影位置,z?0.1: 1.0;


是的,阴影的边界现在是锯齿状的,但我希望其他一些技术可以帮助我以后平滑它。

glPolygonOffset
实际上是坡度比例偏差。扩展近/远平面实际上与您想要的相反,这将损害深度缓冲区的分辨率并导致更多的锯齿。你考虑过级联阴影贴图吗?在透视投影中,它们可以很好地分配阴影精度,但这并不能真正解决问题。另外,我截图的演示目前使用的是层叠阴影贴图,从图像中可以看出,它有时仍然非常糟糕,为什么它不是一个解决方案?该楼梯台阶是由于阴影贴图与投影(灯光空间和视图空间纹理大小)拟合不充分造成的。任何对抗过多/过少采样的方法通常都会有所帮助,但对深度施加偏差实际上并不能解决与坏样本量相关的问题。偏差仅在解决与量化相关的问题时有效(例如,深度缓冲精度不足以记录深度变化)。您的问题在于样本大小,而不是存储深度的准确性。所以正确实现的CSM应该能够完全消除透视混叠?正如我所说的,我从中获取图像的演示目前正在使用CSMNo,除了存储每个texel的单个采样深度值以外的更多信息,没有什么能完全消除这个问题。VSM试图通过深度存储差异来实现这一点;如果没有其他消除偏见的必要性(请参阅以获取解释)。VSM实际上可以与CSM结合,这将有助于两端的混叠(CSM产生更好的样本拟合,VSM允许在重建期间进行更好的过滤)。