最终效果如图:
一、THREE.BufferGeometry介绍
这里只是做个简单的介绍,详细的介绍大家可以看看THREE.BufferGeometry及其属性介绍
THREE.BufferGeometry是Three.js中的一个重要的类,用于管理和操作几何图形数据。它是对THREE.Geometry的一种更新和改进,通过直接操作二进制数组来提高绘制性能。
在Three.js中,几何图形数据通常存储在顶点属性数组中。传统的THREE.Geometry使用JavaScript数组来存储这些数据,而THREE.BufferGeometry则使用更高效的TypedArray(如Float32Array、Uint16Array等)。
使用THREE.BufferGeometry可以获得更好的性能表现,特别是在处理大量几何数据时。它支持动态更新和批量渲染,可以通过改变数据的方式实现动画效果。此外,通过使用缓冲区对象,可以与WebGL的底层实现更好地集成,从而提高绘制性能。
THREE.BufferGeometry
的属性包括:位置(position)、法线(normal)、颜色(color)、UV坐标(uv)等。这些属性对应于顶点的各种属性,可以直接操作数据以改变几何图形的形状、颜色等。
在使用THREE.BufferGeometry创建几何图形
首先要创建一个新的THREE.BufferGeometry对象,并为各个属性创建TypedArray。然后,通过设置属性数组的值来定义顶点属性,并将这些属性分配到几何对象的对应属性中。最后,可以将几何对象传递给渲染器进行绘制。
var geometry = new THREE.BufferGeometry();
接下来,可以通过将数据存储在缓冲区中来定义几何体的属性,例如位置(位置矢量)、颜色、法线、纹理坐标等。数据存储在Float32Array、Uint16Array或Uint32Array等类型的缓冲区中,并绑定到BufferAttribute对象上,然后将这些BufferAttribute对象添加到BufferGeometry中。
例如,下面的示例展示了如何创建一个平面几何体:
var positions = new Float32Array([
-1.0, -1.0, 0.0,
1.0, -1.0, 0.0,
1.0, 1.0, 0.0,
1.0, 1.0, 0.0,
-1.0, 1.0, 0.0,
-1.0, -1.0, 0.0
]);
geometry.addAttribute('position', new THREE.BufferAttribute(positions, 3));
在这个例子中,我们创建了一个顶点位置矢量属性,并将其命名为’position’。这些位置数据存储在一个Float32Array类型的缓冲区中,每个矢量有三个分量。然后,我们通过调用addAttribute方法将这个属性添加到BufferGeometry中。
在创建完BufferGeometry后,我们可以将它应用于渲染器中的模型,例如使用THREE.Mesh创建一个网格对象:
var material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
var mesh = new THREE.Mesh(geometry, material);
这样,我们就创建了一个使用BufferGeometry的平面网格对象。
THREE.BufferGeometry
是Three.js中用于管理和操作几何图形数据的强大工具,通过使用二进制数组和TypedArray来提供更高的绘制性能和灵活性。它在处理大规模几何数据和实现动画效果方面具有很大的优势。
二、创建星云效果
如和使用three.js创建和渲染场景这里就不在详细介绍,下面就说一下实现星云效果的核心步骤
核心步骤如下:
1.使用BufferGeometry创建几何体
const particlesGeometry = new THREE.BufferGeometry();
const count = 5000;
// 设置缓冲区数组
const positions = new Float32Array(count * 3);
// 设置粒子顶点颜色
const colors = new Float32Array(count * 3);
// 设置顶点
for (let i = 0; i < count * 3; i++) {
positions[i] = (Math.random() - 0.5) * 50; // 设置顶点的位置
colors[i] = Math.random();
}
particlesGeometry.setAttribute(
"position",
new THREE.BufferAttribute(positions, 3)
);
particlesGeometry.setAttribute("color", new THREE.BufferAttribute(colors, 3));
2. 使用pointsMaterial 创建点材质
// 设置点材质
const pointsMaterial = new THREE.PointsMaterial();
// pointsMaterial.size = 0.9;
pointsMaterial.color.set(0xfff000);
// 相机深度而衰减
pointsMaterial.sizeAttenuation = true;
// 载入纹理
const textureLoader = new THREE.TextureLoader();
const texture = textureLoader.load("./textures/particles/4.png");
// 设置点材质纹理
pointsMaterial.map = texture;
pointsMaterial.alphaMap = texture;
pointsMaterial.transparent = true;
pointsMaterial.depthWrite = false;
pointsMaterial.blending = THREE.AdditiveBlending;
// 设置启动顶点颜色
pointsMaterial.vertexColors = true;
3. 使用Points创建点物体
const points = new THREE.Points(particlesGeometry, pointsMaterial);
scene.add(points);
4. 完整代码如下:
import * as THREE from "three";
// 导入轨道控制器
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
// 导入动画库
import gsap from "gsap";
// 导入dat.gui
import * as dat from "dat.gui";
// 目标:使用pointes设置随机顶点打造星河
const gui = new dat.GUI();
// 1、创建场景
const scene = new THREE.Scene();
// 2、创建相机
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
// 设置相机位置
camera.position.set(0, 0, 10);
scene.add(camera);
const particlesGeometry = new THREE.BufferGeometry();
const count = 5000;
// 设置缓冲区数组
const positions = new Float32Array(count * 3);
// 设置粒子顶点颜色
const colors = new Float32Array(count * 3);
// 设置顶点
for (let i = 0; i < count * 3; i++) {
positions[i] = (Math.random() - 0.5) * 50; // 设置顶点的位置
colors[i] = Math.random();
}
particlesGeometry.setAttribute(
"position",
new THREE.BufferAttribute(positions, 3)
);
particlesGeometry.setAttribute("color", new THREE.BufferAttribute(colors, 3));
// 设置点材质
const pointsMaterial = new THREE.PointsMaterial();
// pointsMaterial.size = 0.9;
pointsMaterial.color.set(0xfff000);
// 相机深度而衰减
pointsMaterial.sizeAttenuation = true;
// 载入纹理
const textureLoader = new THREE.TextureLoader();
const texture = textureLoader.load("./textures/particles/4.png");
// 设置点材质纹理
pointsMaterial.map = texture;
pointsMaterial.alphaMap = texture;
pointsMaterial.transparent = true;
pointsMaterial.depthWrite = false;
pointsMaterial.blending = THREE.AdditiveBlending;
// 设置启动顶点颜色
pointsMaterial.vertexColors = true;
const points = new THREE.Points(particlesGeometry, pointsMaterial);
scene.add(points);
// 初始化渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);
// 开启场景中的阴影贴图
renderer.shadowMap.enabled = true;
renderer.physicallyCorrectLights = true;
// 将webgl渲染的canvas内容添加到body
document.body.appendChild(renderer.domElement);
// 创建轨道控制器
const controls = new OrbitControls(camera, renderer.domElement);
// 设置控制器阻尼,让控制器更有真实效果,必须在动画循环里调用.update()。
controls.enableDamping = true;
// 设置时钟
const clock = new THREE.Clock();
function render() {
let time = clock.getElapsedTime();
controls.update();
renderer.render(scene, camera);
// 渲染下一帧的时候就会调用render函数
requestAnimationFrame(render);
}
render();
// 监听画面变化,更新渲染画面
window.addEventListener("resize", () => {
// 更新摄像头
camera.aspect = window.innerWidth / window.innerHeight;
// 更新摄像机的投影矩阵
camera.updateProjectionMatrix();
// 更新渲染器
renderer.setSize(window.innerWidth, window.innerHeight);
// 设置渲染器的像素比
renderer.setPixelRatio(window.devicePixelRatio);
});