Latest Demo – September 2018

 

 

 

It’s been a while between drinks, but here’s a link to the latest engine demo:

Lamorna Demo 3.9.18

[For 64 bit modern versions of Windows]

Grab those pick ups and shoot the Shamblers! Just a short demo here, and it’s a bit rough around the edges, but it’s all handmade, the engine runs my custom software renderer, dynamic lightmaps, and a basic entity-component system.  I made the map up in Modo, and as you can tell I’m no level designer. The demo uses a number of assets from the impressive Quake I mod ‘Arcane Dimensions’, big thanks to the team for making those available to the community, check out the Readme included with the demo. Grab the mod from here http://www.simonoc.com/pages/design/sp/ad.htm . The demo is share ware so please share away!

About Me

Hi my name’s Trevor, and my bio is not what you might expect. I’m a former health professional turned self taught game developer. Over the last few years I’ve created a lite 3D game engine from scratch as a learning exercise. The engine features a robust software renderer, collision and sound system, with game logic powered by a simple entity-component system. In addition the engine features a dynamic lightmap scheme, where world surfaces have low resolution lightmaps which accumulate colour for a neat real time painting effect. The work for each frame is characterised as a series of jobs and fed into a custom thread pool, and the performance critical sections of the engine are highly parallelised. The engine makes heavy use of SIMD to improve performance.

I’ve spent my adult life thus far working as a pharmacist, alongside a team of health professionals in a busy store. I found working in health care dissatisfying, but for better or worse stuck with it for some 15 years. As a panacea I taught myself to program in my spare time, and then began to learn about graphics and game development. I’ve always loved gaming and being fascinated by the process of creating virtual worlds through code, decided create rather than consume!. I remember getting a basic scene drawn with OpenGl after a few weeks and feeling quite dissatisfied. All I’d done was stitch some function calls together. I decided I wanted to learn how to do it all myself, right down to the pixel level. Not sure how well advised that decision was looking back but here I am with a software renderer, and a strong grasp on the tenets of low level graphical operations. The most thrilling part of this has been learning how to invoke moving images from lines of arcane script. I love the technical challenge, problem solving and iteration are deeply satisfying, these are the things my work in health care lacked.

I hold a Bachelor of Pharmacy from the University of Queensland, Australia. I understand this has little relevance in the game industry, and my employment prospects are predicated on the skills I hope are inherent in the game demo, however it shows I am academically inclined and able to apply myself. My work has soley been in health care, but it’s not entirely irrelevant. It means I’ve been in the workforce some time, part of a small team of professionals in a busy health care environment, and am used to hard work, responsibility, working alongside superiors, peers, and maintaining professional decorum with staff and patients alike. I’d like to think I’m a friendly and interesting person, I’ve lived in the UK, Australia and New Zealand, and am well travelled. I hold a British and an Australian passport. I’m in my early 40’s, however I like to think I still look and think young, seasoned with the wisdom and consideration that a few years on this earth brings. 

The engine was created using Visual Studio. I use Intel VTune & Very Sleepy for profiling, Cppcheck for linting. I tend to write conservative, data oriented code, and keep it as simple as possible with structs and arrays.

Skillset:

C++, Visual Studio, multi-threading, SIMD. I’ve  done some JIT work that made me familiar with assembly and basic compiler theory. 

Please visit the engine on Github: https://github.com/Lamorna/engine

Please follow me on social media: @lamorna_engine, @trevor_nagel

Latest Demo – April 2018

 

 

 

 

 

Download Lamorna Engine Tech Demo April 2018

[For 64 bit modern versions of Windows]

The last 6 months I’ve had my head down working to bring the engine’s systems to a professional level of quality. In the years spent pottering part time on the engine I found it sufficient just to get a system working then move on. Who wants to spend days on end pouring over minutiae when there’s animation and particle effects to work on? There was no compulsion to put in that final 10% to ensure the system was rock solid. As a result the engine’s functionality has been almost there, but not quite. The collision scheme is a good case in point, it worked most of the time but there would be those moments when the player pressed against a wall at a certain speed and angle and fell straight through the floor. This is acceptable in a home brew project, but not in an aspiring commercial product. There’s a saying along the lines of the last 10% is as hard as the preceding 90% and I found that to be true. After some effort the engine is well on it’s way to being a simple yet robust product. Here’s a brief synopsis of changes:

  • An entity-component system. The old entity code, which was a tangled mess, is gone, replaced by my own take on an ECS. So far I’m very happy with it. Components are stored in a common database, entities only exist implicitly, and systems know nothing about entities, only the components they operate on.
  • Rock solid collision scheme. I converted the collision code to use fixed point math, which gave me the precision guarantees I needed. As an added bonus, the approach will allow me to support non-axis aligned surfaces when the time comes. The collision scheme is now threaded.
  • Fixed point representations for absolute positions. For precision purposes I moved all absolute positions to use 16:16 fixed point. This gives me numerical stability guarantees for larger maps going forwards.
  • MIP-mapping. The engine now does per-fragment mip-mapping. I would have implemented it per-pixel but found myself stymied by the gaps in the  SSE 2.0 vector instruction set. A variadic bit shift and bit scan instruction would have made this possible. I’d like a ubiquitous vector complete ISA please!
  • Texture filtering, then not. I experimented with bi- & tri- linear filtering, coupled with texture blending on a number of surfaces. Since the dynamic light maps that power the world ‘painting’ effect are only updated in the topmost MIP, my idea was to smooth the transition out with filtering. It ended up eating too much performance, and I have returned to point sampling on all surfaces, with multi-texture blending available where needed. Since the the light maps are much lower resolution than the screen, it proved faster to generate new MIP hierarchies for updated surfaces each frame than do filtering in the pixel shader.
  • Switch to 64 bit. I bit the bullet and faced down a bunch of errors relating to compiling in 64 bit, in the end it didn’t take long to resolve.
  • General improvements in renderer. I worked the rendering pipeline code over and tidied up a bunch of things.
  • Broad improvements in the sound system.

There are still a host of minor things to do, but the engine has taken a big step forward. The game systems are pretty much where I want them to be, save a few tweaks. Next I move onto a small game project, details to follow!

 

Changes in perpuity

The next month or so will be spent reviewing the engine’s systems methodically and refreshing them. Some sections of the code haven’t been revisited in quite a while, and this is an opportunity to survey and update if needed. I won’t be doing any major reworking. So far I’ve covered the Windows, threading and sound code. I want to write about a few things I encountered.

Windows

As I began to rework the Windows code I realised I wanted the following:

  • ability to limit platform specific #includes such as’windows.h to a single source file so they are not ‘seen’ all over the project.
  • ability to hide data structures pertaining to platform specific code from the rest of the code base.
  • no globals, declare all in main() and pass down.
  • particularly a way to avoid globals in WinProc

Didn’t take me long to discover I couldn’t have them all. Data hiding means local globals. Declaring everything in main() overloads the stack frame pretty quickly! No way of avoiding globals in WinProc.  I made some headway wrapping Windows API calls for things like the performance counters, D3D calls, but ran into the need for persistent Window API objects like handles. To limit the scope of those in the project i thought about using a data hiding approach like PIMPL, but I could see the obfuscation getting messy quickly. Data hiding is easy enough with private vars, but I don’t like to use member functions. In the end I decided that I couldn’t fight the limitations of the language and embraced the #include panoply that is C/C++, declared global objects but passed them in at as high a function level as possible, and will worry about platform agnostic code another time.

When the engine window has the focus the cursor is hidden, clipped to the window and wrapped around when it hits the edges for seamless mouse look. I made sure the cursor is restored properly when the window loses focus.

Threading

I’ve rolled my own thread pool for the engine and there wasn’t a great deal needing addressing there, except for two glaring things:

  • to wake the main thread after the thread pool finished a job batch I was using events bound to each job! Not particularly robust. I replaced this with a single event which is triggered by the last worker thread to sleep after finishing, where a bit mask set in the shared critical section indicates thread activity.
  • lack of proper shutdown. The main thread now waits for the worker threads to exit in an orderly manner before itself quitting.

Sound

The sound system is one of the most recent additions to the engine and could really be considered gen 1, in that it hasn’t been revisited since being first written. As such there was a fair bit to tidy, and still more left to do:

  • more robust .wav loading. Rather than use strict offsets into the file, I fixed the loader to search for the unique keywords that head each section, ‘RIFF’, ‘FMT’ etc.
  • more rigorous understanding: revisiting the sound system meant reinforcing a number of processes I’d only just grasped the first time I wrote it, and I was able to strip away a fair bit of cruft and bring some clarity to the code
  • fudging attenuation: my first pass attempt at spatial sound and distance fall off come at with half understood theories and some magic numbers that sounded right. This time I set up a proper mapping with a near and far plane for distance, max and min volumes for the stereo channels mapped to the orientation of the player, and an inverse square fall off.
  • real time decompression: the .wav files I am using are all 8 bit UINT PCM format, and I was converting them to reals at load time, as I run a float32 secondary buffer. This now done at runtime, samples are converted, attenuated by the channel volumes, interleaved into frames and mixed into the main buffer, all using vector instructions.
  • improved active sound list: part of the sound system’s job is maintaining a dynamic list of sounds currently needing playing. Triggered sounds are added, finished sounds removed. I replaced the existing clunky playlist structure with an ‘indexed linked list’ , patent pending :). This is my take on a linked list but using indices, not pointers.

Future work: Honestly I’m still not 100% clear on the best way to implement a streaming buffer for sound. I’m mixing all sounds in my own buffer and copying that down into the DirectSound secondary buffer each frame, which seems straight forward enough, but there’s a few wrinkles. DirectSound provides a write cursor beyond which it is safe to write to after locking the buffer, but how much to write? I tried tracking the amount the play cursor had consummed in the previous frame and writing that, but it’s sometimes not enough. My solution was to write ahead of the write cursor somewhat, so there’s a lag of about 60ms in the sound delivery, which is not noticeable, and appears to work well, but still doesn’t seem like an ideal solution. An improvement on that, which I will be implementing in the future, is to write from the write cursor but oversupply by an amount, perhaps 2-2.5 x an average frame’s worth. Then next frame write from the new write cursor position, overwriting some of the last write, but at least leaving a reasonable play buffer for longer frames. Always stuff to do!

Logo

If you do nothing else on this page, you need to check out the amazing logo designed by the inimitable Tim Begent (@tim_begent). It’s a stylised cross section of the engine of the steamship S.S. Great Britain. I saw blueprints of the engine on the internet and loved the simplicity, power and symmetry. May the game engine live up to Brunel’s!

Prepping the demo

An important part of my pitch to potential viewers is that I have a working demo that they can download and play straight away. Since I have no industry experience I need something tangible to establish credibility. Thus the first few weeks of full time work here in NZ have been spent preparing the demo, which you can download below.

Here are some issues I encountered:

  • avoid file dependency issues by static compilation. I want to ship the game as an .exe, as an installation process is surely a barrier to casual uptake, but you run into version issues with dependant files on different Windows installations. Static compilation includes the files in the build at the cost of blowing the size of the .exe out. Going forward I need to par back file dependencies.
  • back buffer allocation error: I was allocating the size of the DirectX back buffer without allowing for the dead space created by the window’s borders and header. The back buffer was smaller than expected, and was being overflowed each write. A call to AdjustWindowsRect() fixed that.
  • better handling of cursor clipping: I improved the code to keep the cursor within the bounds of the window for a smooth mouse look.
  • VM’s for Windows testing: a virtual machine would have been ideal for testing game compatibility across multiple versions of Windows, except they have limited and buggy support for DirectX. Despite running a software renderer I need DirectX to attach a drawing surface to the game window, which I write to each frame. So I went with a ‘Windows to Go’ approach, basically windows installed on a USB device like it was an internal HDD.
  • not distributing copyrighted game assets. I’ve been using assets from the game Quake 1 in the engine for a while now, as they are sufficiently low res and the file formats well documented. I couldn’t include these in a demo distribution though, so had to source alternatives. I ended up using assets from a modern shareware mod for Quake, Alternative Dimensions, so a big thanks to that team for making those free to use for non-commercial purposes.

 

About Me

I am a self taught game programmer. What I lack in formal training however I feel that I make up in passion. I have worked for most of my life as a health professional, but had always been fascinated by games and how they were made. A few years ago I decided to not just play games, but learn how to make them. So began a journey which is only now beginning to gain pace.

I decided early on I wanted to learn it all right down to the pixels, hence the software renderer. I’m certainly no academic, and have had to  sweat long and hard over the math and methods. However there is something deeply satisfying about creating a virtual world from pages of code, much like a vision summoned from some runic script!

I use Visual Studio and write in C++, though I use so few of the features of that language it may as well be C. I like to keep things simple, just structs, arrays and a basket of enums. My debugging is mostly printf, and while it’s worked fine over the years that is one of the things I’d really like to get more rigorous with.

If you want to follow a layman whose had to figure it out the hard way I’m your man!

About Lamorna Engine

Lamorna engine is intended to run low fidelity games for the PC. At it’s heart is a software renderer that motors a moderate scene along quite nicely. This features a triangle binner, hierarchical rasteriser and an index buffer for zero overdraw in the shaders. As this is software rendering there is no theoretical limit on shader complexity, but at this stage the engine manages bilinear filtering on all textures, and texture blending on some model surfaces. The engine relies heavily on SSE2 vectorisation and multi-threading. It has a spatial sound system, and a basic collision scheme that is limited to axis aligned surfaces.

The engine is reasonably well formed at this stage, with the rendering system being the most mature, having received a lot of attention over the last few years, and the sound system being the most recent. There is plenty of room for improvement both in performance and implementation in all engine systems, and I’m looking forward to exploring that over the coming months.

My goals for the engine are quite modest. I’d like a lightweight game engine with sufficient performance to run something of Quake 2/3 complexity without video acceleration. I want as low a barrier to play as possible, so a bunch of data files accompanying an .exe, no installation process.

Welcome

Hi, I’m Trevor Nagel, creator of Lamorna Engine, a handmade game engine designed to power ‘lo-fi’ 3D games and featuring a robust software renderer.

The engine has been developed as a hobby over several years, something I’ve quietly worked on when I have the time, but all that has changed!

I’ve just left a career in health care to work full time on improving the engine and produce simple, fun 3D games for the PC. I’m entirely self taught. Formerly from Brisbane, Australia, I now reside in Tauranga, New Zealand.

I’m not a professional game developer, and have no experience in the industry. However I am passionate about game programming, and have released a game demo to show I know what I am doing! There is still so much to learn, and I am excited about improving the engine, becoming a better programmer & building game play elements.

I’d like to share this process with folk. To that end I’m intending to post regular updates here, make introductory videos on the various game systems, and work up into live streaming. I’ll have a presence on a range of social media. If you have an interest in game development, software rendering or programming in general I’d love you to follow my efforts.

Please download the demo and stay tuned for further updates!