我画了一个反锯齿状四边形作为地面平面,供模型坐在顶部使用以下顶点着色器:
#version 330
out vec2 tex;
uniform mat4 mvp;
const vec2 pos[4] = vec2[](
vec2(-1.0, 1.0),
vec2(1.0, 1.0),
vec2(1.0, -1.0),
vec2(-1.0, -1.0));
void main()
{
tex = pos[gl_VertexID];
/* setup camera */
gl_Position = mvp * vec4(pos[gl_VertexID], 0.0, 1.0);
}和以下片段着色器:
#version 330
in vec2 tex;
out vec4 Out_Color;
float roundedBoxSDF(vec2 uv, float Size, float Radius)
{
return length(max(abs(uv) - Size + Radius, 0.0)) - Radius;
}
void main()
{
/* 95% to make sure there is a screen space derivative present to
calculate against. */
float dist = roundedBoxSDF(tex, 0.95, 0.5);
float smoothedAlpha = dist / length(vec2(dFdx(dist), dFdy(dist)));
Out_Color = vec4(vec3(1, 1, 1), 1.0 - smoothedAlpha);
}如果我把纹理坐标直接画到四边形的边缘,沿四边形边的非圆边总是别名,因为有符号距离场没有屏幕空间导数来计算距离1远离原点的边。

似乎是一个简单的修复:就像上面的片段着色器一样,我只是将纹理坐标缩小到95% roundedBoxSDF(tex, 0.95, 0.5);,所以有一个没有边缘的四边形来收集屏幕空间导数。很好地防止了.

...until,我放大,远出或以斜角度观看。然后,5%的保证金是不够的,我再次得到混叠,因为屏幕空间上没有像素存在,以获得上述导数。

我怎么解释这种事?继续缩小纹理坐标和增长顶点作为距离的一个函数与相机?还有什么比这更聪明的吗?
发布于 2022-09-30 08:15:58
问题不在于衍生品--与你所相信的相反,它们在边缘上有很好的定义。也不是缺少各向异性滤波,因为它也发生在非斜角度。
就像你自己说的,问题是,从某些角度来说,缩小0.95是不够的。这是因为你的形状的分析边缘与四边的距离小于一个像素。在这种情况下,不需要一个不透明像素的情况下,就没有任何像素光栅化了:

如果你走收缩路线,你的收缩量取决于衍生产品--你需要在屏幕空间上缩小一个像素。一个等价但更简单的方法是计算SDF在您的非收缩箱的内部,然后设置out_Color.a = -smoothedAlpha

在任何一种情况下,收缩都是解决问题的一种相当麻烦的方法,因为它会改变形状的有效大小。
更正确的方法是用像素来扩展网格化的三角形。有一个NVidia扩展就是这样做的:扩容。在未扩展的OpenGL中,您可以使用几何着色器获得类似的结果。在这两种情况下,膨胀的三角形将操作,这需要额外的措施,如果你的形状将是部分透明。
https://stackoverflow.com/questions/73903568
复制相似问题