Three.js点与点材质(Points)

球几何体

在这里插入图片描述

// 创建球几何体
const sphereGeometry = new THREE.SphereGeometry(3, 20, 20)
const material = new THREE.MeshBasicMaterial({
  color: 0xff0000,
  wireframe: true // 以线框的形式显示顶点
})
const mesh = new THREE.Mesh(sphereGeometry, material)
scene.add(mesh)

点实现球体

在这里插入图片描述

// 创建球几何体
const sphereGeometry = new THREE.SphereGeometry(3, 20, 20)
const pointsMaterial = new THREE.PointsMaterial({
  size: 0.1, // 点的大小,默认是1.0
  color: 0xfff000,
  sizeAttenuation: false, // 是否因相机的深度而衰减(近大远小), 默认为true
}) // 点材质
const points = new THREE.Points(sphereGeometry, pointsMaterial)
scene.add(points)

点材质

这里打算是将圆形贴图用在每个点上面,没想到在固定模型下是整体修改 ,通过自定义顶点才可以实现该效果
在这里插入图片描述在这里插入图片描述

// 添加纹理
const textureLoader = new THREE.TextureLoader()
const texture = textureLoader.load(`./circle_05.png`)
// 创建球几何体
const sphereGeometry = new THREE.SphereGeometry(3, 30, 30)
const pointsMaterial = new THREE.PointsMaterial({
  size: 0.1, // 点的大小,默认是1.0
  color: 0xfff000,
  // sizeAttenuation: false, // 是否因相机的深度而衰减(近大远小), 默认为true
  map: texture, // 纹理贴图
  alphaMap: texture, // 灰度贴图
  transparent: true, // 允许透明
  depthWrite: false,
  // 默认true,渲染引擎会记录每个渲染对象的深度信息,渲染引擎就能知道哪些对象应该被其他对象遮挡,从而创建出具有正确深度感的3D场景。
  // false,渲染引擎不会记录对象的深度信息,如果你有一个透明的窗户,你希望它后面的物体可见
  blending: THREE.AdditiveBlending // 混合模式:叠加; 当两个或多个对象在屏幕上重叠时,它们的颜色如何组合
}) // 点材质
const points = new THREE.Points(sphereGeometry, pointsMaterial)
scene.add(points)

自定义顶点着色器,打造漫天星空(缓冲区实现)

在这里插入图片描述
在这里插入图片描述

<template>
  <div id="webgl"></div>
</template>

<script setup>
import * as THREE from 'three'
//导入轨道控制器
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
// 导入 dat.gui
import { GUI } from 'three/addons/libs/lil-gui.module.min.js';

const gui = new GUI();
//1.创建场景
const scene = new THREE.Scene()

//2.创建相机 角度  宽高比  近端  远端
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)
// 设置相机位置  x y z 
camera.position.set(0, 0, 10)
// 把相机添加到场景中
scene.add(camera)

// 封装创建点(可绘制多个不同样的)
const createPoints = (url, size = 0.5) => {
	// 添加纹理
	const textureLoader = new THREE.TextureLoader()
	const texture = textureLoader.load(`/${url}.png`)
	
	const particlesGeometry = new THREE.BufferGeometry()
	const count = 5000
	const position = new Float32Array(count * 3)
	const colors = new Float32Array(count * 3)
	for (let i = 0; i < count * 3; i++) {
	  position[i] = Math.random() * 10 - 5 // -5 ~ 5
	  colors[i] = Math.random()
	}
	particlesGeometry.setAttribute('position', new THREE.BufferAttribute(position, 3))
	particlesGeometry.setAttribute('color', new THREE.BufferAttribute(colors, 3))
	
	// 创建球几何体
	const pointsMaterial = new THREE.PointsMaterial({
	  size, // 点的大小,默认是1.0
	  // color: 0xfff000,
	  // sizeAttenuation: false, // 是否因相机的深度而衰减(近大远小), 默认为true
	  map: texture, // 纹理贴图 
	  alphaMap: texture, // 灰度贴图
	  transparent: true, // 允许透明
	  depthWrite: false,
	  // 默认true,渲染引擎会记录每个渲染对象的深度信息,渲染引擎就能知道哪些对象应该被其他对象遮挡,从而创建出具有正确深度感的3D场景。
	  // false,渲染引擎不会记录对象的深度信息,如果你有一个透明的窗户,你希望它后面的物体可见
	  blending: THREE.AdditiveBlending, // 混合模式:叠加; 当两个或多个对象在屏幕上重叠时,它们的颜色如何组合
	  vertexColors: true // 设置启动顶点的颜色
	}) // 点材质
	
	const points = new THREE.Points(particlesGeometry, pointsMaterial)
	scene.add(points)
    return points;
}
const points1 = createPoints("circle_05", 0.1);
const points2 = createPoints("circle_05", 0.1);

// 初始化渲染器
const renderer = new THREE.WebGLRenderer()
// 设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight)
// 开启场景中的阴影贴图
renderer.shadowMap.enabled = true
renderer.physicallyCorrectLights = true

// 将webgel渲染的canvas内容添加到body
document.body.appendChild(renderer.domElement)

// 创建轨道控制器
const controls = new OrbitControls(camera, renderer.domElement)
// 设置控制器的阻尼 更真实 惯性
controls.enableDamping = true

// 添加坐标轴辅助器
const axesHelper = new THREE.AxesHelper(5)
scene.add(axesHelper)

// 设置时钟
const clock = new THREE.Clock()

function render() {
  points1.rotation.x = clock.getElapsedTime() * 0.1
  // 斜着飘
  points2.rotation.x = clock.getElapsedTime() * 0.1
  points2.rotation.y = clock.getElapsedTime() * 0.1

  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)
})
</script>

运用数学知识打造复杂形状必状旋星系

在这里插入图片描述

for (let i = 0; i < params.count; i++) { 
    // 当前的点应该在哪一条分支的角度上  取余012,360/3
    const branchAngel = (i % params.branch) * ((2 * Math.PI) / params.branch)
    // 当前点距离圆心的距离
    const distance = Math.random() * params.radius // 0到5的随机数
    // 根据距离+弯曲的程度
    const current = i * 3;
    positions[current] = Math.cos(branchAngel) * distance
    positions[current + 1] = 0
    positions[current + 2] = Math.sin(branchAngel) * distance
  }

在这里插入图片描述

for (let i = 0; i < params.count; i++) { 
   // 当前的点应该在哪一条分支的角度上  取余012,360/3
   const branchAngel = (i % params.branch) * ((2 * Math.PI) / params.branch)
   // 当前点距离圆心的距离
   const distance = Math.random() * params.radius // 0到5的随机数
   // 根据距离+弯曲的程度
   const current = i * 3;
   positions[current] = Math.cos(branchAngel + distance * params.rotateScale) * distance
   positions[current + 1] = 0
   positions[current + 2] = Math.sin(branchAngel + distance * params.rotateScale) * distance
 }

在这里插入图片描述

for (let i = 0; i < params.count; i++) {
   // 当前的点应该在哪一条分支的角度上  取余012,360/3
   const branchAngel = (i % params.branch) * ((2 * Math.PI) / params.branch)
   // 当前点距离圆心的距离 
   const distance = Math.random() * params.radius // 0到5的随机数
   const randomX = Math.pow(Math.random() * 2 - 1, 3) // -1到1,3次方
   const randomY = Math.pow(Math.random() * 2 - 1, 3)
   const randomZ = Math.pow(Math.random() * 2 - 1, 3)
   // 根据距离+弯曲的程度
   const current = i * 3;
   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
 }

在这里插入图片描述

for (let i = 0; i < params.count; i++) {
   // 当前的点应该在哪一条分支的角度上  取余012,360/3
   const branchAngel = (i % params.branch) * ((2 * Math.PI) / params.branch)
   // 当前点距离圆心的距离 
   const distance = Math.random() * params.radius // 0到5的随机数
   const randomX = Math.pow(Math.random() * 2 - 1, 3) * distance / 5 // 也可以用 distance 中间少两边厚,取反则是 (params.radius - distance)
   const randomY = Math.pow(Math.random() * 2 - 1, 3) * distance / 5
   const randomZ = Math.pow(Math.random() * 2 - 1, 3) * distance / 5
   // 根据距离+弯曲的程度
   const current = i * 3;
   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
 }

在这里插入图片描述

<template>
  <div id="webgl"></div>
</template>

<script setup>
import * as THREE from 'three'
//导入轨道控制器
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
// 导入 dat.gui
import { GUI } from 'three/addons/libs/lil-gui.module.min.js';

// 目标:点光源

const gui = new GUI();
//1.创建场景
const scene = new THREE.Scene()

//2.创建相机 角度  宽高比  近端  远端
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)
// 设置相机位置  x y z 
camera.position.set(0, 0, 10)
// 把相机添加到场景中
scene.add(camera)

const textureLoader = new THREE.TextureLoader()
const texture = textureLoader.load(`./circle_05.png`)

const params = {
  count: 800, // 数量
  size: 0.1, // 大小
  radius: 5, // 半径
  branch: 3, // 分支
  color: '#ffffff',
  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 = () => {
  // 生成顶点
  geometry = new THREE.BufferGeometry()
  // 随机生成位置
  const positions = new Float32Array(params.count * 3)
  // 设置顶点颜色
  const colors = new Float32Array(params.count * 3)
  // 循环生成点
 for (let i = 0; i < params.count; i++) {
    // 当前的点应该在哪一条分支的角度上  取余012,360/3
    const branchAngel = (i % params.branch) * ((2 * Math.PI) / params.branch)
    // 当前点距离圆心的距离 
    const distance = Math.random() * params.radius * Math.pow(Math.random(), 3) // 0到5的随机数
    const randomX = Math.pow(Math.random() * 2 - 1, 3) * (params.radius - distance) / 5 // 也可以用 distance 中间少两边厚,取反则是 (params.radius - distance)
    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 current = i * 3;
    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
    // 混合颜色,形成渐变色
    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))
  
  material = new THREE.PointsMaterial({
    size: params.size, // 点的大小,默认是1.0
    // color: params.color,
    // sizeAttenuation: false, // 是否因相机的深度而衰减(近大远小), 默认为true
    map: texture, // 纹理贴图
    alphaMap: texture, // 灰度贴图
    transparent: true, // 允许透明
    depthWrite: false, // 深度缓冲区写入,默认为true
    blending: THREE.AdditiveBlending, // 混合模式, 此时用的是前后材质会叠加
    vertexColors: true
  }) // 点材质

  points = new THREE.Points(geometry, material)
  scene.add(points)
}

generateGalaxy()

// 初始化渲染器
const renderer = new THREE.WebGLRenderer()
// 设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight)
// 开启场景中的阴影贴图
renderer.shadowMap.enabled = true
renderer.physicallyCorrectLights = true

// 将webgel渲染的canvas内容添加到body
document.body.appendChild(renderer.domElement)

// 创建轨道控制器
const controls = new OrbitControls(camera, renderer.domElement)
// 设置控制器的阻尼 更真实 惯性
controls.enableDamping = true

// 添加坐标轴辅助器
const axesHelper = new THREE.AxesHelper(5)
scene.add(axesHelper)


// 设置时钟
const clock = new THREE.Clock()

function render() {
  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)
})

</script>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值