NewoZero v4 - Postmortem
Page is part of Articles in which you can submit an article
written by owen on 2024-Jan-13.
This update of my racing game sub titled "Zero" started out pretty much the same as the last v3 update with a flash in the pan of an idea. I figured out dot-products. When I say "figured out" I mean that the concept of it mapped directly to the inner workings of my animal brain and it made sense, maybe not at a mathematical level but I could call the function and understood what the result ment.
With this new tool in hand I set out to optimize everything I could get my hands on. This might end up being a really technical article but this is how it is in game development. The changes between v3 and v4 are not as dramatic as prior versions. This time around the changes were to get the game to render faster, everything else was just icing on the cake. I also want to add a 2 player split screen mode so this version I went hard on optimizations. I got rid of the screen tearing at the top - if you noticed it - or at least reduced it a whole lot.
I changed the buildings to 3 quads that faced the camera based on the dot product. Then I added dotproduct into the frustum code as well which led to other things. I started reading up on branchless code as well even though I don't think the Wii has that kind of optimization. But branchless code sparked a curiosity in my head which led me down a path to reduce all my loops to only the essential items. No much looping over the entire array checking if something "is active then continue;". I made the move to create many many lists of things.
Lists of things
Startingfrom about June 2023 I went on a crusade to change every loop in the same to operate on my internal list structure. I would build a list of items in the animate() function then loop over it in the draw() function with minimum checks for whether the thing I am drawing is visible or not. This resulted in smaller loops and less time checking conditions. I even took it a step further by creating several lists instead of a single big list for example, the track itself is rendered in 4 loops over 4 loops instead of intermingling things that are spread out over the track array.
Replacing hard coded objects
I wanted to replace a as many models that are drawn in code with wavefront objs loaded from disk. Hardcoding graphics in code is faster but loading externally makes it easier to swap out and customize when modding. Since wavefront obj files are normally triangulated I end up sending more data to the GPU but its not exorbitant as long as I keep the new models small.
The main downside being that I can no longer have thin models made up of hand coded lines - everything has to be made up of triangles. I did discover a cool new use for objs by rendering them as points (instead of wireframe lines) at the center of each triangle to produce a point cloud that could be used for something in the future. After some work I swapped out all the roof decorations for new designs that I thought up in MOI3d.
I added a new decoration below the raised sections of the track for a bit of visual complexity plus I was sure it would not affect anything. The special sections of the track also got 3 new models that vary based on the stage number.
New Bugs
I had a random frame drop on a particular stage that took 2 hours to debug. A repeating facade texture was causing the frame drop. The GPU was not happy with a particular combination of parameters for the repeat. Also I discovered this bug while testing a new level on real hardware but Dolphin_Emu (in which I was spending most of my time). The process of elimination was more difficult because if you remove a thing or pause the game the fps would return to 60fps. Making it hard to deduce which single thing was causing the issue. Signs? Buildings? skybox? Track? Spritesheets? #gamedev
I like this instant feedback of #gamedev except when it gets so overwhelming that literally anything could break the delicate house of cards and madness that you just spent months constructing.
Colours and more colours
I redid the entire colour engine merely so that I could switch the palette to black and white or red or blue if I wanted. It was a tedious task getting rid of all the hard coded colours and initializing them at level start but it was worth the effort even if it's just a new option in the menu. It's still not perfect because some aspects such as the random coloured signs often choose colours from the reserved set so it's hard to have a red track without red signs popping up somewhere.
Fixed the dpad handling
I finally sat down and added some easing to the dpad resulting in less jerkiness when turning corners - it makes a world of difference - a whole world. So much so that I use the dpad all the time. Its almost better than the analog stick. So good I back ported the handling fixes to v3.16 then released a new version v3.25 while I was still working on v4. No use forcing everyone to wait until 4.0 to get better handling. Because the better handling is worth it more than any graphical improvement that version 4 could bring. This was a prickly task but I managed to do it by digging up an old version which took some head scratching because I never planned to go back to old versions.
Quad.h
I created a new lib called quad.h which accepts world space coords and converts them all into model space in order to draw them in one draw call. I am really deep into this one draw called multi-object batching life. Similar to what I did with the sprite signs+decals but this is for quads. This is how the green landscape is a prototype you can see on youtube. This lib was quickly added into NZ to replace a similar hack for the buildings - I had to do a few calcs to figure out where the 8 corners of the cube fell but it was straight forward once I worked it out. It was not as big of a performance jump as I had hoped but everything is buzzing along nicely for the upcoming NZ4 release.
Building facades and batching
I spend a good deal of time working on batching draw calls instead of drawing things individually. This ment that things that shared the same texture could be drawn together reducing the over head of things such as the signs which are now drawn all at once in model space. It was alot of work but the performance improvement was irresistible. This led me to realise that I could manipulate the repeating texture feature in ways which allowed me to create larger signs with 3 or 6 sections simply by allowing the texture to repeat. Once I did that the building facade problem was solved. Now the builds look unique while only using one texture. They do not look so good up close but far away they look excellent.
Simple prototypes and side projects
One of my goals during the year were to make more prototypes and simply the game engine for possible porting in the future. Some of the enhancement in NZ came from these prototypes. A Lot of this work has been uploaded to the NewoGame youtube channel. Please subscribe for more silent videos that have no purpose.
Conclusion
The NZ codebase has gotten huge. I dread thinking about the number of systems that I have put in place over the 2 years that I have been working on it. Lots of things are happening at the same time especially in the UI to make everything work together. I need to simplify alot of the variables if I ever hope to add multiplayer. But no one knows what the future holds. You just have to enjoy what you have now.
Footnotes
Social Media Links;
twitter.com/NewoGameNewoGame1 youtube
wiibrew.org/wiki/Newo_Zero
permanent link. Find similar posts in Articles.
comments
Comment list is empty. You should totally be the first to Post your comments on this article.