three.js利用点材质打造星空

本文介绍了Three.js中的THREE.BufferGeometry类,它是对传统THREE.Geometry的优化,通过使用TypedArray提高绘制大量几何数据的性能。文章详细阐述了如何创建和操作BufferGeometry,以及如何利用它来实现星云效果,包括设置顶点位置、颜色,以及应用点材质和纹理。
摘要由CSDN通过智能技术生成

最终效果如图:
在这里插入图片描述

一、THREE.BufferGeometry介绍

这里只是做个简单的介绍,详细的介绍大家可以看看THREE.BufferGeometry及其属性介绍

THREE.BufferGeometryThree.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);
});

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jieyucx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值