three.js 实现烟雾, 火灾 烟雾 着火的效果

three.js 实现烟雾, 火灾 烟雾 着火的效果

预览

在这里插入图片描述

import * as THREE from "three";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";

var delta;
var time;

var vs = [];
var fs = [];
var mesh = [];
var tex = [];
var mat = [];

var texture_loader = new THREE.TextureLoader();

const DOM = document.querySelector("#box");
const width = DOM.clientWidth;
const height = DOM.clientHeight;

const renderer = new THREE.WebGLRenderer({
    antialias: true,
    alpha: true
});
renderer.setClearColor(0xb9eeff, 1);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(width, height, false);
DOM.appendChild(renderer.domElement);

const camera = new THREE.PerspectiveCamera(
    45,
    width / height,
    0.05,
    100000
);
camera.position.set(5,5,5)
const scene = new THREE.Scene();
const pl1 = new THREE.PointLight(0xfee3b1, 2);
pl1.position.set(-20, 20, 20);
scene.add(pl1);

const controls = new OrbitControls(camera,renderer.domElement)
controls.target.set(0,0.5,0)

const clock = new THREE.Clock();

tex["smoke"] = texture_loader.load(
    "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAF0WlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDUgNzkuMTYzNDk5LCAyMDE4LzA4LzEzLTE2OjQwOjIyICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIwLTEwLTA2VDE3OjEwOjAzKzAzOjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyMi0wMi0wNlQxMzozOTo0MSswMzowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMi0wMi0wNlQxMzozOTo0MSswMzowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MTA5NzNhNjYtNTFmMC1iMDRlLWE5NDMtNzVjZmFjNDYxZTc4IiB4bXBNTTpEb2N1bWVudElE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"
);

tex["fire"] = texture_loader.load(
    "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAACXBIWXMAAAsTAAALEwEAmpwYAAAF0WlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDUgNzkuMTYzNDk5LCAyMDE4LzA4LzEzLTE2OjQwOjIyICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIyLTAxLTI2VDEyOjMzOjQyKzAzOjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyMi0wMi0wNlQxNjoxMjoyOCswMzowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMi0wMi0wNlQxNjoxMjoyOCswMzowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6ZjliNDEzZTUtOTUyNy0yMjQxLTgwZjktMDBkYjM5Y2NjOGYyIiB4bXBNTTpEb2N1bWVudElE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"
);

tex["grass"] = texture_loader.load(
    "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAACXBIWXMAAAsTAAALEwEAmpwYAAAGoWlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDUgNzkuMTYzNDk5LCAyMDE4LzA4LzEzLTE2OjQwOjIyICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIwLTEwLTA2VDE3OjEwOjAzKzAzOjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyMi0wMS0wNlQwOTo0NzowNyswMzowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMi0wMS0wNlQwOTo0NzowNyswMzowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6ODU0MzgzMmUtMTBiMy1kZDRlLWE4ZDQtZWY1ZjcxZWQ5YWI5IiB4bXBNTTpEb2N1bWVudElEPSJhZG9iZTpkb2NpZDpwaG90b3Nob3A6ZDA2OWRjYTItNmM4OC01OTRiLThkMjMtMDZlYTc1OWEzNzY2IiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6MWJjZmIxZWUtZjc2OC0wODQxLWI1Y2UtMDYwYjVjZmQ1NjQ0Ij4gPHhtcE1NOkhpc3Rvcnk+IDxyZGY6U2VxPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0iY3JlYXRlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDoxYmNmYjFlZS1mNzY4LTA4NDEtYjVjZS0wNjBiNWNmZDU2NDQiIHN0RXZ0OndoZW49IjIwMjAtMTAtMDZUMTc6MTA6MDMrMDM6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE5IChXaW5kb3dzKSIvPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0ic2F2ZWQiIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6ODZhMzU2YTEtZjY1NC1mZDQyLWFhODctNzUyZTlkYzc3ODRlIiBzdEV2dDp3aGVuPSIyMDIyLTAxLTA0VDEzOjIzOjM0KzAzOjAwIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHN0RXZ0OmNoYW5nZWQ9Ii8iLz4gPHJkZjpsaSBzdEV2dDphY3Rpb249InNhdmVkIiBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOjg1NDM4MzJlLTEwYjMtZGQ0ZS1hOGQ0LWVmNWY3MWVkOWFiOSIgc3RFdnQ6d2hlbj0iMjAyMi0wMS0wNlQwOTo0NzowNyswMzowMCIgc3RFdnQ6c29mdHdhcmVBZ2VudD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiBzdEV2dDpjaGFuZ2VkPSIvIi8+IDwvcmRmOlNlcT4gPC94bXBNTTpIaXN0b3J5PiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PuQrPqkAAB4KSURBVHja5XtplF1Hde63q85056HnuVvdrZZkyZZtWfIo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"
);

tex["floor"] = texture_loader.load(
    "data:image/png;base64,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"
);
tex["floor"].wrapS = tex["floor"].wrapT = THREE.RepeatWrapping;
tex["floor"].repeat.set(20, 20);

vs["sprite"] = `


attribute vec3 offset;
attribute vec2 scale;
attribute vec4 quaternion;
attribute float rotation;
attribute vec4 color;
attribute float blend;
attribute float texture;
uniform float time;
varying vec2 vUv;
varying vec4 vColor;
varying float vBlend;
varying float num;
vec3 localUpVector=vec3(0.0,1.0,0.0);


void main(){


float angle=time*rotation;
vec3 vRotated=vec3(position.x*scale.x*cos(angle)-position.y*scale.y*sin(angle),position.y*scale.y*cos(angle)+position.x*scale.x*sin(angle),position.z);


vUv=uv;
vColor=color;
vBlend=blend;
num=texture;


vec3 vPosition;




/*
vec3 vLook=normalize(offset-cameraPosition);
vec3 vRight=normalize(cross(vLook,localUpVector));
vec3 vUp=normalize(cross(vLook,vRight));
vPosition=vRight*vRotated.x+vUp*vRotated.y+vLook*vRotated.z;
*/


vec3 vLook=offset-cameraPosition;
vec3 vRight=normalize(cross(vLook,localUpVector));
vPosition=vRotated.x*vRight+vRotated.y*localUpVector+vRotated.z;



gl_Position=projectionMatrix*modelViewMatrix*vec4(vPosition+offset,1.0);


}


`;

fs["sprite"] = `


const int count=3;
uniform sampler2D map[count];
varying vec2 vUv;
varying vec4 vColor;
varying float vBlend;
varying float num;


void main(){


if(num==0.0){ gl_FragColor=texture2D(map[0],vUv)*vColor; }
else if(num==1.0){ gl_FragColor=texture2D(map[1],vUv)*vColor; }
else if(num==2.0){ gl_FragColor=texture2D(map[2],vUv)*vColor; }


gl_FragColor.rgb*=gl_FragColor.a;
gl_FragColor.a*=vBlend;


}


`;

var particles = [];

// ____________________ GRASS ____________________

var particles_grass_a = [];

particles_grass_a.push({
    offset: [10, 2, 0],
    scale: [4, 4],
    quaternion: [0, 0, 0, 4],
    rotation: 0,
    color: [1, 1, 1, 1],
    blend: 1,
    texture: 2,
});

for (var n = 0; n < 100; n++) {
    var scale = Math.random() * 0.5 + 0.5;
    particles_grass_a.push({
        offset: [Math.random() * 20 - 10, scale / 2, Math.random() * 20 - 10],
        scale: [scale, scale],
        quaternion: [0, 0, 0, 4],
        rotation: 0,
        color: [1, 1, 1, 1],
        blend: 1,
        texture: 2,
    });
}

// ____________________ SMOKE ____________________

var wind_x = 0.002;
var wind_y = 0;
var wind_z = 0;

var particles_smoke_a = [];

var particles_emmiter = [];

particles_emmiter.push({
    position: { x: -2, y: 0, z: -4 },
    radius_1: 0.02,
    radius_2: 1,
    radius_height: 5,
    add_time: 0.1,
    elapsed: 0,
    live_time_from: 7,
    live_time_to: 7.5,
    opacity_decrease: 0.008,
    rotation_from: 0.5,
    rotation_to: 1,
    speed_from: 0.005,
    speed_to: 0.01,
    scale_from: 0.2,
    scale_increase: 0.004,
    color_from: [2, 2, 2],
    color_to: [0, 0, 0],
    color_speed_from: 0.4,
    color_speed_to: 0.4,
    brightness_from: 1,
    brightness_to: 1,
    opacity: 1,
    blend: 0.8,
    texture: 1,
});

particles_emmiter.push({
    position: { x: 0, y: 0, z: -4 },
    radius_1: 0.02,
    radius_2: 1,
    radius_height: 5,
    add_time: 0.1,
    elapsed: 0,
    live_time_from: 10,
    live_time_to: 10.5,
    opacity_decrease: 0.008,
    rotation_from: 0.5,
    rotation_to: 1,
    speed_from: 0.005,
    speed_to: 0.01,
    scale_from: 0.2,
    scale_increase: 0.004,
    color_from: [0.1, 0.1, 0.1],
    color_to: [0.1, 0.1, 0.1],
    color_speed_from: 1,
    color_speed_to: 1,
    brightness_from: 1,
    brightness_to: 1,
    opacity: 1,
    blend: 1,
    texture: 0,
});

particles_emmiter.push({
    position: { x: 2, y: 0, z: -4 },
    radius_1: 0.02,
    radius_2: 0.4,
    radius_height: 5,
    add_time: 0.1,
    elapsed: 0,
    live_time_from: 4,
    live_time_to: 4.5,
    opacity_decrease: 0.004,
    rotation_from: 2,
    rotation_to: 3,
    speed_from: 0.005,
    speed_to: 0.01,
    scale_from: 0.1,
    scale_increase: 0.003,
    color_from: [1, 1, 1],
    color_to: [1, 1, 1],
    color_speed_from: 1,
    color_speed_to: 1,
    brightness_from: 1.0,
    brightness_to: 1,
    opacity: 0.4,
    blend: 0.5,
    texture: 0,
});

particles_emmiter.push({
    position: { x: 4, y: 0, z: -4 },
    radius_1: 2,
    radius_2: 2,
    radius_height: 5,
    add_time: 0.1,
    elapsed: 0,
    live_time_from: 1,
    live_time_to: 1.5,
    opacity_decrease: 0.004,
    rotation_from: 2,
    rotation_to: 3,
    speed_from: 0.005,
    speed_to: 0.01,
    scale_from: 0.0,
    scale_increase: 0.003,
    color_from: [1, 2, 1],
    color_to: [1, 1, 2],
    color_speed_from: 1,
    color_speed_to: 1,
    brightness_from: 1.0,
    brightness_to: 1,
    opacity: 0.4,
    blend: 0.7,
    texture: 0,
});

particles_emmiter.push({
    position: { x: 0, y: 1, z: 0 },
    radius_1: 0.02,
    radius_2: 1,
    radius_height: 5,
    add_time: 0.01,
    elapsed: 0,
    live_time_from: 1,
    live_time_to: 1.5,
    opacity_decrease: 0.008,
    rotation_from: 0.5,
    rotation_to: 1,
    speed_from: 0.005,
    speed_to: 0.01,
    scale_from: 0.2,
    scale_increase: 0.004,
    color_from: [2, 2, 2],
    color_to: [0, 0, 0],
    color_speed_from: 1,
    color_speed_to: 1,
    brightness_from: 1,
    brightness_to: 1,
    opacity: 1,
    blend: 0.8,
    texture: 1,
});

// ____________________ PARTICLES EMMITER EMMIT ____________________

function particles_emmiter_emmit(item) {
    var radius_1 = item.radius_1 * Math.sqrt(Math.random());
    var theta = 2 * Math.PI * Math.random();
    var x_1 = item.position.x + radius_1 * Math.cos(theta);
    var z_1 = item.position.z + radius_1 * Math.sin(theta);

    var radius_2 = item.radius_2 * Math.sqrt(Math.random());
    var theta = 2 * Math.PI * Math.random();
    var x_2 = x_1 + radius_2 * Math.cos(theta);
    var z_2 = z_1 + radius_2 * Math.sin(theta);

    let direction_x = x_2 - x_1;
    let direction_y = item.radius_height;
    let direction_z = z_2 - z_1;

    var speed =
        Math.random() * (item.speed_to - item.speed_from) + item.speed_from;

    var divide =
        (1 /
            Math.sqrt(
                direction_x * direction_x +
                    direction_y * direction_y +
                    direction_z * direction_z
            )) *
        speed;
    direction_x *= divide;
    direction_y *= divide;
    direction_z *= divide;

    var brightness =
        Math.random() * (item.brightness_to - item.brightness_from) +
        item.brightness_from;

    particles_smoke_a.push({
        offset: [x_1, item.position.y, z_1],
        scale: [item.scale_from, item.scale_from],
        quaternion: [direction_x, direction_y, direction_z, 3],
        rotation:
            Math.random() * (item.rotation_to - item.rotation_from) +
            item.rotation_from,
        color: [1, 1, 1, item.opacity],
        blend: item.blend,
        texture: item.texture,
        live:
            Math.random() * (item.live_time_to - item.live_time_from) +
            item.live_time_from,
        scale_increase: item.scale_increase,
        opacity_decrease: item.opacity_decrease,
        color_from: [
            item.color_from[0] * brightness,
            item.color_from[1] * brightness,
            item.color_from[2] * brightness,
        ],
        color_to: [
            item.color_to[0] * brightness,
            item.color_to[1] * brightness,
            item.color_to[2] * brightness,
        ],
        color_speed:
            Math.random() * (item.color_speed_to - item.color_speed_from) +
            item.color_speed_from,
        color_pr: 0,
    });
}

// ____________________ PERTICLES EMMITER UPDATE ____________________

function particles_emmiter_update() {
    var item = particles_emmiter[4].position;
    item.x = Math.sin(time / 1) * 4;
    item.z = Math.cos(time / 1) * 4;

    var max = particles_emmiter.length;

    for (var n = 0; n < max; n++) {
        var item = particles_emmiter[n];

        var add = 0;

        item.elapsed += delta;
        add = Math.floor(item.elapsed / item.add_time);
        item.elapsed -= add * item.add_time;
        if (add > (0.016 / item.add_time) * 60 * 1) {
            item.elapsed = 0;
            add = 0;
        }

        while (add--) {
            particles_emmiter_emmit(item);
        }
    }

    var max = particles_smoke_a.length;
    var alive = new Array(max);
    var i = 0;

    for (var j = 0; j < max; j++) {
        var item = particles_smoke_a[j];

        if (item.color_pr < 1) {
            var color_r =
                item.color_from[0] +
                (item.color_to[0] - item.color_from[0]) * item.color_pr;
            var color_g =
                item.color_from[1] +
                (item.color_to[0] - item.color_from[1]) * item.color_pr;
            var color_b =
                item.color_from[1] +
                (item.color_to[0] - item.color_from[2]) * item.color_pr;
            item.color_pr += delta * item.color_speed;
            item.color[0] = color_r;
            item.color[1] = color_g;
            item.color[2] = color_b;
        } else {
            item.color[0] = item.color_to[0];
            item.color[1] = item.color_to[1];
            item.color[2] = item.color_to[2];
        }

        item.offset[0] += item.quaternion[0] + wind_x;
        item.offset[1] += item.quaternion[1] + wind_y;
        item.offset[2] += item.quaternion[2] + wind_z;
        item.scale[0] += item.scale_increase;
        item.scale[1] += item.scale_increase;

        if (item.live > 0) {
            item.live -= delta;
        } else {
            item.color[3] -= item.opacity_decrease;
        }
        if (item.color[3] > 0) {
            alive[i] = item;
            i++;
        }
    }

    alive.length = i;
    particles_smoke_a = alive;
}

// ____________________ PARTICLES UPDATE ____________________

function particles_update() {
    particles_emmiter_update();

    particles = [];

    var max_1 = particles_smoke_a.length;
    particles.length = max_1;
    for (var n = 0; n < max_1; n++) {
        particles[n] = particles_smoke_a[n];
    }

    var max_2 = max_1 + particles_grass_a.length;
    particles.length = max_2;
    var i = 0;
    for (var n = max_1; n < max_2; n++) {
        particles[n] = particles_grass_a[i];
        i++;
    }

    var count = particles.length;
    var item = camera.position;
    var x = item.x;
    var y = item.y;
    var z = item.z;

    for (var n = 0; n < count; n++) {
        var item = particles[n].offset;
        particles[n].d = Math.sqrt(
            Math.pow(x - item[0], 2) +
                Math.pow(y - item[1], 2) +
                Math.pow(z - item[2], 2)
        );
    }

    particles.sort((a, b) => b.d - a.d);

    var offset = new Float32Array(count * 3);
    var scale = new Float32Array(count * 2);
    var quaternion = new Float32Array(count * 4);
    var rotation = new Float32Array(count);
    var color = new Float32Array(count * 4);
    var blend = new Float32Array(count);
    var texture = new Float32Array(count);

    for (var n = 0; n < count; n++) {
        // 1 VALUE
        var item = particles[n];
        rotation[n] = item.rotation;
        texture[n] = item.texture;
        blend[n] = item.blend;

        // 2 VALUE
        var p = n * 2;
        var one = p + 1;
        var i_scale = item.scale;
        scale[p] = i_scale[0];
        scale[one] = i_scale[1];

        // 3 VALUE
        var p = n * 3;
        var one = p + 1;
        var two = p + 2;
        var i_offset = item.offset;
        offset[p] = i_offset[0];
        offset[one] = i_offset[1];
        offset[two] = i_offset[2];

        // 4 VALUE
        var p = n * 4;
        var one = p + 1;
        var two = p + 2;
        var three = p + 3;
        var i_color = item.color;
        color[p] = i_color[0];
        color[one] = i_color[1];
        color[two] = i_color[2];
        color[three] = i_color[3];
        var i_quaternion = item.quaternion;
        quaternion[p] = i_quaternion[0];
        quaternion[one] = i_quaternion[1];
        quaternion[two] = i_quaternion[2];
        quaternion[three] = i_quaternion[3];
    }

    var item = mesh["sprite"].geometry.attributes;
    item.offset = new THREE.InstancedBufferAttribute(offset, 3).setUsage(
        THREE.DynamicDrawUsage
    );
    item.scale = new THREE.InstancedBufferAttribute(scale, 2).setUsage(
        THREE.DynamicDrawUsage
    );
    item.quaternion = new THREE.InstancedBufferAttribute(
        quaternion,
        4
    ).setUsage(THREE.DynamicDrawUsage);
    item.rotation = new THREE.InstancedBufferAttribute(
        rotation,
        1
    ).setUsage(THREE.DynamicDrawUsage);
    item.color = new THREE.InstancedBufferAttribute(color, 4).setUsage(
        THREE.DynamicDrawUsage
    );
    item.blend = new THREE.InstancedBufferAttribute(blend, 1).setUsage(
        THREE.DynamicDrawUsage
    );
    item.texture = new THREE.InstancedBufferAttribute(texture, 1).setUsage(
        THREE.DynamicDrawUsage
    );

    mesh["sprite"].geometry._maxInstanceCount = count;
}

var geometry = new THREE.InstancedBufferGeometry();
geometry.setAttribute(
    "position",
    new THREE.Float32BufferAttribute(
        new Float32Array([
            -0.5, 0.5, 0, -0.5, -0.5, 0, 0.5, 0.5, 0, 0.5, -0.5, 0, 0.5, 0.5, 0,
            -0.5, -0.5, 0,
        ]),
        3
    )
);
geometry.setAttribute(
    "uv",
    new THREE.Float32BufferAttribute(
        new Float32Array([0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0]),
        2
    )
);
geometry.setAttribute(
    "offset",
    new THREE.InstancedBufferAttribute(new Float32Array(), 3)
);
geometry.setAttribute(
    "scale",
    new THREE.InstancedBufferAttribute(new Float32Array(), 2)
);
geometry.setAttribute(
    "quaternion",
    new THREE.InstancedBufferAttribute(new Float32Array(), 4)
);
geometry.setAttribute(
    "rotation",
    new THREE.InstancedBufferAttribute(new Float32Array(), 1)
);
geometry.setAttribute(
    "color",
    new THREE.InstancedBufferAttribute(new Float32Array(), 4)
);
geometry.setAttribute(
    "blend",
    new THREE.InstancedBufferAttribute(new Float32Array(), 1)
);
geometry.setAttribute(
    "texture",
    new THREE.InstancedBufferAttribute(new Float32Array(), 1)
);

mat["sprite"] = new THREE.ShaderMaterial({
    uniforms: {
        map: { value: [tex["smoke"], tex["fire"], tex["grass"]] },
        time: { value: 0 },
    },
    vertexShader: vs["sprite"],
    fragmentShader: fs["sprite"],
    //side:THREE.DoubleSide,
    transparent: true,
    depthWrite: false,
    blending: THREE.CustomBlending,
    blendEquation: THREE.AddEquation,
    blendSrc: THREE.OneFactor,
    blendDst: THREE.OneMinusSrcAlphaFactor,
});

mesh["sprite"] = new THREE.Mesh(geometry, mat["sprite"]);
mesh["sprite"].frustumCulled = false;
mesh["sprite"].matrixAutoUpdate = false;
mesh["sprite"].updateMatrixWorld = function () {};
scene.add(mesh["sprite"]);

mat["floor"] = new THREE.MeshStandardMaterial({
    map: tex["floor"],
    bumpMap: tex["floor"],
    bumpScale: 0.01,
    metalness: 0.16,
});

mesh["floor"] = new THREE.Mesh(
    new THREE.BoxGeometry(20, 1, 20),
    mat["floor"]
);
mesh["floor"].position.y = -0.5;
scene.add(mesh["floor"]);

scene.add(new THREE.AmbientLight(0xffffff, 3));

var update_time = 0;

function loop() {
    requestAnimationFrame(loop);
    delta = clock.getDelta();
    time = clock.elapsedTime.toFixed(2);

    var started = performance.now();
    particles_update();

    update_time -= delta;

    mat["sprite"].uniforms.time.value = clock.elapsedTime;

    renderer.render(scene, camera);
}

loop();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值