crest
crest copied to clipboard
Add Ocean Object Occluders (using per-pixel mask)
Add the ability to prevent the ocean from rendering on a per-pixel basis. To achieve this you add a script to an object with a mesh (OceanOccluder
), and set the occlusion type to one of 4 settings:
- OccludeAll
- CancelOcclusion
- OccludeWaterBehind
- OccludeWaterInFront
These objects are then rendered using a mask-shader in a pre-pass which marks a screen-space texture about which objects have been renderered with which depth-setting.
The first-two should be used for opaque objects as they are slightly cheaper, and the latter two should be used for transparencies and are slightly more expensive. The plan before this PR is merged is to remove the cost of transparent objects completly if you don't use them (as you can then pack the information about opaque occluders into the general ocean underwater mask).
With Opaque Objects, if you have some kind of enclosed space (eg. a submarine), the goal is to attach the script with OccludeAll
to the internal mesh to prevent the ocean from rendering-inside the submarine, wihlst attaching the script with CancelOcclusion
to the outside in-order to ensure that if the camera is outside the space, the ocean is never occluded.
For transparencies, you will then need to attach the appropropraite OccludeWaterBehind
and OccludeWaterInFront
scripts to the approprate faces of windows.
We need a good example for people to use in the main scene.
---> One of the massive benefits of this technique is that because it's done per-pixel, it will work with convex and concave windows in addition to flat ones.
For OccludeWaterInFront
(windows facing the outside) we need to apply the underwater post-process effect behind an arbitrary transparent surface. This is currently done using a shader pre-pass on a custom surface shader, but any input on how to improve this workflow would be hugely appreciated. Ideally I would want to ensure things "just work" if the OceanOccluder
script is attached to any transparent mesh with the OccludeWaterInFront
setting.
====
Stuff to do before this is merge ready:
This might be useful: https://docs.unity3d.com/Manual/SL-ShaderReplacement.html
- [ ] General Code Cleanup
- [ ] Make these features optional - don't pay for the cost of them if you don't use them
- [ ] Figure out a concrete strategy for setting global crest shader variables (how to handle defines!?)
- [ ] Formalise workflow for creating transparent surface-shader windows
- [ ] Fix bug where the caustics don't align properly through the example transparent material
- [ ] Create some good example assets we could use (or find some?) Simple low-poly submarine?
Motivation for this work:
A user on (StarChick971) is working on replacing some Crest geometry with their own but will still like their own underwater effect to be applied.
This change adds a simple script (UnderwaterEffectFilter) that can be attached to any arbitrary game object with a Renderer.
For now, it simply re-renders that object with the shader mask and it will be treated as regular ocean surface.
The plan is to make this system completely configurable, so that by adding this "filter" to game objects, users will be able have masks which can disable the underwater affect when inside objects, or apply it from a specific depth in the scene (like a window in a submarine).
In the example scene I've added an UnderwaterEffectFilter
component to a giant sphere, this make the sphere apply a mask similar to how the ocean surface would. Working on some custom effects now.
I've been able to create a simple submarine, so outside of it looks as you would expect. But on the inside, there is no post process effect (bear in mind the the geometry has back-face culling turned on, and I couldn't figure-out how to turn it off):
Comparison:
Cool! Maybe create a shader graph and you should be about to disable back faces culling on the master node (two sided maybe)
Hopefully this demos things a bit better, we are inside an object but there is no fog effect applied.

Now the ocean is easily cullable per-pixel. This should allow for some incredibly cool effects.
Implementation is currently hacky, but PR #499 made this particular part possible. :)
Next: Windows.
There are two problems left to solve:
1: https://forum.unity.com/threads/birp-hdrp-render-transparencies-after-fog.887182/ 2: The fact that the darkening-effect applies as you go deeper underwater whilst inside objects.
Some up-to-date screen shots:
Because of the extra work required to support these override masks (especially with transparencies) something I want to do as well (before this is ready for merge) is ensure that this stuff can be disabled so you don't pay the runtime cost for this.
I've got a change that renames a bunch of stuff to make things clearer almost ready to go, but for some reason it's not working. Will try and get that in asap as it might make it easier to review this change.