本文主要是介绍Threejs粒子水波纹效果,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
依赖
- three(这个重要)
- react (这个不重要)
- ahooks(这个不重要)
- unocss(这个不重要)
效果
代码
import React, { useEffect, useRef } from 'react';
import { useGetState } from 'ahooks';
import * as THREE from 'three';const Index= () => {const threeRef = useRef(null);const [, setCamera, getCamera] = useGetState(null);const [, setRenderer, getRenderer] = useGetState(null);const [, setScene, getScene] = useGetState(null);const [, setParticles, getParticles] = useGetState(null);const [, setCount, getCount] = useGetState(0);const SEPARATION = 100,AMOUNT_X = 200,AMOUNT_Y = 200;const init = () => {const newCamera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000);newCamera.position.z = 1000;const newScene = new THREE.Scene();setScene(newScene);const numParticles = AMOUNT_X * AMOUNT_Y;const positions = new Float32Array(numParticles * 3);const scales = new Float32Array(numParticles);let i = 0,j = 0;for (let ix = 0; ix < AMOUNT_X; ix++) {for (let iy = 0; iy < AMOUNT_Y; iy++) {positions[i] = ix * SEPARATION - (AMOUNT_X * SEPARATION) / 2; // xpositions[i + 1] = 0; // ypositions[i + 2] = iy * SEPARATION - (AMOUNT_Y * SEPARATION) / 1; // zscales[j] = 1;i += 3;j++;}}const geometry = new THREE.BufferGeometry();geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));geometry.setAttribute('scale', new THREE.BufferAttribute(scales, 1));const material = new THREE.ShaderMaterial({uniforms: {color: { value: new THREE.Color(0x6380fb) },},vertexShader: `attribute float scale;void main() {vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );gl_PointSize = scale * ( 300.0 / - mvPosition.z );gl_Position = projectionMatrix * mvPosition;}`,fragmentShader: `uniform vec3 color;void main() {if ( length( gl_PointCoord - vec2( 0.5, 0.5 ) ) > 0.475 ) discard;gl_FragColor = vec4( color, 1.0 );}`,});const newParticles = new THREE.Points(geometry, material);newScene.add(newParticles);setParticles(newParticles);const newRenderer = new THREE.WebGLRenderer({ antialias: true });newRenderer.setPixelRatio(window.devicePixelRatio);newRenderer.setSize(window.innerWidth, window.innerHeight);newRenderer.setClearColor(0x0b1121, 1.0);threeRef.current.appendChild(newRenderer.domElement);setRenderer(newRenderer);window.addEventListener('resize', onWindowResize);setCamera(newCamera);animate();};const onWindowResize = () => {const newCamera = getCamera();const newRenderer = getRenderer();if (!newCamera) return;newCamera.aspect = window.innerWidth / window.innerHeight;newCamera.updateProjectionMatrix();newRenderer?.setSize(window.innerWidth, window.innerHeight);};const animate = () => {requestAnimationFrame(animate);render();};const render = () => {const newCamera = getCamera();const newScene = getScene();const newParticles = getParticles();const newRenderer = getRenderer();const count = getCount();if (!newCamera) return;newCamera.position.x += (0 - newCamera.position.x) * 1;newCamera.position.y += (400 - newCamera.position.y) * 1;newCamera.lookAt(newScene.position);const positions = newParticles.geometry.attributes.position.array;const scales = newParticles.geometry.attributes.scale.array;let i = 0,j = 0;for (let ix = 0; ix < AMOUNT_X; ix++) {for (let iy = 0; iy < AMOUNT_Y; iy++) {positions[i + 1] = Math.sin((ix + count) * 0.3) * 50 + Math.sin((iy + count) * 0.5) * 50;scales[j] = (Math.sin((ix + count) * 0.3) + 1) * 20 + (Math.sin((iy + count) * 0.5) + 1) * 20;i += 3;j++;}}newParticles.geometry.attributes.position.needsUpdate = true;newParticles.geometry.attributes.scale.needsUpdate = true;newRenderer.render(newScene, newCamera);setCount((val) => (val += 0.1));};useEffect(() => {if (threeRef.current && !getCamera()) {init();}}, [threeRef]);return <div className="h-full w-full" ref={threeRef}></div>;
};export default Index;
这篇关于Threejs粒子水波纹效果的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!