如何在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()
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()