I'm working on a 3D game.
The game requires around 100 cubes to work, all cube have be dynamic.
I don't really know how much perfomance is required for a game like this, but i'm testing with a tablet with Mali-400 MP2 GPU, 1 GB ram, 1.5 GHz dual core. I know about rendering all of the cubes in one mesh, but then i can't move all of them separately.
This setup gives me a very vacillating fps. Jumping between 20 and 50, mostly under 30. (In emulator 10-15)
When the game starts, i build an arraylist of ModelInstances, all of them is using the same model.
model = new ModelBuilder().createBox(1f, 1f, 1f, new Material(ColorAttribute.createDiffuse(Color.GREEN)), Usage.Position | Usage.Normal);
// width,height,length = 5, creating a total of 125 cubes
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
for (int z = 0; z < length; z++) {
if (this.map[x][y][z] > 0) {
this.modelInstances.add(instance = new ModelInstance(model));
instance.transform.translate(x, -(y * 1.5f), -z);
}
}
}
}
Rendering:
Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
mb.begin(camera3D);
mb.render(this.modelInstances);
mb.end();
The camera initializing:
camera3D = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
camera3D.position.set(0f, 8f, 5f);
camera3D.lookAt(0, 0, 0);
camera3D.near = 1f;
camera3D.far = 300f;
camera3D.update();
- What can i do to increase the perfomance?
- Is the tablet too weak for a game like this? or the problem is the code?
EDIT:
Did some test with webGL too, same tablet, using chrome, rendering 125 cubes: stable 40-50 fps
You can batch all your cubes into a single Model and ModelInstance like this:
But the tricky part is being able to move each of those cubes to a different location and be able to manipulate them independently.
Here's a Cube class that can manipulate the individual cubes from the above model. I think theoretically it should work with any Mesh you create that uses 24 unique vertices per cube, so you could add texture coordinates for example.
This also relies on position and then normal always being the first two Usage attributes of the mesh, so hopefully that holds true in libGDX's Mesh class.
This works basically by keeping track of it's index number in the base mesh (which cube number it is) so it can pick out the vertices that it needs to update in the vertices array. The vertices need to be copied into the mesh each frame.
To use this, first get a mesh reference and create the cubes:
Then in your
render
method:Now CPU vertex manipulation is not as efficient as shader vertex manipulation, so this may become CPU bound if you're moving all your cubes around every frame. If you aren't rotating them much, it would probably help to create a separate "dirty" variable for rotation and only rotate if necessary in the update method.
EDIT: Update from this question
If you want to have transparency, then the cubes must be sortable, so they can be ordered from far to near for drawing. Their
index
values must be updated to the new order since that is how they are ordered into the mesh. Here is a Cube class that supports sorting (the color has to be tracked independently now since the cube might be moved to a different part of the mesh).Here is how you would sort them: