Development Diaries, Volume 5
Posted by Alex Jordan on
The good news: I added water to my game engine.
The bad news: It really sucks and doesn't do what I want it to do.
This video obscures a lot of issues, so please bear with me.
My personality is such that I'm lazy enough to try taking shortcuts, but principled enough to know that I tend to avoid learning valuable lessons when I do so. Adding water to the game engine was one such lesson. I plunked some very valuable code written by XNA guru RandomChaos into my Around The World project codebase and hoped that I could customize it in a way that would prove beneficial to me. Turns out I couldn't.
First, there's the fact that the custom water shader that RandomChaos wrote doesn't really look that nice in conjunction with my own custom world shader that I've built over the last few weeks. This new ocean bares little resemblance to the world's oceans as seen from a great distance. I can tweak its settings, sure, but that will only slightly improve its look.
Not that I didn't try, which brings me to my single biggest issue. Do you notice how small that patch of ocean is? Have you wondered why it doesn't fill the whole screen?
Well, it did. Briefly. The moment it filled the whole screen, the game's framerate plummeted from 60 frames per second to 30 frames per second. A lot of respectable games run at 30 fps these days, but simple edutainment games aren't in that category. More to the point, my framerate being halved by a mere cosmetic addition is worrying enough to look into.
That lead me to decrease the ocean's scale. As a result, my 60 fps came back. Ah, so that's what it was. The shader was not struggling due to the number of, say, waves or effects that made the ocean sparkle. Those calculations are done no matter the size or scale of the ocean. As it stands, only one type of calculation increases when you change scale: the pixel shader. (I discussed vertex versus pixel shaders in an earlier Development Diary.)
When the ocean is smaller, it occupies a relatively small amount of pixels on the screen and requires a relatively small amount of per-pixel calculations. When it covers the whole screen? That requires a lot of calculations. And I guess they're not very efficient. And I can only guess because I didn't write the ocean shader code! I let RandomChaos do it, which doesn't teach me anything, and leaves me in this pretty pickle.
My game still needs an ocean. I can either try to reverse-engineer RandomChaos' code, learn what he did, and try to make it more efficient. Or - and this is what I should do - I should learn up on terrifying new math concepts like Fresnel equations, which determine how water reflects light and whatnot, and incorporate them into yet another test shader. Real fucking fun.
Fun or not, it's pretty unavoidable at this point. Besides, I'm not particularly enamored with how that ocean looks. The remake of The Secret of Monkey Island (which I finally killed off a few weeks ago) had some neat water effects that didn't bother with light reflection or major 3D calculations, as it was a simple 2D game (albeit one with gorgeous art) and didn't have any 3D art to perform calculations on. Although Around The World is in 3D, it only uses 3D as a means to access complex effects. The game itself will be in a traditional top-down, pseudo-2D style. So, it might be a good idea to ditch most of the "watery" aspects of a new water shader and just focus on creating a shader that recreates the sine wave-like pulsing of water body on a simple 2D surface.
Did you understand the implications of that sentence? Neither did I, which means I'm screwed.