Using Stained Bump Distort or similar but pixel perfect, on 2D planes in 3D space

Hi all,

I’m working in low resolution in 2.5D, using only pixel perfect graphics.

I have a rain effect that uses the following image, falling down in sheets:

Note that in the actual image, the black is fully transparent.

It looks fine as is, though I think it’d look a lot better with something like Stained Bump Distort. And when I add it, it seems to have a lot of potential. But it’s not pixel-perfect. It’s very messy-looking and the part that has the effect applied around each drop of rain is huge - like 6 pixels wide or thereabouts.

Is there some way to get that same effect, but strictly only applied to the white / grey / non-transparent pixels in the above image?

Thank you!

Is this for full scene rain, or rain on glass?

Distortion based effects will always be a little messy, though they can be cleaner than what the stained bump distort is doing, you might be better off just using two or three different textures that have the rain falling in different directions.

It’s for full scene rain. The sheets of rain are spawned randomly within a certain range at a certain height above the camera. It would probably be too system intensive, but do you think the effect would be limited just to the relevant pixels if I replaced the sheets of rain with individual drops of rain?

Depends on what your performance bottle neck is, and how many drops of rain you want.

It may in fact be better to do individual drops of rain at it would allow for more control and reduce overdraw, but may be slower on the CPU if there are too many particles, and slower on the GPU if there are too many vertices.

Large textures of many rain drops can be a lot of overdraw, basically the cost if rendering part of a texture that’s blank vs colored or even fully opaque is the same when using a transparent material. With especially simple shaders this isn’t too bad and you can layer a lot before they become a problem, but the glass shader is pretty heavy if you’re using it the way it’s setup with it distorting the screen behind it.

For simple visual styles on modern GPUs neither of these are likely to be a huge concern (though if you try and do 10000 individual rain drops you might be killing framerate significantly), but you may want to try both to see what you can get and what you like.

You might also try some other techniques out. Try searching for “rain drops on glass shader” and see what you find. The short version is having two textures, one that’s the path rain drops follow, and another looks like “waves” of rain, and if you multiply the two together plus some other tricks you can get what looks like rain flowing down a surface.

3160581--240443--rainonglass.gif

3160581--240442--rainOnGlass.png
Use this texture with sRGB disabled and with no compression.

Shader "Unlit/RainOnGlass"
{
    Properties
    {
        _Color ("Rain Color", Color) = (1,1,1,1)
        _MainTex ("Texture", 2D) = "white" {}
        _Speed ("Rain Speed", Float) = 1
    }
    SubShader
    {
        Tags { "Queue" = "Transparent" "RenderType"="Transparent" }
        LOD 100
        Blend SrcAlpha OneMinusSrcAlpha

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog
          
            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            fixed4 _Color;

            float _Speed;
          
            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }
          
            fixed4 frag (v2f i) : SV_Target
            {
                fixed2 pathOffset = tex2D(_MainTex, i.uv).rg;
                float2 rainUV = float2(i.uv.x, (i.uv.y + frac(_Time.y * _Speed) * 2.0 + pathOffset.y) * 0.5);
                fixed rain = tex2D(_MainTex, rainUV).b;

                fixed4 col = _Color;
                col.a *= pathOffset.x * rain;

                UNITY_APPLY_FOG(i.fogCoord, col);
                return col;
            }
            ENDCG
        }
    }
}
2 Likes

It is a great shader :slight_smile: