【问题标题】:How can I add a uniform width outline to WebGL shader drawn circles/ellipses (drawn using edge/distance antialiasing)如何向 WebGL 着色器绘制的圆/椭圆添加统一宽度的轮廓(使用边缘/距离抗锯齿绘制)
【发布时间】:2016-03-22 06:55:01
【问题描述】:

我正在使用单个 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 );',                  

'}'

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

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

我希望 distance 即使在变换四边形时也能保持一致,实际上会在整个圆/椭圆周围产生恒定宽度的轮廓。

任何帮助将不胜感激。

【问题讨论】:

    标签: javascript webgl shader fragment-shader


    【解决方案1】:

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

    您的 FS 是为在方形空间内工作而编写的。所以它总是在x 和y 大小相同(-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 值,而不是反转当前笔划的转换。

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

    【讨论】:

    • 谢谢,我想我明白你在说什么了。所以假设我已经将椭圆的宽度和高度作为制服传递了。我将如何计算行程?
    • 好吧,如果您改为按宽度和高度而不是从外部对其进行转换,那么现在这是一种不同的游戏。你真的必须决定你想要什么:在片段着色器中绘制椭圆和自定义形状?还是从外部进行改造?这个问题开始变得很大了。
    • 如果你想使用片段着色器,我强烈推荐 shadertoy。它比 webgl 小得多,也更容易理解。我写的这个演示可能会给你一些提示:shadertoy.com/view/4scSWr
    • 对不起,我应该更清楚。如果我确定推入宽度/高度,我可以通过计算 texelSizes - (1.0 / width) 和 (1.0 / height) 来计算比例。我只是不确定如何将其应用于中风。
    • 谢谢,我会看看你的shadertoy演示。 :)
    猜你喜欢
    • 1970-01-01
    • 2017-01-30
    • 1970-01-01
    • 2010-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多