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 shaderし、Geometry shaderAndon M. Coleman の回答に言及していますが、質問 2で説明されている問題はまだ解決されていません。

ここに画像の説明を入力

更新 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);
}
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;
}

確かに、これは黒く塗りつぶされたメッシュを生成しますが、色を使用するu_colorと、メッシュの塗りつぶされた部分はワイヤーフレームと区別がつかなくなります。最終的には、ワイヤフレーム カラーとは別の頂点ごとのカラーを定義することをお勧めしますが、その方法を理解するのはあなた次第です。


質問 2 については、エッジの距離を微調整することで解決できます。

リンク先の記事のアイデアは、ジオメトリ シェーダーが出力する三角形ごとに、頂点ごとに反対側のエッジまでの距離を書き込む必要があるというものでした。三角形のエッジの 1 つが内側のエッジであり、ワイヤフレームに含めるべきではないことがわかっている場合は、そのエッジの反対側の頂点の距離を、 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 に答える