我已经扩展了LibGdx TerrainTest example和此Question,以便它可以渲染一组地形块给定一些高度图。这似乎在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 question复制的。您可以在应用程序代码中看到我试图关闭面部剔除。我只能假设它必须是一个缠绕或重复的顶点问题,但我看不出它会吸引那么多的块?
如果这是相关的,这就是我从地形块网格中创建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++;
}
发生了什么事?如果需要,我可以发布完整工作源的链接。
答案 0 :(得分:4)
假设您的网格已编入索引,请使用:
meshPart.numVertices = chunk.getMesh().getNumIndices();
MeshPart#numVertices是要渲染的顶点总数,而不是网格中顶点的数量。另见:http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/graphics/g3d/model/MeshPart.html