2016-11-30 4 views
0

OpenGLではポリゴンは通常、クリップ空間でクリップされ、+ wとの比較で生き残る三角形(またはクリッピングプロセスが分割されている場合は三角形の部分)のみがクリップされます。これは、Sutherland-Hodgmanのようなポリゴンクリッピングアルゴリズムの実装を必要とする。ピクセルあたりの画面空間内の三角形のクリッピング

私は自分のCPUラスタライザを実装していますが、今のところそれを避けたいと考えています。私は使用可能な頂点のNDC座標を持っています(実際にはは位置が範囲[-1、1]にないように何もクリップしなかったのでを正規化していません)。私はこれらの値をすべてのピクセルに補間し、NDCの座標が[-1、1]のx、y、z次元に入るピクセルだけを描画したいと思います。私はさらに、深度テストを実行します。

これは機能しますか?はいの場合、補間はどのように見えますか? hereのように、属性補間のためにOpenGl spec(427ページ14.9)の式を使用できますか?あるいは、3つの座標すべての深度(z)補間に使用される式14.10を使用する必要があります(なぜ、別の座標が使用されるのか分かりません)。

更新:私は2つの方法によってピクセル当たりNDC値を補間しようとしている

w0, w1, w2頂点の重心重みです。

1)float x_ndc = w0 * v0_NDC.x + w1 * v1_NDC.x + w2 * v2_NDC.x; float y_ndc = w0 * v0_NDC.y + w1 * v1_NDC.y + w2 * v2_NDC.y; float z_ndc = w0 * v0_NDC.z + w1 * v1_NDC.z + w2 * v2_NDC.z;

2) float x_ndc = (w0*v0_NDC.x/v0_NDC.w + w1*v1_NDC.x/v1_NDC.w + w2*v2_NDC.x/v2_NDC.w)/ (w0/v0_NDC.w + w1/v1_NDC.w + w2/v2_NDC.w); float y_ndc = (w0*v0_NDC.y/v0_NDC.w + w1*v1_NDC.y/v1_NDC.w + w2*v2_NDC.y/v2_NDC.w)/ (w0/v0_NDC.w + w1/w1_NDC.w + w2/v2_NDC.w); float z_ndc = w0 * v0_NDC.z + w1 * v1_NDC.z + w2 * v2_NDC.z;

クリッピング+デプステストは、常に次のようになります。

if (-1.0f < z_ndc && z_ndc < 1.0f && z_ndc < currentDepth && 1.0f < y_ndc && y_ndc < 1.0f && -1.0f < x_ndc && x_ndc < 1.0f)

ケース1)自分の補間のための方程式14.10を使用することに相当します。ケース2)は、補間のために式14.9を使用することに対応します。

結果documented in gifs on imgur. 1)2番目の立方体がカメラの後ろにあるときや、立方体に入るときに奇妙なことが起こります。 2)奇妙なアーチファクトは見えませんが、カメラが頂点に近づくと消えてしまいます。そして、これはperspective correct interpolation of attributesの頂点(よりカメラに近い)はより大きな重みを持つので、頂点がクリップされるとすぐに、この情報は三角形のピクセルに強い重みで補間されます。

これはすべて期待されているのですか、間違っていますか?

+1

私はあなたがここで何を出すのか分かりません。 Nicol Bolasがすでに指摘しているように、プリミティブが 'z_eye = 0'平面と交差する場合、クリッピングは本当に重要です。そして、そのようなプリミティブの補間は完全に無意味になります(そして、正確に 'z_eye = 0'の頂点では、ゼロで除算されるでしょう)。 NDCの '-1 <= x、y、z <= 1'をチェックすることは' w <= xを満たす点がクリップ空間で '-x <= x、y、 y、z、<= -w'(カメラの背後にある)もそれを実行するでしょう。私はあなたがNDC.wで何を意味するのか分かりません。なぜなら、NDCではwがない(または1になる)からです。 – derhass

+1

これを要約すると、私の意見では、スクリーンスペースでのクリッピングはちょっとした感覚ではありません(あなたは[均質座標でのラスタライズそのもの]をしていません)(http://www.cs.unc.edu/~olano/papers/2dh-tri /))、それはずっと遅くなります。だから私はここで何を得るのか分からない。 – derhass

+0

説明をいただきありがとうございます。私はニコールの答えを正しく理解していませんでした(私は彼がz_eye = 0に対してクリッピングする場合でも数学がうまくいくと考えていたと思いました)。私のコードでは、NDC.wを頂点のカメラ空間zとして使用していました。確かに、それは遠近法部門の後では意味をなさない。 – pseudomarvin

答えて

2

カメラ空間Zで三角形が0に近づかない限り、ニアプレーンとのクリッピングは厳密には必要ありません。一度起これば、均質な座標の数学は奇妙になります。

ほとんどのハードウェアは、画面の幅よりもクリップの幅を超えて広がっている場合、またはカメラがゼロを横切っている場合、三角形をクリップするのに苦労します。この種のクリッピングは「ガードバンドクリッピング」と呼ばれ、クリッピングが安価ではないので、多くのパフォーマンスを節約します。

はい、数学はうまく動作します。あなたのスキャンラインを設定するときに、あなたがしなければならない主なことは、それぞれが画面上でどこで開始/終了するかを理解することです。補間演算はどちらの場合も同じです。

+0

私は、ピクセルが三角形の中にあるかどうかをテストするためにedge-functionを使用しているので、 "scanlinesを設定する"ことは、範囲[0、width - 1]、[0、height - 1]、正しい? – pseudomarvin

2

これはうまくいかない理由はありません。しかし、それは伝統的なクリッピングよりも遅くなるでしょう。プロジェクションセンターの近くの三角形では問題が発生する可能性があります。なぜなら、これらのプロジェクションセンターはわずかに小さくなり、重心座標計算に問題が生じるからです。

式14.9と14.10の違いは、基本的には深度がz/w([0,1]に再マッピングされている)です。遠近法の分割はすでに発生しているため、補間の際には離しておく必要があります。

関連する問題