About/News  ReadMe  Download  Screenshots  Tech Notes  Email  Discord  icculus Valid CSS!

Tech Notes

These are notes about the technology in DarkPlaces engine, not really a blog, more a spillage of techniques and ideas that may be of interest to engine programmers, and may also answer some questions about how the engine works for those who are interested.

Rendering Process - DarkPlaces walks the scene in multiple different ways each time it renders (rather than using a SceneGraph - read Tom Forsyth's article Scene Graphs - just say no for a good explanation of why they are undesirable).

The basic flow is:

Culling methods

Surface rendering tricks

All geometry in each model is merged into one set of vertex arrays (non-interleaved) and uploaded in a Vertex Buffer Object, this minimizes state changes during the rendering of the world model, as surfaces are simply ranges of triangles to render, additionally multiple consecutive surfaces with the same texture are rendered with a single call (since their triangle range can be combined easily), this substantially reduces driver overhead in higher poly scenes.

Additionally, any texture scrolling effects requested by a Quake3 shader file are usually performed using glMatrixMode(GL_TEXTURE), rather than being done manually on the cpu as Quake3 did, other Quake3 shader effects remain cpu-based however (but are infrequently used - things like wavey water surfaces, and autosprite billboards).

Skeletal model rendering tricks

There are two different approaches to skeletal animation used in skeletal model file formats, one is based on each vertex storing an array of weights with vertex positions relative to the bone the weight references (this method is used by zym, dpm, and assorted id Software formats such as md4, mds, md5mesh), this method consumes more memory (and seems to be slightly slower) than Matrix Palette Skinning in which the base mesh is deformed by matrices multiplied by their basepose inverse (meaning all the weights take the same vertex position as input, and simply move it to where it should be), since Matrix Palette Skinning performs better, DarkPlaces engine converts the other type to it at load (which is quite trivial - simply rebuild the base mesh from the weights and basepose of the skeleton, and then only the influence and bone index has to be stored in each weight, discarding the relative position and normal data).

DarkPlaces engine model loaders encode all skeletal weight data as 8 bytes per vertex (two 4 byte per vertex arrays, one storing the influence values renormalized from 0 to 1, to 0 to 255, and the other stores bone indices since most models don't have more than 256 bones), this seems to help with cache performance in the cpu-based skeletal animation.

This format is also mostly suitable for hardware skeletal animation, however harsh limits on number of bones (about 30 on lower end hardware) make it impractical because the model would have to be sliced up and given multiple matrix palettes (each within limits of the hardware) so it has not been implemented (NVIDIA GeForce 6 hardware or ATI Radeon X2x00 series and above are capable of using texture reads in the vertex shader, which would avoid this limitation).

Adding additional complications to the use of hardware skeletal animation, stencil shadow volumes require a software transformed version of the mesh to build triangles from (even if the actual projection of the vertices may be done in hardware - indeed it would have to be, otherwise the skeletal animation may not match up exactly and cause zfighting between a software shadow volume and a hardware lighting pass).

Stencil shadow volume notes

First I would like to dispel a common rumor about stencil shadow volumes requiring specially made models - this is false, as long as the shadow volume is constructed from only lit or only dark faces of the model (meaning triangles duplicated, flipped, and stretched out to the protection distance), there is no need for sealed models, I do not see any particular benefit from other methods (building a volume from both front and back faces, stretched differently) - but if someone wishes to enlighten me on benefits of this approach I welcome the feedback.

Secondly on the subject of edge lists (also commonly used for possibly erroneous reasons) I highly recommend using a "triangle neighbors" array instead - each edge of a triangle can store an index to the neighboring triangle that shares the edge, or -1 if there is no neighbor (or if the edge is shared by 3 or more triangles - yes this does happen on a few models, it must be handled by storing -1), this format is very simple to understand and very practical, in particular you can get better performance by scanning edges of caster triangles than by scanning a separate edgelist (which may have many edges entirely in the non-casting regions of the model).

The DarkPlaces shadow volume builder operates in a multi-stage process:

Collision detection method

To be written.

DP7 network protocol concepts

To be written.


Email me (details on the email page) if you have ideas for additional sections or questions about other technical details missing on this page.