ステンシルバッファを用いた処理とは?

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
bonbo

ステンシルバッファを用いた処理とは?

#1

投稿記事 by bonbo » 10年前

まだ一つ質問が解決していないのですが、ステンシルバッファを用いた
透過処理についてよく理解できないのでトピックを新たにたてて質問させていただきます。
OpenGLES,Xcodeの環境下でプログラムをしています
いくつか分からない点があるのですが
・void glStencilFunc(GLenum func, GLint ref, GLuint mask)
の第二引数refと、どこかを比較して通すか決めるそうなのですが、
このどこかとはいったいどこなのでしょうか。
・比較するx,yを指定できるのでしょうか。
・どうやら描画するポリゴンと指定する領域(?)のポリゴンの2枚
が必要だというように理解しているのですが、これで正しいの
でしょうか。

一度にいくつも質問をしてしまいすみません。
よろしくおねがいします。

bonbo

Re: ステンシルバッファを用いた処理とは?

#2

投稿記事 by bonbo » 10年前

http://tsurumura-seisakusho.blogspot.jp ... 8144790285
このページを参照して同じことがしたかったのですが、

コード:

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{    
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_STENCIL_TEST);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

    glClearColor(0.0f, 0.0f, 0.0f, 1.0);// 背景色

    /* いろいろ必要な処理 */

    // 描画開始
    [self.effect prepareToDraw];

    // ステンシルの設定を開始しまーす。
    glStencilOp(GL_KEEP,GL_REPLACE,GL_REPLACE);// 以降はステンシル値を書き込みます。
    glColorMask(0,0,0,0);
    glDepthMask(0);

    // ここからはステンシル値を1で書き込みます。
    glStencilFunc(GL_ALWAYS, 1, ~0);
    
    // 型紙1枚目描画
    glBindVertexArrayOES(stencilVertexArrayIDs_[0]);
    glDrawArrays(GL_TRIANGLES, 0, 3);

    // ここからはステンシル値を2で書き込みます。
    glStencilFunc(GL_ALWAYS, 2, ~0);
    
    // 型紙2枚目を描画
    glBindVertexArrayOES(stencilVertexArrayIDs_[1]);
    glDrawArrays(GL_TRIANGLES, 0, 3);

    // ここからは絵(ポリゴン)を描きまーす。
    // 設定を絵の描画用に戻す。
    glColorMask(1,1,1,1);
    glDepthMask(1);
    glStencilOp(GL_KEEP,GL_KEEP ,GL_KEEP);// 以降はステンシル値は変更しない。
    
    // ここからはステンシル値がxの部分だけ描画します。
    glStencilFunc(GL_EQUAL, x, ~0);// ※
    
    for (int i=0; i<4; i++)
    {
        glBindVertexArrayOES(vtxArrayIDs_[i]);
        glDrawArrays(GL_TRIANGLES, 0, 3);
    }
    
    glBindVertexArrayOES(0);
}
上記コードの [self.effect prepareToDraw];
ここが明記されていないので
stencilVertexArrayIDs_と
vtxArrayIDs_がいったいどのようなものなのかよくわからないのです。

アバター
h2so5
副管理人
記事: 2212
登録日時: 13年前
住所: 東京
連絡を取る:

Re: ステンシルバッファを用いた処理とは?

#3

投稿記事 by h2so5 » 10年前

bonbo さんが書きました: ・void glStencilFunc(GLenum func, GLint ref, GLuint mask)
の第二引数refと、どこかを比較して通すか決めるそうなのですが、
このどこかとはいったいどこなのでしょうか。
ステンシルバッファのピクセルの値です。
bonbo さんが書きました: ・比較するx,yを指定できるのでしょうか。
意味がよく分かりませんが、指定はできないと思います。
bonbo さんが書きました: ・どうやら描画するポリゴンと指定する領域(?)のポリゴンの2枚
が必要だというように理解しているのですが、これで正しいの
でしょうか。
bonbo さんが書きました: stencilVertexArrayIDs_と
vtxArrayIDs_がいったいどのようなものなのかよくわからないのです。
stencilVertexArrayIDs_とvtxArrayIDs_は頂点データの配列です。
ポリゴンは適当な領域を描画してステンシルバッファの動作を確認するために使っているので別に何枚でもいいです。

bonbo

Re: ステンシルバッファを用いた処理とは?

#4

投稿記事 by bonbo » 10年前

>h2so5さん
ありがとうございます。
返信が送れてしまい申し訳ありません。
いろいろ考えていたのですが、ようやくある程度理解ができました。
ステンシルバッファを書き込むのは、特定のピクセルを指定して
行うのではなく、図として描画をするように書き込むのですね。

コード:

glStencilOp(GL_KEEP,GL_REPLACE,GL_REPLACE);// 以降はステンシル値を書き込みます。
    glColorMask(0,0,0,0);
    glDepthMask(0);
    glStencilFunc(GL_ALWAYS, (number), ~0);// ここからは(number)の値をステンシルに書き込む
でステンシルを書き込む描画タイプにして
以降は普段の描画処理である

コード:

glDrawArrays(GL_TRIANGLES, 0, 3);
をするごとに、その描画された位置のピクセル値がかきかわる
そして、ステンシルの設定が終わったら

コード:

glColorMask(1,1,1,1);
glDepthMask(1);
glStencilOp(GL_KEEP,GL_KEEP ,GL_KEEP);// 以降はステンシル値は変更しない。
絵の描画タイプにもどしてから描画、するとステンシル効果が使える。
ということですね。
まだ実際にプログラムを組み終わった訳ではないので、これから試してみます。

もし間違っているところがありましたら注意してくださると嬉しいです。

bonbo

Re: ステンシルバッファを用いた処理とは?

#5

投稿記事 by bonbo » 10年前

何度もすみません。
一応プログラムを組んでみたのですが

コード:

            glEnable(GL_DEPTH_TEST);// 深度テスト
            glEnable(GL_STENCIL_TEST);
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
            
            glClearColor(0.0f, 0.0f, 0.0f, 1.0);// 背景色
            
            /* いろいろ必要な処理 */
            
            // 描画開始
            
            // ステンシルの設定
            glStencilOp(GL_KEEP,GL_REPLACE,GL_REPLACE);// 以降はステンシル値を書き込みます。
            glColorMask(1,1,1,1);
            glDepthMask(0);
            
            // ここからはステンシル値を1で書き込みます。
            glStencilFunc(GL_ALWAYS, 1, ~0);
            // 分かりやすくするために色を付ける
            unsigned int alpha = 100;
            unsigned int red= 200;
            unsigned int green = 0;
            unsigned int blue =  0;
            // 型紙1枚目描画
            
            GLfloat triv[] = {
                0,	0,
                0,	500,
                420,400,
            };
            
            //長方形を構成する四つの頂点の色を指定します
            //ここではすべての頂点を同じ色にしています
            const GLubyte triangleColors[] = {
                static_cast<GLubyte>(red), static_cast<GLubyte>(green), static_cast<GLubyte>(blue) ,static_cast<GLubyte>(alpha),
                static_cast<GLubyte>(red), static_cast<GLubyte>(green), static_cast<GLubyte>(blue) ,static_cast<GLubyte>(alpha),
                static_cast<GLubyte>(red), static_cast<GLubyte>(green), static_cast<GLubyte>(blue) ,static_cast<GLubyte>(alpha),
            };
            
            //三角形を描画します
            glVertexPointer(2, GL_FLOAT, 0, triv);
            glEnableClientState(GL_VERTEX_ARRAY);
            glColorPointer(4, GL_UNSIGNED_BYTE, 0, triangleColors);
            glEnableClientState(GL_COLOR_ARRAY);
            
            glDrawArrays(GL_TRIANGLES, 0, 3);
            
            // 設定を絵の描画用に戻す。
            glColorMask(1,1,1,1);
            glDepthMask(1);
            glStencilOp(GL_KEEP,GL_KEEP ,GL_KEEP);// 以降はステンシル値は変更しない。
            
            // ここからはステンシル値が0の部分だけ描画します。
            glStencilFunc(GL_EQUAL,0, ~0);
            {
            alpha = 100;
            red= 0;
            green = 200;
            blue =  0;
            GLubyte triangleColors2[] = {
                    static_cast<GLubyte>(red), static_cast<GLubyte>(green), static_cast<GLubyte>(blue) ,static_cast<GLubyte>(alpha),
                    static_cast<GLubyte>(red), static_cast<GLubyte>(green), static_cast<GLubyte>(blue) ,static_cast<GLubyte>(alpha),
                    static_cast<GLubyte>(red), static_cast<GLubyte>(green), static_cast<GLubyte>(blue) ,static_cast<GLubyte>(alpha),
                };
            GLfloat triv2[] = {
                100,	0,
                0,	500,
                420,400,
            };
            
            //長方形を構成する四つの頂点の色を指定します
            //ここではすべての頂点を同じ色にしています
            
            
            //三角形を描画します
            glVertexPointer(2, GL_FLOAT, 0, triv2);
            glEnableClientState(GL_VERTEX_ARRAY);
            glColorPointer(4, GL_UNSIGNED_BYTE, 0, triangleColors2);
            glEnableClientState(GL_COLOR_ARRAY);
            
            glDrawArrays(GL_TRIANGLES, 0, 3);
            }
            
            glBindVertexArrayOES(0);
赤と緑の半透明の2つの三角形が表示され、
成功するとおそらくその重なっている部分の赤が消えるはずなのですが
なぜか
glStencilFunc(GL_EQUAL,(number), ~0)
の第二引数を変えても表示が変化しません。
どこがおかしいのでしょうか。

bonbo

Re: ステンシルバッファを用いた処理とは?

#6

投稿記事 by bonbo » 10年前

// ここからはステンシル値が0の部分だけ描画します。
glStencilFunc(GL_EQUAL,0, ~0);
の部分で
glStencilFunc(GL_NEVER,0, ~0);
に書き換えても変化が無いのはOpenGLES 1.0の関数を使っているから
でしょうか。

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: ステンシルバッファを用いた処理とは?

#7

投稿記事 by ISLe » 10年前

以前ステンシルバッファを提案されたとき、GLUTの初期化を試されていたようですが、そこは解決されたのですか?
デバイスの初期化時にステンシルバッファを有効化していないので機能しないのではないでしょうか。

うろ覚えですがXcodeではステンシルバッファは拡張扱いになっていて、サーフェースにアタッチする手順が必要だとかいう記述を見た覚えがあります。

bonbo

Re: ステンシルバッファを用いた処理とは?

#8

投稿記事 by bonbo » 10年前

>Isleさん
ありがとうございます。
初期化の処理を行っていなかったのが原因でした。
一応やり方は分かりました。

何度も何度もありがとうございました。
またなにかありましたら、よろしくおねがいします。

bonbo

Re: ステンシルバッファを用いた処理とは?

#9

投稿記事 by bonbo » 10年前

おっと失礼…解決を押すのをわすれていました。

閉鎖

“C言語何でも質問掲示板” へ戻る