Unreal engine Direct3D 10 renderer
Epic, Human Head and Ion Storm were kind enough to release headers/libraries with which to create C++ mods for their games. These code releases included the code for the default OpenGL and Direct3D 6/7 renderers and the files these need to include/link against to compile (each game's renderer needs that game's specific support files).
Having those files to work with, building this new renderer was of course possible from the get-go; it was just a matter of implementing one side of the renderer interface (setting state, drawing geometry, texture conversion and cache). Unfortunately messy, badly documented existing renderer code and not having access to the game engine side of the picture meant it required quite some experimenting and reverse engineering. On top of that, the standard renderers have their share of glitches, as do the games themselves (over agressive BSP, Deus Ex being rather buggy altogether) which might or might not have been apparent on Glide cards back in the day. Anyhow, here's the source code which might or might not be helpful to you.
The source code includes:
- Visual Studio 2008 solution that builds for the supported games.
- Documentation on how the solution's laid out and the build targets work.
- Documentation which describes not just the D3D10 part, but also the Unreal renderer interface.
Debugging in Visual Studio doesn't work with Steam executables by the way.
Source downloads If you're interested in how Unreal renderers work, for example to make your own, I recommend looking at the code of version 17. Later versions are much more complicated due to their use of multiple shaders and post processing.
As noted, to build the renderer for the various games, their headers and libraries are required. The following archive contains the necessary files, fixed to work with VS2008. The original, complete sources for each game are also included. A seperate download as including it with each source release would be too large; unzip to the solution's directory.
Rendering passes / shaders
External textures allow the games' world textures to be replaced or augmented by external .dds files, which are easier to create than .utx files and can include full alpha information.
First of all, an example: download this file and unzip it to your Deus Ex textures subdirectory. After doing this, start the training area: the brick texture will have been replaced by one from the DirectX SDK, and the UNATCO seal will have been replaced with the one from New Vision, with added alpha blended edges. Enabling the renderer's bump mapping and parallax occlusion mapping settings will have a clear effect on the walls.
There are two kinds of external textures: override textures and extra textures. Overrides outright replace a standard texture, this can be a diffuse wall texture, a detail texture, a model's skin, a user interface item, etc. The renderer simply looks for .dds files matching the UnrealEd name of the original, so 'UNATCO.Misc.UNATCOseal_A' will be replaced by 'unatco\misc\unatcoseal_a.dds'.
If an override file is found, the renderer also looks for '[texture filename].flags', for example 'unatcoseal_a.dds.flags'. The Unreal engine blend flags contained in this file are OR-ed with the ones provided by the game. The main use of this is to enable alpha blending (flag 0x00001000). This way, previously masked (i.e. 1-bit alpha) textures can use a real alpha channel, for nicer looking edges. Alpha to Coverage AA, when enabled, has a similar effect, but doesn't look quite as good and can lead to glitches in textures not designed for this. It's a better solution to just create textures with a nice looking alpha channel. Of course, DXT3 or 5 compression is recommended in this case, DXT1 is unsuitable. The following picture, while not using a great example texture, shows the difference:
Extra textures are looked for once an override file is found (i.e. they can not be used without a diffuse override). Again, they are found by filename, using a suffix. A detail texture, for example, will be called 'unatcoseal_a.detail.dds'. They don't require an analogous texture to be present in the game files; for example a detail texture can be offered for a material that does not have one set in UnrealEd. Extra textures use the texture coordinates of their parent diffuse texture. They should only be provided for diffuse textures: for example providing a bump map texture for one of the original detail textures just wastes memory and disk space. Currently supported are:
- Detail textures. Suffix: detail. Supported for: world geometry. Detail textures similar to the ones that come with the games. Should be grayscale.
- Bump maps. Suffix: bump. Supported for: world geometry and models. RGB should contain a normal map. Note that due to a lack of true per-pixel lighting bump mapping might look different than expected. A fixed light direction of (1,1,1) is used for the bump mapping calculations.
- Height maps. Suffix: height. Supported for: world geometry. Used for parallax occlusion mapping (if not present the detail texture is used). Should be grayscale, only the R channel is used.
Mipmap levels: it's wise to include pre-generated mip levels in the .dds file, although they will be generated by Direct3D otherwise. Only the largest mip level of detail and height map textures is used, as such it's a waste to include mips for these.
View to world transform (for my own reference)
D3DXMATRIX trans; D3DXVECTOR3 pos(Frame->Uncoords.Origin.X,Frame->Uncoords.Origin.Y,Frame->Uncoords.Origin.Z); D3DXVECTOR3 at(Frame->Uncoords.XAxis.X,Frame->Uncoords.XAxis.Y,Frame->Uncoords.XAxis.Z); at+=pos; D3DXVECTOR3 up(Frame->Uncoords.ZAxis.X,Frame->Uncoords.ZAxis.Y,Frame->Uncoords.ZAxis.Z); D3DXMatrixLookAtRH(&trans,&pos,&at,&up); D3DXVECTOR3 point(Poly->Pts[i]->Point.X,Poly->Pts[i]->Point.Y,Poly->Pts[i]->Point.Z); D3DXVECTOR4 out; D3DXVec3Transform(&out,&point,&trans);