Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411423 Posts in 69363 Topics- by 58416 Members - Latest Member: JamesAGreen

April 19, 2024, 12:14:04 AM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)How to render tons of billboards in OpenGL?
Pages: [1]
Print
Author Topic: How to render tons of billboards in OpenGL?  (Read 2782 times)
Quarry
Level 10
*****


View Profile
« on: July 22, 2014, 05:49:30 PM »

I would like to render a lot of billboards (camera facing 3D sprites) in OpenGL and current I can think of two ways that both doth perform too well:

A) CPU calculate vertices and then glBufferSubData them each frame, this is slow because it uses CPU to do the transformation and uploading data is always slow

B) glDrawBuffers for each sprite and apply transformations for them individually, slow because of obvious reasons

Is there any other method that is considerably faster for this job?
Logged
Twinklebear
Level 0
**


View Profile
« Reply #1 on: July 22, 2014, 07:56:30 PM »

You can do 3D camera facing billboards really nicely by expanding the quad out from its center point in the vertex shader, if you then instance the quads to render tons of them, it should perform quite well.

To expand the quad out from its center point in the vertex shader you can compute the direction to the camera, find the horizontal and vertical vectors spanning the plane perpendicular to this direction and then based on gl_VertexID pick the right directions along these vectors to expand the quad out in. You could also multiply in scaling factors to change the size of the quad at this point.

When you then want to render a ton of them you could push all your sprite textures into a texture atlas (or array of atlases if they don't fit in one) and index into this with some extra instance data, eg. a sprite id which you then use to look up into a uniform buffer containing uvs (and texture array indices). You'd then use the vertex id again to pick which uv coordinate to use and pass this through to the fragment shader (along with texture array index) to apply the right texture.

When you want to update positions or attributes you can use glMapBuffer(Range) to make your modifications. It will also be best to keep all of this data in a single buffer (positions, sprite ids, etc).

I think I've got (or nearly got) a non-textured sample of this if you'd like to see it. It may need some tweaks/clean-up though.

Edit: You can also do a similar thing with point sprites and skip the quad expansion, but point sprites have their own issues (clipping), so it depends what you want.
Logged
Columbo
Level 0
***


View Profile
« Reply #2 on: July 22, 2014, 11:23:31 PM »

You can render a lot of particles very fast using your method A, but if you really need millions of particles instead of just tens/hundreds of thousands, then I think you need to look at doing your simulation on the GPU.

Here is a old article about it: http://www.gamasutra.com/view/feature/130535/building_a_millionparticle_system.php

Googling 'gpu particle systems' will yield lots of other results.
Logged

Twinklebear
Level 0
**


View Profile
« Reply #3 on: July 23, 2014, 03:30:51 PM »

So I got my demo running, there's still one issue that I'm not quite sure how to solve, if you look at them with your view direction near parallel to the +Y axis the billboards spin some, which isn't really correct. This is due to the view direction being too parallel to the up vector (+Y) we use to compute the horizontal vector of the quad.

One way to fix it is to detect this case where they get too parallel and switch the up axis you're using (eg. to +Z/+X) to find the horizontal vector but this causes a noticeable jump on the billboards when you change axes. I may ask around some places later or see what I can work out that behaves nicer. Although if you won't be viewing things from this angle then it's not really an issue Tongue haha.

Anyways, here's the demo: https://github.com/Twinklebear/vsbillboards. The README has a high level overview of what's going on and then you can start reading main and the vertex shader (in res/vertex.glsl) to get into the details of it.

Note that for the instance attributes (position & sprite id) I used two buffers out of lazyness but for best performance you should really be using a single buffer.

If anyone has any ideas about the +Y issue let me know!
Logged
Pages: [1]
Print
Jump to:  

Theme orange-lt created by panic