4

我正在尝试创建一个方法,该方法返回由使用 libgdx 和 PixMap 的叠加层修改的纹理。

假设我有 2 个图像: FileHandle textureInput 中的基本图像 在此处输入图像描述

以及 FileHandle overLay 中的叠加图像

在此处输入图像描述

它应该产生这种纹理:

在此处输入图像描述

所以它应该使用来自 textureInput 的 RGB 值和来自 overLay 的 alpha 值并创建最终图像。我相信我可以使用 Pixmap 类来做到这一点,但我似乎无法找到确切的方法。

这是我收集到的应该是该方法的结构:

public Texture getOverlayTexture(FileHandle overLay, FileHandle textureInput){
    Pixmap inputPix = new Pixmap(textureInput);
    Pixmap overlayPix = new Pixmap(overLay);

    Pixmap outputPix = new Pixmap(inputPix.getWidth(), inputPix.getHeight(), Format.RGBA8888);

    // go over the inputPix and add each byte to the outputPix
    // but only where the same byte is not alpha in the overlayPix

    Texture outputTexture =  new Texture(outputPix, Format.RGBA8888, false);

    inputPix.dispose();
    outputPix.dispose();
    overlayPix.dispose();
    return outputTexture;
}

我只是在寻找一些关于从这里去哪里的方向。非常感谢任何帮助。如果这个问题太模糊或者我的方法完全不正确,我深表歉意。

谢谢!

4

1 回答 1

4

我终于找到了做到这一点的方法。

我的游戏是如何设置的,每个项目都会自己绘制。他们得到了一个 spritebatch,可以用它做一些事情。我这样做是出于各种原因。有一个包含项目列表的项目管理器。每个项目都有不同的属性。每个项目都有自己的渲染方法以及其他独立的方法。这是最终奏效的方法:

不使用任何 alpha 掩码的普通项目的渲染方法:

public void render(SpriteBatch batch, int renderLayer) {
    if(renderLayer == Integer.parseInt(render_layer)){              // be in the correct render layer
        batch.draw(item.region, 
                item.position.x,                                    // position.x 
                item.position.y,                                    // position.y
                0,                                                  //origin x 
                0,                                                  //origin y
                item.region.getRegionWidth() ,                      //w 
                item.region.getRegionHeight(),                      //h
                item.t_scale,                                       //scale x
                item.t_scale,                                       //scale y
                item.manager.radiansToDegrees(item.rotation));      //angle
    }
}

因此,它会收到一个 spritebatch,它使用正确的图像、位置、比例和旋转来绘制它,就是这样。

在玩了我在这里找到的东西之后:https ://gist.github.com/mattdesl/6076846一段时间,这终于适用于需要使用 alpha 遮罩的项目:

public void render(SpriteBatch batch, int renderLayer) {
    if(renderLayer == Integer.parseInt(render_layer)){
        batch.enableBlending();

        //draw the alpha mask
        drawAlphaMask(batch, item.position.x, item.position.y, item.region.getRegionWidth(), item.region.getRegionHeight());

        //draw our foreground elements
        drawForeground(batch, item.position.x, item.position.y, item.region.getRegionWidth(), item.region.getRegionHeight());
        batch.disableBlending();
    }
}

有一个名为 alphaMask 的 TextureRegion 包含一个黑色形状。它可以是任何图像,但在这种情况下,假设它的形状/图像:

一个

这是上面调用的使用该图像的函数:

private void drawAlphaMask(SpriteBatch batch, float x, float y, float width, float height) {
    //disable RGB color, only enable ALPHA to the frame buffer
    Gdx.gl.glColorMask(false, false, false, true);

    // Get these values so I can be sure I set them back to how it was
    dst = batch.getBlendDstFunc();
    src = batch.getBlendSrcFunc();

    //change the blending function for our alpha map
    batch.setBlendFunction(GL10.GL_SRC_ALPHA, GL10.GL_ZERO);

    //draw alpha mask sprite
    batch.draw(alphaRegion, 
            x,                                                  // position.x 
            y,                                                  // position.y
            0,                                                  // origin x 
            0,                                                  // origin y
            alphaRegion.getRegionWidth(),                       // w 
            alphaRegion.getRegionHeight(),                      // h
            item.t_scale,                                       // scale x
            item.t_scale,                                       // scale y
            item.manager.radiansToDegrees(item.rotation));      // angle
    //flush the batch to the GPU
    batch.flush();
}

有多种“材料”适用于任何形状。在任何情况下,其中之一都分配给 spriteRegion 变量。假设现在是这样的:

在此处输入图像描述

所以上面调用的 drawForeground 方法使用这样的图像:

private void drawForeground(SpriteBatch batch, float clipX, float clipY, float clipWidth, float clipHeight) {
    //now that the buffer has our alpha, we simply draw the sprite with the mask applied
    Gdx.gl.glColorMask(true, true, true, true);
    batch.setBlendFunction(GL10.GL_DST_ALPHA, GL10.GL_ONE_MINUS_DST_ALPHA);

    batch.draw(spriteRegion, 
            clipX,                                      // corrected center position.x 
            clipY,                                      // corrected center position.y
            0,                                                  //origin x 
            0,                                                  //origin y
            spriteRegion.getRegionWidth() ,                         //w 
            spriteRegion.getRegionHeight(),                             //h
            item.t_scale,                                       //scale x
            item.t_scale,                                       //scale y
            item.manager.radiansToDegrees(item.rotation));      //angle


    //remember to flush before changing GL states again
    batch.flush();

    // set it back to however it was before
    batch.setBlendFunction(src, dst);
}

这一切都在桌面构建中立即起作用,并且可以在游戏中很好地产生“砖梁”(或其他):

在此处输入图像描述

然而,在 Android 和 GWT 构建中(因为毕竟,我使用的是 libgdx),它没有包含 alpha 掩码,而是呈现了完整的砖方块。

经过大量环顾后,我发现了这一点:https ://github.com/libgdx/libgdx/wiki/Integrating-libgdx-and-the-device-camera

因此,为了在 Android 中解决这个问题,我修改了 MainActivity.java onCreate 方法,如下所示:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    AndroidApplicationConfiguration cfg = new AndroidApplicationConfiguration();
    cfg.useGL20 = false;
    cfg.r = 8;
    cfg.g = 8;
    cfg.b = 8;
    cfg.a = 8;
    initialize(new SuperContraption("android"), cfg);

    if (graphics.getView() instanceof SurfaceView) {
        SurfaceView glView = (SurfaceView) graphics.getView();
        // force alpha channel - I'm not sure we need this as the GL surface
        // is already using alpha channel
        glView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
    }
}

这为Android修复了它。

我仍然无法弄清楚如何让它在 gwt 中正常工作,因为我无法弄清楚如何告诉 libgdx 告诉 GWT 告诉 webGl 继续并注意 alpha 通道。我对如何以更简单或更便宜的方式做这样的事情很感兴趣(尽管这似乎工作正常)。

如果有人知道如何使用 GWT 进行这项工作,请作为另一个答案发布。

如果您想查看纹理问题,这里是非工作 GWT 构建:

https://supercontraption.com/assets/play/index.html

于 2014-02-23T19:07:36.563 回答