April 27, 2013

UDK Ocean WIP (2) + shader source

Few days ago I've created ocean shader for UDK based on nVidia Island11 demo. You can find it here:

Not a ready solution - it shouldn't be used for production, but it's a good point to start. I think it's a good idea to share my work with you :)

Download UDK Ocean shader (packages saved with February 2013 UDK).

Brief description
  • Designed for DirectX11 tesselation (flat version for DX9);
  • Opacity with dynamic shadows on ocean surface (can be used with dynamic lighting and has bug-free DOF);
  • Subsurface scattering (SSS) simulation;
  • All the data is generated from one 256x256x32b normal map.

Should be added/fixed for production (shader):
  • Height displacement and normal disturbance fading near the shore;
  • Render targets square resolution support (independent from screen resolution);
  • Z-displacement for reflections is wrong when camera is close to surface;
  • Wind vector/speed dependence (if you need);
  • Skyline tiling issues fix (ripple);
  • Performance optimization, quality switches, etc.

Other improvements to do:
  • Ocean mesh/LOD system;
  • SceneCapture actors and player's FOV should be dynamically related;
  • Disable capture actors when refraction feature isn't used;

It's just a common directions of development, there are a lot ot them more. First of all you should understand what you want to get from ocean. F.e. today I'm using simplified shader to get optimal performance and organic view exactly for my game.


You'll find three files in archive above:
  1. SC_PlayerController.uc - contains Unreal Script code for fake opacity control. You should integrate it into your PC class (you can use my class for tests also);
  2. SC_OceanTest.upk - shader resources, materials, etc.;
  3. SC_Island11.udk - test mapl
There are four key actors on map:

1. Ocean surface mesh. You must set two options for it:
  • Object tag is "MyBelovedOcean";
  • "Only owner can see" is on;
2-3. Render targets for scene depth ("DepthTrickster" tag) and scene color ("ColorTrickster" tag) capturing. FOV must be the same as used for player.

4. Reflection capture actor. Simple one, but important. No special tags required.

Main idea of "opaque material with opacity" is to use scene capture actors to get scene depth and color behind surface from scene "without ocean". 

We've made ocean mesh visible only for owner, and capture actors don't see it. Position and rotation of these actors are synced with player controller's position and rotation, FOV is the same, so we can easily make projection of render targets to screen space. Profit :)

Of course, this trick has its limitations and bottlenecks, but it's useful for my game, and I'm happy about it. If you needn't dynamic lighting for your water surface you can always modify material to be truly traslucent.

to FFT or not to FFT?

I know that one of the frequent requests is "how to make FFT Ocean", f.e. like this one. It's really possible to do it with UDK (you should use ScriptedTextures), but:
  1. it'll work only with DirectX11 - tesselation displacement is only one solution for heightmap from texture, even generated on the flow;
  2. FFT passes work relatively slow, 'cause you have to use script buffers, not a solid shader;
  3. You can try to make it faster using sets of pre-calculated FFT data (like in Assasin Creed 3), but you have to use float textures. Their support (.float) in UDK is something from Hell.
I want to say that FFT algorythm is not useful for in-game ocean with UDK. It's better to use Gerstner-based solutions. But for portfolio demos it would be a great thing. It looks pretty cool.


There are a lot of different approaches for ocean simulation in games. This shader is just only one of them. Hope you'll find it useful, and you're free to use it as you want.

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.