提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
课程知识点
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.效果

总结
五一前看的,全被自己吃进肚子里了,想想怎么实现的一头雾水!还是要看之前代码,很烦...


















