Water 2.0

I got a request some time ago to make a video showing the water. So I did!


I also took the time to make some additions which we got as requests from the students. The first was to be able to have depth fog, so whenever something is really far away from the water plane, it gets fogged, so as to simulate really deep water.

I also added, per request, a foam effect. The foam works just like the fog, based on a distance and the per-pixel difference in depth, apply either the foam texture or the fog color. The foam is showed in the video as the white outline around the house, which helps with getting a more realistic interaction between the water and other solid objects.

You can also see that the objects beneath the water become more opaque depending on how close to the water surface they are. This also gives it a more realistic effect, since it looks like the water thins out and thus obscures the underlying object less until it hits the water surface.

Currently, the water has two color settings, one for the water color and one for the fog color. The fog color applies to any geometry beneath the water distance based on a distance factor. This is also visible in the video when you see the big island patch being submerged more and more, it turns purple because of the fog color purple, while the water surface however, remains blue.

Oh, and you can also see the fake reflections. I should really implement a way to get real reflections instead of having that screen-space cheat…


Current status

Since the game projects started, we haven’t quite had the time to work on the tech or to post updates here, but let me instead give you a brief overview of what’s going on.

Obviously, we’ve been finding bugs and fixing them, nothing to fancy or weird, except for one special thing. It so happens, on some computers, that we get thread deadlocks. We have yet to understand why this happens, since Nebula doesn’t have cross-depending threads in any way. This seems to happen whenever we start to animate characters, however, it doesn’t happen if we just animate characters. Here is where the fun comes in. I’ve setup a test environment with a computer identical to the ones getting this problem. I tested this by just creating a render application which only rendered characters. I thought it might be some kind of performance problem, so I just put tons of characters in the scene and pushed it down to 2-8 fps. It never happened. There seem to be something else amiss here, and even though we’ve found a solution, we’re still uncertain how good it is.

The solution was to, quite simply, remove the render thread. This doesn’t mean we remove the rendering, but just put the render system on the main thread. We hesitate to do this since there must be a reason for the render thread in the first place, be it for the PS3, or just to handle multi-core PCs better. One theory we have to why this is a problem might be that the window handle and the window event loop is actually on another thread than the actual application, something which caused random deadlocks before. However, in the case with the previous WinProc problem, the thread actually hanged inside the procedure instead of somewhere else.

This got me thinking, maybe it is time to redesign the render system, not because it’s wrong or poorly implemented, but because we could benefit from another approach to render with multiple threads, instead of having a render system back end which is enormous and complex. Instead, we could make good use of modern graphics hardware to implement several render devices, and move the parallelism to only perform draw calls. Note that this will not be possible to utilize in older hardware, but seeing as we are 100% focused on the PC platform, this shouldn’t be a problem for us. This is similar to what Andre Weissflog has already implemented in the official Bigpoint branch of Nebula.

We might also want to rethink how models work. The system today with model hierarchies is really nice, and provides a very accurate 1:1 representation of the Maya content into Nebula. The only problem is its performance. If we have a complex model with a huge hierarchy, the update time per model can be murder for the cache, since it has to recursively traverse each model node and perform updates. Instead, it would be much neater to just have a list of model nodes, which can be processed in a much more data-driven manner. Having said that, the majority of the render system works nicely, is easily maintainable, and should be easy to implement into this new design idea.

We’ve also been considering redesigning application to have it be slightly less flexible but more data-driven in design. We’re a bit suspicious that game applications run so much slower than render applications. Obviously this would be the case since we have lots of game mechanics to compute and handle, but the application system doesn’t quite scale well with lots of entities. Both redesign considerations are of course projects for the future, and will not be started with in the near future.

What I am currently working on, instead of fixing and finding bugs in the tools our game groups and internship guys are using, is a way to tie Nebula, and any other game engine for that manner, to make effects for shaders. Much like the Microsoft Effects system, effects provide a really clean and flexible way to create shader pipelines by combining shader programs, and render states into a manageable construct which can be written in a file, compiled, read in your game engine and then used with a very simple interface. The only problem is that up to this point in time, nothing with the same level of functionality has yet been provided for OpenGL.

I give to you AnyFX. Well, I don’t really, because it’s not done yet, but I can at least give you the concept.

AnyFX strives to implement a language which looks like C, and thus also resembles HLSL and GLSL, but also handles shader linkage, render states, and variable handling. At the same time, I also wanted a simple way of porting shaders to use with AnyFX, as well as maintain the same level of optimization and language-specific intrinsics without having to write an extremely complex compiler, since this is way above my level of knowledge and not within a reasonable time frame. AnyFX works by writing all wrapping code in the AnyFX language standard, although all code handled inside the function scope is target language native. To avoid further confusion, variables can be declared as either GLSL or HLSL types, although identical data types will internally be represented the same. AnyFX comprises of two parts, a compiler, and an API. An AnyFX file has to be compiled into a binary blob, during which it gets evaluated for cross shader linkage, semantic and static analysis. The compiler then outputs target language, which only covers variable declarations and function headers, nothing more, nothing less.

The API can load a binary compiled AnyFX file, at which point it loads all structures, such as render states, sampler states and programs. The back end is fed this information, and is implemented depending on the target platform. So for example, if I build an AnyFX file with profile glsl4, the back end will implement an GLSL4Effect, or if I build an AnyFX file with the hlsl5 profile, I get an HLSL5Effect. The front end can simply call Apply to apply the effect, meaning it will set the render state, and Commit, which basically just updates constant variable buffers if present. Just like it works currently in Nebula, we can simply integrate AnyFX to replace both Effects11, but more importantly, have an actual effects interface for OpenGL.

This time you get no videos or pictures I’m afraid, because to be honest, there is nothing new and cool to show off.