提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
课程知识点
1. 实现星际编辑器
2. 创建粒子 1000, 在随机位置
3. 创建材质 PointsMaterial
4. Points() 接收
5. 放到gui 中调试 但是会发现调整size 等 属性 页面无变化
因此有两种方法 onChange() onFinishChange()
这个时候更改就会 将参数传到 generateGalaxy
同样有问题 增加可以 ,因为在数值增加 不断生成新的星系
数值缩小时候,但是没有消减
因此要在函数外部 创建geometry,position,material 这些变量
判断是否和之前相等 ,不相等则 dispose() 清除几何体缓存,材质缓存同时
删除这些点 scene.remove(points)
// 实现漩涡星系 思路
首先将所有粒子 放到一条直线上 ,x position[i3 + 0] = Math.random() * parameters.radius
要实现分支 % 取余操作
这样在循环中 就可以得到 branchAngle=0,1,2,0,1,2,0,1,2,0,1,2,
对应的 i =0,1,2,3,4,5,6,7,8,9
下面主要是数学的应用 通过更改数值 实现星系
一、代码
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import * as lil from 'lil-gui'
import { AdditiveBlending } from 'three'
/*
课程知识点
1. 实现星际编辑器
2. 创建粒子 1000, 在随机位置
3. 创建材质 PointsMaterial
4. Points() 接收
5. 放到gui 中调试 但是会发现调整size 等 属性 页面无变化
因此有两种方法 onChange() onFinishChange()
这个时候更改就会 将参数传到 generateGalaxy
同样有问题 增加可以 ,因为在数值增加 不断生成新的星系
数值缩小时候,但是没有消减
因此要在函数外部 创建geometry,position,material 这些变量
判断是否和之前相等 ,不相等则 dispose() 清除几何体缓存,材质缓存同时
删除这些点 scene.remove(points)
// 实现漩涡星系 思路
首先将所有粒子 放到一条直线上 ,x position[i3 + 0] = Math.random() * parameters.radius
要实现分支 % 取余操作
这样在循环中 就可以得到 branchAngle=0,1,2,0,1,2,0,1,2,0,1,2,
对应的 i =0,1,2,3,4,5,6,7,8,9
下面主要是数学的应用 通过更改数值 实现星系
*/
/**
* Base
*/
// Debug
const gui = new lil.GUI()
// Canvas
const canvas = document.querySelector('canvas.webgl')
// Scene
const scene = new THREE.Scene()
/*
* Galaxy 星系 Generator 编辑器
*/
const parameters = {}
parameters.count = 100000
parameters.size = 0.01
parameters.color = '#ffffff'
parameters.radius = 5 // 半径
parameters.branches = 3 // 分支
parameters.spin = 1 // 旋转
parameters.randomness = 0.2 // 随机值
parameters.randomnessPower = 3 //
parameters.insideColor = '#ff6030' //
parameters.outsideColor = '#1b3984'
let geometry = null
let points = null
let material = null
const generateGalaxy = () =>{
/*
* Destroy old galaxy
*/
if(points !== null){
geometry.dispose()
material.dispose()
scene.remove(points)
}
// Geometry
geometry = new THREE.BufferGeometry()
// 创建粒子 位置参数
const position = new Float32Array(parameters.count * 3)
const colors = new Float32Array(parameters.count * 3)
const colorInside = new THREE.Color(parameters.insideColor)
const colorOutside = new THREE.Color(parameters.outsideColor)
// 设置随机位置
for(let i=0;i<parameters.count;i++){
const i3 = i * 3
// position
const radius = Math.random() * parameters.radius
const sponAngle = radius * parameters.spin
const branchAngle = (i % parameters.branches) / parameters.branches * Math.PI * 2
const randomX = Math.pow(Math.random(), parameters.randomnessPower) * (Math.random() < 0.5 ? 1 : -1)
const randomY = Math.pow(Math.random(), parameters.randomnessPower) * (Math.random() < 0.5 ? 1 : -1)
const randomZ = Math.pow(Math.random(), parameters.randomnessPower) * (Math.random() < 0.5 ? 1 : -1)
position[i3 + 0] = Math.cos(branchAngle + sponAngle) * radius + randomX
position[i3 + 1] = randomY
position[i3 + 2] = Math.sin(branchAngle + sponAngle) * radius + randomZ
// position[i3 + 0] = (Math.random() - 0.5) * 10 // x位置
// position[i3 + 1] = (Math.random() - 0.5) * 10 // y
// position[i3 + 2] = (Math.random() - 0.5) * 10 // z
// color
const mixedColor = colorInside.clone()
mixedColor.lerp(colorOutside,radius/parameters.radius)
colors[i3 + 0] = mixedColor.r
colors[i3 + 1] = mixedColor.g
colors[i3 + 2] = mixedColor.b
}
geometry.setAttribute(
'position',
new THREE.BufferAttribute(position,3)
)
geometry.setAttribute(
'color',
new THREE.BufferAttribute(colors,3)
)
// Material
material = new THREE.PointsMaterial({
// color:parameters.color,
size:parameters.size,
sizeAttenuation:true, // 衰减
depthWrite:false, // 深度缓冲区
blending: THREE.AdditiveBlending,
vertexColors:true
})
// material.vertexColors = true
/*
* Points
*/
points = new THREE.Points(
geometry,
material
)
scene.add(points)
}
gui.add(parameters, 'count').min(100).max(100000).step(100).onFinishChange(generateGalaxy)
gui.add(parameters, 'size').min(0.001).max(1).step(0.001).onFinishChange(generateGalaxy)
gui.add(parameters, 'radius').min(0.01).max(20).step(0.01).onFinishChange(generateGalaxy)
gui.add(parameters, 'branches').min(2).max(20).step(1).onFinishChange(generateGalaxy)
gui.add(parameters, 'spin').min(-5).max(5).step(0.001).onFinishChange(generateGalaxy)
gui.add(parameters, 'randomness').min(0).max(2).step(0.001).onFinishChange(generateGalaxy)
gui.add(parameters, 'randomnessPower').min(1).max(10).step(0.001).onFinishChange(generateGalaxy)
gui.addColor(parameters, 'insideColor').onFinishChange(generateGalaxy)
gui.addColor(parameters, 'outsideColor').onFinishChange(generateGalaxy)
generateGalaxy()
/**
* 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.x = 3
camera.position.y = 3
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()
// Update controls
controls.update()
// Render
renderer.render(scene, camera)
// Call tick again on the next frame
window.requestAnimationFrame(tick)
}
tick()
二、知识点
1.思路图
2.效果
总结
五一前看的,全被自己吃进肚子里了,想想怎么实现的一头雾水!还是要看之前代码,很烦...