如何为WebGL着色器绘制的圆/椭圆(使用边/距离抗锯齿绘制)添加均匀宽度轮廓

时间:2016-03-21 21:33:20

标签: javascript webgl shader fragment-shader

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

目前我的片段着色器是:

'#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 );',                  

'}'

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

enter image description here

然而,只要我变换四边形(缩放它)以将圆形变成椭圆形,distance计算就会随之变换,从而使轮廓也可以缩放。我的理解是,我会以某种方式需要通过反转它来解释四边形的变换。

enter image description here

我想要的是distance即使变换四边形也能保持均匀,实际上在整个圆/椭圆周围产生一个恒定的宽度轮廓。

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:1)

问题是,你的片段着色器(FS)现在是一种黑盒子(因为代码缺乏信息)。

你的FS写在方形空间内工作。因此,它始终在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值,而不是反转当前笔划的变换。

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