three.js 火焰效果

代码是网上找的代码,通过调参、修改、封装实现的。

代码:

/**
 * 火焰
 */

import * as THREE from '../build/three.module.js';

let MyFire3 = function () {

    let fireVertexShader = `
attribute vec4 orientation;
attribute vec3 offset;
attribute vec2 scale;
attribute float life;
attribute  random;

varying vec2 vUv;
varying  vRandom;
varying  vAlpha;

float range(float oldValue,float oldMin,1)">float oldMax,1)">float newMin,1)"> newMax) {
    float oldRange = oldMax - oldMin;
    float newRange = newMax - newMin;
    return (((oldValue - oldMin) * newRange) / oldRange) + newMin;
}

// From Inigo Quilez http://www.iquilezles.org/www/articles/functions/functions.htm
float pcurve(float x,1)">float a,1)"> b) {
    float k = pow(a + b,a + b) / (pow(a,a) * pow(b,b));
    return k * pow(x,a) * pow(1.0 - x,b);
}

void main() {
    vUv = uv;
    vRandom = random;

    vAlpha = pcurve(life,1.0,2.0);

    vec3 pos = position;

    pos.xy *= scale * vec2(range(pow(life,1.5),0.0,0.6),range(pow(life,0.6,1.2));

    vec4 or = orientation;
    vec3 vcV = cross(or.xyz,pos);
    pos = vcV * (2.0 * or.w) + (cross(or.xyz,vcV) * 2.0 + pos);

    gl_Position = projectionMatrix * modelViewMatrix * vec4(pos,1.0);
}
`;

    let fireFragmentShader = `
uniform sampler2D uMap;
uniform vec3 uColor1;
uniform vec3 uColor2;
uniform  uTime;

varying vec2 vUv;
varying  vAlpha;
varying  vRandom;

 main() {
    vec2 uv = vUv;

    float spriteLength = 10.0;
    uv.x /= spriteLength;
    float spriteIndex = mod(uTime * 0.1 + vRandom * 2.0,1)">);
    uv.x += floor(spriteIndex * spriteLength) / spriteLength;

    vec4 map = texture2D(uMap,uv);

    gl_FragColor.rgb = mix(uColor2,uColor1,map.r);
    gl_FragColor.a = vAlpha * map.a;
}
`;

    let embersVertexShader = `
attribute  size;
attribute  life;
attribute vec3 offset;

varying float impulse(float k,1)"> x) {
    float h = k * x;
    return h * exp(1.0 - h);
}

 main() {
    vAlpha = impulse(6.28,life);

    vec3 pos = position;
    pos += offset * vec3(life * 0.7 + 0.3,life * 0.9 + 0.1,life * 0.7 + 0.3);

    vec4 mvPosition = modelViewMatrix * vec4(pos,1)">);
    gl_PointSize = size * (80.0 / length(mvPosition.xyz));
    gl_Position = projectionMatrix * mvPosition;
}
`;

    let embersFragmentShader = `
uniform sampler2D uMap;
uniform vec3 uColor;

varying  main() {
    vec2 uv = vec2(gl_PointCoord.x,1.0 - gl_PointCoord.y);
    vec4 mask = uColor;
    gl_FragColor.a = mask.a * vAlpha * 0.8;
}
`;

    let hazeVertexShader = `
attribute vec3 base;
attribute vec3 offset;
attribute vec4 orientation;
attribute vec2 scale;
attribute  life;

varying  vAlpha;
varying vec2 vUv;

 uv;
    vAlpha = pcurve(life,1)"> position;

    pos.xy *= scale * (life * 0.7 + 0.3);

    vec4 or = pos);

    pos += base;
    pos += offset * vec3(life * 0.7 + 0.3,1)">);

    gl_Position = projectionMatrix * modelViewMatrix * vec4(pos,1)">);;
}
`;

    let hazeFragmentShader = `
uniform sampler2D uMap;
uniform sampler2D uMask;
uniform vec2 uResolution;

varying  main() {
    vec2 uv = gl_FragCoord.xy / uResolution;
    vec2 mask = texture2D(uMask,vUv).ra - vec2(0.5);
    uv -= mask * 0.1;
    vec4 tex = tex.rgb;
    gl_FragColor.a = vAlpha * 0.5;
}
`;

     random(min,max,precision) {
        var p = Math.pow(10return Math.round((min + Math.random() * (max - min)) * p) / p;
    }


    let _scene;
    let _renderer;
    let _camera;
    let _controls;
    let _rtt;
    let _fire;
    let _width;
    let _height;

    this.objs = [];

    let _self = this;

    this._isShow = false;

    let _pos_x;
    let _pos_y;
    let _pos_z;

    this.config =  (scene_,renderer_,camera_,controls_) {
        _width = 1920;
        _height = 1040;

        _renderer = renderer_;
        _scene = scene_;
        _camera = camera_;
        _controls = controls_;

        var _parameters = {
            minFilter: THREE.LinearFilter,magFilter: THREE.LinearFilter,format: THREE.RGBAFormat,stencilBuffer: 
        };
        _rtt = new THREE.WebGLRenderTarget(_width * 0.5,_height * 0.5this.setPosition =  name(x,y,z) {
        _pos_x = x;
        _pos_y = y;
        _pos_z = z;
    }

    this.showFire =  () {
        initFire();
        initEmbers();
        initHaze();
        true;
    }

    this.refresh =  () {
        _self.loop();
        _self.loop2();
        _self.loop3();
    }

    this.isShow =  () {
        return ._isShow;
    }

    this.hide =  () {
        _self.objs.map(obj => {
            _scene.remove(obj);
        });
        this.show =  {
            _scene.add(obj);
        });
        =====// Fire //========================================//     

     initFire() {
        var _geometry,_shader,_mesh,_group;
        var _num = 50;

        var _x = new THREE.Vector3(1,0);
        var _y = new THREE.Vector3(0,1,1)">var _z = );

        var _tipTarget = new THREE.Vector3();
        var _tip = var _diff =  THREE.Vector3();

        var _quat =  THREE.Quaternion();
        var _quat2 =  THREE.Quaternion();

        ( () {
            initGeometry();
            initInstances();
            initShader();
            initMesh();
        })();

         initGeometry() {
            _geometry =  THREE.InstancedBufferGeometry();
            _geometry.maxInstancedCount = _num;

            var shape = new THREE.PlaneBufferGeometry(500,500);
            shape.translate(0,0.4,1)">);
            var data = shape.attributes;

            _geometry.addAttribute('position',1)">new THREE.BufferAttribute(new Float32Array(data.position.array),3));
            _geometry.addAttribute('uv',1)">new Float32Array(data.uv.array),2));
            _geometry.addAttribute('normal',1)">new Float32Array(data.normal.array),1)">));
            _geometry.setIndex(new Uint16Array(shape.index.array),1)">));
            shape.dispose();
        }

         initInstances() {
            var orientation = new THREE.InstancedBufferAttribute(new Float32Array(_num * 4),4var randoms = new Float32Array(_num),1)">var scale = new Float32Array(_num * 2),1)">var life = );

            for (let i = 0; i < _num; i++) {
                orientation.setXYZW(i,0,1)">);
                life.setX(i,i / _num + 1);
            }

            _geometry.addAttribute('orientation''life' initShader() {
            var uniforms = {
                uMap: {
                    type: 't'null
                },uColor1: {
                    type: 'c'new THREE.Color(0x961800)
                }, red
                uColor2: {
                    type: 'c'new THREE.Color(0x4b5828 yellow
                uTime: {
                    type: 'f'=  THREE.ShaderMaterial({
                uniforms: uniforms,vertexShader: fireVertexShader,fragmentShader: fireFragmentShader,blending: THREE.AdditiveBlending,transparent: var textureLoader =  THREE.TextureLoader();
            textureLoader.load('images/myFire3/flame.png',t => _shader.uniforms.uMap.value = t);
        }

         initMesh() {
            _group =  THREE.Group();
            _mesh =  THREE.Mesh(_geometry,_shader);
            _mesh.frustumCulled = ;
            _group.add(_mesh);
            _scene.add(_group);
            _self.objs.push(_group);
            _fire = _group;
        }

        _self.loop =  () {
            let e = 100;
            _shader.uniforms.uTime.value = e * 0.001;

            var life = _geometry.attributes.life;
            var orientation = _geometry.attributes.orientation;
            var scale = _geometry.attributes.scale;
            var randoms = _geometry.attributes.random;

            ) {
                var value = life.array[i];
                value += 0.04;

                if (value > 1) {
                    value -= 1;

                    _quat.setFromAxisAngle(_y,random(0,3.14,1)">));
                    _quat2.setFromAxisAngle(_x,random(-1,2) * 0.1);
                    _quat.multiply(_quat2);
                    _quat2.setFromAxisAngle(_z,2) * 0.3);
                    _quat.multiply(_quat2);
                    orientation.setXYZW(i,_quat.x,_quat.y,_quat.z,_quat.w);

                    scale.setXY(i,random(0.8,1.2,3),random(0.8,1)">));
                    randoms.setX(i,1)">));
                }

                life.setX(i,value);
            }
            life.needsUpdate = ;
            orientation.needsUpdate = ;
            scale.needsUpdate = ;
            randoms.needsUpdate = ;

            _group.position.x = _pos_x; Math.sin(e * 0.002) * 1.4;
            _group.position.y = _pos_y + 150; Math.cos(e * 0.0014) * 0.2;
            _group.position.z = _pos_z; Math.cos(e * 0.0014) * 0.5;

            let tipOffset = 0.4;
            _tipTarget.copy(_group.position);
            _tipTarget.y += tipOffset;
            _tip.lerp(_tipTarget,0.1);

            _diff.copy(_tip);
            _diff.sub(_group.position);
            let length = _diff.length();
            _group.scale.y = (length / tipOffset - 1) * 0.4 + 1;

            _group.quaternion.setFromUnitVectors(_y,_diff.normalize());
        }
    }

    =====// Embers //========================================//     

     initEmbers() {
        var _num = 8;

        ( () {
            initGeometry();
            initShader();
            initMesh();
        })();

         THREE.BufferGeometry();
            _geometry.addAttribute('position',1)">new Float32Array(_num * 3),1)">));
            _geometry.addAttribute('offset',1)">));
            _geometry.addAttribute('size',1)">));
            _geometry.addAttribute('life',1)">));
            );
            _geometry.addAttribute('scale'for (var i = 0; i < _num; i++) {
                _geometry.attributes.life.setX(i,3) + 1);
            }
        }

        new THREE.Color(0xffe61e THREE.TextureLoader();
            textureLoader.load('images/myFire3/ember.png',1)"> initMesh() {
            _points =  THREE.Points(_geometry,_shader);
            _points.frustumCulled = ;
            _scene.add(_points);
            _self.objs.push(_points);
        }

        _self.loop2 =  () {
            var position = _geometry.attributes.position;
            var size = _geometry.attributes.size;
            var offset = _geometry.attributes.offset;
             life.array[i];
                value += 0.02;

                    position.setXYZ(i,_pos_x,_pos_y + 0.1),random(200,600,random(-100,100,1)">)
                    );
                    size.setX(i,random(20,1)">));

                    scale.setXY(i,50,50);
                }

                life.setX(i,value);
            }

            life.needsUpdate = ;
            position.needsUpdate = ;
            size.needsUpdate = ;
            offset.needsUpdate = ;
        }
    }

    =====// Haze //========================================//     

     initHaze() {
        var _num = 4 () {
            initGeometry();
            initInstances();
            initShader();
            initMesh();
            window.addEventListener('resize',resizeHaze,1)">);
            resizeHaze();
        })();

        new THREE.PlaneBufferGeometry(0.1,0.1var base = var offset = var rotation = );
            }

            _geometry.addAttribute('base''orientation''life' initShader() {
            let dpr = _renderer.getPixelRatio();
            'v2'new THREE.Vector2(_width * dpr,_height * dpr)
                },vertexShader: hazeVertexShader,fragmentShader: hazeFragmentShader,1)"> THREE.TextureLoader();
            textureLoader.load('images/myFire3/haze.png',t => _shader.uniforms.uMask.value = initMesh() {
            _mesh = ;
            _scene.add(_mesh);
            _self.objs.push(_mesh);
        }

         resizeHaze() {
            let dpr = _renderer.getPixelRatio();
            _shader.uniforms.uMap.value = _rtt.texture;
            _shader.uniforms.uResolution.value.set(_width * dpr,1)"> dpr);
        }

        _self.loop3 =  () {

            let e = 100;
            _mesh.visible = ;
            _renderer.render(_scene,_camera,_rtt);
            _mesh.visible = var base = _geometry.attributes.base;
            var rotation = _geometry.attributes.rotation;
             life.array[i];
                value += 0.008;

                    rotation.setX(i,1)">));

                    base.setXYZ(i,random(-220,220,random(300,0
                    );
                    scale.setXY(i,random(0.6,3));
                    scale.setXY(i,50,1)">);
                }

                _quat.copy(_camera.quaternion);
                _quat2.setFromAxisAngle(_z,rotation.array[i]);
                _quat.multiply(_quat2);
                orientation.setXYZW(i,_quat.w);

                life.setX(i,1)">;
            base.needsUpdate = ;
        }
    }


}

MyFire3.prototype.constructor = MyFire3;

export { MyFire3 }
View Code

如何使用(部分代码):

import { MyFire3 } from '../js.my/MyFire3.js';


let myFire3;


if (!myFire3) {
    myFire3 =  MyFire3();
    myFire3.config(scene,renderer,camera,controls);
    myFire3.setPosition(417,1134);
    myFire3.showFire();
} else {
    if (myFire3.isShow()) {
        myFire3.hide();
    }  {
        myFire3.show();
    }
}


 renderLoop() {
    requestAnimationFrame(renderLoop);

    myFire3 && myFire3.refresh && myFire3.refresh();
}

renderLoop();
View Code

说明:myFire3.config的参数中的controls未用到,scene、renderer、camera分别是three.js的Scene、WebGLRenderer和PerspectiveCamera对象

 

原文地址:https://www.cnblogs.com/s0611163

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


kindeditor4.x代码高亮功能默认使用的是prettify插件,prettify是Google提供的一款源代码语法高亮着色器,它提供一种简单的形式来着色HTML页面上的程序代码,实现方式如下: 首先在编辑器里面插入javascript代码: 确定后会在编辑器插入这样的代码: <pre
这一篇我将介绍如何让kindeditor4.x整合SyntaxHighlighter代码高亮,因为SyntaxHighlighter的应用非常广泛,所以将kindeditor默认的prettify替换为SyntaxHighlighter代码高亮插件 上一篇“让kindeditor显示高亮代码”中已经
js如何实现弹出form提交表单?(图文+视频)
js怎么获取复选框选中的值
js如何实现倒计时跳转页面
如何用js控制图片放大缩小
JS怎么获取当前时间戳
JS如何判断对象是否为数组
JS怎么获取图片当前宽高
JS对象如何转为json格式字符串
JS怎么获取图片原始宽高
怎么在click事件中调用多个js函数
js如何往数组中添加新元素
js如何拆分字符串
JS怎么对数组内元素进行求和
JS如何判断屏幕大小
js怎么解析json数据
js如何实时获取浏览器窗口大小
原生JS实现别踩白块小游戏(五)
原生JS实现别踩白块小游戏(一)