2

我正在尝试实现单通道线框,但在此过程中遇到了一些问题。

问题 #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;
}

几何着色器:

#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. Coleman,但问题2 中描述的问题仍未解决。

在此处输入图像描述

更新 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.
//

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);
}
4

1 回答 1

4

您的第一个问题与您使用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;
}

当然,这将产生一个黑色填充网格,但如果您使用 color 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:

        边图

想象一个三角形镜像穿过虚线边缘,然后您应该对几何着色器正在做什么有一个很好的了解。

于 2014-05-15T17:37:14.990 回答