Hey there! I'm Fábio Fontes and I’m making cars do funky stuff in Buck Up And Drive!, a procedurally generated endless driving game with all the speeds and none of the common sense. It's also fully 3D and was made in GameMaker Studio 2!
... What's that? GameMaker can't do 3D?! Yeah, I also had the "GameMaker no do them 3Ds" mindset. I knew it could be done, but figured it would be either crude-looking or a complete pain in the donkey to set up... or both. How true is this mindset? Well, keep reading!
GETTING STARTED WITH 3D
I got into this rabbit hole through DragoniteSpam's videos on how to set up a 3D environment by setting up a perspective camera, learning about vertex buffers (how 3D models are stored for use, basically) and apply matrix transformations to them so we can put them in the game world. After some fiddling...
WE GOT A BOX, WOOOOOOOOOOOOOO!!!
Shortly after I realised I could also apply matrix transformations to sprites for some billboarding (see the sprite dude above). Add some crude collisions based on those of a top-down game, and... it actually looks like something now!
"Wait, this doesn't look like a driving game!", I hear you scream from the rooftops. Yep, this started as a general-purpose 3D environment, which is still in the game (looks a bit different now) and you can access it by hitting Shift+F5 in the main menu!
Then I added a "vehicle mode", and... now we're going somewhere.
IT'S BILLBOARDS ALL THE WAY DOWN
Now, what do you do when you have that nice 3D environment one could drive around?!... you create a new one with a conveyor belt track because you wanna make an OutRun clone! Logically!
This is when the actual game started. And in many ways it's still as crude now as it was back then. All those basic top-down racers people do as they're getting into gamedev? It’s that but with a fancier camera projection.
Background elements, cars, effects... all sprites moved about using matrix transformations and used as billboards. No fancy shaders (except the one for palette swaps by PixellatedPope) or anything. At this point the only 3D model was the skybox, as it was easier to rotate that than to set up some scrolling for the sky. Laziness or convenience? You decide!
So things would stay like this for a bit. While I COULD have verticality before, I was somewhat limited by the fact I'd have to make sprites for every action and manage them accordingly. If I wanted the car to jump, I'd have to get sprites for that. Sure, pre-renders would make the process easier than actually drawing them, but I intended to add extra cars over time, and... you can see how unmanageable that'd potentially become. Keep your scope in check, kids! Also I couldn't move the camera around too much or it'd break the illusion from the billboarded sprites (that one still somewhat applies today).
I could import models, but at the time they'd lack that cel-shaded look, something I considered important to the game's visual flair. So I kept things a bit modest with what the car could do, while making it look over the top enough to be enjoyable. Focus on the boost-based gameplay for all of them fasts.
That'd be enough... right?!
IT WOULDN'T BE ENOUGH
I started to mess with shaders for fun, specifically lighting... and I figured how to implement the type of cel-shading I was using for the car pre-renders. It's based on the techniques used by Arc System Works for their recent fighting games, focused on flat colors with clean, sharp lines, rather than intricate patterns, by having the UVs arranged in a somewhat unconventional way in a texture that's... almost exclusively just a bunch of squares.
For the shading itself, it uses a color ramp like many cel-shading methods… but instead of affecting the colors directly, it shifts the model’s UVs to other areas of the texture that contain the same layout in different colors. This allows me to have full control of what colors the model has for shaded and highlighted areas, rather than leaving it to the lighting. As for the rim light, that's achieved by using the camera's coordinates instead of the light source’s.
That's when the cars changed to real-time 3D models. The limitations from sprites were now gone. The track would still stay mostly billboard-based, but I could now do whatever I wanted with the cars! I could make their already existent actions look more intense. Adding new cars would no longer require organizing sprites, it was just a simple mesh swap! I could move the wheels independently from the car's body! And... you know where this is going...
... making the car jump was now trivial. Making it do silly flips in mid-air? Same thing. From here I just went hog wild.
My current setup has limitations, I'll be the first to say it. There's no advanced lighting with multiple light sources. Skeletal animation's taking a leave of absence. There's jank all over the place. Performance could be better. A lot of it is put together with duct tape and a wish. And there's no 4k texelated-raytraced-samplemapping, or whatever the current technical buzzword is.
But it does what I need it to do, and it looks pretty.