如何将统一宽度的轮廓添加到绘制 circles/ellipses 的 WebGL 着色器(使用 edge/distance 抗锯齿绘制)

How can I add a uniform width outline to WebGL shader drawn circles/ellipses (drawn using edge/distance antialiasing)

我在 WebGL 中使用单个四边形和片段着色器绘制 circles/ellipses,以便以独立于分辨率的方式绘制它们(边缘距离抗锯齿)

这是我当前的片段着色器:

'#extension GL_OES_standard_derivatives : enable',
'precision mediump float;',
'varying vec2 coord;',
'vec4 circleColor = vec4(1.0, 0.5, 0.0, 1.0);',
'vec4 outlineColor = vec4(0.0, 0.0, 0.0, 1.0);',

'uniform float strokeWidth;',          
'float outerEdgeCenter = 0.5 - strokeWidth;',

'void main(void){',

      'float dx = 0.5 - coord.x;',
      'float dy = 0.5 - coord.y;',
      'float distance = sqrt(dx*dx + dy*dy);',

      'float delta = fwidth(distance);',
      'float alpha = 1.0 - smoothstep(0.45 - delta, 0.45, distance);',
      'float stroke = 1.0 - smoothstep(outerEdgeCenter - delta, outerEdgeCenter + delta, distance);',

      'gl_FragColor = vec4( mix(outlineColor.rgb, circleColor.rgb, stroke), alpha );',                  

'}'

这将创建一个带有黑色轮廓的橙色圆圈,无论大小如何都完美抗锯齿。

但是,一旦我变换四边形(对其进行缩放)以将圆变成椭圆,distance 计算就会随之变换,从而导致轮廓也进行缩放。我的理解是,我会以某种方式需要通过反转它来解释四边形的变换。

我希望 distance 即使在四边形变换时也能保持均匀,实际上在整个 circle/ellipse.

周围产生一个恒定宽度的轮廓

任何帮助将不胜感激。

问题是,您的片段着色器 (FS) 现在有点像黑盒子(因为代码缺少信息)。

你的 FS 被写成在方块内工作 space。所以它总是在 space 中呈现圆圈,其中 xy 大小相同(-1.0;1.0 间隔)。

虽然 quad 在外部(在 VS 或其他任何地方)进行了转换,但还没有办法在 FS 中反映该转换。

为了解决这个问题,我建议将有关缩放的附加信息推送到 FS。 Shadertoy 之类的东西在着色器输入中提供:

uniform vec3 iResolution; // viewport resolution (in pixels)

除了这不是屏幕尺寸的分辨率,而是关于四边形变换的信息,比如:

varying vec2 trans;
// where value (1.0, 1.0) mean no transformation

然后你可以使用这个值来计算不同的行程。我宁愿为它计算唯一的 dx 和 dy 值,而不是反转当前笔划的转换。

有更多方法可以实现工作解决方案,这取决于您以后想如何使用它(应该可以进行哪些类型的转换等)。所以我只提供基本但最简单的解决方案。