上图

着色器设置点材质时,在顶点着色器中,最好设置gl_PointSize,不然看不到你在页面中添加的点
main.js
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'import gsap from 'gsap'import theVertexShader from './shader/13/vertex.glsl?raw'
import theFragmentShader from './shader/13/fragment.glsl?raw'const scene = new THREE.Scene()const camera = new THREE.PerspectiveCamera(75, window.innerHeight / window.innerHeight, 0.1, 1000)
camera.position.set(0, 0, 5)
camera.aspect = window.innerWidth / window.innerHeight
scene.add(camera)const axesHelper = new THREE.AxesHelper(5)
scene.add(axesHelper)
const textureLoader = new THREE.TextureLoader()
let texture = textureLoader.load('../public/assets/texture/particles/9.png')
let texture1 = textureLoader.load('../public/assets/texture/particles/10.png')
let texture2 = textureLoader.load('../public/assets/texture/particles/11.png')const params = {count: 1000, size: 0.1, radius: 5, branch: 4, color: '#ff6030',outColor: '#1b3984'
}let geometry = null
let material = null
let point = null
let galaxyColor = new THREE.Color(params.color)
let outGalaxyColor = new THREE.Color(params.outColor)const generateGalaxy = () => {if (point !== null) {geometry.dispose()material.dispose()scene.remove(point)}geometry = new THREE.BufferGeometry() const position = new Float32Array(params.count * 3) const colors = new Float32Array(params.count * 3) const imgIndex = new Float32Array(params.count) const size_arr = new Float32Array(params.count) for (let i = 0; i < params.count; i++) {const current = i * 3const branchAngel = (i % params.branch) * ((2 * Math.PI) / params.branch)const distance = Math.random() * params.radiusconst randomX = (Math.pow(Math.random() * 2 - 1, 3) * (params.radius - distance)) / 5const randomY = (Math.pow(Math.random() * 2 - 1, 3) * (params.radius - distance)) / 5const randomZ = (Math.pow(Math.random() * 2 - 1, 3) * (params.radius - distance)) / 5position[current] = Math.cos(branchAngel) * distance + randomXposition[current + 1] = 0 + randomYposition[current + 2] = Math.sin(branchAngel) * distance + randomZconst mixColor = galaxyColor.clone()mixColor.lerp(outGalaxyColor, distance / params.radius)colors[current] = mixColor.rcolors[current + 1] = mixColor.gcolors[current + 2] = mixColor.bimgIndex[current] = i % 3size_arr[current] = Math.random()}geometry.setAttribute('position', new THREE.BufferAttribute(position, 3))geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3))geometry.setAttribute('imgIndex', new THREE.BufferAttribute(imgIndex, 1))geometry.setAttribute('asize', new THREE.BufferAttribute(size_arr, 1))material = new THREE.ShaderMaterial({vertexShader: theVertexShader,fragmentShader: theFragmentShader,transparent: true,vertexColors: true,depthWrite: false,blending: THREE.AdditiveBlending,uniforms: {uTime: {value: 0},uTexture: {value: texture},uTexture1: {value: texture1},uTexture2: {value: texture2},uColor: {value: galaxyColor}}})point = new THREE.Points(geometry, material)scene.add(point)
}generateGalaxy()const renderer = new THREE.WebGLRenderer()
renderer.shadowMap.enabled = true
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)const controls = new OrbitControls(camera, renderer.domElement)
controls.enableDamping = true
controls.dampingFactor = 0.01const clock = new THREE.Clock()
function animate() {const elapsedTime = clock.getElapsedTime()material.uniforms.uTime.value = elapsedTimerequestAnimationFrame(animate)renderer.render(scene, camera)
}
animate()window.addEventListener('resize', () => {camera.aspect = window.innerWidth / window.innerHeightcamera.updateProjectionMatrix()renderer.setSize(window.innerWidth, window.innerHeight)renderer.setPixelRatio(window.devicePixelRatio)
})
vertex.glsl
precision lowp float;varying vec2 vUv;attribute float asize;
attribute float imgIndex;
varying float vImgIndex;uniform float uTime;varying vec3 vColor;void main() {vUv = uv;vColor = color;vImgIndex = imgIndex;vec4 modelPosition = modelMatrix*vec4(position, 1.0);`获取顶点的角度注:【atan(y, x)】计算两点之间的角度(以弧度为单位)`float angle = atan(modelPosition.x, modelPosition.z);`获取顶点到中心的距离注:按道理得这么写:【length(vec2(modelPosition.x, modelPosition.z))】如果 modelPosition 是一个三维向量,并且,你只需要 x 和 z 分量,length(modelPosition.xz)这样写也可以`float distanceToCenter = length(modelPosition.xz);`角度偏移angleOffset,是基于,顶点到中心距离的倒数,乘以时间uTime来计算的这种方法会导致:当顶点接近中心时,偏移量变得非常大,导致快速旋转`float angleOffset = 1.0/distanceToCenter*uTime;`当前旋转的度数`angle = angle+angleOffset;modelPosition.x = cos(angle)*distanceToCenter;modelPosition.z = sin(angle)*distanceToCenter;vec4 viewPosition = viewMatrix*modelPosition;gl_Position = projectionMatrix*viewPosition;`不设置 gl_PointSize 页面上就啥也没有1、GLSL中,`gl_PointSize`是一个特殊的输出变量,用于,设置点渲染时点的大小,2、以【gl_PointSize = 200.0/-viewPosition.z*asize】为例:涉及,视点空间中,顶点的z坐标(viewPosition.z),和一个属性asize的值`gl_PointSize = 200.0/-viewPosition.z*asize;
}
fragment.glsl
precision lowp float;uniform sampler2D uTexture;
uniform sampler2D uTexture1;
uniform sampler2D uTexture2;varying float vImgIndex;varying vec3 vColor;void main() {vec4 textureColor;if(vImgIndex==0.0) {textureColor = texture2D(uTexture, gl_PointCoord);} else if(vImgIndex==1.0) {textureColor = texture2D(uTexture1, gl_PointCoord);} else {textureColor = texture2D(uTexture2, gl_PointCoord);}gl_FragColor = vec4(vColor, textureColor.r);
}