wave-harmonic / crest

A class-leading water system implemented in Unity
MIT License
3.5k stars 478 forks source link

Receive illumination on the water surface of spot and point Lights #357

Open ftejada17 opened 5 years ago

ftejada17 commented 5 years ago

Simply what I want is that the surface of the water receives the illumination of other sources of light, like for example the spotLight or pointLight.

Here I leave a video of the Ultimate Water System asset in which it looks like it receives the light of a SpotLight. Where it gives light, under the ocean there is NO land. https://youtu.be/LUnDvCD0i2g And in this video I show Crest in a similar situation. It looks like Crest simply doesn't seem to receive SpotLight light or pointLight as already mentioned. https://youtu.be/3vT9wBNUZOk

I have no experience in Shaders programming and I find it impossible to implement something so that Crest has this feature. Anyway I think it is something quite important that you should value if you put natively in Crest.

Another thing that I have not been able to test properly, is if under water the light is absorbed by the water according to the depth ... If not, it should be included as it is essential.

Regards

huwb commented 5 years ago

Thanks for adding this, good to have it tracked.

I'm not sure if/when i'll have bandwidth to put time into the built-in RP sadly, but i've put the help wanted label on this, perhaps someone from the community can contribute the solution.

daleeidd commented 4 years ago

I tried adding an extra pass as an experiment to add point and spot lights, but it seemed to be the wrong way to go about it. There is some artifacting which could be due to the ocean tiling, blending or something else:

Lights Tiling

Trying to calculate lighting in a single pass is supposedly taxing on performance.

I believe the way to accomplish this is to look at how shadows are done. It would require using a compute shader (or a standard shader could be use?) to write the light data into a texture array. Then the texture array can be sampled in the ocean shader. An RGB texture array could be used to capture the light's colour.

The shadow compute shader was written by looking and reimplementing code from UnityCG.cginc since we don't have geometry to work with. It might be the same case for lighting.

The directional light (sun) doesn't need all of this because it is everywhere and has no boundaries (those are shadows which is compute). Point lights and spot lights have a limited range. Again, I might be misdiagnosing the issue.

The steps would be:

  1. Architecture (LOD Manager etc) Easy
  2. Compute shader populating texture array (use OceanGUIDebug to view output) Hard
  3. Sample data in ocean shader Medium

@huwb would this be correct?

adamjm123 commented 4 years ago

I'd love to see this feature also!

huwb commented 4 years ago

Thanks @daleeidd!

That is an odd artifact.. hmm.. it doesnt immediately look like its aligned ot the geometry tiles, although it might be. The ocean verts are displaced so i would expect the visible boundary to be not straight, and the shapes/edges in the 2 screenshots look more screenaligned to me rather than tile-aligned. But i'm not sure..

Trying to calculate lighting in a single pass is supposedly taxing on performance.

It's interesting, I'm not sure about this. I think having the ocean surface broken up into tiles is helpful as they may only calculate lighting for overlapping lights. Also i'm not convinced that redrawing the surface multiple times is cheap, especially with the ocean which has a non-trivial vertex shader that has to sample the displacements.

The solution you described is interesting. Its seems similar to "forward plus" renderers which compose a light list. Usually the light list is composed in screen space but your idea composes it in world space and stores it in cascaded textures? I like it, but i would agree it sounds hard. One challenge that comes to mind is there might be multiple/many lights overlapping. Besides needing logic to select the N best lights of the set (nontrivial problem I'd guess), we'd need enough textures to store all the data, which could be a large amount of memory.

Given the that ocean tiles are "normal" unity objects - maybe the light data is already provided to the shader and we just have to use them. Specifically, from https://docs.unity3d.com/Manual/SL-UnityShaderVariables.html , it may be that

unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0

Are populated and ready to go, and "just" need the routines from Lighting.cginc called to do the lighting?

daleeidd commented 4 years ago

Thank you for pointing me in the right direction.

There is some tiling artifacting in the second image, but this is because I was doing the lighting wrong. I still get some tiling in certain situations. The following is done in the same pass, and it is just applied after the OceanEmission for now:

Lights Good Lights Bad

I'll probably do a WIP PR sometime later in the week.

rockretep commented 4 years ago

@daleeidd Fantastic work, I'm looking forward to seeing how you put that together; I've been trying, and failing to get lights without the tiling for a while now. Did you manage to get both vertex and pixel lights working?

daleeidd commented 4 years ago

@rockretep Thanks!

The first two images are pixel lights. They are done with an extra pass. There is white screen space tiling right now. This is caused by the specular calculations when blending the passes. Right now the extra pass is just a copy-paste with some extra stuff for the light attenuation added so distilling it to leave only what is necessary for the lights should fix it. I have made some changes which have mostly fixed tiling (green is a spotlight):

Pixel Lights Pixel Lights (Important Lights)

The second two are vertex lights thanks to @huwb recommendation. Tiling only occurs when a spot light is used (which behave as point lights anyway). Changing the lights to point solved it:

Vertex Lights Vertex Lights (Unimportant Lights)

I am not sure if Crest will want the complexity or performance cost of an extra pass. I haven't tried merging the two branches together yet. Experimental PR is on track for this week.