Search Unity

  1. We would like to hear your feedback about Unity and our products. Click here for more information.
    Dismiss Notice

rain question

Discussion in 'Shaders' started by grobonom, May 23, 2019.

  1. grobonom


    Jun 23, 2018
    Hi all.

    I created a raindome giving some visuals that suit to me.

    The problem i have is that the raindome is showing rain inside rooms or under meshes.

    Is there a way, in shader to 'clip' my dome ( based on a sphere ) when crossing a mesh in the Y axix ?

    Or maybe y should calculate sphere intersection with the other gameobjects ?

    I feel there's a cheap ( in a matter of calculation ) shader solution. but i see none.

    Anyone could help please ? :)

    thanks in advance and happy unitying !
  2. bgolus


    Dec 7, 2012
    The usual solutions are:
    Do physics collisions of some kind. If you're using Unity's built in particle system to do the rain, you could use this option. If you're doing a custom system then you'd need to do the raycasts yourself. It's also the worst option in terms of performance.

    Do screen space collisions. Common for GPU based particle systems, like Unreal's particle effects system is capable of. Neither of Unity's particle systems support this, but that's fine since it won't solve this particular issue. If you're standing in a room, the ceiling wouldn't stop the rain unless you're looking up!

    Do collisions based on some other representation of the scene. Unity's VFX Graph lets you place particle colliders, which are simple geometric shapes that can block or otherwise affect particles. This would be functional, but it would take a lot of manual work to place properly, as well as you'd be limited to some fixed number of colliders. A better option would be to generate some kind of SDF of your scene that represents all of the static collision in your scene. I don't think Unity has an official tool for this, though Robert Cupisz (who works at Unity on a lot of this kind of thing) has posted videos of one he wrote for internal use which may someday be released publicly. The only other one I know of is this one by another Unity employee.

    This can also be used in a shader to simply hide rain particles rather than do collision. This is a good option for custom rain systems or even using Unity's built in particle system. However you don't really need a full SDF to do this. You could render out a depth map of your scene from the direction of the rain falling and clip the particle that way too. Like this:

    That's an Unreal based game, but the concepts can be applied to any game engine.
    Peter77 and grobonom like this.
  3. grobonom


    Jun 23, 2018
    ahah 8-D @bgolus caviar !!!!!

    I know i have lots of thinking and learning in sight :D

    Thanks a lot for your answer !

    i'll run around all you gave me and try to find a solution on my prob. but yes.... intuitively i feel that my solution is in the 'mesh intersection' way :/
    This pisses me off as it's an heavy solution....

    I don't use particles.
    Not because i don't like them... ( see my fireworks over here :) )

    but because they're damn heavy/almost unusable on mobile systems....

    The raindome ( wich is no more than a skydome ) is the mandatory solution for me, as i want to run Carcassonne on mobile devices.

    All solutions i found ( the particles ones ) are too expensive for me :/
    must invent/create a lighter thingie......

    Any idea is very welcome :)

    happy unitying !!!!
  4. grobonom


    Jun 23, 2018
    S*** !!!!!

    It's so damn simple that i didn't even think about it !!!!!

    A heightmap baked in difference with the ground !
    hey in difference with the navmesh ?

    waw !!!! i have to dig in this !!!!!

    i be back very soon on this :)
    for now i go on watching the vid. it's caviar ! ( except the binary lesson at the beginning :p lol )
  5. grobonom


    Jun 23, 2018

    now i got a depth texture seen from above the scene.....


    and i figured out how to clip raindomes according to world y in surface shader....


    now i have to pass this depth texture to my shader and retrieve where the world fragments lead in the texture....
    Then a damn simple y comparison will clip the domes :)

    I just got no clear idea of how to retrieve the world location in this texture :/
    Would you have any idea @bgolus of how to achieve this please ?

    thanks and happy unitying :)
  6. grobonom


    Jun 23, 2018
    weeeeee 8-D

    Seems it works not too bad :)

    at the lower part: the observer capsule

    in white the raindomes

    in red a rain obstacle....

    OK. all is setup to zero: ground, observer, etc....
    the heightmap camera is located at 30m above ground, is ortho and has the size of the ground: 100m. it writes in a 512x512 rendertex that is then passed to my instanced raindomes shader.

    In shader, i read the occluding map with hardcoding sizes: camera width and camera height. I gonna have to make it more intelligent.... with some shader parameters ;)

    here's my shader so far :)
    Code (CSharp):
    1. Shader "prout/Rain" {
    2. Properties {
    3.     _Color ("Main Color", Color) = (1,1,1,1)
    4.     _MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
    5.     _AlphaClip("Alpha cutoff", Range(0,1)) = 0.5
    6.     _ClipTex ("Clipping depth tex", 2D) = "white" {}
    7.     _fac1("height_fact", Range(-100,100)) = 0
    9. }
    11. SubShader {
    12.     Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
    13.     LOD 200
    16.    #pragma surface surf Lambert alpha:fade
    18.    sampler2D _MainTex;
    19.    sampler2D _ClipTex;
    20.    fixed4 _Color;
    21.    half _AlphaClip;
    22.    float _fac1;  
    25.    struct Input {
    26.        float2 uv_MainTex;
    27.        float3 worldPos;
    28.    };
    31.      UNITY_DEFINE_INSTANCED_PROP(fixed4, _Parameters)
    34.    void surf (Input IN, inout SurfaceOutput o)
    35.    {
    37.       float3 wp=IN.worldPos;
    39.       float3 height=tex2D(_ClipTex, wp.xz/100+0.5);
    41.       if((height.r)*_fac1 > wp.y) clip(-1);
    44.       // per instance parameters:
    45.       // x=rotation speed
    46.       // y=rain falling speed
    47.       // z=x offset in texture
    48.       // w=y offset in texture
    49.       fixed4 tmp=UNITY_ACCESS_INSTANCED_PROP(Props, _Parameters);
    50.       fixed4 c = tex2D(_MainTex, IN.uv_MainTex + _Time * tmp.xy) * _Color;
    51.       clip(c.a-_AlphaClip);
    52.       o.Albedo = c.rgb;
    53.       o.Alpha = c.a;
    54.    }
    55. ENDCG
    56. }
    58. Fallback "Legacy Shaders/Transparent/VertexLit"
    59. }
    and the final result:

    hope you like it :D

    and thanks a bunch @bgolus !!!

    happy unitying !
    bgolus likes this.
  7. grobonom


    Jun 23, 2018
    Hey @bgolus :)

    Back there for a lil question i appear unable to answer...
    things work fine on windows but not on android ( when i compile project and run it on my phone.

    After investigating, i noticed that the 'heights' texture is inverted.
    Okay, i made a
    hgt = 1.0 - hgt;
    in shader and it works on android.

    Is there a way in shaderlab to make target plaform conditionnal compilation ?

    the define UNITY_REVERSED_Z seems to do nothing :/

    I could set this up in a script ( as script knows about the target platform ) but i believe this can be done in shader.

    Please help :)

    happy unitying !
  8. bgolus


    Dec 7, 2012
    That should be the solution, though I'm curious how exactly you're generating the height texture. Are you using are replacement shader pass, or copying off the depth texture?
  9. grobonom


    Jun 23, 2018
    hey @bgolus
    errrr.... i guess i do it the simples way i can x))
    plz gimme some fem minutes so that i show you what i did :)

    i'm back verysoon

    now x))...

    Here's the base scene in a visual way.....
    red are obstacles, and blue are raindomes....

    The method is pretty simple :))
    setting up a cam above the scene. This cam samples the depth through this shader:
    Code (CSharp):
    1. // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
    3. Shader "Custom/RenderDepth"
    4. {
    5.      Properties
    6.      {
    7.          _MainTex ("Base (RGB)", 2D) = "white" {}
    8.      }
    9.      SubShader
    10.      {
    12.         ColorMask 0
    14.          Pass
    15.          {
    16.              CGPROGRAM
    17.              #pragma vertex vert
    18.              #pragma fragment frag
    19.              #include "UnityCG.cginc"
    21.              uniform sampler2D _MainTex;
    22.              uniform sampler2D _CameraDepthTexture;
    23.              uniform half4 _MainTex_TexelSize;
    24.              struct input
    25.              {
    26.                  float4 pos : POSITION;
    27.                  half2 uv : TEXCOORD0;
    28.              };
    29.              struct output
    30.              {
    31.                  float4 pos : SV_POSITION;
    32.                  half2 uv : TEXCOORD0;
    33.              };
    34.              output vert(input i)
    35.              {
    36.                  output o;
    37.                  o.pos = UnityObjectToClipPos(i.pos);
    38.                  o.uv = MultiplyUV(UNITY_MATRIX_TEXTURE0, i.uv);
    39.                  // why do we need this? cause sometimes the image I get is flipped. see:
    40.                  #if UNITY_UV_STARTS_AT_TOP
    41.                  if (_MainTex_TexelSize.y < 0)
    42.                          o.uv.y = 1 - o.uv.y;
    43.                  #endif
    44.                  return o;
    45.              }
    47.              fixed4 frag(output o) : COLOR
    48.              {
    49.                  float depth = UNITY_SAMPLE_DEPTH(tex2D(_CameraDepthTexture, o.uv));
    50. #if defined(UNITY_REVERSED_Z)
    51.                  depth = 1.0-Linear01Depth(depth);
    52. #endif                
    53.                  return depth;
    54.              }
    56.              ENDCG
    57.          }
    58.      }
    59. }
    and here's the resulting rendertex whet windows is choosen as a target ( the image in the center )
    This is just what i expect. :)

    now i target android with this app and compile for an apk and run it on my phone.....

    well it appears i said S***ty things.....
    it works fine on android :/ the bad part is that i don't know what i changed for makin it work :/
    I don't like this....
    Well, then all previous things in this post are out of topic....

    Do you think @bgolus there's a way to enhance the visual result of all this ? any idea ?
    mostly on domes 'cutting' that don't give a nice visual result....
    Would you need i post a package of all this so that you could play with it ? :)


    and happy unitying !
    Last edited: May 25, 2019
  10. bgolus


    Dec 7, 2012
    Maybe have the domes wave a little in and out per vertex so the dome shape isn't so obvious?