Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm writing an app which renders a random island planted with trees. The trees are currently two quads, criss-crossed and drawn with textures. I plan to have more complex meshes that form different plant types, e.g. a palm tree, oak, grasses etc..

Sample island

The problem I face is that because the textures are transparent I must draw them from back to front. Plan-b is to call of using discard in the frag shader, but z-order gives better results:

uniform float uTreeAlpha;
uniform sampler2D uTexture;

varying vec2 vTexCoordOut;

void main (void)
{
  vec4 colour = texture2D(uTexture, vTexCoordOut);
  if (colour.a < 0.1) {
    discard;
  }
  gl_FragColor = vec4(colour.rgb, colour.a * uTreeAlpha);   
}

The second problem is because the order changes depending on camera & lookat I do not know an efficient way to draw them in OpenGL in a single call.

At present my rendering code looks like this pseudocode:

if cameraChangedFromLastTime() then
  sortTreesBackToFront();
end
for i = 0 to trees.size() -1
  drawTree()
end

Where every drawTree() sets some uniforms, sets the texture, and then calls glDrawArrays(). I have some optimisations to skip setting a texture or updating texture coords if the last tree and the current are the same, and setting some common uniforms outside the loop, and of skipping trees which are too far away but basically if I have 3000 trees I go 3000 times around the loop.

Drawing each tree individually is the performance killer. If I could draw them in a single call, or batches (while preserving Z-order) I'd probably so in 1/10th the time.

So how would I do that. Bear in mind that my trees are placeholders and eventually I would have:

  • Different meshes for different trees
  • Different scales and angles for trees to give some more variety
  • Different textures for different trees, potentially multiple textures applied to a mesh (e.g. leaves one texture, trunk another)
  • Trees are all mixed together so no simple way to draw one kind and then another
  • Some form of simple cyclical animation (branches bobbing in the wind)
  • All textures would reside in a single atlas

So what's best approach here? Is it feasible to render in a single pass? If I used glDrawElements, rebuilding the indices but not the vertices, could I achieve this?

share|improve this question
    
vterrain.org , see right column under section plants for plant rendering, respective left column, section rendering for level of detail/general rendering speedups. Beware though: the source is more listing of research papers than tutorial. –  sarahm Mar 27 '13 at 20:17
    
I don't know much about this stuff. But check out VUE software. It is used to create landscapes with trees, mountains, atmosphere and a lot more, in 3d. But I'm not sure if it will help in your situation –  user1981248 Mar 27 '13 at 23:03

2 Answers 2

What you want is hardware instancing. Note: I've done this in XNA (i.e. DirectX), but I don't know much about OpenGL. I'm positive there is a comparable feature, though. Basically what it amounts to is binding together the vertexes of your tree model with another vertex stream that carries world coordinates for each instance.

share|improve this answer
1  
The OpenGL equivalent would be extension opengl.org/registry/specs/EXT/draw_instanced.txt. But, for a start, display Lists in legacy OpenGL and Vertex Array Objects/Vertex Buffer Objects in modern OpenGL might do. In both cases, an object/mesh is stored in the List/VAO/VBO, then each instance is drawn with a different transform. Using static meshes, the data can be uploaded once and then reused. sol.gfxile.net/instancing.html gives a short overview over the different methods. –  sarahm Mar 27 '13 at 23:37
    
Thanks,instancing is an interesting idea. I couldn't use a draw_instanced extension however since I'm using OpenGL ES 2.0 and I'm working on somethign which works on everything. I'm thinking perhaps that I can load the various tree meshes into a VBO (potentially with simpler models further away), z-sort, and then draw them in batches from an index buffer which I'd build for each batch. I might be able to draw 30 or 40 at a time that way. –  locka Mar 28 '13 at 11:52

The transparency only needs to be ordered if it uses non-additive blending. For a ton of distant billboards, the blending is unnecessary (you can't really see it). Render at least the further ones with cutout transparency (alpha of only 1 or 0) and you don't need to sort them.

You can use a sprite sheet of sorts to render different types of trees, with baked animations. Draw meshes for closer trees which you can animate with more fidelity based on winds or whatever you want.

share|improve this answer
    
I've experimented with using discard and no sorting, but the results look a bit duff - trees tend to overlap a lot so if there is no consistent order, I get a lot of pop where one tree goes in front of the other and "wins" the pixel. I've left the discard in because there are still occasional collisions (e.g. 2 trees with the exact same distance from the camera) but it's a fallback. I've also experimented with billboards and the effect is too fake especially for flyovers. –  locka Mar 28 '13 at 11:43
    
Use better billboards. Ideally, have a tree model. Generate the billboard sprite for a viewing angle, and use that sprite where the angle approximately matches. For cutouts, they work best at a distance, where you can't see the difference. As you close in, you need to use more cocmplicated models (maybe a few quads per tree), or you can switch to screen-door transparency. –  Sean Middleditch Mar 28 '13 at 17:12
    
At some point, you need to figure out the acceptablce balance between quality and speed. You won't get "blazingly fast" and "perfect" for most complex scenes on commodity hardware. –  Sean Middleditch Mar 28 '13 at 17:13

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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