Spooky Pooky #40 - Rendering Recap
Published on 29 Jan 2016 by Joe
Some more notes on rendering.
For Spooky Pooky I chuck all sprites to be rendered into a big array - this includes the particles. At the end of the first pass of the rendering process I then sort this array by a few things (depth, blend-mode, shader) then I sweep through it filling up a big interleaved array of data to give to OpenGL.
I flush out this array to OpenGL every time I change the blend-mode or shader. However, at the moment I only really have two shaders - one is just a simple texture-blit (from spritesheet coordinates) which is used for nearly everything. The other is the water shader which blends two textures together with a wibble offset.
The blend mode doesn't change much typically - at the moment I only change it for electrical sparks.
Everything has a depth though so it's possible that I have electrical stuff at multiple depths, which will cause a few flushes.
Typically though most frames are rendered with maybe 6-10 drawcalls (using glDrawArrays with GL_TRIANGLES) to OpenGL.
The actual tilemap I use for the level data also goes into the drawcall and is sorted - this is also rendered with the same texture blit call but from a VBO with static coordinates that covers the whole screen. I offset it by a scroll amount and change the texture coordinates each frame.
So much for Spooky Pooky - QB1-0 was all a lot simpler.
The ships, asteroids, font, etc were drawn with a single call to OpenGL with GL_LINES and the particles where similarly drawn with another call using GL_POINTs.
QB1-0 was only on the iOS though and when I wrote it I was using an iPhone 4 as my base level. So it had to be 60fps on that with no frame dropping. The biggest problem I had was with the 'black-hole' enemy type. These are simple gravitational attractors that basically pull everything on the screen (including particles) towards them.
I decided to render them purely through particles. So they emit particles with a velocity perpendicular to the spin of the entity - this means the particles go into a nice expanding orbit and it ends up being a cool swirly effect. However it took a lot of particles to make it look good, which would sometimes pull the framerate down.
To solve this I have two update functions for particles. If the count is not too high I apply the full physics model to them and let them wrap-round the screen. If the particle count goes too high then particles go through the 'fast' route, where they have a simplified physics model (no attraction) and they stop wrapping the screen and just get returned to the pool when they fall off the edge.
This worked pretty well as if there's that many particles on the screen you can't really tell what's going on anyway :) All told I think I had a max limit of about 10,000 particles for that game.
Of course nowadays I'm sure that an iPhone 6 could copy with a lot more ... plus I'm also sure that there's a lot of other things I'm doing wrong :) For a start I use linked lists a lot which probably means I get a lot of cache misses (even though the source data for the list is from a big contiguous pool).
Hey-ho life can be too short to worry about that sort of thing until you need to ..