24

我有一些简单的多边形(少于 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 个三角形),那么我如何在片段着色器中插值以绘制给定的边框厚度?我假设我将边缘标志以及所需的线条粗细传递给片段着色器,它会进行一些插值计算来计算边缘与非边缘顶点之间的距离,并将颜色阈值作为边框/填充适当?

4

1 回答 1

29

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

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

说明计算与每个边缘的距离的图表

下面是两个解释如何做到这一点的教程,通常这用于渲染线框覆盖,因此您可能会更好地搜索它。出于您的目的,由于这实际上是线框渲染的一种特殊化(此外,您希望丢弃不属于外部多边形边缘的线),您将需要识别边缘顶点并执行额外的处理。

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

显示如何排除内部边缘的图表

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

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

https://web.archive.org/web/20190220052115/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

于 2013-08-05T21:36:11.493 回答