Sprite Clipping in Strife: Veteran Edition Explained

The intention of this post is to document and share some information on how some of the features in the renderer works for Strife: Veteran Edition. I am hoping that this may be useful for source port authors and programming hobbyists alike.

One of the most common issues seen in OpenGL source ports is that when rendering sprites, they intend to get ‘clipped’ by the surrounding floor/ceiling geometry because of the depth buffer. Since there’s no such thing as a depth buffer in the software renderer, sprites could be drawn on top of anything.

A typical solution would to simply nudge the sprite a few units above the ground. Since most sprites in Doom pokes only a few minor pixels below the ground, which wouldn’t be a problem to adjust them. Strife on the other hand, suffers this problem the most as most of the sprites are clipped halfway through, which looks really ugly and undesirable and nudging them wouldn’t be a good solution.

Below is a example:


OpenGL (Hardware)

My approach is to leverage frame buffer objects (FBOs). Before rendering the walls and floors, I bind the FBO and render all sprites from a single scene into a texture, which is then blended on top of the final scene, allowing them to be drawn on top of the floor. This however exposed another problem: they are now being drawn on top of everything, including walls!


So I had to come up with another way to fix this. I needed to find a way to properly clip the sprites by the walls but still let them draw on top of the floors and ceilings. I decided to take advantage of the depth buffer to accomplish this. So during BSP traversal, I store a list of visible linedefs (not segs) into a draw list. This also includes linedefs facing away from the player’s view. Culling is not accounted for during this step.

Before rendering walls and flats, I bind the FBO and disable color masking and culling and then I render the draw list containing the linedefs (I call this draw list ‘occlusion’ lines). This draws them ONLY into the depth buffer, after which color masking and culling are re-enabled and then sprites can be drawn afterwards. But there’s another problem, since masked/translucent walls are drawn last, the sprites in the FBO are now drawing on top of them. To fix this, I had to also draw the masked/translucent walls after rendering the sprites in the FBO. While this fixed it, it introduced some rendering glitches when viewing masked walls behind translucent geometry. Simply re-drawing the masked walls (after rendering the scene as normal but before blending the FBO) fixes this.

The process in rendering the occlusion lines is like this: when rendering a one-sided occlusion line, the top and bottom z-axis of the vertices (that makes up the geometry to render the wall) is extended into infinity, making sure that we fill the depth information on the screen. For upper/lower sidedefs, the upper z-axis is extended for upper sidedefs while the lower z-axis is extended for lower sidedefs.

However, this introduced yet another problem which, compared to software mode, still doesn’t look right:


So to fix that, we just simply not draw them if the player’s view z axis is higher/above the geometry used to create that occlusion line. Allowing us to finally mimic the way sprites are drawn in software mode:

View Z Axis above the lower sidedef geometry. Occluder is ignored

View Z Axis below the lower sidedef geometry. Occluder is drawn to the depth buffer

This technique is also used for skies as well. Linedefs that’s connected to skies are added to a draw list and are drawn into the depth buffer, with the top portion of the geometry extended into infinity.



That just about covers it. This isn’t the BEST way to do it and it results in A LOT of overdraw but this seems to be the best approach that doesn’t involve shaders or any advanced OpenGL feature. If there’s anything else that you guys might like to have documented or explained, then let me know!

The Mysterious Easter Egg That Never Was

For those who don’t know, Doom 64 was suppose to have a very well-hidden easter egg in the level ‘Breakdown’ that only the developers knew about. It was first mentioned by Doom 64 designer Tim Heydelaar in the Doom 64 developer interview. Unfortunately, this easter egg never existed and only remnants of triggers and unused scripts exist in the map. While these items are still in, they do not do anything and most of the data is disabled/incomplete when the level loads. Even if these triggers were hacked to be initially enabled, they still do not do anything.

As mentioned in the interview, the player had to ‘use’ several walls in a specific order to trigger the hidden message and no ‘oof’ sound is played when the player successfully triggers them.

Below is the overview map of Breakdown. The colored arrows are explained below:


* Yellow Arrows – Walls flagged as ‘secret’ which prevents the player from making the ‘oof’ sound when pressing use on it. Unfortunately any triggers or specials associated with them are removed. Tim claims there’s only 3 of these ‘switches’ that you have to hit but I’ve found more than 3, though he’s correct about one switch in the BFG secret and the other in the red key room.

* Red Arrow – While hidden in the automap, there’s a small inaccessible room that contains several triggers that’s triggered on level start (in Doom 64, a linedef with a tag of 999 is automatically triggered on level load). These triggers call several scripts that never does anything (explained further below).

* Green Arrow – This trigger is inaccessible from the player and is flagged to be triggered by walking over it. Oddly, the script associated with this trigger enables itself.

In addition to this, there are several unused scripted events that’s never referenced anywhere on the map, though some seems to be linked to the script that’s triggered on level load.

* Script #15 – Spawns darts, though none exist in the map. Could be leftover stuff from an earlier revision. It’s assumed that this level used to be a ‘castle’ themed map since there are some unseen castle textures scattered throughout the map.

* Script #16 – Never used anywhere. Enables script #25, which is not present in the map data at all.

* Script #17 – This script is automatically activated on level load. It disables scripts #17, #20, #21, #22, and #23

* Script  #18 – Enables script #18 (weird)

* Script #20 – Not used in map. Enables script #22

* Script #21 – Not used in map. Enables script #23

* Script #22 – Not used in map. Enables script #24, which doesn’t exist in the map data

* Script #23 – Not used in map. Lowers sector floor tagged #27. There is no sector in that map that has this tag. It’s assumed that this is where the ‘secret’ is revealed.

Majority of the scripts listed seems to be responsible for the order in which the switches had to be triggered, but several scripts and a tagged sector is missing in the map’s data so we will never know what this secret was suppose to be.

Status on Version 2.6 and TurokEX Updates

Sorry for the lack of updates; work and obsession with TurokEX has prevented me from making frequent updates to Doom64EX however, version 2.6 will be available sometime this month. Hopefully this version will address the remaining bugs that’s present in version 2.5 and the next releases after that will be focused primarily on features and mod support.

I’ve been spending a large chunk of time invested in getting TurokEX done and just realized just how complicated this project has become, but despite of this, I’ve been making a lot of progress. Some of the latest features I’ve worked on is enhancing the renderer and incorporating some modern rendering features such as motion blur, FXAA, bloom, and light scattering. Hopefully, I’ll figure out how to properly incorporate shadow maps and SSAO as well.

Eventually there will be a new wordpress site dedicated to TurokEX but that will happen as soon as the project matures more.

In the meantime, here are some more progress screenshots of TurokEX: