Skip to main content

Gothic 3. Mixed Impressions.

· 5 min read

Today's patient is the Gothic 3 renderer. Problems started right from the beginning. Gothic absolutely refuses to run under PixWin. Some statically linked DLL fails during initialization. I tried debugging it, but unfortunately I don't have enough skill to solve the problem. :) That leaves NVPerfHUD. The developers forgot to remove its support from the code, so no forcing tricks were necessary. However, PerfHUD doesn't export all resources (Gothic crashes frequently), and finding the draw call you're interested in isn't particularly easy.

So there won't be many screenshots today.

Recently I discovered a simple and quick way to determine the quality of a renderer. Just run the game using the debug Direct3D runtime and see where and how it crashes. :) Gothic crashes very quickly. The very first rendered frame is the GUI. As a counter-example, consider Relic's engine (Warhammer 40K: Dawn of War, W40K: Winter Assault, W40K: Dark Crusade, Company of Heroes). I played through a couple of missions in Dark Crusade before I even noticed I was running with the debug runtime. That's a good renderer. :) Sorry, got distracted.

The game was tested on: A64X2 4200+, 2GB RAM, GF7800GT. Graphics settings: High.

FPS ranges between 15 and 20. The first thing that surprises you is the small number of DIP calls. 400–700. Always. Without dynamic shadows it's closer to 300. Everything looks great until you pull out a torch. Then the DIP count jumps to 1200. You immediately thought of omnidirectional shadow maps too, didn't you? Correct, they're there. :) Interestingly enough, FPS only drops by 2–3.

What gets rendered in Gothic, and in what order:

  1. Shadow map from the sun (directional light). Nothing unusual here. A 20-meter square centered around the player is taken, and every object inside it is rendered. PSM, TSM, LiSPSM, and similar techniques are not used. Instead, the NV depth texture hack is used.

  2. If a torch is active, an R32F cubemap is rendered.

  3. Z-only pass. Not everything is rendered, only large objects. Very sensible.

  4. Bounding boxes for HW Occlusion Queries. Again, not all objects participate.

  5. If the Depth of Field effect is enabled, MRT is used. Two render targets:

    • Color (R8G8B8A8)
    • Depth (also R8G8B8A8) Depth is written directly. No float packing into 8-bit channels is performed.
  6. Character rendering. GPU skinning, normal maps, per-pixel point lights (I observed two), directional lights, two shadow maps (from the point light and the sun), a precomputed terrain shadow texture. They even use Spherical Harmonics (don't ask me what those are, I only vaguely understand them myself :) ). I won't show the shaders because they're long and terrifying.

  7. Nearby terrain is rendered in a very similar way. No skinning, but several texture layers blended by a mask. I'd show the textures, but for the reasons mentioned earlier (PIX doesn't work), I wasn't able to extract them. Sorry.

  8. Nearby objects (trees, rocks, grass).

  9. Various distant objects. Huge terrain chunks. SpeedTree trees. Large objects. The shaders here are simple. Usually just fog plus a single texture. The resulting images look roughly like this:

  10. Simple sky.

Post-processing follows.

  1. Downsample the image. A color remap is used to isolate bright regions.

  2. Blur the resulting image once.

  3. Compose the final image. Bloom texture + scene + scene depth. The main image is blurred using a Poisson filter, with the blur radius determined from the depth texture. Not exactly Depth of Field, but something reasonably close.

I almost forgot about the water. I didn't spend much time exploring the game world, but the ocean water is definitely not the kind described by Kurt Pelzer in ShaderX2 - Tips and Tricks. It's fairly simple. I thought that if they were already pushing effect complexity this far, they would go all the way. Although they probably couldn't afford any additional rendering passes at that point. :)

The GUI is good. Not rendered letter by letter. :) Let me digress once more. Now there is a GUI in Supreme Commander Multiplayer Beta! A proper GUI. :) For those unfamiliar with it, it's a real-time strategy game. The entire in-game GUI is rendered using a single draw call. One. Draw. Call. :) Impressive.

Short conclusions.

What I liked: I was impressed by the technical sophistication of the renderer. The draw call reduction optimizations are excellent. They allowed the developers to implement something as exotic as omnidirectional shadows.

What I didn't like: There is a noticeable sense of carelessness. Debug Direct3D runtime. Vertex buffers and index buffers being constantly created at runtime. Overall, I liked the renderer more than I disliked it. Even despite the heavy shaders and the resulting low frame rate.

Update

Found parallax mapping. It's present on the stone square in the starting town. By request, here are more screenshots that help illustrate the geometry batching situation. Nearby grass: Nearby terrain: Distant trees: Rocks: Distant terrain: Inside cities everything is fairly standard. Buildings are split into pieces. Separate objects for benches, lamp posts, fences, and so on.