Getting Water Right in Unreal Engine (While Also Being the IT Department)

I'm Kirby Cooper, and on any given day at Monster Gaming I might be debugging a water shader, configuring a CI/CD pipeline, or explaining to our AI fleet why the build broke. Welcome to startup life, where your job title is "yes."

This week, I'm trying to get water working in Unreal Engine 5.7. Not "working" as in it renders — it renders fine. "Working" as in it looks like water that a player would believe exists in a world they want to spend time in. There's a difference, and that difference is about 40 hours of shader tweaking.

The Water Problem

Water in games is one of those things players never notice when it's right and immediately notice when it's wrong. The uncanny valley of fluid dynamics. Your brain has seen so much real water in its life that it has extremely specific expectations about how light should scatter through it, how waves should propagate, how the surface should respond to objects passing through it.

Unreal gives you a water system. It's good. It's also the starting line, not the finish line.

What I'm working on right now:

  • Caustics that don't look like a screensaver. The default caustic patterns tile visibly after about 20 meters. Our levels have lakes. You can see 200 meters of shoreline. That means the same little light pattern repeating ten times in a row. Nobody wants to swim in a lake that's clearly made of copy-pasted light.
  • Shore interaction that doesn't clip. Where water meets land is where the illusion lives or dies. Get the foam right, get the transparency falloff right, and the player believes. Get it wrong and it looks like someone drew a blue line on the ground.
  • Performance on console hardware. Our water looks gorgeous on a 4090. It needs to look good on a Switch 2. That's a 10x GPU gap. Every shader instruction counts.

Meanwhile, In CI/CD Land

While my water shaders are compiling (Unreal shader compilation: the world's most effective patience trainer), I'm also getting our Horde CI/CD pipeline actually building things.

We run Epic's Horde — their build system for Unreal Engine. Three build agents across our infrastructure: LUXBUILDBOT (Linux), LUXBUILD-2 (Linux), and WINBUILD-1 (Windows). In theory, I push a change, Horde picks it up, distributes the build across agents, and delivers a packaged game.

In practice, I'm currently debugging why the JobDriver DLL isn't loading on the Windows agent. It's always Windows.

The Linux agents are solid. They connected cleanly, they report status, they're ready to build. The Windows agent connected too — then immediately started having opinions about DLL paths and .NET runtime versions. I've spent more time in Windows Event Viewer this week than I have in the Unreal editor, which is not the ratio anyone signed up for.

The Startup Hat Rack

Here's what my Tuesday looked like:

  • 9:00 AM — Review water shader changes from overnight AI-assisted iteration
  • 9:30 AM — Debug Horde agent connectivity on WINBUILD-1
  • 10:00 AM — Perforce merge conflict on a material asset (binary merge conflicts are a special kind of pain)
  • 11:00 AM — Back to water — testing caustic patterns at different sun angles
  • 12:00 PM — Lunch while reading about subsurface scattering optimizations
  • 1:00 PM — Help Jake debug an API key rotation issue on the AI fleet
  • 2:00 PM — Write Horde pool configuration for the Fob1943 pipeline
  • 3:00 PM — Water again — shore foam is broken on the new terrain
  • 4:00 PM — Test Perforce replication to LUXBUILD-2
  • 5:00 PM — Realize the shore foam was broken because I was testing on the wrong map

At a big studio, each of those would be a different person's full-time job. At a startup, it's Tuesday. And honestly? I wouldn't trade it. There's something deeply satisfying about understanding the whole stack — from the GPU shader instructions to the CI/CD pipeline that delivers them to players.

What's Next

The water needs about two more days of work before I'm happy with it. The Horde pipeline needs one good Windows debugging session (I'm bringing snacks — it's going to be a long one). And somewhere in there, I need to review the security configurations that our AI agents are apparently managing now.

That's the thing about startups — the to-do list never gets shorter. It just gets more interesting.


Kirby Cooper is a developer at Monster Gaming, where he works on everything from Unreal Engine rendering to CI/CD infrastructure. He has strong opinions about water shaders and weak opinions about which Linux distro is best (they're all fine).