…continued from Part 1
So it’s the beginning of 1992, and having secured myself a rip-roaring 286 I set about exploring the capabilities that dwarfed my old CPC464. I even purchased a Sound Blaster card for it, which from memory cost just $200 and could do 44kHz mono or 22kHz stereo! The first piece of audio I ever digitally sampled was Laurie Anderson’s O Superman, which ended up occupying pretty much all the free space on my 40MB hard drive since it was uncompressed and very very long. Why I decided to sample a song so incredibly long, repetitive and minimal is beyond me. I think I just really liked it at the time.
Having a computer with such awesome graphical capabilities (1MB of video RAM!) inspired me to buy a few games for the first time in years, and the only ones I can still remember are the original Prince of Persia and Well-tris, a 3d take on Tetris. About the same time I think I got hold of Wolfenstein 3D, which rekindled my interest in 3D graphics, specifically with regard to texture-mapping, a technique that was rather new in the world of realtime graphics. I spent some small amount of time trying to do stuff in QuickBasic but quickly decided it was time to revisit assembler language, only this time it would be for x86 rather than Z80 processors. For this I used the totally awesome A86 by Eric Isaacson, which has the distinction of being the first (and one of the few) pieces of shareware I ever paid for.
I then bought a book called 3D Computer Animation by John Vince, which I still have (it being one of the few books I can’t bring myself to give away) and started teaching myself 3D all over again, having forgotten most of what I had painstakingly worked out through trial and error several years earlier.
x86 Coders of my generation will know that there was a distinct disadvantage to programming for the 286 (vs the 386DX or 486), and that was the absence of a maths coprocessor. What this meant is that if you coded in assembly you did not get any floating-point functionality (ie support numbers arbitrarily large or small), nor did you even have full 32-bit integer support, so your work was really cut out for you if you wanted to create 3D graphics in real-time.
NB: My decision to push ahead with assembler instead of learning C was less a decision and more a complete ignorance on my part. In fact I almost wish I could go back in time and hand myself a book on C programming. The only benefit to learning assembler first is that it gives you a much greater appreciation of C, pointer arithmetic, and the handling of stack based variables.
So given that I was compiling x86 assembler directly to a COM file (not an EXE), I had created some pretty spectacular limitations for myself, but in truth I kind of enjoyed the challenge and set about learning how to recreate floating point math with 16-bit integer code and write my own maths functions like sin() cos() sqrt() etc.
I should point out that by this time I got to this point I had quit my crappy job (which was really quite a bad and low-paying one) and left Sydney, then annoyed my girlfriend by living with her in Bathurst for a while, then driven my crappy old car up north to visit my parents– at which point I totally ran out of money and so opted to move back in with them for a while, as young people with no money are wont to do. Being back in my home town with no distractions (like things I wanted to do or people I wanted to see) meant that I had lots and lots of time to teach myself maths and programming stuff (and remember this is 1992, before anyone outside a university had really even heard of the internet, so no distractions there either).
I worked on flat-shaded polygon graphics, having been inspired by memories of the old flight sim games on the Amiga and of the appearance of Virtua Racing in the arcades, and was pleased to get some pretty smooth motion out of it (speed was the one obvious advantage of working in assembler in those days). I remember zooming through canyons of brightly colored triangle meshes and trying to explain to my parents why it was so goddamn awesome. Questions of “what is it supposed to be?”, “what is it for?” and “Will this help you get a job?” annoyed me slightly, but I was so wrapped up in the technical purity of what I was doing I didn’t care.
Having mastered flat shading (IMHO) I set about working out how to do texture mapping (the hot new thing!), and for a while my efforts consisted of an ugly 256 x 256 bitmap of a skull rotating full screen, with reasonable smoothness. Rotating a bitmap was easy enough, and could be done with relative ease using a fairly short amount of assembler, but fitting that bitmap onto an arbitrary shape was a lot more complicated than I expected. And even when I worked that out, I found myself stuck again when I realized that the simple mapping I was using was incapable of creating a true perspective effect (eg drawing road surfaces without massive distortion). The problem was far from trivial and can even be seen as a wonky tearing effect in many driving games on the first generation Playstation.
So rather than making a really nice, fun, flat-shaded game, I decided that my “game” must have texture mapping galore, and that I would have near infinite landscapes to fly over. I set about creating an obscenely complicated system of textures within textures, basically 16 x 16 tiles except instead of pixels each element would be another 16×16 tile, and this could be supported up to four levels deep. As well as colors I wanted to map displacement (ie bumpiness) and implemented a similar block structure for this too, which led me to the codename for the project: TDM, for Texture & Displacement Mapping. In hindsight the recursive block structure truly was the biggest waste of time and effort, because it complicated both the rendering engine and the texture editor immensely, and never really produced visual results better than unusual and abstract… certainly not anything particularly realistic.
By this time I had been receiving unemployment benefits for some time and moved back to Sydney, ending up living in a bedsit where I worked on my trusty 286 out of a wardrobe with the keyboard sitting on a drawer pulled out a bit. I was going a bit mad perhaps. Still working 100% in assembler (on a computer running within MS-DOS) I set about making a GUI to edit my stupid multi-level-texture system, which ended up looking like an early Mac desktop in negative with overlapping windows and scroll bars rendered light on dark. I was able to access higher resolution screen modes (800 x 600) on my 1MB Trident graphics card by using hardware signals unique to that model (ie my software was able to run only on that particular video card, brilliant!). I also remember being quite chuffed that I added a third “scrollbar” to my GUI windows to control zoom level, because more features is always better.
And then I finally worked out how to render a cloudy sky, with perspective correction. I was extremely excited about that, because I had never seen it done in real time for an arbitrary orientation– It had only ever been used for texturing a perfectly flat floor-plane (eg Doom). My method used adaptive scanline subdivision, so depending on the epsilon I set I could either make it perfectly accurate and extremely slow, or good enough and fast enough.
So now I had a weird landscape engine with a texture mapped sky that did nothing in particular and didn’t look particularly real, although at the time I thought it looked kind of cool, and I had no real plan for what to do next.
To be continued…