opengl-es - 使用 OpenGL ES 2.0 进行模板制作

标签 opengl-es opengl-es-2.0 libgdx framebuffer stencil-buffer

我正在尝试找出一种方法来剪切背景纹理的特定区域,以便特定的自定义图案不会在该背景的屏幕上呈现。例如: enter image description here

这个正方形可以是任何图案。 我正在使用帧缓冲区对象和模板缓冲区来实现这种效果。这是代码:

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 方面也遇到了一些困难。如果有人能够阐明这两点,那将非常有帮助。

更新:我也尝试过使用 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();

这段代码产生了这样的结果: enter image description here 而不是这样的:(忽略窗口大小和色调) enter image description here

注意:我正在使用 libgdx 库。

最佳答案

绘制到 SpriteBatch 时,状态更改将被忽略,直到调用 end() 为止。如果您想将模板与 SpriteBatch 一起使用,则需要分解批量绘图。有一点,我遗漏了 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 >>
}

输入处理器允许通过键盘(桌面上的 libgdx)设置两个 bool 标志 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();
}

关于opengl-es - 使用 OpenGL ES 2.0 进行模板制作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11055050/

相关文章:

opengl-es - OpenGL ES 2.0 中的剪裁平面

iphone - OpenGL ES 2.0 如何正确设置 glVertexAttribPointers

javascript - WebGL - 使用多个纹理时的条纹

android - 调整文本按钮中的文本大小

java - Libgdx 有两个用自己的坐标系绘制的不同 View ?

android - 在 OpenGL ES 2.0 和索引信息中使用单独的缓冲区

android - OpenGL (ES) -- 截锥体和正视体有什么区别?

java - 单击按钮时屏幕响应

iphone - glDrawElements VAO/VBO 在 iOS 上崩溃

android - 如何在 OpenGL 中翻转图像?