2013-03-07 141 views
14

考虑到我使用GL_LINES画线,是否可以在片段着色器中添加线条粗细?我看到的大多数示例似乎只访问片段着色器中基元内的纹理元素,并且线条着色器需要写入线基元外部的纹理元素以获取厚度。如果可能的话,一个非常小的,基本的例子会很棒。是否可以在片段着色器中绘制线条粗细?

回答

12

片段着色器有很多可能。看看what some guys are doing。我远离这个水平我自己但是这个代码可以给你出个主意:

#define resolution vec2(500.0, 500.0) 
#define Thickness 0.003 

float drawLine(vec2 p1, vec2 p2) { 
    vec2 uv = gl_FragCoord.xy/resolution.xy; 

    float a = abs(distance(p1, uv)); 
    float b = abs(distance(p2, uv)); 
    float c = abs(distance(p1, p2)); 

    if (a >= c || b >= c) return 0.0; 

    float p = (a + b + c) * 0.5; 

    // median to (p1, p2) vector 
    float h = 2/c * sqrt(p * (p - a) * (p - b) * (p - c)); 

    return mix(1.0, 0.0, smoothstep(0.5 * Thickness, 1.5 * Thickness, h)); 
} 

void main() 
{ 
    gl_FragColor = vec4(
     max(
     max(
      drawLine(vec2(0.1, 0.1), vec2(0.1, 0.9)), 
      drawLine(vec2(0.1, 0.9), vec2(0.7, 0.5))), 
     drawLine(vec2(0.1, 0.1), vec2(0.7, 0.5)))); 
} 

enter image description here

另一种方法是用texture2D检查附近的像素的颜色 - 这样你可以让你图像发光或变厚(例如,如果任何调整像素是白色的 - 使当前像素变为白色,如果紧邻的像素是白色的 - 则使当前像素变灰)。

+0

男人,那个网站很棒! – Meda 2013-10-12 21:34:36

+7

虽然这个“有效”,但应该指出的是,这可能是世界绘制三条线的最低效方式。在混合过程中,99%的加工碎片被扔掉。 – Damon 2013-10-21 18:56:06

+1

+ Damon肯定它不是最佳实践,我的例子有点愚蠢;而仅仅是为了演示着色器的原理和可能性 - 类似的方式可以做不同的发光效果或粒子效果,或者通过距离场不使用单个顶点来渲染整个地形的高度贴图或复杂的几何分形。令人惊讶的着色器可以非常快。 – defhlt 2013-10-21 20:49:18

1

不,这在片段着色器中是不可能的。但是,您可以使用几何着色器将线展开为四边形(或实际上两个三角形),这可能会形成粗线。

Here's关于该主题的一个很好的讨论(与代码示例)。

+0

所以在片段着色器只能访问/修改的图元中的片段?这是有道理的。至于你提出的解决方案,谢谢,但在opengl我不能使用几何着色器:( – Meda 2013-03-07 16:55:36

+0

不能访问 - 你可以从任何来源读取,但你只能写入一个位置,这是由光栅器给你。 – ltjax 2013-03-07 17:05:50

+2

从不说“不”,除非你能证明它 – GottZ 2016-04-21 08:54:54

2

这是我的方法。令p1和p2为界定线的两点,让点为距你想测量的线的点。点最有可能是gl_FragCoord.xy/resolution;

下面是该功能。

float distanceToLine(vec2 p1, vec2 p2, vec2 point) { 
    float a = p1.y-p2.y; 
    float b = p2.x-p1.x; 
    return abs(a*point.x+b*point.y+p1.x*p2.y-p2.x*p1.y)/sqrt(a*a+b*b); 
} 

然后在你的mix和smoothstep函数中使用它。

还检查了这样的回答: https://stackoverflow.com/a/9246451/911207

相关问题