Odds and ends

I’ve been getting back into the swing of things with a set of smaller changes and improvements. I haven’t yet started work on the major focus of the 2.1 release, which is planned to be Multiplayer improvements.

2.0.2 will be out on Saturday, July 1st, with a couple of bugfixes that I hope will be useful. As usual, I will post the details after the build is available.

The recent changes include:

  • Stability improvements. Several methods that went against the C++ standard were revised. Reliance on undefined behavior was leading to compiler optimization issues particularly with the latest GCC 7. Also, error reporting is now more robust. For instance, previously when something went wrong during busy mode (like engine startup), it could easily lead to a crash because the client app wasn’t reacting to the situation appropriately. When the error message was being shown, the application was still trying to do something in the background.
  • More powerful model scripting. Starting animations and timeline scripts via Doomsday Script.
  • The model renderer shaders support more macros for easier customizability. Generally speaking, using macros is more future-proof than writing completely customized shaders.
  • Resource identification fixes. There was a duplicate IWAD spec for Heretic 1.3 vs. SOSR. Now only the latter remains; if you have problems with your Heretic IWADs, Clear Cache and restart Doomsday. Also, autogenerated package IDs had a problem with special characters in file names. Doomsday will choose package IDs based on the file name of the data file, however it allowed spaces and quotes be included in the IDs. This lead to problems because whitespace characters are used as separators in lists of IDs, and quotes may not be accurately escaped in Info strings. Again, Clear Cache is recommended.
  • Assimp build option. There’s a new CMake build option (DENG_ASSIMP_EMBEDDED) for disabling the use of Doomsday’s customized version of Assimp. This allows one to configure Doomsday to use the Assimp installed as a system library, which is more common on Linux for instance.
  • More UI tweaks. Plenty of small things:
    • Minor dialog layout improvements to avoid awkward dimensions.
    • Changed the UI font on Windows.
    • Added popup outlines for visual clarity.
    • Fixed Home tab scrolling with the mouse wheel so that it doesn’t always jump to the previously selected item when switching between tabs.
    • Game icons are refreshed when package availability changes. No more missing and incorrect icons shown for game profiles.
    • Fixed missing window fullscreen state notification (was affecting the appearance of the “Quit” button on Mac).
  • Monitor refresh rate. Yesterday I started working on monitor refresh rate configuration options. I realized these have been completely missing from the settings for some time now. Doomsday does query the supported display modes, which includes information about refresh rates, so now you have the option of choosing which refresh rate Doomsday will prefer when switching modes on Windows/Linux (display mode changes are not done at all on macOS). However, I recommend you consider adjusting the game pixel density instead of the screen resolution to keep the UI sharp and crispy.

Doomsday 2.0 released

The first stable build of Doomsday 2.0 is now available.

The highlighted features of 2.0 are:

  • Home Screen replaces the frontend app. A launcher is no longer needed; games and add-ons can be managed using Doomsday itself.
  • Built-in support for different data file and package formats. Used packages are tracked in saved games and multiplayer games.
  • The new 3D model renderer that has been in development since the 1.15 release is now mature enough for use. It supports FBX and MD5 models, skeletal animation, GLSL shaders, and scripting.
  • This is the first 64-bit stable release for Windows.

See the Manual for the complete release notes.

Thanks to everyone who reported bugs in the release candidates! A number of nasty bugs were found and fixed. There is still a few less serious known issues that have been scheduled for next month’s 2.0.1 update.

Work on the 2.x series will now continue along the lines planned in the roadmap, with the first focus area being multiplayer improvements. Under the hood, there is still lots to do with updating remaining old OpenGL rendering code so we can take full advantage of shaders in future releases.

Holiday update

As usual December has been a busy time, but a little bit of progress has been happening with Doomsday, too.

Saving 3D model state. I’ve put the most effort into ensuring that the state of 3D model animations gets saved and restored when writing and reading savegames. This has no bearing on gameplay as such, but visually it is pretty important that the objects get rendered the same way before and after loading a save. In practice, this was quite challenging because the new model renderer supports advanced features like multiple animation sequences, scripted rendering passes, and shader variables. All this state information gets included in the savegame package as a new file, so it can also be gracefully ignored in case any compatibility issues or other problems arise when dealing with old save files.

Multiplayer resource check. When joining a multiplayer game, the client checks that the same packages are loaded as on the server. This includes all WADs, DEHs, and PK3s. Any resource mismatches could lead to crashes or other problems during MP games.

Mac menu. I did a small tweak for the Mac UI: Doomsday now has a native menu bar for switching between the available games.

Fate. Finally, I’d like to call attention to a cool Hexen mod by fate that I recently enjoyed playing through. If like me you are a fan of Hexen, this is a nice way to spend a few hours during your holidays: fate_v0.1.pk3. Please leave your feedback and/or comments to the author on the forums.

Merry Christmas and happy holidays everyone! *<:)

3D model editor

The final week of 2015 turned out to be quite prolific.

There was a new stable build on Friday: 1.15.7.

I made a little bit of progress with animating player weapons by introducing the vanilla-style walk bobbing for the new model renderer. The final missing detail now is to improve how the weapon is positioned, so that FOV and viewport size changes don’t so easily move the weapon out of view. This has always been a bit of a problem with the old model renderer, so doing it better this time around is important.

I continued last week’s work on reflections by incorporating cubemaps to each of the default shaders. Cubemaps can now be put in packages and loaded as assets: there is a new asset type for environment cubemaps (texture.reflect).

It turned out part of the confusion last week was due to some mistakes I had made earlier in how light directions were being passed to and calculated in the shaders. This was causing artifacts such as specular highlights in the wrong places on the model. While fixing the shaders, I also managed to streamline them a little and remove excessive texture lookups.

Overall, we are now getting closer to calling the shaders feature complete. The next step is to apply some final adjustments so that lighting on 3D models will appear natural yet distinctive. However, a big part of making models look good is tuning all the shader and material parameters correctly for each model asset. It is quite challenging to do this if one only has a text file and the appropriate values have to be found via trial and error. Therefore, I added a new editor sidebar for making adjustments to 3D models. I got a nice head start on this by reusing a bunch of code from the Renderer Appearance editor.

The model asset editor should provide all the tools for perfecting how a 3D model appears in Doomsday. It shows basic information about the model file and allows interactively adjusting shader variables, enabling and disabling rendering passes, changing materials, and trying out animations. The editor will not write definition files, though, it just allows finding the best parameters. This is partly because the definitions may incorporate Doomsday Script, and partly to ensure that one can’t accidentally mess up the parameters of a model.

Reflections

This week’s festive screenshot shows a bunch of test models that I’ve been using for developing environment mapping for 3D model reflections. While the current map renderer is not efficient enough for rendering cube maps on the fly, 3D models will be able to benefit from manually prepared cube maps.

This has been an interesting implementation challenge. It turned out the code I had previously written for transforming objects was not quite compatible with how cube maps needed to be rendered. I thought I was being clever by setting up player weapon models directly in view space, since they are affixed to the camera. For a while I was getting confused by all the different transformations needed for moving between tangent, model, world, and view space coordinates (cube maps are defined in world space). Models already in view space needed to be handled differently than objects in world space.

Eventually I decided to scrap that approach and wrote some new code that positions all models in world space, so their lighting and reflections can be done in the same way. This was much easier to get working correctly. K.I.S.S. wins again!

I’ve also been making some bug fixes for the upcoming 1.15.7 patch. Noteworthy fixes include support for Freedoom’s FreeDM multiplayer IWAD as a recognized game, and correct handling of command line options in the Shell app. The same fixes are already available in the 2.0 unstable builds.

Wand update and custom shaders

This week’s screenshot shows a work-in-progress version of veirdo’s beautiful new Sapphire Wand model for Hexen. It takes advantage of the new model rendering features such as random alternative animation sequences, animated shader variables, and custom GL parameters for drawing layered effects.

On the topic of weapon models, the new renderer still lacks the vanilla-style walk bobbing. That shouldn’t be a lot of work to implement, though. After some additional weapon position fine-tuning this should be ready for prime time, and we can start preparing some models for distribution and use with the 2.0 builds.

As planned, last week I was working on a better way to load shaders from packages. I managed to complete the improved functionality as planned: when any package is loaded, it is checked for shader definitions; if found, the shaders are added to the runtime shader bank. Similarly when a package is unloaded, its shaders are removed from the the shader bank. Now there is no longer any special case logic needed for the net.dengine.client packages, as their shaders are loaded the same way as shaders from any other package.

I then proceeded to add a way to customize shaders using macros. Like C, GLSL allows defining macros for the preprocessor. This enables injecting custom code at compile time. For example, let’s say a model wants to continuously scroll its texture. This could be done using Doomsday Script, however one would need to keep restarting the script at regular intervals to keep the animation going — not the most efficient way to do things if you have a lot of objects using the model. However, if the model injects a line of code into the model shader for modifying its UV coordinates on every frame, all the work is done cheaply by the GPU. And even better, if the shader is later updated (for example when the user installs a new version of the engine), the model has a much better chance of continuing to work correctly.

Click the screenshot below for a short animation:

UV scrolling shader

Naturally model packages can also provide their completely custom shaders that do not depend on the net.dengine.client shaders in any way.

I was also briefly obsessed with improving the formatting of log entries. There is something about formatting text that manages to hook me every time. The most visible changes are that the so-called “log sections” that contain contextual information about where a log entry was created are now placed within square brackets. This should improve readability. In the doomsday.out/runtime debug output, the content now uses better alignment to visually indicate which entries belong together.

#1815 200.594 I  (v) [BindContext] 'global' cleared
#1815 200.594 I  (v)               'deui' cleared
#1815 200.594 I  (v)               'console' cleared
#1815 200.594 I  (v)               'message' cleared
#1815 200.594 I  (v)               'chat' cleared

Miscellany

Last week I was working on various odds and ends. It has been a nice change of pace after a few weeks of focusing only on the new model renderer.

That’s not to say I didn’t do anything model related. I made several minor improvements:

  • The model definition can specify an offset to apply to the object origin (worldOffset).
  • Special built-in shader variables are made available for model rendering, for instance uMapTime that stores the time since the start of the map. This is useful for continous material animations.
  • Fixed a bug that caused lighting to be incorrect on scaled models.
  • Autoscaling is no longer enabled by default. The assumption is that the model author has sized the model as intended. Enabling autoscaling will make Doomsday match the height of the model with the height of the thing’s bounding box.

On the Linux front, I upgraded my Fedora installation to 23 and was quite impressed with how it’s coming along. A few test builds showed that our CMake configuration wasn’t working quite right with the newest CMake versions (failed to enable C++11). Another issue that needed addressing was the incorrect linking of the FluidSynth plugin — it was causing a crash at startup.

I have decided to disable Oculus Rift support in the distribution packages. We haven’t updated Doomsday’s Oculus Rift code since LibOVR 0.5, so it has become incompatible with the current Oculus SDK. I think the wisest course of action is to revamp the code after Oculus releases the official 1.0 SDK. I have to say, though, that I am currently not planning to upgrade my Windows PC to be compatible with the Oculus Rift system requirements. It may take until a later time when Oculus Rift support is fully restored. (One can of course use the older builds with the older Oculus SDK versions.)

I also did a small fix on the dengine.net Forums: our phpBB style template was a bit broken and it wasn’t showing the attachment and poll creation options.

We have been releasing patch builds for the stable release on the first of every month. This means 1.15.6 is coming on Tuesday with a fixed OS X build, removed Oculus Rift support, and some source cleanup.