单通线框问题(Single-pass wireframe issue)

2019-10-20 03:17发布

我想实现单通线框,但我有几个在这个过程中的问题。

问题1

对于一些原因,我没有得到仅线框(像glPolygoneMode -线)充满几何后,我的几何着色器的工作。

但是,如果我禁用几何着色器让我的几何形状:

我真正想实现的是几何和它的线框。

问题2

其实,我的原语三角形带。 我用它们来避免使用四边形来提高性能。 我怎么能跳过线框的边缘,而在画什么? (我已经看到了后如何可以做,但它仍然是不明确我。)

这里是我的着色器:

顶点着色器:

#version 330
//
// (C) Copyright 2010 Patrick Cozzi and Deron Ohlarik
//
// Distributed under the MIT License.
// See License.txt or http://www.opensource.org/licenses/mit-license.php.
//

layout(location = 0) in vec3 in_Position;

uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform mat4 modelMatrix;
uniform mat4 og_viewportTransformationMatrix;

out vec2 windowPosition;

vec4 og_ClipToWindowCoordinates(vec4 v, mat4 viewportTransformationMatrix);

void main()                     
{
    gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(in_Position, 1.0);

    windowPosition = og_ClipToWindowCoordinates(gl_Position, og_viewportTransformationMatrix).xy;
}

vec4 og_ClipToWindowCoordinates(vec4 v, mat4 viewportTransformationMatrix)
{
    v.xyz /= v.w;                                                  // normalized device coordinates
    v.xyz = (viewportTransformationMatrix * vec4(v.xyz, 1.0)).xyz; // window coordinates
    return v;
}

Geomerty着色器:

#version 330 
//
// (C) Copyright 2010 Patrick Cozzi and Deron Ohlarik
//
// Distributed under the MIT License.
// See License.txt or http://www.opensource.org/licenses/mit-license.php.
//

layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;

in vec2 windowPosition[];
noperspective out vec3 distanceToEdges;

float og_distanceToLine(vec2 f, vec2 p0, vec2 p1);

void main()
{
    vec2 p0 = windowPosition[0];
    vec2 p1 = windowPosition[1];
    vec2 p2 = windowPosition[2];

    gl_Position = gl_in[0].gl_Position;
    distanceToEdges = vec3(og_distanceToLine(p0, p1, p2), 0.0, 0.0);
    EmitVertex();

    gl_Position = gl_in[1].gl_Position;
    distanceToEdges = vec3(0.0, og_distanceToLine(p1, p2, p0), 0.0);
    EmitVertex();

    gl_Position = gl_in[2].gl_Position;
    distanceToEdges = vec3(0.0, 0.0, og_distanceToLine(p2, p0, p1));
    EmitVertex();
}

float og_distanceToLine(vec2 f, vec2 p0, vec2 p1)
{
    vec2 l = f - p0;
    vec2 d = p1 - p0;

    //
    // Closed point on line to f
    //
    vec2 p = p0 + (d * (dot(l, d) / dot(d, d)));
    return distance(f, p);
}

片段着色器:

#version 330
//
// (C) Copyright 2010 Patrick Cozzi and Deron Ohlarik
//
// Distributed under the MIT License.
// See License.txt or http://www.opensource.org/licenses/mit-license.php.
//

uniform float u_halfLineWidth;
uniform vec3 u_color;

noperspective in vec3 distanceToEdges;
out vec4 fragmentColor;

void main()
{
    float d = min(distanceToEdges.x, min(distanceToEdges.y, distanceToEdges.z));

    if (d > u_halfLineWidth + 1.0)
    {
        discard;
    }

    d = clamp(d - (u_halfLineWidth - 1.0), 0.0, 2.0);
    fragmentColor = vec4(u_color, exp2(-2.0 * d * d));
}

帮我找出我的位置弄错了。

更新:

我已经更新Fragment shaderGeometry shader在他的回答如上面所提到的Andon M.科尔曼,但在第二个问题中所述问题仍然没有解决。

更新2

我刚才做一些小的修改在fragmet着色器,并且解决了我的问题。

更新片段着色器

#version 330
//
// (C) Copyright 2010 Patrick Cozzi and Deron Ohlarik
//
// Distributed under the MIT License.
// See License.txt or http://www.opensource.org/licenses/mit-license.php.
//

uniform float u_halfLineWidth;
uniform vec3 u_color;

noperspective in vec3 distanceToEdges;
out vec4 fragmentColor;

void main()
{
    float d = min(distanceToEdges.y, max(distanceToEdges.x, distanceToEdges.z));

    if (d > u_halfLineWidth + 1.0)
    {
        fragmentColor =  vec4(u_color, 1);
        return;
    }

    fragmentColor = vec4(vec3(0,0,0), 1);
}

Answer 1:

你的第一个问题是有关您使用的discard

目前,你丢弃不适当的距离内从谎言中的片段着色器的线框的片段。 这是不正确的行为,这样只会画线框。

什么,你需要做的其实就是更换discard用不同的颜色。

if (d > u_halfLineWidth + 1.0)
{
    //discard; // DO NOT DO THIS

    //
    // Instead, do this
    //
    fragmentColor = vec4 (0.0, 0.0, 0.0, 1.0);
    return;
}

诚然这会产生黑色填充网格,但如果你使用的颜色u_color ,网格的填充部分会从线框难以区分。 最终,你可能想定义每个顶点的颜色,是从线框颜色分开的,但它是由你来弄清楚如何做到这一点。


对于问题2,即通过调整边距解决:

您链接到这篇文章的想法是,你的几何着色器发出的每个三角形,它应该写一个距离,每个顶点的相对边缘。 如果你知道你的三角形边缘之一是内部边缘,因此不应该被列入线框,你应该设置的距离为边相对的顶点距离足够远,它从来没有插值为0(或任何宽度你选择了线框)。

以下修改您的GS将删除三角形带的内部边缘:

void main()
{
    vec2 p0 = windowPosition[0];
    vec2 p1 = windowPosition[1];
    vec2 p2 = windowPosition[2];

    // Alternate between using the first and last vertex as the one opposite the
    // interior edge based on primitive ID.
    bool strip_flip = (bool (gl_PrimitiveIDIn & 1));

    gl_Position = gl_in[0].gl_Position;
    if (strip_flip)
      distanceToEdges = vec3(og_distanceToLine(p0, p1, p2), 0.0, 0.0);
    else
      distanceToEdges = vec3(og_distanceToLine(p0, p1, p2), 0.0, 99999.0);
    EmitVertex();

    gl_Position = gl_in[1].gl_Position;
    if (strip_flip)
      distanceToEdges = vec3(99999.0, og_distanceToLine(p1, p2, p0), 0.0);
    else
      distanceToEdges = vec3(0.0,     og_distanceToLine(p1, p2, p0), 99999.0);
    EmitVertex();

    gl_Position = gl_in[2].gl_Position;
    if (strip_flip)
      distanceToEdges = vec3(99999.0, 0.0, og_distanceToLine(p2, p0, p1));
    else
      distanceToEdges = vec3(    0.0, 0.0, og_distanceToLine(p2, p0, p1));
    EmitVertex();
}

这是通过作为所述带插入所述内部边缘相对顶点第一/最后顶点之间交替。 对于每个奇数三角形,内部边缘是所述第一顶点的对面,为每个偶数三角形它是相对的最后一个。 这基本上三角形条带的运作,该反转在每个连续的三角形绕组,这使得它易于识别,以除去其边缘。

为了确保distanceToEdges从未插值以任何小于或等于u_HalfLineWidth + 1.0在该边缘的方向,所述坐标是从它们的正常0.0值推送到99999.0。

因此,如果你指的虚线边缘下图中,Q是99999.0:

试想一下跨破灭边缘镜像的三角形,那么你应该有什么样的几何着色器做一个不错的主意。



文章来源: Single-pass wireframe issue