crest icon indicating copy to clipboard operation
crest copied to clipboard

Add Ocean Object Occluders (using per-pixel mask)

Open moosichu opened this issue 4 years ago • 8 comments

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).

moosichu avatar Apr 04 '20 10:04 moosichu

image

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.

moosichu avatar Apr 04 '20 10:04 moosichu

image

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):

image

Comparison:

image

moosichu avatar Apr 04 '20 10:04 moosichu

Cool! Maybe create a shader graph and you should be about to disable back faces culling on the master node (two sided maybe)

huwb avatar Apr 04 '20 11:04 huwb

image

Hopefully this demos things a bit better, we are inside an object but there is no fog effect applied.

moosichu avatar Apr 05 '20 12:04 moosichu

image

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.

moosichu avatar May 08 '20 15:05 moosichu

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:

image

image

image

image

moosichu avatar May 10 '20 11:05 moosichu

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.

moosichu avatar May 10 '20 11:05 moosichu

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.

moosichu avatar May 23 '20 18:05 moosichu