These posts concerning the game are intended to record things that have driven me insane or insights I've gained while working on it. But first here are some pretty pictures:
This first picture is of the first 'world' - the game will be split up into worlds, each with its own theme - the theme of this first world being "Deco".
Next is a picture of the same scene but without the game pieces or HUD.
Finally here's a picture of the deco-block mesh that makes up the solid blocks in the Deco world.
Materials
So far I've developed 2 CgFx materials: a basic celshading/toon material and a basic phong material. Both materials have black outlines to remain consistent and to bring out more of the features of the various meshes.
I've designed materials so that they share all uniform and varying parameters - typically these are just various projection, view and world transform matrices, a diffuse sampler, specular colour, diffuse colour, shininess, and light positions/colours. My reasoning behind this is so that I can move all the parameters (in code), up into a superclass for materials. This allows me to abstract any of the game materials, where I may change the parameters of a material without needing to know the material I'm dealing with. Of course, I lose this abstraction if I ever create really complicated materials with unusual parameters - but for the purposes of this game, I doubt I'll have any materials of that sort.
To deal with the CGcontext and other persistent Cg-type objects I created a singleton manager for CgFx - this makes creating, getting, and destroying those objects easy and centralizes that functionality. It also provides a central place to load effects and check for errors in the Cg runtime.
Instancing Issues
Probably the most time consuming and troubling issue I've had so far was dealing with instancing of the blocks/bricks that make up game levels. When I first drew a full level with all of its bricks, CgFx materials included, I had a frame rate of 10... which seemed absolutely ridiculous on a NVIDIA 8800 GT - my goal for this game is to ALWAYS keep the frame rate at 60 fps. So at that point there was much science to be done; I had never dealt with extreme instancing before and I had some ideas of what the problem was...
- Naive hypothesis: high polygon block meshes
- Less Naive hypothesis, but still naive: using only one display list many times
- Partly good hypothesis: overly complicated CgFx shaders (move outline pass out of shader, simplify some of the math)
- Correct hypothesis: ALL material parameters are being changed for EVERY BLOCK (yikes!)
I was able to remedy the problem by rendering the entire level as a set of individual display lists for all the blocks, each display list with that block's full world transform set as vertex positions - sure it takes up more memory, but the blocks are really small anyway. Then, as I draw each of the display lists I only set the transform parameters once and the only varying parameter for now is the diffuse colour. This remedy put the frame rate back at 60 fps.
This is obviously NOT a solution that uses "instancing" in the sense of modern GPU instancing (i.e., one that uses the latest and greatest OpenGL extensions for instancing or even using pseudo instancing), but it's certainly a solution that works.