2

3D エンジンで反射面をレンダリングしています。2 つのステンシル操作を実行する必要があります。まず、深度テストを使用して反射面を描画し、表面の可視領域を見つけます。次に、モデルを G-Buffer に描画する必要があります。G-Buffer も、スカイボックスを描画する領域を見つけるためにステンシルされます。

  • Draw Surface: 常に描画し、ビット #1 を書き込みます

  • モデルの描画: ビット #1 が設定されている場合のみ描画し、ビット #2 を書き込みます

OpenGLを使用してこれを行うにはどうすればよいですか? glStencilFunc ref と mask の値と glDepthMask の値の関係がよくわかりません。

4

1 に答える 1

5

ドキュメントは非常に具体的ですが、単にマスクを作成してアクティブ化したい場合に何をすべきかが常に直感的または明白であるとは限りません. これらを簡単な出発点として使用します...

マスクを作成する

ステンシル バッファをゼロにクリアし、描画先のすべてのピクセルに 1 を書き込みます。

void createStencilMask()
{
    // Clear the stencil buffer with zeroes.
    // This assumes glClearStencil() is unchanged.
    glClear(GL_STENCIL_BUFFER_BIT);

    // Enable stencil raster ops
    // 1. Enables writing to the stencil buffer (glStencilOp)
    // 2. If stencil test (glStencilFunc) fails, no frags are written
    glEnable(GL_STENCIL_TEST);

    // sfail GL_KEEP - keep original value if stencil test fails
    // dpfail GL_KEEP - also keep if the stencil passes but depth test fails
    // dppass GL_REPLACE - write only if both pass and you'd normally see it
    //                     this writes the value of 'ref' to the buffer
    glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);

    // func GL_ALWAYS - the stencil test always passes
    // ref 1 - replace with ones instead of zeroes
    // mask 1 - only operate on the first bit (don't need any more)
    // Assumes glStencilMask() is unchanged
    glStencilFunc(GL_ALWAYS, 1, 1);
}

上記の関数を呼び出して、描画します。glDepthMaskglColorMaskを設定できるので、これは実際には現在の色/深度とシーンには影響せず、ステンシル バッファのみに影響します。

マスクを使って描く

前のステップからの 1 を持つピクセルにのみ描画します。

void useStencilMask()
{
    // Enable stencil raster ops
    glEnable(GL_STENCIL_TEST);

    // Just using the test, don't need to replace anything.
    glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);

    // Only render if the current pixel stencil value is one.
    glStencilFunc(GL_EQUAL, 1, 1);
}

描画し、glDisable(GL_STENCIL_TEST)完了したらテストを無効のままにします。

異なるビットの読み取りと書き込み

さて、あなたの質問に焦点を当てます...

ステンシル テストと置換する値の両方refで の同じ値glStencilFunc()が使用されるため、これは少し注意が必要です。ただし、マスクを使用してこれを回避できます。

  1. テスト/読み取り時にビットを無視するためmaskに inを使用します。glStencilFunc()
  2. glStencilMask()特定のビットの書き込みを停止するために使用します。

あなたの場合、最初のビットは既に設定されているため、書き込まれないようにマスクする必要はありません。とに更新useStencilMask()するだけです。isであるため、等価性のテストでは最初のビットのみが使用されます。ただし、 3 (つまり)の全体が書かれています。(これは) を使用して、最初のビットが書き込まれるのを止めることができますが、それは既に 1 であるため、問題ではありません。glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE)glStencilFunc(GL_EQUAL, 3, 1);mask1ref0b11glStencilMask(2)0b10

GL_INCRwhich を使用して、2 番目のビットを設定し、最初のビットを削除することもできます。または、1 でクリアして、GL_ZERO両方のビットをマークするために使用することもできます。

于 2015-05-13T13:19:27.297 に答える