Last active
April 15, 2025 09:04
-
-
Save w0wca7a/355b73d2956540e038ce347f31397ee6 to your computer and use it in GitHub Desktop.
Gorgeous rain on glass shader for Stride game engine
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Copyright (c) Stride contributors (https://stride3d.net). | |
| // Distributed under the MIT license. | |
| using Stride.Engine; | |
| using Stride.Graphics; | |
| namespace Additionals.Shader.ShadertoyExam | |
| { | |
| [Display("RainDrops effect")] | |
| [ComponentCategory("Effects")] | |
| public class RainEffect : StartupScript | |
| { | |
| public Texture Texture { get; set; } | |
| public override void Start() | |
| { | |
| base.Start(); | |
| var model = Entity.Components.Get<ModelComponent>(); | |
| model.Materials[0].Passes[0].Parameters.Set(RainEffectKeys.Texture, this.Texture); | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // original shader https://www.shadertoy.com/view/M3G3zV | |
| // Copyright (c) Stride contributors (https://stride3d.net). | |
| // Distributed under the MIT license. | |
| namespace Additionals.Shader.ShadertoyExam | |
| { | |
| shader RainEffect<bool CheapNormals, bool UsePostProcessing, bool UseZoom, bool UseBlur> : Texturing, ComputeColor, ShaderBase | |
| { | |
| // Текстура / texture | |
| rgroup PerMaterial | |
| { | |
| stage Texture2D Texture; // Основная текстура | |
| } | |
| compose ComputeColor Texture; | |
| // Вспомогательные функции шума / Noises generators | |
| float3 N13(float p) | |
| { | |
| float3 p3 = frac(float3(p) * float3(.1031f, .11369f, .13787f)); | |
| p3 += dot(p3, p3.yzx + 19.19f); | |
| return frac(float3((p3.x + p3.y)*p3.z, (p3.x+p3.z)*p3.y, (p3.y+p3.z)*p3.x)); | |
| } | |
| float4 N14(float t) | |
| { | |
| return frac(sin(t*float4(123.f, 1024.f, 1456.f, 264.f))*float4(6547.f, 345.f, 8799.f, 1564.f)); | |
| } | |
| float N(float t) | |
| { | |
| return frac(sin(t*12345.564f)*7658.76f); | |
| } | |
| float Saw(float b, float t) | |
| { | |
| return smoothstep(0.f, b, t)*smoothstep(1.f, b, t); | |
| } | |
| // Функции генерации капель | |
| float2 DropLayer2(float2 uv, float t) | |
| { | |
| float2 UV = uv; | |
| uv.y += t*0.75f; | |
| float2 a = float2(6.f, 1.f); | |
| float2 grid = a*2.f; | |
| float2 id = floor(uv*grid); | |
| float colShift = N(id.x); | |
| uv.y += colShift; | |
| id = floor(uv*grid); | |
| float3 n = N13(id.x*35.2f + id.y*2376.1f); | |
| float2 st = frac(uv*grid) - float2(.5f, 0.f); | |
| float x = n.x - .5f; | |
| float y = UV.y*20.f; | |
| float wiggle = sin(y + sin(y)); | |
| x += wiggle*(.5f - abs(x))*(n.z - .5f); | |
| x *= .7f; | |
| float ti = frac(t + n.z); | |
| y = (Saw(.85f, ti) - .5f)*.9f + .5f; | |
| float2 p = float2(x, y); | |
| float d = length((st - p)*a.yx); | |
| float mainDrop = smoothstep(.4f, .0f, d); | |
| float r = sqrt(smoothstep(1.f, y, st.y)); | |
| float cd = abs(st.x - x); | |
| float trail = smoothstep(.23f*r, .15f*r*r, cd); | |
| float trailFront = smoothstep(-.02f, .02f, st.y - y); | |
| trail *= trailFront*r*r; | |
| y = UV.y; | |
| float trail2 = smoothstep(.2f*r, .0f, cd); | |
| float droplets = max(0.f, (sin(y*(1.f - y)*120.f) - st.y))*trail2*trailFront*n.z; | |
| y = frac(y*10.f) + (st.y - .5f); | |
| float dd = length(st - float2(x, y)); | |
| droplets = smoothstep(.3f, 0.f, dd); | |
| float m = mainDrop + droplets*r*trailFront; | |
| return float2(m, trail); | |
| } | |
| float StaticDrops(float2 uv, float t) | |
| { | |
| uv *= 40.f; | |
| float2 id = floor(uv); | |
| uv = frac(uv) - .5f; | |
| float3 n = N13(id.x*107.45f + id.y*3543.654f); | |
| float2 p = (n.xy - .5f)*.7f; | |
| float d = length(uv - p); | |
| float fade = Saw(.025f, frac(t + n.z)); | |
| float c = smoothstep(.3f, 0.f, d)*frac(n.z*10.f)*fade; | |
| return c; | |
| } | |
| float2 Drops(float2 uv, float t, float l0, float l1, float l2) | |
| { | |
| float s = StaticDrops(uv, t)*l0; | |
| float2 m1 = DropLayer2(uv, t)*l1; | |
| float2 m2 = DropLayer2(uv*1.85f, t)*l2; | |
| float c = s + m1.x + m2.x; | |
| c = smoothstep(.3f, 1.f, c); | |
| return float2(c, max(m1.y*l0, m2.y*l1)); | |
| } | |
| // Основная функция шейдера | |
| override float4 Compute() | |
| { | |
| // Получаем координаты | |
| float2 uv = streams.TexCoord.xy; | |
| float2 center = float2(0.5, 0.5); | |
| uv -= center; | |
| float2 UV = streams.TexCoord.xy; | |
| // Управление временем и параметрами | |
| float T = Global.Time; | |
| float t = T * 0.2f; | |
| // Интенсивность дождя | |
| float rainAmount = sin(T * 0.05f) * 0.3f + 0.7f; | |
| // Настройки размытия | |
| float maxBlur = 0.0f; | |
| float minBlur = 0.0f; | |
| if (UseBlur) | |
| { | |
| maxBlur = lerp(3.f, 6.f, rainAmount); | |
| minBlur = 2.0f; | |
| } | |
| // Эффект приближения | |
| if (UseZoom) | |
| { | |
| float zoom = -cos(T * 0.2f); | |
| uv *= 0.7f + zoom * 0.3f; | |
| UV = (UV - 0.5f) * (0.9f + zoom * 0.1f) + 0.5f; | |
| } | |
| // Генерация капель | |
| float staticDrops = smoothstep(-0.5f, 1.f, rainAmount) * 2.f; | |
| float layer1 = smoothstep(0.25f, 0.75f, rainAmount); | |
| float layer2 = smoothstep(0.f, 0.5f, rainAmount); | |
| float2 c = Drops(uv, t, staticDrops, layer1, layer2); | |
| // Вычисление нормалей | |
| float2 n; | |
| if (CheapNormals) | |
| { | |
| n = float2(ddx(c.x), ddy(c.x)); // Быстрые нормали | |
| } | |
| else | |
| { | |
| float2 e = float2(0.001f, 0.f); | |
| float cx = Drops(uv + e, t, staticDrops, layer1, layer2).x; | |
| float cy = Drops(uv + e.yx, t, staticDrops, layer1, layer2).x; | |
| n = float2(cx - c.x, cy - c.x); // Качественные нормали | |
| } | |
| // Применение эффектов к текстуре | |
| float focus = lerp(maxBlur - c.y, minBlur, smoothstep(0.1f, 0.2f, c.x)); | |
| float4 col = Texture.Sample(LinearSampler, UV + n, focus); | |
| //float4 col = Texture.Compute().a + focus; | |
| // Постобработка | |
| if (UsePostProcessing) | |
| { | |
| t = (T + 3.f) * 0.5f; | |
| float colFade = sin(t * 0.2f) * 0.5f + 0.5f; | |
| col.rgb *= lerp(float3(1.f), float3(0.8f, 0.9f, 1.3f), colFade); | |
| float fade = smoothstep(0.f, 10.f, T); | |
| float lightning = sin(t * sin(t * 10.f)); | |
| lightning *= pow(max(0.f, sin(t + sin(t))), 10.f); | |
| col.rgb *= 1.f + lightning * fade; | |
| col.rgb *= 1.f - dot(UV - 0.5f, UV - 0.5f); | |
| col.rgb *= fade; | |
| } | |
| return col; | |
| } | |
| }; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment