Opengl es 使用OpenGl ES 2.0制作模板
我正在试图找出一种方法来剪切背景纹理的某个区域,这样某个自定义图案就不会在屏幕上为该背景渲染。例如: 这个正方形可以是任何图案。 我使用帧缓冲区对象和模具缓冲区来实现这种效果。代码如下:Opengl es 使用OpenGl ES 2.0制作模板,opengl-es,opengl-es-2.0,libgdx,framebuffer,stencil-buffer,Opengl Es,Opengl Es 2.0,Libgdx,Framebuffer,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); G
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();
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();
然而,这根本不起作用。我应该如何使用模具缓冲区来实现这一点?我还面临着理解glStencilFunc和glStencilOp的一些困难。如果有人能解释一下这两个问题,那将是非常有帮助的
更新:我也尝试过使用glColorMask制作同类产品。代码如下:
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();
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库。
Gdx.gl20.glStencilFunc(gl20.GL\u替换,gl20.GL\u替换,gl20.GL\u替换)代码>
这些参数不是glStencilFunc的正确参数。我想你指的是glStencilOp
您需要在代码中使用glGetError,它会提醒您这些类型的错误 我相信您的问题在于,您最初的GL_REPLACE
模具操作由您的rHeart.draw应用于所有绘制的像素,而与应用于四边形的任何纹理的形状无关
因此,模具值将应用于四边形的每一个像素,从而解决问题
如果应用在四边形上的纹理具有alpha通道,因为不支持GL_alpha_TEST
,您可以将着色器设置为放弃
完全透明的像素,防止它们被绘制到模具缓冲区。绘制到SpriteBatch
时,忽略状态更改,直到结束()
被调用。如果要使用带有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 >>
}
@宠坏了:你用glGetError吗?嗯,我不确定。我对模板缓冲区没有经验,尽管我对它的工作原理有很好的了解,而且我觉得你那里的东西看起来很正常。你能详细说明一下在你的例子中“完全不工作”是什么意思吗?@Tim这意味着渲染的背景不包含任何已模板化的“图案”。这意味着我得到的是一个完全粉红色的屏幕,而不是一个带有黑框的粉红色屏幕(如上所示)。对于桌面,我正在使用LwjglApplication,将LwjglApplication配置对象的模具值设置为8。您确定模具可以与SpriteBatch一起使用吗?我只是简单地看了一下,我不确定。我不确定。那么,作为替代方案,我应该尝试什么呢?为什么你会认为SpriteBatch可能无法与模具缓冲区一起工作?OpenGL ES 2.0实现不允许GL_ALPHA_测试,而Glalphafuncy对我来说根本不起作用。它创建了一个矩形遮罩,根本不关心精灵的alpha值。