threejs(7)-Proficient in particle effects

1. First introduction to Points and point materials

//Set point material
const pointsMaterial = new THREE.PointsMaterial();
import * as THREE from "three";
//Import track controller
import {<!-- --> OrbitControls } from "three/examples/jsm/controls/OrbitControls";
//Import animation library
import gsap from "gsap";
//Import dat.gui
import * as dat from "dat.gui";

// Goal: get to know points

const gui = new dat.GUI();
// 1. Create scene
const scene = new THREE.Scene();

// 2. Create camera
const camera = new THREE.PerspectiveCamera(
  75,
  window.innerWidth / window.innerHeight,
  0.1,
  1000
);

//Set camera position
camera.position.set(0, 0, 10);
scene.add(camera);

//Create ball geometry
const sphereGeometry = new THREE.SphereBufferGeometry(3, 30, 30);
delete sphereGeometry.attributes.uv;
// const material = new THREE.MeshBasicMaterial({<!-- -->
// color: 0xff0000,
// wireframe: true,
// });
// const mesh = new THREE.Mesh(sphereGeometry, material);
// scene.add(mesh);

//Set point material
const pointsMaterial = new THREE.PointsMaterial();
pointsMaterial.size = 0.1;
pointsMaterial.color.set(0xfff000);
// Attenuation due to camera depth
pointsMaterial.sizeAttenuation = true;

//Load texture
const textureLoader = new THREE.TextureLoader();
const texture = textureLoader.load("./textures/particles/2.png");
//Set point material texture
pointsMaterial.map = texture;
pointsMaterial.alphaMap = texture;
pointsMaterial.transparent = true;
pointsMaterial.depthWrite = false;
pointsMaterial.blending = THREE.AdditiveBlending;

const points = new THREE.Points(sphereGeometry, pointsMaterial);

scene.add(points);

//Initialize renderer
const renderer = new THREE.WebGLRenderer();
//Set the rendering size
renderer.setSize(window.innerWidth, window.innerHeight);
// Turn on the shadow map in the scene
renderer.shadowMap.enabled = true;
renderer.physicallyCorrectLights = true;

// console.log(renderer);
//Add the canvas content rendered by webgl to the body
document.body.appendChild(renderer.domElement);

// // Use the renderer to render the scene through the camera
// renderer.render(scene, camera);

//Create track controller
const controls = new OrbitControls(camera, renderer.domElement);
// To set the controller damping to make the controller more realistic, .update() must be called in the animation loop.
controls.enableDamping = true;

//Add axis helper
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);
// Set the clock
const clock = new THREE.Clock();

function render() {<!-- -->
  let time = clock.getElapsedTime();
  controls.update();
  renderer.render(scene, camera);
  // The render function will be called when rendering the next frame.
  requestAnimationFrame(render);
}

render();

// Monitor screen changes and update the rendering screen
window.addEventListener("resize", () => {<!-- -->
  // console.log("The screen has changed");
  //Update camera
  camera.aspect = window.innerWidth / window.innerHeight;
  //Update the camera's projection matrix
  camera.updateProjectionMatrix();

  //Update renderer
  renderer.setSize(window.innerWidth, window.innerHeight);
  //Set the pixel ratio of the renderer
  renderer.setPixelRatio(window.devicePixelRatio);
});

2. In-depth analysis of point material properties

import * as THREE from "three";
//Import track controller
import {<!-- --> OrbitControls } from "three/examples/jsm/controls/OrbitControls";
//Import animation library
import gsap from "gsap";
//Import dat.gui
import * as dat from "dat.gui";

// Goal: get to know points

const gui = new dat.GUI();
// 1. Create scene
const scene = new THREE.Scene();

// 2. Create camera
const camera = new THREE.PerspectiveCamera(
  75,
  window.innerWidth / window.innerHeight,
  0.1,
  1000
);

//Set camera position
camera.position.set(0, 0, 10);
scene.add(camera);

//Create ball geometry
const sphereGeometry = new THREE.SphereBufferGeometry(3, 30, 30);
// const material = new THREE.MeshBasicMaterial({<!-- -->
// color: 0xff0000,
// wireframe: true,
// });
// const mesh = new THREE.Mesh(sphereGeometry, material);
// scene.add(mesh);

//Set point material
const pointsMaterial = new THREE.PointsMaterial();
pointsMaterial.size = 0.1;
pointsMaterial.color.set(0xfff000);
// Attenuation due to camera depth
pointsMaterial.sizeAttenuation = true;

//Load texture
const textureLoader = new THREE.TextureLoader();
const texture = textureLoader.load("./textures/particles/2.png");
//Set point material texture
pointsMaterial.map = texture;
pointsMaterial.alphaMap = texture;
pointsMaterial.transparent = true; // Allow transparency
pointsMaterial.depthWrite = false; // Used when overlaying
pointsMaterial.blending = THREE.AdditiveBlending; // Color superposition after example overlap

const points = new THREE.Points(sphereGeometry, pointsMaterial);

scene.add(points);

//Initialize renderer
const renderer = new THREE.WebGLRenderer();
//Set the rendering size
renderer.setSize(window.innerWidth, window.innerHeight);
// Turn on the shadow map in the scene
renderer.shadowMap.enabled = true;
renderer.physicallyCorrectLights = true;

// console.log(renderer);
//Add the canvas content rendered by webgl to the body
document.body.appendChild(renderer.domElement);

// // Use the renderer to render the scene through the camera
// renderer.render(scene, camera);

//Create track controller
const controls = new OrbitControls(camera, renderer.domElement);
// To set the controller damping to make the controller more realistic, .update() must be called in the animation loop.
controls.enableDamping = true;

//Add axis helper
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);
// Set the clock
const clock = new THREE.Clock();

function render() {<!-- -->
  let time = clock.getElapsedTime();
  controls.update();
  renderer.render(scene, camera);
  // The render function will be called when rendering the next frame.
  requestAnimationFrame(render);
}

render();

// Monitor screen changes and update the rendering screen
window.addEventListener("resize", () => {<!-- -->
  // console.log("The screen has changed");
  //Update camera
  camera.aspect = window.innerWidth / window.innerHeight;
  //Update the camera's projection matrix
  camera.updateProjectionMatrix();

  //Update renderer
  renderer.setSize(window.innerWidth, window.innerHeight);
  //Set the pixel ratio of the renderer
  renderer.setPixelRatio(window.devicePixelRatio);
});

3. Apply vertex shading to create a colorful starry sky

import * as THREE from "three";
//Import track controller
import {<!-- --> OrbitControls } from "three/examples/jsm/controls/OrbitControls";
//Import animation library
import gsap from "gsap";
//Import dat.gui
import * as dat from "dat.gui";

// Goal: use points to set random vertices to create a galaxy

const gui = new dat.GUI();
// 1. Create scene
const scene = new THREE.Scene();

// 2. Create camera
const camera = new THREE.PerspectiveCamera(
  75,
  window.innerWidth / window.innerHeight,
  0.1,
  1000
);

//Set camera position
camera.position.set(0, 0, 10);
scene.add(camera);

const particlesGeometry = new THREE.BufferGeometry();
const count = 5000;

//Set buffer array
const positions = new Float32Array(count * 3);
//Set particle vertex color
const colors = new Float32Array(count * 3);
//Set vertices
for (let i = 0; i < count * 3; i + + ) {<!-- -->
  positions[i] = (Math.random() - 0.5) * 100;
  colors[i] = Math.random();
}
particlesGeometry.setAttribute(
  "position",
  new THREE.BufferAttribute(positions, 3)
);
particlesGeometry.setAttribute("color", new THREE.BufferAttribute(colors, 3));

//Set point material
const pointsMaterial = new THREE.PointsMaterial();
pointsMaterial.size = 0.5;
pointsMaterial.color.set(0xfff000);
// Attenuation due to camera depth
pointsMaterial.sizeAttenuation = true;

//Load texture
const textureLoader = new THREE.TextureLoader();
const texture = textureLoader.load("./textures/particles/zs2.png");
//Set point material texture
pointsMaterial.map = texture;
pointsMaterial.alphaMap = texture;
pointsMaterial.transparent = true;
pointsMaterial.depthWrite = false;
pointsMaterial.blending = THREE.AdditiveBlending;
//Set the starting vertex color
pointsMaterial.vertexColors = true;

const points = new THREE.Points(particlesGeometry, pointsMaterial);

scene.add(points);

//Initialize renderer
const renderer = new THREE.WebGLRenderer();
//Set the rendering size
renderer.setSize(window.innerWidth, window.innerHeight);
// Turn on the shadow map in the scene
renderer.shadowMap.enabled = true;
renderer.physicallyCorrectLights = true;

// console.log(renderer);
//Add the canvas content rendered by webgl to the body
document.body.appendChild(renderer.domElement);

// // Use the renderer to render the scene through the camera
// renderer.render(scene, camera);

//Create track controller
const controls = new OrbitControls(camera, renderer.domElement);
// To set the controller damping to make the controller more realistic, .update() must be called in the animation loop.
controls.enableDamping = true;

//Add axis helper
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);
// Set the clock
const clock = new THREE.Clock();

function render() {<!-- -->
  let time = clock.getElapsedTime();
  controls.update();
  renderer.render(scene, camera);
  // The render function will be called when rendering the next frame.
  requestAnimationFrame(render);
}

render();

// Monitor screen changes and update the rendering screen
window.addEventListener("resize", () => {<!-- -->
  // console.log("The screen has changed");
  //Update camera
  camera.aspect = window.innerWidth / window.innerHeight;
  //Update the camera's projection matrix
  camera.updateProjectionMatrix();

  //Update renderer
  renderer.setSize(window.innerWidth, window.innerHeight);
  //Set the pixel ratio of the renderer
  renderer.setPixelRatio(window.devicePixelRatio);
});

import * as THREE from "three";
import {<!-- --> texture, equirectUV } from "three/nodes";

import WebGPU from "three/addons/capabilities/WebGPU.js";
import WebGPURenderer from "three/addons/renderers/webgpu/WebGPURenderer.js";

import {<!-- --> OrbitControls } from "three/addons/controls/OrbitControls.js";

if (WebGPU.isAvailable() === false) {<!-- -->
  document.body.appendChild(WebGPU.getErrorMessage());

  throw new Error("No WebGPU support");
}

const container = document.createElement("div");
document.body.appendChild(container);

camera = new THREE.PerspectiveCamera(
  45,
  window.innerWidth / window.innerHeight,
  0.25,
  20
);
camera.position.set(1, 0, 0);

const equirectTexture = new THREE.TextureLoader().load(
  "textures/2294472375_24a3b8ef46_o.jpg"
);
equirectTexture.flipY = false;

scene = new THREE.Scene();
scene.backgroundNode = texture(equirectTexture, equirectUV(), 0);

function render() {<!-- -->
  controls.update();
  renderer.render(scene, camera);
}

renderer = new WebGPURenderer();
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setAnimationLoop(render);
container.appendChild(renderer.domElement);

controls = new OrbitControls(camera, renderer.domElement);
controls.autoRotate = true;
controls.rotateSpeed = -0.125; // negative, to track mouse pointer
controls.autoRotateSpeed = 1.0;

window.addEventListener("resize", onWindowResize);

function onWindowResize() {<!-- -->
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();

  renderer.setSize(window.innerWidth, window.innerHeight);
}

4. Realizing snowflakes flying in the sky through packaging and camera cropping


The effect of flying snowflakes can be simulated using rotation

function render() {<!-- -->
  let time = clock.getElapsedTime();
  points.rotation.x = time * 0.3;
  points2.rotation.x = time * 0.5;
  points2.rotation.y = time * 0.4;
  points3.rotation.x = time * 0.2;
  points3.rotation.y = time * 0.2;
  controls.update();
  renderer.render(scene, camera);
  // The render function will be called when rendering the next frame.
  requestAnimationFrame(render);
}

render();
import * as THREE from "three";
//Import track controller
import {<!-- --> OrbitControls } from "three/examples/jsm/controls/OrbitControls";
//Import animation library
import gsap from "gsap";
//Import dat.gui
import * as dat from "dat.gui";

// Goal: Set up a sky full of snowflakes

const gui = new dat.GUI();
// 1. Create scene
const scene = new THREE.Scene();

// 2. Create camera
const camera = new THREE.PerspectiveCamera(
  75,
  window.innerWidth / window.innerHeight,
  0.1,
  30
);

//Set camera position
camera.position.set(0, 0, 40);
scene.add(camera);

function createPoints(url, size = 0.5) {<!-- -->
  const particlesGeometry = new THREE.BufferGeometry();
  const count = 10000;

  //Set buffer array
  const positions = new Float32Array(count * 3);
  //Set particle vertex color
  const colors = new Float32Array(count * 3);
  //Set vertices
  for (let i = 0; i < count * 3; i + + ) {<!-- -->
    positions[i] = (Math.random() - 0.5) * 100;
    colors[i] = Math.random();
  }
  particlesGeometry.setAttribute(
    "position",
    new THREE.BufferAttribute(positions, 3)
  );
  particlesGeometry.setAttribute("color", new THREE.BufferAttribute(colors, 3));

  //Set point material
  const pointsMaterial = new THREE.PointsMaterial();
  pointsMaterial.size = 0.5;
  pointsMaterial.color.set(0xfff000);
  // Attenuation due to camera depth
  pointsMaterial.sizeAttenuation = true;

  //Load texture
  const textureLoader = new THREE.TextureLoader();
  const texture = textureLoader.load(`./textures/particles/${<!-- -->url}.png`);
  //Set point material texture
  pointsMaterial.map = texture;
  pointsMaterial.alphaMap = texture;
  pointsMaterial.transparent = true;
  pointsMaterial.depthWrite = false;
  pointsMaterial.blending = THREE.AdditiveBlending;
  //Set the starting vertex color
  pointsMaterial.vertexColors = true;

  const points = new THREE.Points(particlesGeometry, pointsMaterial);

  scene.add(points);
  return points;
}

const points = createPoints("1", 1.5);
const points2 = createPoints("xh", 1);
const points3 = createPoints("xh", 2);

//Initialize renderer
const renderer = new THREE.WebGLRenderer();
//Set the rendering size
renderer.setSize(window.innerWidth, window.innerHeight);
// Turn on the shadow map in the scene
renderer.shadowMap.enabled = true;
renderer.physicallyCorrectLights = true;

// console.log(renderer);
//Add the canvas content rendered by webgl to the body
document.body.appendChild(renderer.domElement);

// // Use the renderer to render the scene through the camera
// renderer.render(scene, camera);

//Create track controller
const controls = new OrbitControls(camera, renderer.domElement);
// To set the controller damping to make the controller more realistic, .update() must be called in the animation loop.
controls.enableDamping = true;

//Add axis helper
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);
// Set the clock
const clock = new THREE.Clock();

function render() {<!-- -->
  let time = clock.getElapsedTime();
  points.rotation.x = time * 0.3;
  points2.rotation.x = time * 0.5;
  points2.rotation.y = time * 0.4;
  points3.rotation.x = time * 0.2;
  points3.rotation.y = time * 0.2;
  controls.update();
  renderer.render(scene, camera);
  //The render function will be called when rendering the next frame.
  requestAnimationFrame(render);
}

render();

// Monitor screen changes and update the rendering screen
window.addEventListener("resize", () => {<!-- -->
  // console.log("The screen has changed");

  //Update camera
  camera.aspect = window.innerWidth / window.innerHeight;
  //Update the camera's projection matrix
  camera.updateProjectionMatrix();

  //Update renderer
  renderer.setSize(window.innerWidth, window.innerHeight);
  //Set the pixel ratio of the renderer
  renderer.setPixelRatio(window.devicePixelRatio);
});

5. Use mathematical knowledge to create complex-shaped arm spiral galaxies

import * as THREE from "three";
//Import track controller
import {<!-- --> OrbitControls } from "three/examples/jsm/controls/OrbitControls";
//Import animation library
import gsap from "gsap";
//Import dat.gui
import * as dat from "dat.gui";

// Goal: Use mathematical knowledge to design a galaxy of a specific shape

const gui = new dat.GUI();
// 1. Create scene
const scene = new THREE.Scene();

// 2. Create camera
const camera = new THREE.PerspectiveCamera(
  75,
  window.innerWidth / window.innerHeight,
  0.1,
  30
);

const textureLoader = new THREE.TextureLoader();
const particlesTexture = textureLoader.load("./textures/particles/1.png");
//Set camera position
camera.position.set(0, 0, 10);
scene.add(camera);

const params = {<!-- -->
  count: 10000,
  size: 0.1,
  radius: 5,
  branch: 3,
  color: "#ff6030",
  rotateScale: 0.3,
  endColor: "#1b3984",
};

let geometry = null;
let material = null;
let points = null;
const centerColor = new THREE.Color(params.color);
const endColor = new THREE.Color(params.endColor);
const generateGalaxy = () => {<!-- -->
  // Generate vertices
  geometry = new THREE.BufferGeometry();
  // Randomly generate position sum
  const positions = new Float32Array(params.count * 3);
  //Set vertex color
  const colors = new Float32Array(params.count * 3);

  // Loop generation point
  for (let i = 0; i < params.count; i + + ) {<!-- -->
    // Which branch angle should the current point be at?
    const branchAngel = (i % params.branch) * ((2 * Math.PI) / params.branch);

    //The distance between the current point and the center of the circle
    const distance = Math.random() * params.radius * Math.pow(Math.random(), 3);
    const current = i * 3;

    const randomX =
      (Math.pow(Math.random() * 2 - 1, 3) * (params.radius - distance)) / 5;
    const randomY =
      (Math.pow(Math.random() * 2 - 1, 3) * (params.radius - distance)) / 5;
    const randomZ =
      (Math.pow(Math.random() * 2 - 1, 3) * (params.radius - distance)) / 5;

    // const randomX = (Math.pow(Math.random() * 2 - 1, 3) * distance) / 5;
    // const randomY = (Math.pow(Math.random() * 2 - 1, 3) * distance) / 5;
    // const randomZ = (Math.pow(Math.random() * 2 - 1, 3) * distance) / 5;

    positions[current] =
      Math.cos(branchAngel + distance * params.rotateScale) * distance +
      randomX;
    positions[current + 1] = 0 + randomY;
    positions[current + 2] =
      Math.sin(branchAngel + distance * params.rotateScale) * distance +
      randomZ;

    // Mix colors to form gradient colors
    const mixColor = centerColor.clone();
    mixColor.lerp(endColor, distance / params.radius);

    colors[current] = mixColor.r;
    colors[current + 1] = mixColor.g;
    colors[current + 2] = mixColor.b;
  }

  geometry.setAttribute("position", new THREE.BufferAttribute(positions, 3));
  geometry.setAttribute("color", new THREE.BufferAttribute(colors, 3));

  //Set point material
  material = new THREE.PointsMaterial({<!-- -->
    // color: new THREE.Color(params.color),
    size: params.size,
    sizeAttenuation: true,
    depthWrite: false,
    blending: THREE.AdditiveBlending,
    map: particlesTexture,
    alphaMap: particlesTexture,
    transparent: true,
    vertexColors: true,
  });

  points = new THREE.Points(geometry, material);
  scene.add(points);
};
generateGalaxy();

//Initialize renderer
const renderer = new THREE.WebGLRenderer();
//Set the rendering size
renderer.setSize(window.innerWidth, window.innerHeight);
// Turn on the shadow map in the scene
renderer.shadowMap.enabled = true;
renderer.physicallyCorrectLights = true;

// console.log(renderer);
//Add the canvas content rendered by webgl to the body
document.body.appendChild(renderer.domElement);

// // Use the renderer to render the scene through the camera
// renderer.render(scene, camera);

//Create track controller
const controls = new OrbitControls(camera, renderer.domElement);
// To set the controller damping to make the controller more realistic, .update() must be called in the animation loop.
controls.enableDamping = true;

//Add axis helper
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);
// Set the clock
const clock = new THREE.Clock();

function render() {<!-- -->
  let time = clock.getElapsedTime();

  controls.update();
  renderer.render(scene, camera);
  //The render function will be called when rendering the next frame.
  requestAnimationFrame(render);
}

render();

// Monitor screen changes and update the rendering screen
window.addEventListener("resize", () => {<!-- -->
  // console.log("The screen has changed");

  //Update camera
  camera.aspect = window.innerWidth / window.innerHeight;
  //Update the camera's projection matrix
  camera.updateProjectionMatrix();

  //Update renderer
  renderer.setSize(window.innerWidth, window.innerHeight);
  //Set the pixel ratio of the renderer
  renderer.setPixelRatio(window.devicePixelRatio);
});