我有一个帧缓冲区,其中一些形状是使用ShapeRenderer绘制的。现在我想用图像掩码来掩盖这个帧缓冲区。在此之前,我使用ShapeRenderer绘制的简单圆形蒙版进行处理。但我需要使用更复杂的蒙版,所以我必须使用图像。面膜是黑色面具和透明背景的png。这是我的代码:
@Override
public void draw(Batch batch, float parentAlpha) {
//disable RGB color, only enable ALPHA to the frame buffer
Gdx.gl.glColorMask(false, false, false, true);
//change the blending function for our alpha map
batch.setBlendFunction(GL20.GL_ZERO, GL20.GL_SRC_ALPHA);
//draw alpha mask sprite(s)
batch.draw(maskTexture, MASK_OFFSET_X + getX(), MASK_OFFSET_Y + getY());
//flush the batch to the GPU
batch.flush();
Gdx.gl.glColorMask(true, true, true, true);
batch.setBlendFunction(GL20.GL_DST_ALPHA, GL20.GL_ONE_MINUS_DST_ALPHA);
//The scissor test is optional, but it depends
Gdx.gl.glEnable(GL20.GL_SCISSOR_TEST);
Gdx.gl.glScissor(MASK_OFFSET_X + (int) getX(), MASK_OFFSET_Y + (int) getY(), maskTexture.getWidth(), maskTexture.getHeight());
//draw framebuffer to be masked
batch.draw(frm, getX(), getY(), frmSizeX, frmSizeY);
//remember to flush before changing GL states again
batch.flush();
//disable scissor before continuing
Gdx.gl.glDisable(GL20.GL_SCISSOR_TEST);
//set default blend function
batch.setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
}
我的图像确实被屏蔽了,但是掩模图像有一个黑色背景(它应该是透明的)。 它现在看起来像这样:
它应该看起来像这样的例子(除了这个例子没有面具所以ofc paint不应该在头脑之外):
另请注意,涂料是半透明的。 (我不知道它是否会改变一些代码)。
Ofc我正在使用RGBA8888格式,这里是初始化代码:
frmBuff = new FrameBuffer(Format.RGBA8888, frmSizeX, frmSizeY, false);
frm = new TextureRegion(frmBuff.getColorBufferTexture());
frmCam = new OrthographicCamera(frmSizeX, frmSizeY);
frmCam.translate(frmSizeX / 2, frmSizeY / 2);
maskTexture = game.manager.get("my_mask.png", Texture.class);
maskTexture.setFilter(TextureFilter.Linear, TextureFilter.Linear);
我在乱搞setBlendFunction并取得了截然不同的结果,但其中没有一个确实是正确的。
我该如何解决这个问题?
顺便说一下,我的代码基于这个例子: https://gist.github.com/mattdesl/6076846
我也已经读过这个: https://github.com/mattdesl/lwjgl-basics/wiki/LibGDX-Masking
答案 0 :(得分:1)
我知道这是一个老帖子。但是我对这个问题的所有研究只引出了我的观点。我在https://gist.github.com/mattdesl/6076846上阅读了这篇文章,并意识到问题在于你只是考虑了面具的alpha,但实际上你需要面具和前景(紫色油漆)产品的alpha。
//disable RGB color, only enable ALPHA to the frame buffer
Gdx.gl.glColorMask(false, false, false, true);
//change the blending function for our alpha map
batch.setBlendFunction(GL20.GL_ZERO, GL20.GL_SRC_ALPHA);
//draw alpha mask sprite(s)
batch.draw(maskTexture, MASK_OFFSET_X + getX(), MASK_OFFSET_Y + getY());
//change the function for our source
batch.setBlendFunction(GL20.GL_ONE_MINUS_SRC_ALPHA, GL20.GL_SRC_ALPHA);
//draw the source alpha
river_sprite.draw(batch);
//flush the batch to the GPU
batch.flush();
答案 1 :(得分:0)
我终于使用着色器完成了它。
我的代码基于本教程: https://github.com/mattdesl/lwjgl-basics/wiki/ShaderLesson4
private SpriteBatch spriteBatch;
private FrameBuffer frmBuff;
private TextureRegion frm;
private OrthographicCamera frmCam;
private FrameBuffer maskBuff;
private TextureRegion msk;
int frmSizeX = 500;
int frmSizeY = 700;
private ShapeRenderer renderer;
private ShaderProgram shader;
public static final int MASK_OFFSET_X = 55 - (int) Constants.BACKGROUND_OFFSET_X - 8;
public static final int MASK_OFFSET_Y = 150;
Texture tex0;
Texture mask;
SpriteBatch myBatch;
final String VERT =
"attribute vec4 "+ShaderProgram.POSITION_ATTRIBUTE+";\n" +
"attribute vec4 "+ShaderProgram.COLOR_ATTRIBUTE+";\n" +
"attribute vec2 "+ShaderProgram.TEXCOORD_ATTRIBUTE+"0;\n" +
"uniform mat4 u_projTrans;\n" +
" \n" +
"varying vec4 vColor;\n" +
"varying vec2 vTexCoord;\n" +
"void main() {\n" +
" vColor = "+ShaderProgram.COLOR_ATTRIBUTE+";\n" +
" vTexCoord = "+ShaderProgram.TEXCOORD_ATTRIBUTE+"0;\n" +
" gl_Position = u_projTrans * " + ShaderProgram.POSITION_ATTRIBUTE + ";\n" +
"}";
final String FRAG =
//GL ES specific stuff
"#ifdef GL_ES\n" //
+ "#define LOWP lowp\n" //
+ "precision mediump float;\n" //
+ "#else\n" //
+ "#define LOWP \n" //
+ "#endif\n" + //
"varying LOWP vec4 vColor;\n" +
"varying vec2 vTexCoord;\n" +
"uniform sampler2D u_texture;\n" +
"uniform sampler2D u_texture1;\n" +
"uniform sampler2D u_mask;\n" +
"void main(void) {\n" +
" //sample the colour from the first texture\n" +
" vec4 texColor0 = texture2D(u_texture, vTexCoord);\n" +
"\n" +
" //sample the colour from the second texture\n" +
" vec4 texColor1 = texture2D(u_texture1, vTexCoord);\n" +
"\n" +
" //get the mask; we will only use the alpha channel\n" +
" float mask = texture2D(u_mask, vTexCoord).a;\n" +
"\n" +
" //interpolate the colours based on the mask\n" +
" gl_FragColor = vColor * mix(texColor0, texColor1, mask);\n" +
"}";
public SprayRenderer(ShapeRenderer renderer) {
super();
this.renderer = renderer;
ShaderProgram.pedantic = false;
spriteBatch = new SpriteBatch();
tex0 = new Texture(Gdx.files.internal("snowman_back.png"));
mask = new Texture(Gdx.files.internal("balwan_maska.png"));
maskBuff = new FrameBuffer(Format.RGBA8888, frmSizeX, frmSizeY, false);
msk = new TextureRegion(maskBuff.getColorBufferTexture());
frmBuff = new FrameBuffer(Format.RGBA8888, frmSizeX, frmSizeY, false);
frm = new TextureRegion(frmBuff.getColorBufferTexture());
frmCam = new OrthographicCamera(frmSizeX, frmSizeY);
frmCam.translate(frmSizeX / 2, frmSizeY / 2);
frmCam.update();
renderer.setProjectionMatrix(frmCam.combined);
frmBuff.begin();
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
frmBuff.end();
SpriteBatch batch = new SpriteBatch();
frmCam.update();
batch.setProjectionMatrix(frmCam.combined);
maskBuff.begin();
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.draw(mask, 0, 0, 0, 0, 500, 700, 1, 1, 0, 0, 0, 500, 700, false, true);
batch.end();
maskBuff.end();
shader = new ShaderProgram(VERT, FRAG);
if (!shader.isCompiled()) {
System.err.println(shader.getLog());
System.exit(0);
}
if (shader.getLog().length()!=0)
System.out.println(shader.getLog());
shader.begin();
shader.setUniformi("u_texture1", 1);
shader.setUniformi("u_mask", 2);
shader.end();
//bind mask to glActiveTexture(GL_TEXTURE2)
msk.getTexture().bind(2);
//bind dirt to glActiveTexture(GL_TEXTURE1)
// tex1.bind(1);
frm.getTexture().bind(1);
//now we need to reset glActiveTexture to zero!!!! since sprite batch does not do this for us
Gdx.gl.glActiveTexture(GL20.GL_TEXTURE0);
}
@Override
public void draw(Batch batch, float parentAlpha) {
batch.flush();
batch.setShader(shader);
batch.draw(tex0, getX() + MASK_OFFSET_X, getY() + MASK_OFFSET_Y);
batch.flush();
batch.setShader(null);
}
}