如何在libgdx的android游戏中使用深度缓冲来剪辑table

How to use depth buffer to clip table in libgdx's android game

Table' 默认剪辑是使用 scissorstack,但 scissorstack 只支持矩形。而我想用圆来裁剪它,所以我选择使用深度缓冲区。

这是我的代码,但它没有成功剪辑 table。 table 显示为原来的样子。

@Override
protected void drawBackground(Batch batch, float parentAlpha, float x, float y) {
    // TODO Auto-generated method stub
                 batch.end();
               //       //1. clear screen
                 Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

                //2. clear our depth buffer with 1.0
                Gdx.gl.glClearDepthf(1f);
                Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

                //3. set the function to LESS
                Gdx.gl.glDepthFunc(GL10.GL_LESS);

                //4. enable depth writing
                Gdx.gl.glEnable(GL10.GL_DEPTH_TEST);

                 //5. Enable depth writing, disable RGBA color writing 
                Gdx.gl.glDepthMask(true);
                Gdx.gl.glColorMask(false, false, false, false);

                ///////////// Draw mask shape(s)

                //6. render your primitive shapes
                shapes.begin(ShapeType.Filled);

                shapes.setColor(1f, 1f, 1f, 0.5f);
                shapes.circle( PositionArray.detail_x, PositionArray.detail_y,100);

                shapes.end();
                batch.begin();              

                ///////////// Draw sprite(s) to be masked
                //8. Enable RGBA color writing
                //   (SpriteBatch.begin() will disable depth mask)
                Gdx.gl.glColorMask(true, true, true, true);

                 //9. Make sure testing is enabled.
                Gdx.gl.glEnable(GL10.GL_DEPTH_TEST);

                //10. Now depth discards pixels outside our masked shapes
                Gdx.gl.glDepthFunc(GL10.GL_EQUAL);

                //push to the batch
                super.drawBackground(batch, parentAlpha, x, y);
                //  batch.draw(grass, 0, 0);
                //end/flush your batch
                Gdx.gl.glDisable(GL10.GL_DEPTH_TEST);
}   

任何帮助将不胜感激!

改进:

在采纳了Tenfour04的建议后,我修改了我的代码,但还是没有解决我的问题。

public class MyTable extends Table {
ShapeRenderer shapes;
private final Matrix4 tmpM = new Matrix4();
    public MyTable() {
        super();
        // TODO Auto-generated constructor stub
        shapes = new ShapeRenderer();
    }
@Override
protected void drawBackground(Batch batch, float parentAlpha, float x, float y) {
    // TODO Auto-generated method stub
                 batch.end();
               //       //1. clear screen
//Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
//                  
////2. clear our depth buffer with 1.0
//Gdx.gl.glClearDepthf(1f);
//Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);


                //3. set the function to LESS
                Gdx.gl.glDepthFunc(GL10.GL_LESS);

                //4. enable depth writing
                Gdx.gl.glEnable(GL10.GL_DEPTH_TEST);

                 //5. Enable depth writing, disable RGBA color writing 
                Gdx.gl.glDepthMask(true);
                Gdx.gl.glColorMask(false, false, false, false);

                ///////////// Draw mask shape(s)

                //6. render your primitive shapes
                shapes.setProjectionMatrix(getStage().getViewport().getCamera().combined);
                shapes.setTransformMatrix(tmpM.idt().translate(0, 0, -0.5f));
                shapes.begin(ShapeType.Filled);

                shapes.setColor(1f, 0f, 0f, 0.5f);
                shapes.circle( PositionArray.detail_x, PositionArray.detail_y,100);

                shapes.end();

                batch.begin();              

                ///////////// Draw sprite(s) to be masked
                //8. Enable RGBA color writing
                //   (SpriteBatch.begin() will disable depth mask)
                Gdx.gl.glColorMask(true, true, true, true);

                 //9. Make sure testing is enabled.
                Gdx.gl.glEnable(GL10.GL_DEPTH_TEST);

                //10. Now depth discards pixels outside our masked shapes
                Gdx.gl.glDepthFunc(GL10.GL_LEQUAL);

                //push to the batch
                super.drawBackground(batch, parentAlpha, x, y);
                //  batch.draw(grass, 0, 0);
                //end/flush your batch
                batch.flush();
                Gdx.gl.glDisable(GL10.GL_DEPTH_TEST);
   }                    
}

我看到了几个问题:

1) 在刷新批次之前禁用深度测试。 SpriteBatch 仅在刷新或调用 end 时将网格发送到 GPU 进行绘制。因此,在禁用深度测试之前添加行 batch.flush()

2) 您从未清除深度缓冲区位。此外,您不应多次调用 glClear。最好是在 stage.draw() 之前而不是在 actor 的 draw 方法中间调用它!我会在 stage.draw() 之前添加以下内容:

Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);

并从您的 Actor 中删除相似的台词。没有理由调用 Gdx.gl.glClearDepthf(1f);,因为无论如何默认值都是 1。

3) 如果您的蒙版形状与您正在绘制的其他所有形状的单位相同,则形状渲染需要使用与舞台相同的投影矩阵。此外,通过将矩阵保留为默认值,我认为您是在 Z=1(深度 0)处绘制蒙版,而不是在 Z=0 处绘制精灵批次。把这个放在 shapes.begin:

之前
shapes.setProjectionMatrix(getStage().getViewport().getCamera().combined);

4) 我想舍入可能会导致 GL_EQUAL depthFunc 失败。如果以上都做了还是不行,试试把圆往后拉一点。

private final Matrix4() tmpM = new Matrix4();

//...

//right before shapes.begin:
shapes.setTransformMatrix(tmpM.idt().translate(0, 0, -0.5f));

然后当您为蒙面精灵设置 depthFunc 时,使用 LEQUAL 而不是 EQUAL

感谢Tenfour04帮我解决这个problem.Here是我修改后的代码

@Override
public void draw(Batch batch, float arg1) {
    // TODO Auto-generated method stub
    batch.end();
    // //1. clear screen
    // Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
    //
    // //2. clear our depth buffer with 1.0
    // Gdx.gl.glClearDepthf(0f);
    // Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

    // 3. set the function to LESS
    Gdx.gl.glDepthFunc(GL10.GL_LESS);

    // 4. enable depth writing
    Gdx.gl.glEnable(GL10.GL_DEPTH_TEST);

    // 5. Enable depth writing, disable RGBA color writing
    Gdx.gl.glDepthMask(true);
    Gdx.gl.glColorMask(false, false, false, false);

    ///////////// Draw mask shape(s)

    // 6. render your primitive shapes
    shapes.setProjectionMatrix(getStage().getViewport().getCamera().combined);
    // shapes.setTransformMatrix(tmpM.idt().translate(0, 0, 0.5f));
    shapes.begin(ShapeType.Filled);

    shapes.setColor(1f, 0f, 0f, 0.1f);
    shapes.circle(PositionArray.detail_x, PositionArray.detail_y, 100);

    shapes.end();

    batch.begin();

    ///////////// Draw sprite(s) to be masked
    // 8. Enable RGBA color writing
    // (SpriteBatch.begin() will disable depth mask)
    Gdx.gl.glColorMask(true, true, true, true);

    // 9. Make sure testing is enabled.
    Gdx.gl.glEnable(GL10.GL_DEPTH_TEST);

    // 10. Now depth discards pixels outside our masked shapes
    Gdx.gl.glDepthFunc(GL10.GL_EQUAL);

    // push to the batch
    super.draw(batch, arg1);
    // batch.draw(grass, 0, 0);
    // end/flush your batch
    batch.flush();
}   

最后,在[=之前添加Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); 17=]stage.draw()