0
\$\begingroup\$

I've been working on coding a new 3D engine in Java. For the moment at least I'm sticking to openGL...

Currently I'm reworking how meshes get transformed and then drawn. ATM each mesh created has its own VBO and IBO along with its own draw method so if I wanted to draw multiple meshes it would look like this:

mesh1 = MeshLoader.loadMesh("cube.obj");
mesh2 = MeshLoader.loadMesh("pyramid.obj");

mesh1.addToBuffers(); //adds vertex and index data to vbo and ibo
mesh2.addToBuffers();

mesh1.draw();
mesh2.draw();

The draw method defined in class Mesh enables vertex attribute arrays, binds the bufffers, and then draws elements based on the ibo.

Then I send my projection matrix (transformation and perspective) as a uniform to the vertex shader.

QUESTION:

  1. Games are made of many many meshes and each has to be identified so that transformation can be applied. I want to be able to apply transformations (translate, rotate, scale) directly to a given mesh, independent of the other meshes. In other words I want to move mesh1 and only mesh1 5 units to the right (on its own axis) without it affecting mesh2.

  2. How do I do all this without making a million draw calls to the gpu?

Any advice appreciated.

\$\endgroup\$
  • \$\begingroup\$ Multiple draw calls aren't so bad if you don't rebind the vertex buffers. You can draw a portion of the buffer, set new uniforms, and draw a different portion. Another technique (which I'm using currently) is using a texture to hold per-part matrices (4 floating RGBA texture pixels per matrix), and a part-id as a single attribute on each vertex to know which row of texture to reference. Changing matrices involves updating the texture. All 1 draw call. \$\endgroup\$ – david van brink Apr 3 '15 at 4:24
  • \$\begingroup\$ Hmm I hadn't though of storing multiple meshes in a single vbo.. that's something I can work with thanks! \$\endgroup\$ – Andrew Graham Apr 3 '15 at 11:55
1
\$\begingroup\$

As I understand it, now you are making some transforms and pass the matrix as a uniform which is the same for all meshes.

What you should do, is send different matrices for each mesh, which could be for example members of the mesh class. Then send the uniforms before rendering each mesh. Something like this:

void Update(){
    mesh1.transform = rotate/translate/scale....
    mesh2.transform = rotate/translate/scale....
    .
    .
}


void Render(){
    mesh1.SetUniforms(); // send mesh1.transform to the shader as usual
    mesh1.Draw();
    mesh2.SetUniforms(); // send mesh2.transform to the shader which is different
    mesh2.Draw();
    //...same for other meshes
}


void MainLoop(){
    while(...){
        Update();
        Render();
    }
}

and of course they could use the same shader.

\$\endgroup\$
  • \$\begingroup\$ Not terrible... I'm trying to avoid making multiple render calls though. It tends to slow stuff down big time. \$\endgroup\$ – Andrew Graham Apr 2 '15 at 23:20
  • \$\begingroup\$ Having some draw calls to draw multiple meshes is not so bad as david said, particularly when the meshes have nothing to do with each other (one mesh for a car, another for the terrain, another for the trees). However when you have meshes that are very similar (many cars, many trees) then you should look into instanced rendering: rendering many similar meshes with one draw call. \$\endgroup\$ – trmag Apr 3 '15 at 8:29

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.