PDA

View Full Version : Minimizing glDrawArrays for triangles with and without textures



PalidinoDH
06-13-2017, 12:46 AM
Okay so a quick overview of what I'm doing. I'm using a Java program that relies 100% on software/CPU rendering of a 3D game. I'm trying to add in an OpenGL option without rewriting the entire render system, but this has made it a bit more difficult to achieve the best performance. Specifically, I'm trying to direct off the calls to the software triangle rendering and hand it over to OpenGL so that it'll cover the entire render process without having to get crazy with how much would have to be done to implement a full OpenGL setup.

The challenge I'm having is that the 3D models are specifically not designed around depth buffering and will glitch into eachother if it's enabled, breaking my ability to truly limit the number of glDrawArrays calls.

So, here's what I do when I have depth buffering enabled, and also gives me the FPS I want while using fullscreen, though the custom triangle priority system is lost from depth buffering causing some issues.
I have two Java ByteBuffers which store the non-textured vertices and colors. Then each texture (~50 in total although a map usually won't use over ~3) has its own buffers along with an additional buffer for uv coordinates. Depending on whether its a textured triangle or not decides which buffers the triangle information is stored. Once the scene is rendered for this frame, I send the entire non-textured buffer with one glDrawArrays call, and then one for each texture being used. This ends with only 4 glDrawArrays callsper frame. Runs fast, great FPS.

However to get around the triangle priority system used, I have to disable depth buffering and call glDrawArrays twice any time a textured triangle is rendered (send current non-textured triangles and then again as soon as a non-textured triangle or a different textured triangle is rendered). With the current system this game uses, these leaves me with about 1.6k glDrawArrays per frame, giving a fair FPS impact.

I'm not sure there's anything more I can do without diving deeper into the current software renderer to imbed OpenGL at a deeper level, but if anyone sees a way around doing so I would appreciate the help.

Quick stats involving per frame rendering: 27k triangles per frame including textured and just colored, 1k-2k glDrawArrays calls when not using depth buffering, 1k times a texture has to be bound

According to a program called JVisualVM which can help diagnose slow Java code, the top culprits involving OpenGL (in order) when I don't use depth buffering for correct triangle order is: glDrawArrays (35%), glEnable(GL_TEXTURE_2D) (10%) , glDisable(GL_TEXTURE_2D) (10%). All three of these are under 6% When I can batch them off to just a few glDrawArrays calls with depth buffering.


Main rendering code: https://pastebin.com/hR9z3KS4
Texture class: https://pastebin.com/QGjRGNxW

One idea I have is to use a texture atlas and to pass uv coords as all 0 for triangles that aren't textured and use a shader to make sure the colored triangle gets rendered if the uvs are 0 for the whole triangle, however I'm not sure if that's possible or how to go about making it happen. Possibly by adding a texture on the atlas with a certain color that when selected would result in the vertex color being chosen instead.