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); });