登峰造极境

  • WIN
    • CSharp
    • JAVA
    • OAM
    • DirectX
    • Emgucv
  • UNIX
    • FFmpeg
    • QT
    • Python
    • Opencv
    • Openwrt
    • Twisted
    • Design Patterns
    • Mysql
    • Mycat
    • MariaDB
    • Make
    • OAM
    • Supervisor
    • Nginx
    • KVM
    • Docker
    • OpenStack
  • WEB
    • ASP
    • Node.js
    • PHP
    • Directadmin
    • Openssl
    • Regex
  • APP
    • Android
  • AI
    • Algorithm
    • Deep Learning
    • Machine Learning
  • IOT
    • Device
    • MSP430
  • DIY
    • Algorithm
    • Design Patterns
    • MATH
    • X98 AIR 3G
    • Tucao
    • fun
  • LIFE
    • 美食
    • 关于我
  • LINKS
  • ME
Claves
长风破浪会有时,直挂云帆济沧海
  1. 首页
  2. Programming
  3. babylon.js
  4. 正文

Babylonjs的下雨雨落shader

2025-02-21

链接

rain drop | Babylon.js Playground

Heartfelt

代码

class Playground {
    public static CreateScene(engine: BABYLON.Engine, canvas: HTMLCanvasElement): BABYLON.Scene {
        // This creates a basic Babylon Scene object (non-mesh)
        var scene = new BABYLON.Scene(engine);

        // This creates and positions a free camera (non-mesh)
        var camera = new BABYLON.FreeCamera("camera1", new BABYLON.Vector3(0, 5, -10), scene);

        // This targets the camera to scene origin
        camera.setTarget(BABYLON.Vector3.Zero());

        // This attaches the camera to the canvas
        camera.attachControl(canvas, true);

        // This creates a light, aiming 0,1,0 - to the sky (non-mesh)
        var light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, 1, 0), scene);

        // Default intensity is 1. Let's dim the light a small amount
        light.intensity = 0.7;

        // Our built-in 'ground' shape. Params: name, options, scene
        var ground = BABYLON.MeshBuilder.CreatePlane("ground", { width: 6, height: 6 }, scene);

        const mat = new BABYLON.ShaderMaterial('mat', scene, 'planeMat', {
            attributes: ['position', 'normal', 'uv'],
            uniforms: ['world', 'worldView', 'worldViewProjection', 'view', 'projection', 'iTime', 'iResolution', 'iMouse'],
            samplers: ['iChannel0']
        });
        ground.material = mat;

        BABYLON.Effect.ShadersStore['planeMatVertexShader'] = `
            precision highp float;

            attribute vec3 position;
            attribute vec2 uv;
            attribute vec3 normal;

            uniform mat4 worldViewProjection;

            varying vec2 vUV;

            void main(){
            gl_Position = worldViewProjection * vec4(position, 1.0);
            vUV = uv;
            }
        `;
        BABYLON.Effect.ShadersStore['planeMatFragmentShader'] = `
            precision highp float;

            varying vec2 vUV;

            uniform vec3 iResolution;
            uniform vec4 iMouse;
            uniform float iTime;
            uniform sampler2D iChannel0;


            #define S(a, b, t) smoothstep(a, b, t)
            #define HAS_HEART
            #define USE_POST_PROCESSING

            vec3 N13(float p) {
            vec3 p3 = fract(vec3(p) * vec3(.1031,.11369,.13787));
            
            p3 += dot(p3, p3.yzx + 19.19);
                return fract(vec3((p3.x + p3.y)*p3.z, (p3.x+p3.z)*p3.y, (p3.y+p3.z)*p3.x));
            }

            vec4 N14(float t) {
                return fract(sin(t*vec4(123., 1024., 1456., 264.))*vec4(6547., 345., 8799., 1564.));
            }
            float N(float t) {
                return fract(sin(t*12345.564)*7658.76);
            }

            float Saw(float b, float t) {
            return S(0., b, t)*S(1., b, t);
            }


            vec2 DropLayer2(vec2 uv, float t) {
                vec2 UV = uv;
                
                uv.y += t*0.75;
                vec2 a = vec2(6., 1.);
                vec2 grid = a*2.;
                vec2 id = floor(uv*grid);
                
                float colShift = N(id.x); 
                uv.y += colShift;
                
                id = floor(uv*grid);
                vec3 n = N13(id.x*35.2+id.y*2376.1);
                vec2 st = fract(uv*grid)-vec2(.5, 0);
                
                float x = n.x-.5;
                
                float y = UV.y*20.;
                float wiggle = sin(y+sin(y));
                x += wiggle*(.5-abs(x))*(n.z-.5);
                x *= .7;
                float ti = fract(t+n.z);
                y = (Saw(.85, ti)-.5)*.9+.5;
                vec2 p = vec2(x, y);
                
                float d = length((st-p)*a.yx);
                
                float mainDrop = S(.4, .0, d);
                
                float r = sqrt(S(1., y, st.y));
                float cd = abs(st.x-x);
                float trail = S(.23*r, .15*r*r, cd);
                float trailFront = S(-.02, .02, st.y-y);
                trail *= trailFront*r*r;
                
                y = UV.y;
                float trail2 = S(.2*r, .0, cd);
                float droplets = max(0., (sin(y*(1.-y)*120.)-st.y))*trail2*trailFront*n.z;
                y = fract(y*10.)+(st.y-.5);
                float dd = length(st-vec2(x, y));
                droplets = S(.3, 0., dd);
                float m = mainDrop+droplets*r*trailFront;
                
                return vec2(m, trail);
            }

            float StaticDrops(vec2 uv, float t) {
                uv *= 40.;
                
                vec2 id = floor(uv);
                uv = fract(uv)-.5;
                vec3 n = N13(id.x*107.45+id.y*3543.654);
                vec2 p = (n.xy-.5)*.7;
                float d = length(uv-p);
                
                float fade = Saw(.025, fract(t+n.z));
                float c = S(.3, 0., d)*fract(n.z*10.)*fade;
                return c;
            }

            vec2 Drops(vec2 uv, float t, float l0, float l1, float l2) {
                float s = StaticDrops(uv, t)*l0; 
                vec2 m1 = DropLayer2(uv, t)*l1;
                vec2 m2 = DropLayer2(uv*1.85, t)*l2;
                
                float c = s+m1.x+m2.x;
                c = S(.3, 1., c);
                
                return vec2(c, max(m1.y*l0, m2.y*l1));
            }

            void main(){
                vec2 uv = (vUV - 0.5) * iResolution.y / iResolution.x;
                // vec2 uv = ;
                vec2 UV = vUV;
                vec3 M = vec3(0.0);
                float T = iTime;
                
                
                float t = T*.2;
                
                float rainAmount = iMouse.z>0. ? M.y : sin(T*.05)*.3+.7;
                
                float maxBlur = mix(3., 6., rainAmount);
                float minBlur = 2.;
                
                float story = 0.;
                float heart = 0.;
                
                #ifdef HAS_HEART
                    story = S(0., 70., T);
                    
                    t = min(1., T/70.);						// remap drop time so it goes slower when it freezes
                    t = 1.-t;
                    t = (1.-t*t)*70.;
                    
                    float zoom= mix(.3, 1.2, story);		// slowly zoom out
                    uv *=zoom;
                    minBlur = 4.+S(.5, 1., story)*3.;		// more opaque glass towards the end
                    maxBlur = 6.+S(.5, 1., story)*1.5;
                    
                    vec2 hv = uv-vec2(.0, -.1);				// build heart
                    hv.x *= .5;
                    float s = S(110., 70., T);				// heart gets smaller and fades towards the end
                    hv.y-=sqrt(abs(hv.x))*.5*s;
                    heart = length(hv);
                    heart = S(.4*s, .2*s, heart)*s;
                    rainAmount = heart;						// the rain is where the heart is
                    
                    maxBlur-=heart;							// inside the heart slighly less foggy
                    uv *= 1.5;								// zoom out a bit more
                    t *= .25;
                    #else
                    float zoom = -cos(T*.2);
                    uv *= .7+zoom*.3;
                #endif
                    UV = (UV-.5)*(.9+zoom*.1)+.5;
                    
                    float staticDrops = S(-.5, 1., rainAmount)*2.;
                    float layer1 = S(.25, .75, rainAmount);
                    float layer2 = S(.0, .5, rainAmount);
                    
                    
                    vec2 c = Drops(uv, t, staticDrops, layer1, layer2);

                #ifdef CHEAP_NORMALS
                    vec2 n = vec2(dFdx(c.x), dFdy(c.x));// cheap normals (3x cheaper, but 2 times shittier ;))
                    #else
                    vec2 e = vec2(.001, 0.);
                    float cx = Drops(uv+e, t, staticDrops, layer1, layer2).x;
                    float cy = Drops(uv+e.yx, t, staticDrops, layer1, layer2).x;
                    vec2 n = vec2(cx-c.x, cy-c.x);		// expensive normals
                #endif
                
                
                #ifdef HAS_HEART
                    n *= 1.-S(60., 85., T);
                    c.y *= 1.-S(80., 100., T)*.8;
                #endif
                
                    float focus = mix(maxBlur-c.y, minBlur, S(.1, .2, c.x));
                    vec3 col = textureLod(iChannel0, UV+n, focus).rgb;
                
                
                #ifdef USE_POST_PROCESSING
                    t = (T+3.)*.5;										// make time sync with first lightnoing
                    float colFade = sin(t*.2)*.5+.5+story;
                    col *= mix(vec3(1.), vec3(.8, .9, 1.3), colFade);	// subtle color shift
                    float fade = S(0., 10., T);							// fade in at the start
                    float lightning = sin(t*sin(t*10.));				// lighting flicker
                    lightning *= pow(max(0., sin(t+sin(t))), 10.);		// lightning flash
                    col *= 1.+lightning*fade*mix(1., .1, story*story);	// composite lightning
                    col *= 1.-dot(UV-=.5, UV);							// vignette
                                    
                #ifdef HAS_HEART
                    col = mix(pow(col, vec3(1.2)), col, heart);
                    fade *= S(102., 97., T);
                #endif
                    col *= fade;										// composite start and end fade
                #endif
                
                //col = vec3(heart);
                gl_FragColor = vec4(col, 1.);
            }
        `;

        const { width, height } = scene.getEngine().getRenderingCanvas()!;
        const texture = new BABYLON.Texture(Assets.textures.Checker_albedo_png.path, scene);

        mat.onBindObservable.add(() => {
            mat.getEffect().setVector3('iResolution', new BABYLON.Vector3(width, height, width / height));
            mat.getEffect().setTexture('iChannel0', texture);
            mat.getEffect().setFloat('iTime', time);
        });

        let time = 0;
        scene.registerAfterRender(() => {
            time += 0.03;
        });

        scene.onPointerDown = (event) => {
            mat.setVector4('iMouse', new BABYLON.Vector4(event.clientX, event.clientY, event.buttons === 1 ? 1 : 0, 1.0));
        };

        return scene;
    }
}
标签: 暂无
最后更新:2025-02-21

代号山岳

知之为知之 不知为不知

点赞
< 上一篇
下一篇 >

COPYRIGHT © 2099 登峰造极境. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang

蜀ICP备14031139号-5

川公网安备51012202000587号