Libgdx掩盖与图像

时间:2015-10-09 11:51:02

标签: java android opengl-es libgdx

我有一个帧缓冲区,其中一些形状是使用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);
   }

我的图像确实被屏蔽了,但是掩模图像有一个黑色背景(它应该是透明的)。 它现在看起来像这样:

enter image description here

它应该看起来像这样的例子(除了这个例子没有面具所以ofc paint不应该在头脑之外):

enter image description here

另请注意,涂料是半透明的。 (我不知道它是否会改变一些代码)。

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

2 个答案:

答案 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);
    }
}