2

メッシュとプレーンの交差輪郭を計算するジオメトリ シェーダーを作成しましたが、交差ポイントで 2 つの線の間に 1 ピクセル幅のギャップが生じることがあります。

ここに画像の説明を入力

シェーダーはまず、三角形の頂点から平面までの符号付き距離を計算します。次に、2 つの距離の符号が異なるかどうかをチェックして、エッジとの交差があるかどうかを判断します。その場合、エッジ ポイント間の加重平均として計算される交点で頂点を放出します。

#version 330
layout(triangles) in;
layout(line_strip, max_vertices = 3) out;

out vec3 vertexPosition;

uniform vec3 planePos;
uniform vec3 planeNormal;
uniform mat4 mvpMatrix;
uniform vec2 screenSize;

void intersection(in vec4 a, in float distA, in vec4 b, in float distB)
{
  if (sign(distA) * sign(distB) <= 0.0f && !(sign(distA) == 0 && sign(distB) == 0))
  {
    float fa = abs(distA);
    float fb = abs(distB);
    float fab = fa + fb;
    vec4 ptIntersection;
    // Don't divide by zero.
    if (fab < 0.001)
      ptIntersection = (a + b) * 0.5;
    else
      ptIntersection = (fa * b + fb * a) / fab;
    gl_Position = mvpMatrix * ptIntersection;
    vertexPosition = gl_Position.xyw;
    EmitVertex();
  }
}

void main()
{
  vec4 a = gl_in[0].gl_Position;
  vec4 b = gl_in[1].gl_Position;
  vec4 c = gl_in[2].gl_Position;

  float distA = dot(a.xyz - planePos, planeNormal);
  float distB = dot(b.xyz - planePos, planeNormal);
  float distC = dot(c.xyz - planePos, planeNormal);

  intersection(a, distA, b, distB);
  intersection(b, distB, c, distC);
  intersection(c, distC, a, distA);
}

3 つの点すべてが平面上にあるという特殊なケースを無視したので、それがちょっと安っぽいことはわかっています。は!(sign(distA) == 0 && sign(distB) == 0)、2 つの点が平面上にある場合、そのエッジに対して頂点が放出されないようにします。したがって、3 つすべてが平面上にある場合、出力はありません。しかし、それは必ずしも悪いことではないと思います。私が気に入っているのは、クレイジーな分岐がないことです。可能であればそのままにしておきたいです。

だから私は疑問に思っています:なぜこれらのギャップが見えるのですか? 2 つの三角形 (a、b、c) と (c、b、d) があるとします。a と b は平面の上にあり、c と d は下にあります。最初の三角形では、シェーダーは (b,c) との交点を生成し、2 番目の三角形では (c,b) との交点を生成します。2 つの float の加算が可換であると仮定すると、intersection関数は入力に関して対称であるため、結果は同じになるはずです。これらのギャップがまだ見られるのはなぜですか?

4

2 に答える 2

3

その答えは、OpenGL 仕様が提供する Bresenham ライン ラスタライズ アルゴリズムの仕様にあります。OpenGL 3.3 Specのセクション 3.5.1 からの引用:

pa で始まり pb で終わる線分をラスタライズすると、pb が Rf に含まれる場合を除いて、pa で始まり pb で終わる線分が Rf と交差するフラグメント f が生成されます [フラグメントを中心とするダイヤモンド領域]。

あなたの2つの隣接する線が残念ながら反対方向に走っている場合(つまり、同じ点で終わっている場合)、エンドポイントがまったくラスタライズされず、そのエンドポイントがピクセル中心の周りのダイヤモンドに含まれているという効果があります。したがって、顕著なギャップが表示されます。

すでにジオメトリ シェーダーを使用しているため、もちろん (少し追加の計算を行うことで) 三角形を出力して「真の」幅の広い線を作成できます。

于 2013-06-02T20:10:28.907 に答える