ステンシルバッファ

stencil-buffer.png

ステンシルとは?

ステンシル,stencilは型板のことです.板に星型の穴をあけて,その板越しに色を塗ると紙には星型のマークが書ける.
そういう板のことをステンシルといいます.
OpenGL上で実現されるステンシルバッファの機能もまさにそのとおりのものになります.
buffers.jpg

ステンシル処理では描画の有効/無効がピクセルごとに切替えられます。
まず GL の描画プリミティブを使ってステンシルプレーンに描画し、 次に幾何形状やイメージをレンダリングする。
この際にステンシルプレーンが使われ、スクリーンの一部をマスクして 描画しないようにされる。
ステンシル処理は普通はマルチパスレンダリングアルゴリズムを 使って特殊な効果を得るために使われる。

例えば、転写、輪郭線抽出、CSG (constructive solid geometry) レンダリング などである。

ステンシルテストは、参照値とステンシルバッファ内の値の比較結果に 基づいて、条件的にピクセルを削除する。
ステンシルテストを有効または無効にするには、 glEnable および glDisable を引き数を 指定して GL_STENCIL_TEST を呼ぶ。
ステンシルテストの結果に従って起こる動作を指定するには glStencilOp を呼ぶ。

ステンシルバッファとは

1つのピクセルあたり、1個の深さ(少なくとも8bit)を持つ。
ステンシルバッファはオプションなので、デフォルトではオフになっているはず。
このピクセルごとの値によって何が決まるか?
ピクセルが更新されるかどうかが決まります。

使い方

Androidの場合はGLSurfaceViewにてこれをやらないといけない

                //red,grn,bl,al,dpt,stencil
        setEGLConfigChooser(8, 8, 8, 8, 16, 8);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
glClearStencil(int s);

ステンシルバッファの全てのピクセルを初期化するのに使用されるステンシル値
0〜$2^n-1$の範囲で指定する。
mSmallCube.initShapes(0,0);
        mLargeCube.initShapes(0,0);
        //initShapes(trans.x,trans.y);
        // Redraw background color
        GLES20.glClearStencil(0);
 
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT|GLES20.GL_STENCIL_BUFFER_BIT);
        GLES20.glEnable(GL10.GL_BLEND);
        GLES20.glBlendFunc(GL10.GL_SRC_ALPHA,GL10.GL_ONE_MINUS_SRC_ALPHA);
        GLES20.glDisable(GLES20.GL_DEPTH_TEST); 
 
        muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");    
        GLES20.glUseProgram(mProgram);
        GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false,mMapController.mModelViewProjMatrix.matrix, 0);
 
        GLES20.glEnable(GLES20.GL_STENCIL_TEST);
        GLES20.glStencilFunc(GLES20.GL_ALWAYS, 1,-1);
        GLES20.glStencilOp(GLES20.GL_KEEP,GLES20.GL_KEEP,GLES20.GL_REPLACE);
        GLES20.glColorMask(false, false, false, false);
        GLES20.glDepthMask(false);
        mSmallCube.draw(maPositionHandle);
        //枠を描く
        GLES20.glColorMask(true, true, true, true);
        GLES20.glDepthMask(true);
        GLES20.glStencilFunc(GLES20.GL_NOTEQUAL, 1,-1);
        GLES20.glStencilOp(GLES20.GL_KEEP,GLES20.GL_KEEP,GLES20.GL_REPLACE);
        mLargeCube.draw(maPositionHandle);
 
        GLES20.glDisable(GLES20.GL_STENCIL_TEST);
        GLES20.glDisable(GL10.GL_BLEND);

void glStencilFunc(GLenum func, GLint ref, GLuint mask);

ステンシルバッファは最初0で初期化される
引数名 意味 初期値
func comparision func refの値がステンシルバッファの中で比較される方法を示す GL_ALWAYS
ref reference value ref はステンシルバッファに既にある値を比較関数funcを使って比較されるための値。 0〜$2^n-1$の範囲に限定される。 ここで $n$ はステンシルバッファのビットプレーンの数である。 0
mask mask value funcでrefとステンシルバッファに既に書いてある値とを比較する前に、「ref」と「ステンシルバッファに既にある値」にマスクをかける。つまり (ref&mask) func (stencil & mask) 1

もし、refがステンシルバッファの値よりも小さいとそのフラグメントは合格する。
初期値は全ビットが1となっている。

funcの取りうる値

GL_NEVER 必ず失敗する。
GL_LESS ( ref & mask ) < ( stencil & mask ) の場合に通過する。
GL_LEQUAL ( ref & mask ) <= ( stencil & mask ) の場合に通過する。
GL_GREATER ( ref & mask ) > ( stencil & mask ) の場合に通過する。
GL_GEQUAL ( ref & mask ) >= ( stencil & mask ) の場合に通過する。
GL_EQUAL ( ref & mask ) == ( stencil & mask ) の場合に通過する。
GL_NOTEQUAL ( ref & mask ) != ( stencil & mask ) の場合に通過する。
GL_ALWAYS 必ず通過する。

glStencilOp(fail,zfail,zpass)

glStencilFuncの次の段階。
glStencilfuncによりフラグメントがステンシルテスト不合格なったとき、
ステンシルバッファのデータがそのように修正されるのかを指定する。
fail フラグメントがステンシルテストに不合格だった場合にどうするか指定する
zfail デプステストが失敗したときにどうするのか指定する GL_KEEP
zpass デプステストに合格したときどうするのか指定する。 GL_KEEP

fail,zfail,zpassの取りうる値

GL_KEEP 現在の値をそのままにする
GL_ZERO 0に置き換える
GL_REPLACE reference値に置き換える
GL_INCR 加算する
GL_DECR 減算する
GL_INVERT ビットを反転させる

stencil

サポートサイト Wikidot.com stencil