java - libGDX 3D 阴影伪像

标签 java api 3d libgdx shadows

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

图片(左-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

最佳答案

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

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

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

删除剔除面属性可能会导致您的正常渲染出现其他问题(否则您一开始就不会在其中添加它)。这很可能是因为您的模型的顶点缠绕不正确。你说你创建这些使用:

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

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

如果出于某种原因,您不想更正顶点缠绕,则可以调用 Gdx.gl.glFrontFace (GL20.GL_CW); 来交换使用的顶点缠绕逆时针到顺时针。但是请注意,这可能会导致其他( future )问题,因为最常见的是假定默认值(逆时针方向)。

关于java - libGDX 3D 阴影伪像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25213058/

相关文章:

java - JTextArea 中的插入符号位置已关闭

java - 全局 Web 应用程序参数

java - 如何使用 clp-java 的示例

javascript - Facebook - 获取带有/不带有访问 token 的页面 ID

java - 适用于 Mindflow 类型应用程序的良好 API

api - 使用Mozilla音频API创建提示音

opengl - 如何在 3D 中使用 opengl 渲染海浪?

java - 将 "PNG"图像文件加载到我的 Java Fx 应用程序时,Java fx 引擎失败

algorithm - 找到连接立方体两个面的线

javascript - Javascript 和 html5 中带有 GPS 数据的 3D 世界