three+webgl实现飞机引擎运行空气流动粒子动画效果代码

代码语言:html

所属分类:粒子

代码描述:three+webgl实现飞机引擎运行空气流动粒子动画效果代码

代码标签: 引擎 运行 空气 流动 粒子 动画 效果

下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开

<!DOCTYPE html>
<html lang="en" >

<head>

  <meta charset="UTF-8">
  

  
  
<style>
body {
  margin: 0;
  height: 100vh;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #222;
}
</style>



</head>

<body >
  

  
      <script type="module">
import * as THREE from "https://threejs.org/build/three.module.js";
import { OrbitControls } from "https://threejs.org/examples/jsm/controls/OrbitControls.js";

let camera, scene, renderer;
let mainPropeller, bladeSetA, bladeSetB, bladeSetC;
let step = 0;
const { PI, random, sin, cos } = Math;
const TAU = 2 * PI;
const uniforms = {
  time: { value: 0 } };


const map = (value, sMin, sMax, dMin, dMax) => {
  return dMin + (value - sMin) / (sMax - sMin) * (dMax - dMin);
};
const range = (n, m = 0) =>
Array(n).
fill(m).
map((i, j) => i + j);
const vec = (x = 0, y = 0, z = 0) => new THREE.Vector3(x, y, z);
const polar = (ang, r = 1) => [r * cos(ang), r * sin(ang)];
const bladeGeometry = getBladeGeometry();

function init() {
  scene = new THREE.Scene();

  renderer = new THREE.WebGLRenderer({ antialias: true });
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);

  camera = new THREE.PerspectiveCamera(
  60,
  window.innerWidth / window.innerHeight,
  1,
  1000);

  camera.position.set(-44.93624743716165, 27.39247486400745, 85.03167637469498);
  camera.rotation.x = -0.31164690514668836;
  camera.rotation.y = -0.46605157569574196;
  camera.rotation.z = -0.1437609504660436;

  const controls = new OrbitControls(camera, renderer.domElement);

  addAmbientLight(scene);
  addDirectionalLight(scene);
  addResizeHandler(renderer, camera);
  addObjects(scene);
  render();
}

function render() {
  update();

  renderer.render(scene, camera);
  requestAnimationFrame(render);
}

function addObjects(scene) {
  createAxis(scene);

  mainPropeller = createMainPropeller(scene);

  bladeSetB = createBladeSetStageB(scene);
  bladeSetC = createBladeSetStageC(scene);
  bladeSetA = createBladeSetStageA(scene);
  createAirParticles(scene, uniforms);
  createGasParticles(scene, uniforms);
}

function update() {
  mainPropeller.rotation.x += 0.02;
  bladeSetA.rotation.x += 0.01;
  bladeSetB.rotation.x -= 0.01;
  bladeSetC.rotation.x += 0.01;

  step = (step + 1) % 500;

  uniforms.time.value = step / 500;
}
init();

function createAxis(scene) {
  function getPath() {
    const c1 = curve(
    [3.94, 8.851],
    [3.98, 12.526],
    [2.123, 14.144],
    [2.063, 17.139]);

    const c2 = line([2.063, 17.139], [1.76, 38.948]);
    const c3 = curve(
    [1.76, 38.948],
    [2.349, 40.783],
    [3.988, 42.028],
    [4.119, 43.994]);

    const c4 = line([4.119, 43.994], [4.119, 47.009]);
    const c5 = curve(
    [4.119, 47.009],
    [3.988, 51.596],
    [-0.01, 55.266],
    [0.056, 55.266]);


    const path = new THREE.CurvePath();
    path.add(c1);
    path.add(c2);
    path.add(c3);
    path.add(c4);
    path.add(c5);
    return path.getSpacedPoints(100);
  }
  const geometry = new THREE.LatheGeometry(getPath(), 32);
  const material = mat("#1a508b");
  const lathe = new THREE.Mesh(geometry, material);
  lathe.rotation.z = PI / 2;

  lathe.position.x = 30;
  scene.add(lathe);
}

function addResizeHandler(renderer, camera) {
  window.addEventListener(
  "resize",
  () => {
    const { innerWidth: w, innerHeight: h } = window;
    renderer.setSize(w, h);
    camera.aspect = w / h;
    camera.updateProjectionMatrix();
  },
  false);

}

function addDirectionalLight(scene) {
  const color = 0xffffff;
  const intensity = 0.6;
  const light = new THREE.DirectionalLight(color, intensity);
  light.position.set(-1, 2, 4);
  scene.add(light);
}

function addAmbientLight(scene) {
  const color = 0xffffff;
  const intensity = 0.6;
  const light = new THREE.AmbientLight(color, intensity);
  scene.add(light);
}

function createGasParticles(scene, uniforms) {
  const particles = 10000;

  function getPathTexture() {
    const points = 1000;
    const c1 = curve(
    [0.222, -0.013],
    [0.47, 0.365],
    [0.866, 1.179],
    [0.979, 2.012]);

    const c2 = curve(
    [0.979, 2.012],
    [1.415, 4.167],
    [1.487, 6.031],
    [1.366, 7.944]);

    const path = new THREE.CurvePath();
    path.add(c1);
    path.add(c2);

    const data = path.
    getSpacedPoints(points).
    reduce((acc, { x, y, z }) => [...acc, x, y, z], []);

    return new THREE.DataTexture(
    new Float32Array(data),
    points + 1,
    1,
    THREE.RGBFormat,
    THREE.FloatType);

  }

  const fragmentShader = `
varying float alpha;
varying vec3 vColor;
float map(float value, float sMin, float sMax, float dMin, float dMax){
    return dMin + ((value - sMin) / (sMax - sMin)) * (dMax - dMin);
}
vec3 hsb2rgb( in vec3 c ){
    vec3 rgb = clamp(abs(mod(c.x*6.0+vec3(0.0,4.0,2.0),
                             6.0)-3.0)-1.0,
                     0.0,
                     1.0 );
    rgb = rgb*rgb*(3.0-2.0*rgb);
    return c.z * mix( vec3(1.0), rgb, c.y);
}

void main() {
    vec3 c = hsb2rgb(vec3(map(alpha, 0.0, 1.0, 0.0, 0.25), 0.9, 0.9)) ;
    gl_FragColor = vec4( c, 1.0-alpha );
}

`;

  const vertexShader = `
uniform sampler2D tex;
attribute vec3 config;
uniform float time;
varying vec3 vColor;
varying float alpha;
const float TAU = 6.2831853071;
  float map(float value, float sMin, float sMax, float dMin, float dMax){
      return dMin + ((value - sMin) / (sMax - sMin)) * (dMax - dMin);
  }

  vec2 polar(float ang, float r){
      return vec2(r*cos(ang), r*sin(ang));
  }
void main() {

    float radius = config.x;
    float ang = config.y;
    float offset = config.z;


    alpha = mod(offset+time*3., 1.);

    float pointRadius = texture2D(tex, vec2(mod(offset+time*3., 1.), 0.1)).r;


    vec3 p = vec3(0., 0., 0.);

    p.x = map(mod(offset+time*3., 1.), 0., 1., 14., 50.);
    
    vec2 newP = polar(map(mod(ang, 1.), 0., 1., 0., TAU), map(radius, 0., 1., 0., pointRadius*6.));

    p.y = newP.x;
    p.z = newP.y;



    vColor = color;

    vec4 mvPosition = modelViewMatrix * vec4( p, 1.0 );

    gl_PointSize = 0.4 * ( 300.0 / -mvPosition.z );

    gl_Position = projectionMatrix * mvPosition;

}
`;
  const shaderMaterial = new THREE.ShaderMaterial({
    vertexShader,
    fragmentShader,
    uniforms: { ...uniforms, tex: { value: getPathTexture() } },

    blending: THREE.AdditiveBlending,
    depthTest: false,
    transparent: true,
    vertexColors: true });


  const geometry = new THREE.BufferGeometry();

  const positions = [];
  const colors = [];
  const config = [];

  const color = new THREE.Color("#ffe227");

  for (let i = 0; i < particles; i++) {
    const r = random();
    const ang = random();
    const offset = random();

    positions.push(0, 0, 0);

    config.push(r, ang, offset);

    colors.push(color.r, color.g, color.b);
  }

  geometry.setAttribute(
  "position",
  new THREE.Float32BufferAttribute(positions, 3));

  geometry.setAttribute("color", new THREE.Float32BufferAttribute(colors, 3));
  geometry.setAttribute("config", new THREE.Float32BufferAttribute.........完整代码请登录后点击上方下载按钮下载查看

网友评论0