3
$\begingroup$

I am writing a large 3D game in Java with OpenGL.

Question #1

As of now, I am rendering my 3D objects using a Model class that I defined. This class contains vertex, color, model matrix, code (a custom attribute I defined), and index arrays. I defined a method addModels that can concatenate an array of Model instances into a new, larger Model (it concatenates all the attribute arrays using System.arraycopy). For instance, to draw a forest; for every tree, I create a Model; and at the end I combine them all into one forest Model, which I render. This procedure is a very object-oriented way of doing it, and consists of fitting together many bundles of attribute arrays into larger ones. Simple example code:

Model[] models = new Model[trees.length];
for (int i=0; i<trees.length; i++) {
    models[i] = getTreeModel(trees[i]);
}
Model result = addModels(models);
return result;

However, this procedure may be bad practice memory-wise, since I create many Model instances per frame. (Nonetheless, I read in this answer that objects do not take much memory.) Would it be better practice to lean towards a more data-oriented approach; like first declaring large attribute arrays (vertex, color, etc.), and creating them individually? Simple example code:

float[] vertices, colors;
for (int i=0; i<trees.length; i++) {
    float[] treeVertices = getTreeVertices(trees[i]),
            treeColors = getTreeColors(trees[i]);
    // copy treeVertices into vertices, and treeColors into colors at appropriate positions
}
return new Model(vertices, colors);

Please note that either option results in one model that is going to be rendered finally.

Are there any better ways of doing this?

Question #2

When I render a Model, I convert each attribute array into an attribute buffer (e.g. float[] into FloatBuffer). Would it make my game run faster to, first, load data into a buffer without using the array at all? (I'm using arrays because they're easier for me to manipulate.)

Question #3

Would it be more efficient to call glBufferSubData then to concatenate all the attribute arrays into longer ones and then call glBufferData (or a similar method)?

Question #4

One tutorial I read defined a Model class as containing multiple Meshs. Then, they drew each mesh separately to the screen. Is this good practice if I have a lot of meshes (trees) per model (forest)? I heard it isn't good to make a lot of glDraw* calls.

$\endgroup$
1
$\begingroup$

Don't copy around huge chunks of data if you don't have to.

I would delay collecting and building the final forest mesh for as long as possible.

However when you have multiple of the same mesh that just needs to be translated and rotated a bit you can use instancing. Which lets you draw thousands of copies of a tree with a single draw call.

The most efficient way of getting data to the gpu is to map the buffer and fill that. In java that means using a Buffer.

$\endgroup$
  • $\begingroup$ For instancing would that mean to use glDrawElementsInstanced? $\endgroup$ – clabe45 Aug 3 '17 at 16:08
  • $\begingroup$ @clabe45 yeah or glDrawArraysInstanced $\endgroup$ – ratchet freak Aug 3 '17 at 16:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.