在 opengl 中使用重心坐标的抗锯齿线

Anti-aliased lines using barycentric coordinates in opengl

我正在通过连接两个三角形来绘制线段。三角形的每个顶点都有一组唯一的坐标作为可变变量 (vec3 vBC)。然后在片段着色器中,我为这个变量得到的值是一个内插值,表明片段在三角形内的位置。我用这个值来确定片段离三角形的边缘有多远,而三角形的边缘又被用来对边缘进行抗锯齿。

查看下图中的问题:

注意矩形 1 中的锯齿状边缘。这是因为我没有对边缘 BC 和 DE 应用抗锯齿,因为它们是内部边缘。因为长度 x 很小,靠近顶点 C 和 D 的边 BC 和 DE 上的锯齿状边缘变得可见;这些锯齿状边缘的长度比长度 x 长。如果我对这两个边缘(BC 和 DE)应用抗锯齿,我会看到 Rect 2。这是因为抗锯齿期间的平滑过程将 alpha 值 0.0 分配给位于边缘或非常靠近边缘的片段。所以anti-aliased BC和DE在里面引入了一条白色对角线。

所以我的问题是我怎样才能平滑 Rect 1?

片段着色器:

varying vec4 DestinationColor;
varying vec2 TexCoordOut;
varying vec3 vBC;
uniform sampler2D Texture;
uniform int TexEnabled;
float edgeFactor();

void main() {
  if (TexEnabled == 1) {
     gl_FragColor = texture2D(Texture, TexCoordOut) * DestinationColor;
  } else{
     gl_FragColor = vec4(DestinationColor.xyz, edgeFactor());
  }
}

float edgeFactor() {
  vec3 d = fwidth(vBC);
  vec3 a3 = smoothstep(vec3(0.0), d*1.5, vBC);
  return a3.y;
};

在着色器代码中,a3.y 指的是一组坐标中的第二个值(顶点 D 或 C 与片段之间的距离),即 y 表示 D(0,1,0) 中的 1,第一个 0第二个0分别代表x和z。

该算法基本上是合理的,但是您需要一些方法来区分内部边缘和外部边缘,而这对于简单的几何图形是做不到的。您需要复制顶点,以便构成内部边的顶点可以具有一些独特的属性,从而使它们看起来与外部边不同。也就是说,听起来很贵...

创建一个小纹理可能更简单,该纹理具有朝向边缘的透明 alpha 值,该值应用于整个线宽,并沿线宽重复。它可能比所有额外的逐顶点数据更快,尤其是在具有延迟几何处理的移动设备上。