红色的光点(Red Dots)

红色的光点(Red Dots)


更多有趣示例 尽在 知屋安砖社区

示例

在这里插入图片描述

HTML

<script src="https://unpkg.com/three@0.85.0/build/three.min.js"></script>
<script src="https://unpkg.com/three@0.85.0/examples/js/Detector.js"></script>
<script src="https://cdn.rawgit.com/dataarts/dat.gui/master/build/dat.gui.min.js"></script>

CSS

body{
    margin: 0;
    padding: 0;
    overflow: hidden;
    cursor: none;
    background: rgb( 30, 38, 48 );
}

JS

console.clear();

window.addEventListener( 'load', function(){
    if (!Detector.webgl) Detector.addGetWebGLMessage();
    
    var vertexShader = [
        'void main() {',
            'gl_Position = vec4( position, 1.0 );',
        '}'
    ].join('');
    
    var colorizeShader = [
        'uniform vec2 resolution;',
        'uniform sampler2D texture;',
        'uniform vec3 color1;',
        'uniform vec3 color2;',

        'void main( void ){',
            'vec2 uv = gl_FragCoord.xy / resolution;',
            'gl_FragColor = vec4( mix( ',
                'color1,',
                'color2,',
                'texture2D( texture, uv ).r',
            '), 1.0);',
        '}'
    ].join('');
    
    var gameOfLife = [
        'uniform int timer;',
        'uniform vec2 resolution;',
        'uniform vec2 mouse;',
        'uniform sampler2D texture;',

        'vec2 pos;',
        'vec2 texColor;',
        'vec2 offset;',
        'float pixelSize = 3.0;',

        'void main( void ){',
            'pos = vec2(',
                'floor( gl_FragCoord.x / pixelSize ) * pixelSize + pixelSize / 2.0,',
                'floor( gl_FragCoord.y / pixelSize ) * pixelSize + pixelSize / 2.0',
            ');',
        
            'vec3 color = texture2D( texture, pos / resolution ).rgb;',
        
            'float neighbors = 0.0;',
            'for( float y = -1.0; y<=1.0; y++){',
                'for( float x = -1.0; x<=1.0; x++){',
                    'neighbors += step(',
                        '0.5,',
                        'texture2D( texture, (pos + vec2( x * pixelSize, y * pixelSize ) ) / resolution ).r',
                    ');',
                '}',
            '}',
        
            'float status = step(0.5, color.r );', 
            'neighbors -= status;',
        
            // Dying
            'if( status == 1.0 && ( neighbors >= 4.0 || neighbors <= 1.0 )){',
                'color = vec3(0.49);',
            '}',
        
            // Birth
            'else if( status == 0.0 && neighbors == 3.0 ){',
                'color = vec3(1.0);',
            '}',
            'else if( floor(pos / (pixelSize*2.0)) == floor(mouse / (pixelSize*2.0)) ){',
                'color = vec3(1.0);',
            '}',
            
            // Stasis
            'else color = vec3(status );',

            'gl_FragColor = vec4(color, 1.0);',
        '}'
    ].join('');
    
    var w = window.innerWidth, h = window.innerHeight,
        camera, scene, renderer, uniforms,
        uniforms2, ctx, startText,
        bufferScene, ping, pong,
        timer = 0, mouse = { x : 0, y : 0 };

    var params = {
        color1 : [ 30, 38, 48 ],
        color2 : [ 251, 53, 80 ]
    };

    ( function init() {
        var container = document.body;
        var color1 = new THREE.Vector3( params.color1[ 0 ] / 255, params.color1[ 1 ] / 255, params.color1[ 2 ] / 255 );
        var color2 = new THREE.Vector3( params.color2[ 0 ] / 255, params.color2[ 1 ] / 255, params.color2[ 2 ] / 255 );

        function setStartTex(){
            ctx.fillStyle = 'black';
            ctx.fillRect( 0, 0, 1024, 512 );
            ctx.font = '800 400px Roboto';
            ctx.fillStyle = 'yellow';
            ctx.textAlign = 'center';
            ctx.textBaseline = 'middle';
            ctx.fillText( 'Game', 1024 / 2, 512 / 4 );
            ctx.fillText( 'of', 1024 / 2, 512 / 2 );
            ctx.fillText( 'Life', 1024 / 2, 3 * 512 / 4 );
        }

        ( function initStartTex(){
            var cnvs = document.createElement( 'canvas' );
            cnvs.width = 1024;
            cnvs.height = 512;
            ctx = cnvs.getContext( '2d' );
            setStartTex();
            startText = new THREE.Texture( cnvs );
        } )();

        ( function setupPingPong(){
            bufferScene = new THREE.Scene();

            var renderTargetParams = {
                minFilter: THREE.LinearFilter,
                magFilter: THREE.LinearFilter,
                format: THREE.RGBAFormat,
                type: THREE.FloatType
            };

            ping = new THREE.WebGLRenderTarget( w, h, renderTargetParams );
            pong = new THREE.WebGLRenderTarget( w, h, renderTargetParams );
            ping.texture.wrapS = THREE.ClampToEdgeWrapping;
            ping.texture.wrapT = THREE.ClampToEdgeWrapping;
            pong.texture.wrapS = THREE.ClampToEdgeWrapping;
            pong.texture.wrapT = THREE.ClampToEdgeWrapping;

            uniforms2 = {
                timer : {
                    type: 'i',
                    value: 0
                },
                resolution : {
                    type : 'v2',
                    value : new THREE.Vector2()
                },
                mouse : {
                    type : 'v2',
                    value : new THREE.Vector2()
                },
                color1 : {
                    type : 'v3',
                    value : color1
                },
                color2 : {
                    type : 'v3',
                    value : color2
                },
                texture : {
                    type : 't',
                    value : startText
                },
                dA : {
                    type: 'f',
                    value : params.dA
                },
                dB : {
                    type: 'f',
                    value : params.dB
                },
                kill : {
                    type: 'f',
                    value : params.kill
                },
                feed : {
                    type: 'f',
                    value : params.feed
                },
                dT : {
                    type: 'f',
                    value : params.dT
                },
            };

            var material2 = new THREE.ShaderMaterial( {
                uniforms : uniforms2,
                vertexShader : vertexShader,
                fragmentShader : gameOfLife
            } );

            var geometry2 = new THREE.PlaneBufferGeometry( 2, 2 );

            var mesh2 = new THREE.Mesh( geometry2, material2 );
            bufferScene.add( mesh2 );

            startText.needsUpdate = true;
        } )();

        ( function setupScene(){
            renderer = new THREE.WebGLRenderer( { preserveDrawingBuffer: true } );
            renderer.setPixelRatio( 1 );
            renderer.setClearColor( 0x665544, 1 );
            container.appendChild( renderer.domElement );

            camera = new THREE.Camera();
            camera.position.z = 1;
            scene = new THREE.Scene();
            
            var geometry = new THREE.PlaneBufferGeometry( 2, 2 );
            
            uniforms = {
                resolution : {
                    type : 'v2',
                    value : new THREE.Vector2( w, h )
                },
                texture : {
                    type : 't',
                    value : pong.texture,
                    minFilter : THREE.NearestFilter 
                },
                color1 : {
                    type : 'v3',
                    value : color1
                },
                color2 : {
                    type : 'v3',
                    value : color2
                }
            };
            
            var material = new THREE.ShaderMaterial( {
                uniforms : uniforms,
                vertexShader : vertexShader,
                fragmentShader : colorizeShader
            } );

            var mesh = new THREE.Mesh( geometry, material );
            scene.add( mesh );
        } )();
    } )();

    ( function setupEvents(){
        function updateMouse( canvas, evt ) {
            var rect = canvas.getBoundingClientRect();
            mouse.x = evt.clientX - rect.left;
            mouse.y = evt.clientY - rect.top;
        }

        renderer.domElement.addEventListener( 'mousemove', function( evt ) {
            updateMouse( renderer.domElement, evt );
            uniforms2.mouse.value.x = mouse.x;
            uniforms2.mouse.value.y = (h - mouse.y);
        } );

        function onWindowResize( event ) {
            w = window.innerWidth;
            h = window.innerHeight;

            renderer.setSize( w, h );
            uniforms.resolution.value.x = w;
            uniforms.resolution.value.y = h;

            ping.setSize( w, h );
            pong.setSize( w, h );
            uniforms2.resolution.value.x = w;
            uniforms2.resolution.value.y = h;

            uniforms2.timer.value = 0;
            uniforms2.texture.value = startText;
        }
        onWindowResize();
        window.addEventListener( 'resize', onWindowResize, false );
    } )();

    ( function rendering(){
        var t=0;
        ( function render() {
            requestAnimationFrame( render );
            t++;
            if( t % 3 == 1 ){
                stepSim();

                renderer.render( scene, camera );
                ++ uniforms2.timer.value;
            }
        } )();

        function stepSim() {
            renderer.render( bufferScene, camera, ping, true );
            swapBuffers();
        }

        function swapBuffers() {
            var a = pong;
            pong = ping;
            ping = a;
            uniforms2.texture.value = pong.texture;
        }
    } )();
} );
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值