当前位置: 首页 > 知识库问答 >
问题:

LibGdx三维地形网格绘制在OpenGL ES 1.0而不是2.0中工作

张鸿志
2023-03-14

我扩展了LibGdx TerrainTest示例和这个问题,以便它可以呈现给定一些HeightMap的地形块集合。这似乎在GL10中工作良好,正如示例所使用的,但是当我使用modelbatch和默认着色器在GL20上移动代码时,网格不会完全呈现(参见图--在这张图中,我们只尝试呈现一个32x32块)。

这是应用程序的代码:

public class TerrainExperiment extends InputAdapter implements ApplicationListener {

private  PerspectiveCamera camera;
private long lastTime = TimeUtils.nanoTime();
private Terrain terrain;
private ModelBatch modelBatch;
private DefaultShader mockShader;

@Override
public void create () {

    terrain = new Terrain("testTerrain", 0, 0, "body", 32, 32, "137Industries",
            new Flat[]{
                    //new Flat(0, 0, 10, 5, 5, ColorHelper.toHex(Color.MAGENTA), "yeaaah" ),
                    //new Flat(5,5, 5, 7, 7, ColorHelper.toHex(Color.BLACK), "yolo")
            });

    //setup shader for terrain

    if(useGL20){

        //this is default shader, except we turn face culling off
        DefaultShader.Config config = new DefaultShader.Config();
        //turn off lights and culling, just in case
        config.defaultCullFace = 0;
        config.defaultDepthFunc = GL20.GL_LEQUAL;
        config.numPointLights = 0;
        config.numDirectionalLights = 0;

        mockShader = new DefaultShader(terrain.getModelInstance().getRenderable(new Renderable()), config);
        mockShader.init();

        modelBatch = new ModelBatch(new DefaultShaderProvider() {
            @Override
            public Shader getShader(Renderable renderable) {
                return mockShader;
            }

            @Override
            public void dispose() {
                mockShader.dispose();
            }
        });
    }

    camera = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
    camera.position.set(-5f, 0, 0);
    camera.lookAt(0, 0, 0);
    camera.near = 0.1f;
    camera.far = 300f;
    camera.update();

}


@Override
public void resize(int width, int height) {

}

@Override
public void render () {

    camera.update();

    if(useGL20){
        GL20 gl = Gdx.graphics.getGL20();
        gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
        gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
        gl.glEnable(GL20.GL_DEPTH_TEST);

        //render the terrain model using the model batch
        modelBatch.begin(camera);
        if(terrain != null){
            modelBatch.render(terrain.getModelInstance());
        }
        modelBatch.end();

    }else{
        GL10 gl = Gdx.graphics.getGL10();
        gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
        gl.glEnable(GL10.GL_DEPTH_TEST);
        camera.apply(gl); //for gl10
        //render meshes in the terrain model
        for (Mesh mesh : terrain.getModelInstance().model.meshes) {
            mesh.render(GL10.GL_TRIANGLES);
        }
    }

    handleInput(Gdx.input, Gdx.graphics.getDeltaTime());

    if (TimeUtils.nanoTime() - lastTime > 1000000000) {
        Gdx.app.log("TerrainExperiment", "fps: " + Gdx.graphics.getFramesPerSecond());
        lastTime = TimeUtils.nanoTime();
    }
}

@Override
public void pause() {    }

@Override
public void resume() {    }

@Override
public void dispose() {    }

private void handleInput (Input input, float delta) {
    if (input.isTouched()) {
        // simply modifying speed
        delta = delta + 0.0485f;

        // camera mouse look
        // find vector 90° to me
        Vector3 v90 = camera.direction.cpy();
        Quaternion q = new Quaternion(camera.up, 90);
        q.transform(v90);

        // go to plane x,z
        v90.y = 0;

        // set rotation up/down
        Quaternion qUpDown = new Quaternion(v90, Gdx.input.getDeltaY());

        // set rotation left/right
        Quaternion qLeftRight = new Quaternion(camera.up, -Gdx.input.getDeltaX());

        // apply the rotations
        qUpDown.transform(camera.direction);
        qLeftRight.transform(camera.direction);

    }

    if (input.isKeyPressed(Keys.W)) {
        Vector3 forward = new Vector3().set(camera.direction).scl(delta);
        camera.position.add(forward);
    }
    if (input.isKeyPressed(Keys.S)) {
        Vector3 backward = new Vector3().set(camera.direction).scl(delta);
        camera.position.sub(backward);
    }

    if (input.isKeyPressed(Keys.A)) {
        Vector3 left = new Vector3().set(camera.direction.cpy().crs(camera.up).nor()).scl(delta);
        camera.position.sub(left);
    }
    if (input.isKeyPressed(Keys.D)) {
        Vector3 right = new Vector3().set(camera.direction.cpy().crs(camera.up).nor()).scl(delta);
        camera.position.add(right);
    }
}

private static final boolean useGL20 = true; //change this to use GL10

public static void main(String[] args) {

    LwjglApplicationConfiguration cfg = new LwjglApplicationConfiguration();
    cfg.title = "BrowserThreeD";
    cfg.useGL20 = useGL20;
    cfg.width = 640;
    cfg.height = 480;
    new LwjglApplication(new TerrainExperiment(), cfg);

}

}

我用来制作地形块顶点和索引的代码直接复制自我上面提到的SO问题。您可以在应用程序代码中看到,我也尝试过关闭人脸剔除。我只能假设它一定是一个缠绕或重复顶点的问题,但我看不出它会画出这么多块?

如果这是相关的,这就是我如何从地形块网格创建libgdx模型:

Model result = new Model();

    int chunkNum = 0;
    for (TerrainChunk chunk : chunks) {

        Material material = heightMap.getMaterial();

        MeshPart meshPart = new MeshPart();
        meshPart.id = "terrainChunk" + chunkNum;
        meshPart.indexOffset = 0;
        meshPart.numVertices = chunk.getMesh().getNumVertices();
        meshPart.primitiveType = GL20.GL_TRIANGLES;
        meshPart.mesh = chunk.getMesh();

        NodePart nodePart = new NodePart();
        nodePart.material = material;
        nodePart.meshPart = meshPart;

        Node node = new Node();
        node.id = "terrainNode"+chunkNum;
        node.parts.add(nodePart);

        result.meshes.add(chunk.getMesh());
        result.materials.add(material);
        result.nodes.add(node);
        result.meshParts.add(meshPart);
        result.manageDisposable(chunk.getMesh());

        chunkNum++;
    }

有事吗?我可以张贴一个链接到完整的工作源,如果需要。

共有1个答案

卫弘懿
2023-03-14

假设您的网格是索引的,请使用:

meshpart.numvertices=chunk.getmesh().getnumindices();

meshpart#numvertices是要渲染的顶点总数,而不是网格中的顶点数。另请参见:http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/graphics/g3d/model/meshpart.html

 类似资料:
  • 我用libgdx和box2d做卡车游戏。在我的游戏中,1米=100像素。我的2D地形是由我生成的,是由点制作的。 我所做的,是为整个多边形创建一个polygonregion并使用texturewrap.repeat。问题是,我的游戏大小被缩小了100倍,以适应box2d单位。 所以我的相机宽度是800/100,高度是480/100。(8x4.8像素)

  • 我正在尝试模拟一个带有背景图像和前景图像的火炬视图。它在API 27及以下版本上运行良好,但在API 28上绘制一个矩形。 知道为什么它在Android Pie上不起作用吗? 火炬视图类

  • 我似乎在绘制正确的十六进制网格时遇到了一点麻烦: 正如您所看到的,六边形只是稍微不对齐,尽管我相信我的数学是正确的(其中一些可以通过http://www.redblobgames.com/grids/hexagons/进行验证)。 我的绘制方法是从左上六边形(第一行的第一个瓷砖)开始,绘制那一行瓷砖。然后对于下一行,有一个负X偏移量和正Y偏移量等,直到它到达中间行,在中间行X偏移量增加,直到0:

  • 我一直在编写迷宫算法,并希望绘制使用JavaFX生成的迷宫。 首先,我试图画一个简单的网格——但是由更小的形状组成,这样我以后就能把网格的形状变成迷宫。 我使用了小的左上角形状(像┏)和一个< code>GridPane,但是这导致了单元格之间的小的不连续。(截图和下面的代码)。我怎样才能无缝地把这些形状拼在一起?关于< code>Gridpane的想法,我是不是找错了对象? 目前已尝试绘制网格

  • 问题内容: 好的,我有这个代码 并且它将淡蓝色的背景绘制到屏幕上。我正在尝试创建一个渐变,该渐变从顶部的深蓝色到底部的浅蓝色。有没有简单的方法可以做到这一点?我是Libgdx和OpenGL的新手,所以我正尝试从书中学习,但我似乎找不到答案。我听说过要绘制一个大正方形并为顶点设置不同的颜色,但是我不确定该怎么做。 问题答案: 在libGDX中,ShapeRenderer对象包含一个方法,该方法为其位

  • 我目前正在使用libgdx为我的Android游戏开发一个对话框窗口。此对话框窗口包含标签和按钮的集合,但也应该包含图像。该图像表示“剩余健康指示器”,即带有指示玩家健康的符号的空指示器。这个指示器必须用代表剩余健康量的彩色矩形填充(见下面的屏幕截图)。 为了在libgdx的对话框中呈现这一点,我必须绘制一个图像和一个彩色矩形(红色矩形表示剩余健康的实际数量)。我知道对话框支持图像的渲染,但我不知