So I’ve been playing around trying to implement the Nubis cloud density model into Unreal. If you’re not familiar with it, it’s an updated version of the Horizon Zero Dawn cloud system, which you can read about here. Andrew Schneider also wrote a chapter in GPU Pro 7 which is here. The Nubis follow up talk can be found here, and some more examples of very similar implementations can be found here and here, and if you look on shadertoy you can see many more examples of similar methods. There is also a gamedev forum thread here in which it is discussed in detail, with Andrew himself weighing in a few times.
The density model itself is quite simple, but I just can’t seem to get good results no matter what I try, and I’ve tried A LOT of variations that I’ve discovered, all to not much avail. I don’t know if anyone else has had any success with it, but I’ll break down some of what I’ve tried and my results, and it would be interesting to know if anyone has got anywhere close. I feel like I’m banging my head against a wall at this point. But this is the breakdown of the basic method covered in the Horizon, Nubis, and GPU pro talks/article.
The first step is to implement Coverage (in this case just some static noise. Generating better coverage maps will come after getting the base shapes right) and a height signal, or height/density function. Ive done this according to the functions specified. You can see in the image below the material setup, their implementation and results, and mine.
As you can see, that all works as expected, no problems there. The problem arises when adding the noise to it. All implementations of this rely on the same principal; to construct a noise FBM using a remap, then remapping the resulting noise * height signal, using coverage. In the next image you can again see the material implementation and the original code from the GPU Pro 7 chapter.
This results however in almost no visual change as the remap function will never take density away from the cloud (which is the point), but this means we’re left with essentially what we had before? If we don’t negate the low input in the remap, then we take more noise away, but this is incorrect. This Image just shows mapping the red line to the green line (result in blue) with different low inputs. It’s a neat way to see what these remap functions are doing.
This is the resulting clouds from using 1 – x (non-negated) and -(1 – x)
As you can see, the proposed method has no visual effect, and the non-negated result creates non-homogenous cloud shapes, which are not what we want. I’m using the perlin-worley noise included with the volumetrics plugin, but I’ve tried many other noise textures with the same result.
I’ve tried so many implementations of this now it’s crazy, including just writing the entire shader in HLSL (which obviously made no difference) and it never looks even close to the other examples I’ve seen. I might be missing something really obvious here, but if anyone has any insight into this I’d love to hear it. There are of course many other ways to get nice looking clouds, but this seems such a simple and elegant solution and it’s now my mission to try and solve this.
Thanks for reading, and I hope someone can crack this one!