libGDX 3D阴影瑕疵

时间:2014-08-08 22:18:49

标签: java api 3d libgdx shadows

我在使用libgdx 3d阴影时遇到了一些麻烦。在我的游戏中,我实现了实验性DirectionalShadowLight。一切都在桌面上运行良好但是当我在android上运行时,地面上有很多文物。

图片(左 - 右,右桌面):

我几乎直接从libgdx' github存储库中的测试中获取了渲染代码。

    Gdx.gl.glClearColor(ExtendedEnvironment.FarBackgroundColor.r,ExtendedEnvironment.FarBackgroundColor.g,ExtendedEnvironment.FarBackgroundColor.b,1);
    Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);

    terrain.prepareForShadows();

    environment.shadowLight.begin(new Vector3(cam.position.x+10,0,0), cam.direction);
    shadowBatch.begin(environment.shadowLight.getCamera());

    ball.draw(shadowBatch, null);
    terrain.draw(shadowBatch, null);

    shadowBatch.end();
    environment.shadowLight.end();

    terrain.recoverFromShadows(ball.getPosition().x);

对此并不多。另外考虑到它在桌面上运行我会认为影子实现本身有问题。有什么办法可以解决这个问题吗?考虑到我的生活中从未触及过着色器。一些简单的黑客可能吗?如果没有,也许有人可以为libgdx推荐其他工作影子实现?

谢谢。

编辑:附加代码:

BlendingAttribute  blendAttribute = new BlendingAttribute(1f)
IntAttribute intAttribute = IntAttribute.createCullFace(GL20.GL_FRONT);


 public void prepareForShadows(){

    batchedCubesInstance.materials.first().remove(blendAttribute.type);
    batchedCubesInstance.materials.first().remove(intAttribute.type);


}

public void recoverFromShadows(float posX){

    batchedCubesInstance.materials.first().set(blendAttribute);
    batchedCubesInstance.materials.first().set(intAttribute);

}

    //creating the batchedMesh:

    ModelBuilder builder = new ModelBuilder();
    builder.begin();
    MeshPartBuilder mpb = builder.part("cubes", GL20.GL_TRIANGLES, (Usage.Position | Usage.Normal | Usage.Color), new Material(
            IntAttribute.createCullFace(GL20.GL_FRONT),//For some reason, libgdx ModelBuilder makes boxes with faces wound in reverse, so cull FRONT
            blendAttribute = new BlendingAttribute(1f), //opaque since multiplied by vertex color
            new DepthTestAttribute(true), //don't want depth mask or rear cubes might not show through
            ColorAttribute.createDiffuse(Color.WHITE) //white since multiplied by vertex color
            ));

    for (int i=0; i < NUMCUBES; i++){

        mpb.box(1, 1, 1); 

    }
    batchedCubes = builder.end();
    batchedCubesInstance = new ModelInstance(batchedCubes);

enter image description here

1 个答案:

答案 0 :(得分:7)

您遇到的问题称为阴影痤疮(与peter平移相反),这是由(浮点)精度错误引起的。这些在移动设备上比在桌面设备上更明显,因为桌面设备上的精度通常更好。有几种方法可以避免阴影痤疮。其中之一是确保相机的近处和远处平面尽可能彼此靠近。因此,请勿使用非常小的cam.near和非常高的cam.far值。 DepthShader(用于创建深度缓冲区)通过仅使背面投射阴影来尝试避免阴影痤疮。为此它使用正面剔除。

但是,您还要正面剔除正常渲染(您只需渲染模型的背面)。这导致用于生成深度缓冲区的可见面和面相同。因此阴影痤疮。

您可以在生成阴影贴图时使用背面剔除来解决此问题。但是,这会使代码过于复杂,并可能导致其他(未来)问题。相反,您应该尝试将正面保持为可见面,从而删除IntAttribute.createCullFace(GL20.GL_FRONT)。请注意,默认情况下,后脸被剔除,您无需指定。

删除剔除脸部属性可能会导致正常渲染中的其他问题(否则您首先不会在那里进行渲染)。这很可能是因为模型的顶点缠绕不正确。你说你用以下方法创建这些:

for (int i=0; i < NUMCUBES; i++){
    mpb.box(1, 1, 1); 
}

这实际上是您用于在图像中创建模型的代码的可能性极小(这只会在同一位置创建一个未定义数量的相同大小的框)。根据您用于创建场景的方法,您可以通过交换水平或垂直坐标轻松校正顶点绕组,但只能更换其中一个。

如果由于某种原因,您不想纠正顶点绕组,那么您可以调用Gdx.gl.glFrontFace​(GL20.GL_CW);将逆时针使用的顶点绕组交换为顺时针方向。但请注意,这可能会导致其他(未来)问题,因为最常见的是默认值(逆时针)。