使用片段着色器在2d多边形上绘制边框

时间:2013-08-03 17:59:48

标签: opengl-es opengl-es-2.0 glsl fragment-shader vertex-shader

我有一些简单的多边形(少于20个顶点)在一个简单的xy平面上渲染平面,使用GL_TRIANGLES和一个平面颜色,一个2d模拟。

我想为这些多边形添加可变厚度和不同颜色的边框。我有一些使用相同顶点和glLineWidth / GL_LINE_LOOP实现的东西,它起作用,但是是另一个渲染过程并重复所有顶点变换。

我想我应该可以使用gl_FragCoord和顶点数据和/或纹理坐标在片段着色器中完成此操作,但我不确定,我的天真尝试显然是不正确的。

我想象以下内容。

uniform vec2 scale;  // viewport h/w
uniform float line_width;
uniform vec4 fill_color;
uniform vec4 border_color;

varying vec4 vertex; // in world coords

void main()
{
    if (distance_from_edge(gl_FragCoord, vertex, scale) < line_width)
    {
        // we're close to the edge the polygon, so we're the border.
        gl_FragColor = border_color;
    }
    else
    {
        gl_FragColor = fill_color;
    }
}

我想弄清楚的部分是distance_from_edge函数 - 如何计算?使用gl_FragCoord是错误的方法 - 我应该使用某种纹理映射吗?

作为一项实验,我尝试用刻度将顶点转换为像素空间,然后计算它与gl_FragCoord之间的距离(以像素为单位),但这会产生我并不真正理解的奇怪结果。另外我需要到边缘的距离,而不是顶点,但我不知道如何得到它。

有什么想法吗?

编辑:根据尼科尔的回答,我的问题变成了:

假设我有一个三角形,其中3个角顶点标记为边缘顶点,中间的一个顶点标记为非边缘(因此总共渲染了3个三角形),那么如何在片段着色器中插值以绘制边框给定厚度?我假设我将边缘标志传递给片段着色器,以及所需的线条粗细,并进行一些插值计算以计算边缘与非边缘顶点之间的距离,并将颜色阈值设置为适当的边界/填充?

1 个答案:

答案 0 :(得分:25)

你所需要的只是重心坐标,因为你正在处理三角形。为三角形的每个顶点指定一个标识,然后使用硬件在顶点和片段阶段之间的内置插值来计算片段着色器中每个顶点的相对距离。

您可以将每个顶点的重心坐标视为距相对边缘的距离。在下图中,顶点P0的相对边是e1,它的距离用h1表示;它的重心坐标是<0.0, h1, 0.0>。当在光栅化期间生成片段时,GPU可以在内部使用此坐标空间来插入三角形的顶点属性,它可以根据三角形内的位置快速加工每顶点属性。

Diagram illustrating the calculation of distance from each edge

以下两个教程解释了如何执行此操作,通常这用于渲染线框覆盖,以便您可以更好地搜索它。出于您的目的,由于这实际上是线框渲染的特化(除了您想要抛出不属于外部多边形边的线),您还需要识别边缘顶点并执行其他处理。

例如,如果一个顶点不是外边缘的一部分,那么你需要为它指定一个类似于&lt; 1,100,0&gt;的重心坐标。和连接的顶点&lt; 0,100,1&gt;并且将忽略内边缘(假设它是与指定的顶点<0,0,0相对的边缘,如下图所示)。这个想法是你永远不希望沿着这个边缘的点插值到0.0附近的任何位置(或者你用来将一个片段作为边界的一部分着色的任何阈值),使它与三角形的中心相距极远。相反的顶点将解决这个问题。

Diagram showing how to exclude interior edges

没有几何着色器(OpenGL ES友好):

如果您能够修改顶点数据以保持重心坐标,那么这是一个解释如何执行此操作的链接。它具有更高的存储和预处理要求(特别是,相邻边缘之间的顶点共享可能不再可能,因为您需要每个三角形由三个顶点组成,每个顶点具有不同的输入重心坐标 - 这就是为什么几何着色器是一个理想的解决方案)但是,它将运行在比需要几何着色器的更通用解决方案更多的OpenGL ES类硬件上。

http://codeflow.org/entries/2012/aug/02/easy-wireframe-display-with-barycentric-coordinates/

使用几何着色器( OpenGL ES友好):

或者,您可以使用几何着色器在渲染时计算每个三角形的重心坐标,如本教程中所示。有可能在OpenGL ES中你无法访问几何着色器,所以这可能会被忽略。

http://strattonbrazil.blogspot.com/2011/09/single-pass-wireframe-rendering_10.html http://strattonbrazil.blogspot.com/2011/09/single-pass-wireframe-rendering_11.html

此解决方案的理论基础可以在这里找到(由Internet Archive Wayback Machine提供):

http://web.archive.org/web/ * / http://cgg-journal.com/2008-2/06/index.html