ThreeJs 学习之旅(十二)—Particle(粒子)

点(Points)

一个用于显示点的类。 由WebGLRenderer渲染的点使用 gl.POINTS

构造器

Points( geometry : Geometry, material : Material )

geometry —— (可选)是一个Geometry或者BufferGeometry的实例,默认值是一个新的BufferGeometry。
material —— (可选) 是一个对象,默认值是一个具有随机颜色的新的PointsMaterial。

点材质(PointsMaterial)

Points使用的默认材质。

PointsMaterial( parameters : Object )

parameters - (可选)用于定义材质外观的对象,具有一个或多个属性。 材质的任何属性都可以从此处传入(包括从Material继承的任何属性)。

属性color例外,其可以作为十六进制字符串传递,默认情况下为 0xffffff(白色),内部调用Color.set(color)。

利用 形状 创建粒子

例: 

const count=50
const particlesGeometry=new THREE.SphereBufferGeometry(1,32,32);
const particlesMaterial=new THREE.PointsMaterial();
particlesMaterial.size=0.2;
particlesMaterial.sizeAttenuation=false
const particles=new THREE.Points(particlesGeometry,particlesMaterial)
scene.add(particles)

.sizeAttenuation : Boolean

指定点的大小是否因相机深度而衰减。(仅限透视摄像头。)默认为true。

particlesMaterial.sizeAttenuation=true

 利用数组创建粒子

const count=500
// const particlesGeometry=new THREE.SphereBufferGeometry(1,32,32);
const particlesGeometry=new THREE.BufferGeometry();
const positions=new Float32Array(count*3)
for(let i=0;i<count*3;i++){
  positions[i]=Math.random()
}
particlesGeometry.setAttribute("position",
  new THREE.BufferAttribute(positions,3)
)
 
const particlesMaterial=new THREE.PointsMaterial();
particlesMaterial.size=0.2;
particlesMaterial.sizeAttenuation=false
const particles=new THREE.Points(particlesGeometry,particlesMaterial)
scene.add(particles)

 设置例子材质贴图

贴纸素材:

const textureLoader=new THREE.TextureLoader();
const textures=textureLoader.load('textures/particles/2.png')
const count=50000
// const particlesGeometry=new THREE.SphereBufferGeometry(1,32,32);
const particlesGeometry=new THREE.BufferGeometry();
const positions=new Float32Array(count*3)
for(let i=0;i<count*3;i++){
  positions[i]=(Math.random()-0.5)*10
}
particlesGeometry.setAttribute("position",
  new THREE.BufferAttribute(positions,3)
)
 
const particlesMaterial=new THREE.PointsMaterial();
particlesMaterial.size=0.2;
particlesMaterial.sizeAttenuation=true
particlesMaterial.color=new THREE.Color('red')
particlesMaterial.map=textures
const particles=new THREE.Points(particlesGeometry,particlesMaterial)
scene.add(particles)

问题 存在着边缘

 加入alphMap

const textureLoader=new THREE.TextureLoader();
const textures=textureLoader.load('textures/particles/2.png')
particlesMaterial.transparent=true
particlesMaterial.alphaMap=textures

 好了一些但是依然存在

.alphaTest : Float

设置运行alphaTest时要使用的alpha值。如果不透明度低于此值,则不会渲染材质。默认值为0

particlesMaterial.alphaTest=0.001;

这样就好了很多 

 但是依然有边出现

 particlesMaterial.depthWrite=false;

.depthTest : Boolean

是否在渲染此材质时启用深度测试。默认为 true

.depthWrite : Boolean

渲染此材质是否对深度缓冲区有任何影响。默认为true

这样就没有问题了 

让每个小圈圈不同颜色 

.blending : Blending

在使用此材质显示对象时要使用何种混合。
必须将其设置为CustomBlending才能使用自定义blendSrc, blendDst 或者 [page:Constant blendEquation]。 混合模式所有可能的取值请参阅constants。默认值为NormalBlending。

.vertexColors : Integer

是否使用顶点着色。默认值为THREE.NoColors。 其他选项有THREE.VertexColors 和 THREE.FaceColors。

const textureLoader=new THREE.TextureLoader();
const textures=textureLoader.load('textures/particles/2.png')
const count=5000
// const particlesGeometry=new THREE.SphereBufferGeometry(1,32,32);
const particlesGeometry=new THREE.BufferGeometry();
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)*10
  colors[i]=Math.random()
}
particlesGeometry.setAttribute("position",
  new THREE.BufferAttribute(positions,3)
)
particlesGeometry.setAttribute("color",
new THREE.BufferAttribute(colors,3)
)
const particlesMaterial=new THREE.PointsMaterial();
particlesMaterial.size=0.2;
particlesMaterial.sizeAttenuation=true
particlesMaterial.color=new THREE.Color('#ff88cc')
particlesMaterial.transparent=true
particlesMaterial.alphaMap=textures
particlesMaterial.blending=THREE.AdditiveBlending
particlesMaterial.vertexColors=true
particlesMaterial.depthWrite=false;
const particles=new THREE.Points(particlesGeometry,particlesMaterial)
scene.add(particles)

 粒子动画

.needsUpdate : Boolean

该标志位指明当前 attribute 已经被修改过,且需要再次送入 GPU 处理。当开发者改变了该队列的值,则标志位需要设置为 true。

const tick = () => {
  const elapsedTime = clock.getElapsedTime();

  for(let i=0;i<count;i++){
    const x=particlesGeometry.attributes.position.array[i*3]
    particlesGeometry.attributes.position.array[i*3+1]=Math.sin(elapsedTime+x)
  }
  

  
  particlesGeometry.attributes.position.needsUpdate=true
  // Update controls
  controls.update();

  // Render
  renderer.render(scene, camera);

  // Call tick again on the next frame
  window.requestAnimationFrame(tick);
};

今日完整代码

import "./style.css";
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import * as dat from "dat.gui";
import ky from "kyouka";

/**
 * Base
 */
// Debug
const gui = new dat.GUI();

// Canvas
const canvas = document.querySelector("canvas.webgl");

// Scene
const scene = new THREE.Scene();

/**
 * Textures
 */
const textureLoader=new THREE.TextureLoader();
const textures=textureLoader.load('textures/particles/2.png')
const count=5000
// const particlesGeometry=new THREE.SphereBufferGeometry(1,32,32);
const particlesGeometry=new THREE.BufferGeometry();
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)*10
  colors[i]=Math.random()
}
particlesGeometry.setAttribute("position",
  new THREE.BufferAttribute(positions,3)
)
particlesGeometry.setAttribute("color",
new THREE.BufferAttribute(colors,3)
)
const particlesMaterial=new THREE.PointsMaterial();
particlesMaterial.size=0.2;
particlesMaterial.sizeAttenuation=true
particlesMaterial.color=new THREE.Color('#ff88cc')
particlesMaterial.transparent=true
particlesMaterial.alphaMap=textures
particlesMaterial.blending=THREE.AdditiveBlending
particlesMaterial.vertexColors=true
particlesMaterial.depthWrite=false;
const particles=new THREE.Points(particlesGeometry,particlesMaterial)
scene.add(particles)

/**
 * Sizes
 */
const sizes = {
  width: window.innerWidth,
  height: window.innerHeight,
};

window.addEventListener("resize", () => {
  // Update sizes
  sizes.width = window.innerWidth;
  sizes.height = window.innerHeight;


  // Update camera
  camera.aspect = sizes.width / sizes.height;
  camera.updateProjectionMatrix();

  // Update renderer
  renderer.setSize(sizes.width, sizes.height);
  renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
});

/**
 * Camera
 */
// Base camera
const camera = new THREE.PerspectiveCamera(
  75,
  sizes.width / sizes.height,
  0.1,
  100
);
camera.position.z = 3;
scene.add(camera);

// Controls
const controls = new OrbitControls(camera, canvas);
controls.enableDamping = true;

/**
 * Renderer
 */
const renderer = new THREE.WebGLRenderer({
  canvas: canvas,
});
renderer.setSize(sizes.width, sizes.height);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));

/**
 * Animate
 */
const clock = new THREE.Clock();

const tick = () => {
  const elapsedTime = clock.getElapsedTime();

  for(let i=0;i<count;i++){
    const x=particlesGeometry.attributes.position.array[i*3]
    particlesGeometry.attributes.position.array[i*3+1]=Math.sin(elapsedTime+x)
  }
  

  
  particlesGeometry.attributes.position.needsUpdate=true
  // Update controls
  controls.update();

  // Render
  renderer.render(scene, camera);

  // Call tick again on the next frame
  window.requestAnimationFrame(tick);
};

tick();

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值