如何向WebGL着色器绘制的圆/椭圆添加统一的宽度轮廓(使用边缘/距离抗锯齿绘制) [英] How can I add a uniform width outline to WebGL shader drawn circles/ellipses (drawn using edge/distance antialiasing)

查看:342
本文介绍了如何向WebGL着色器绘制的圆/椭圆添加统一的宽度轮廓(使用边缘/距离抗锯齿绘制)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am drawing circles/ellipses in WebGL using a single Quad and a fragment shader, in order to draw them in a resolution independent manner (Edge distance anti-aliasing)

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

Here is my fragment shader currently:

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

'}'

这会创建一个带有黑色轮廓的橙色圆圈,无论大小如何,该圆圈都可以完美消除锯齿.

This creates an orange circle with a black outline that is perfectly antialiased whatever the size.

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

However, as soon as I transform the quad (scale it) in order to turn the circle into an ellipse, the distance calculation transforms along with it, causing the outline to also scale. My understanding is that I would somehow need to account for the quad's transform by inverting it.

我希望distance即使在四边形转换时也保持均匀,实际上会在整个圆/椭圆上产生恒定的宽度轮廓.

What I would like is for the distance to remain uniform even when the quad is transformed, in effect producing a constant width outline around the whole circle/ellipse.

任何帮助将不胜感激.

推荐答案

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

The problem is, your fragment shader (FS) is kind of blackbox now (becausethe the code is lack of information).

您的FS被编写为在方形空间内工作.因此,它总是在xy大小相同(-1.0; 1.0间隔)的空间中渲染圆.

Your FS is written to work within square space. So it always render circle in space where x and y are same size ( -1.0; 1.0 interval).

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

While quad is transformed outside (in VS or anywhere else) and there is no way how to reflect that transformation in FS yet.

为解决此问题,我建议将有关缩放的其他信息推送到FS中.诸如 Shadertoy 之类的东西在着色器输入中提供:

To solve the problem, I suggest to push an additional information into FS about the scaling. Something like Shadertoy provides in shader inputs:

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

除了这不是屏幕尺寸的分辨率,而是有关四边形转换的信息,因此类似:

except this wont be the resolution of the screen size, but the information about quad transformation, so something like:

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

然后您可以使用此值来计算不同的笔划.我宁愿计算唯一的dx和dy值,也不愿颠倒当前笔画的变换.

Then you can use this value to calculate different stroke. Instead of inverting the transformation for the current stroke, I would rather calculate unique dx and dy values for it.

有更多方法可以实现有效的解决方案,这取决于您以后如何使用它(应该进行哪些类型的转换等).因此,我仅介绍基本但最简单的解决方案.

There are more ways to achieve the working solution and it depends on how do you want to use it later (what kinds of transformations should be possible etc.). So I present only the basic but the easiest solution.

这篇关于如何向WebGL着色器绘制的圆/椭圆添加统一的宽度轮廓(使用边缘/距离抗锯齿绘制)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆