5

背景テクスチャの特定の領域を切り取って、その背景の特定のカスタム パターンが画面に表示されないようにする方法を見つけようとしています。例えば: ここに画像の説明を入力

この正方形は任意のパターンにすることができます。この種の効果を得るために、Frame Buffer Object と Stencil Buffer を使用しています。コードは次のとおりです。

fbo.begin();
//Disables ColorMask and DepthMask so that all the rendering is done on the Stencil Buffer
Gdx.gl20.glColorMask(false, false, false, false);
Gdx.gl20.glDepthMask(false);
Gdx.gl20.glEnable(GL20.GL_STENCIL_TEST);
Gdx.gl20.glStencilFunc(GL20.GL_ALWAYS, 1, 0xFFFFFFFF);
Gdx.gl20.glStencilOp(GL20.GL_REPLACE, GL20.GL_REPLACE, GL20.GL_REPLACE);

stage.getSpriteBatch().begin();
rHeart.draw(stage.getSpriteBatch(), 1); //Draws the required pattern on the stencil buffer

//Enables the ColorMask and DepthMask to resume normal rendering
Gdx.gl20.glColorMask(true, true, true, true);
Gdx.gl20.glDepthMask(true);

Gdx.gl20.glStencilFunc(GL20.GL_EQUAL, 1, 0xFFFFFFFF);
Gdx.gl20.glStencilOp(GL20.GL_KEEP, GL20.GL_KEEP, GL20.GL_KEEP);

background.draw(stage.getSpriteBatch(), 1); //Draws the background such that the background is not rendered on the required pattern, leaving that area black.

stage.getSpriteBatch().end();
Gdx.gl20.glDisable(GL20.GL_STENCIL_TEST);
fbo.end();

ただし、これはまったく機能していません。ステンシル バッファーを使用してこれを行うにはどうすればよいですか? また、glStencilFunc と glStencilOp を理解するのに苦労しています。誰かがこれら2つに光を当てることができれば、非常に役に立ちます。

更新: glColorMask を使用して同じ種類のものを作成しようとしました。コードは次のとおりです。

Gdx.gl20.glClearColor(0, 0, 0, 0);
stage.draw();
FrameBuffer.clearAllFrameBuffers(Gdx.app);
fbo1.begin();
Gdx.gl20.glClearColor(0, 0, 0, 0);
batch.begin();
rubber.draw(batch, 1);
Gdx.gl20.glColorMask(false, false, false, true);
coverHeart.draw(batch, 1);
Gdx.gl20.glColorMask(true, true, true, false);
batch.end();        
fbo1.end();

toDrawHeart = new Image(new TextureRegion(fbo1.getColorBufferTexture()));
batch.begin();
toDrawHeart.draw(batch, 1);
batch.end();

このコードはこれを生成しています: ここに画像の説明を入力 このようなものの代わりに: (ウィンドウのサイズと色調を無視してください) ここに画像の説明を入力

注: libgdx ライブラリを使用しています。

4

3 に答える 3

6

に描画している間、が呼び出されるSpriteBatchまで、状態の変更は無視されます。end()でステンシルを使用する場合SpriteBatchは、バッチ描画を分割する必要があります。1つは、FBOを省略したことですが、違いはありません。

@Override
public void create() {      
    camera = new OrthographicCamera(1, 1);
    batch = new SpriteBatch();

    texture = new Texture(Gdx.files.internal("data/badlogic.jpg"));
    texture.setFilter(TextureFilter.Linear, TextureFilter.Linear);

    TextureRegion region = new TextureRegion(texture, 0, 0, 256, 256);

    sprite = new Sprite(region);
    sprite.setSize(1f, 1f);
    sprite.setPosition(-0.5f, -0.5f);

    spriteUpsideDown = new Sprite(new TextureRegion(texture, 1f, 1f, 0f, 0f));
    spriteUpsideDown.setSize(1f, 1f);
    spriteUpsideDown.setPosition(-0.5f, -0.5f);

    pattern = new Sprite(region);
    pattern.setSize(0.5f, 0.5f);
    pattern.setPosition(-0.25f, -0.25f);

    << Set Input Processor >>
}

入力プロセッサでは、2つのブールフラグをキーボード(デスクトップではlibgdx)を介して設定できますbreakBatch1breakBatch2これらは、SpriteBatchの描画を中断するために使用されます。

@Override
public void render() {      
    Gdx.gl.glClearColor(1, 1, 1, 1);
    Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_STENCIL_BUFFER_BIT);
    batch.setProjectionMatrix(camera.combined);

    // setup drawing to stencil buffer
    Gdx.gl20.glEnable(GL20.GL_STENCIL_TEST);
    Gdx.gl20.glStencilFunc(GL20.GL_ALWAYS, 0x1, 0xffffffff);
    Gdx.gl20.glStencilOp(GL20.GL_REPLACE, GL20.GL_REPLACE, GL20.GL_REPLACE);
    Gdx.gl20.glColorMask(false, false, false, false);

    // draw base pattern
    batch.begin();
    pattern.draw(batch);

    if(breakBatch1) { batch.end(); batch.begin(); }

    // fix stencil buffer, enable color buffer
    Gdx.gl20.glColorMask(true, true, true, true);
    Gdx.gl20.glStencilOp(GL20.GL_KEEP, GL20.GL_KEEP, GL20.GL_KEEP);

    // draw where pattern has NOT been drawn
    Gdx.gl20.glStencilFunc(GL20.GL_NOTEQUAL, 0x1, 0xff);
    sprite.draw(batch);

    if(breakBatch2) { batch.end(); batch.begin(); }

    // draw where pattern HAS been drawn.
    Gdx.gl20.glStencilFunc(GL20.GL_EQUAL, 0x1, 0xff);
    spriteUpsideDown.draw(batch);
    batch.end();
}
于 2012-06-18T20:16:54.117 に答える
2

Gdx.gl20.glStencilFunc(GL20.GL_REPLACE, GL20.GL_REPLACE, GL20.GL_REPLACE);

これらは glStencilFunc の正しい引数ではありません。ここで glStencilOp を意味していると思います。

コードで glGetError を使用する必要があります。これにより、これらの種類のエラーが警告されます。

于 2012-06-15T17:42:53.343 に答える
1

あなたの問題は、クワッドに適用されたテクスチャの形状に関係なく、最初のGL_REPLACEステンシル操作が描画されたすべてのピクセルに適用されることだと思います。rHeart.draw

したがって、クワッドのすべてのピクセルにステンシル値が適用され、問題が発生します。

クワッドに適用されたテクスチャにGL_ALPHA_TESTサポートされていないアルファ チャネルがある場合は、シェーダーをdiscard完全に透明なピクセルに設定して、ステンシル バッファーに描画されないようにすることができます。

于 2012-06-17T18:59:41.557 に答える