As stated in the previous post, we’ve recently moved over to the Portal 2 branch of the Source Engine. With it comes a pretty big feature: dynamic water reflections. Now, you may be thinking “but Sam, hasn’t Source had dynamic water reflections since Half-Life 2?”. The answer is yes, it has. The issue is how it deals with rendering said reflection.
Source makes use of a BSP system for deciding which parts of a level should be rendered. The game is given a “potential visibility set” by the map compiler, and this is used to decide what to render and what not to. It’s also used by various parts of the engine when it comes to allocating rendertargets, such as those used by the dynamic water reflections. Herein lies the problem; Valve originally designed Source to work f or Half-Life 2, and Half-Life 2 had no need for levels with more than one height of water in an area at once (in rare exceptions, they used a cheaper water that had no reflection). As such, they never built the engine to allow for multiple heights of water at once (much the same as the engine was never built to allow for more than one monitor scene being rendered at a time). Most mappers didn’t see this as a problem, or worked around it, so everything was fine. And then there was Portal.
Portal has unique challenges when it comes to rendering the scene. When the game decides which water surfaces should or should not be rendered, it doesn’t take in to account other cameras in the scene – typically, func_monitors simply don’t render water, but portals never had this sort of protection added to them. Instead, the game freaks out and will try to render intermittently between the three camera locations – the player, the blue, and the orange portals. Being a fairly small project, the team were unable to rewrite the dynamic water rendering system to allow for multiple camera angles in time for release, and so went with simple lightmapped textures with scrolling normal maps instead (which actually worked better for puzzle cues, allowing light to hit the surface is great for directing the eye toward something).
For Outside Influence, I always wanted to get that dynamic reflection look, but keep the lightmaps that were so good for directing the eye of the player in levels. I spent a long, long while tinkering, and tried many different methods of achieving this. A 2012 test map (bizarrely called “product.bsp”) shows off some of the methods I’d used throughout early development, but most of them hinge upon layering of multiple textures, such as a translucent lightmapped texture above a dynamic reflection. This “layering” technique was used frequently, as modders were unable to add custom shaders to Portal due to the closed-source DLLs. I thought that if I hid the dynamic reflections under enough guff, no one would notice the glitching.
Naturally, the problems with reflections in Portal kept raising their head. These attempts never looked good, and I don’t know how I managed to delude myself into thinking that they did. In 2013 the next, and eventually final, iteration of the water technique, one must look toward the GoldSrc engine era of games. I was replaying Half-Life Blue Shift when I noticed the very snazzy looking laboratory with a reflective floor. Curious, I took a peek underneath to discover the entire room and all visible models had been replicated below a translucent textured surface, flipped to appear as a reflection. This was genius – why write a complicated rendering method for something that’ll only be seen once or twice? Just flip the whole room!
I thought that, given the usually boxy nature of Portal tests, this method might work out for me. I repurposed my translucent lightmapped surface, created a refractive water material to go underneath it, and viola! Pretty convincing looking reflections in Portal, with no rendering issues! There were other issues though – most notable being that you could no longer build rooms anywhere close to underneath water any more, but it was a good compromise. I refined it a few times, tweaking normal maps, tints and particle effects (even adding a series of ripples scattered across the surface of the water). The result is what was seen in the Outside Influence Greenlight trailer, and a previously unreleased video, linked below. Of course, it didn’t reflect physics props, turrets or any non-fixed gameplay element, but I’m still proud of the result given the limitations.
All this work is sorta moot now that I’m working with Portal 2 – water is as easy as creating the brush and slapping the material on it (and creating a custom flowmap, if one wants the pretty flowing effects), but I thought I’d share some insight into some of the weird crap I tried to pull off in the Portal engine at one time or another (and trust me, there’s plenty more weird experiments that I’ll go into sometime).
I hope to show off some stuff more pertinent to the current, and hopefully final, version of the game soon. Until then, take care!