3.js - 着色器设置点材质(螺旋星系特效)

embedded/2024/9/24 13:52:11/

上图

在这里插入图片描述



着色器设置点材质时,在顶点着色器中,最好设置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.radius// 中心点多,外围的点少const 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.b// 根据索引值,设置不同的贴图imgIndex[current] = i % 3// 顶点的大小size_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))//#region 点材质// material = new THREE.PointsMaterial({//   color: new THREE.Color(params.color),//   size: params.size,//   map: texture,//   transparent: true,//   alphaMap: texture,//   depthWrite: false,//   sizeAttenuation: true,//   blending: THREE.AdditiveBlending// })//#endregionmaterial = 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()// ---------------------------------------------------------------------------//#regionconst 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() {// controls.update()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)
})//#endregion

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);// modelPosition.z = sin(angle);modelPosition.x = cos(angle)*distanceToCenter;modelPosition.z = sin(angle)*distanceToCenter;vec4 viewPosition = viewMatrix*modelPosition;// 计算顶点在裁剪空间中的位置,`gl_Position`,是GLSL内置的输出变量,用于存储顶点的最终位置gl_Position = projectionMatrix*viewPosition;// gl_Position = projectionMatrix*viewMatrix*modelPosition;`不设置 gl_PointSize 页面上就啥也没有1、GLSL中,`gl_PointSize`是一个特殊的输出变量,用于,设置点渲染时点的大小,2、以【gl_PointSize = 200.0/-viewPosition.z*asize】为例:涉及,视点空间中,顶点的z坐标(viewPosition.z),和一个属性asize的值`// 根据,顶点的深度(即:离视点的距离)和每个顶点可能具有的不同大小(asize)来动态调整点的大小。gl_PointSize = 200.0/-viewPosition.z*asize;// gl_PointSize = 10.0; // 你可以写死试试
}

fragment.glsl

precision lowp float;uniform sampler2D uTexture;
uniform sampler2D uTexture1;
uniform sampler2D uTexture2;varying float vImgIndex;varying vec3 vColor;void main() {// 方案- 1// gl_FragColor = vec4(gl_PointCoord, 0.0, 1.0);// 方案- 2 - 设置渐变圆// float strength = distance(gl_PointCoord,vec2(0.5));// strength*=2.0;// strength = 1.0-strength;// gl_FragColor = vec4(strength);// 方案- 3 - 圆形点// float strength = 1.0-distance(gl_PointCoord, vec2(0.5));// strength = step(0.5, strength);// gl_FragColor = vec4(strength);// 方案- 4 - 设置贴图// vec4 textureColor = texture2D(uTexture, gl_PointCoord);// gl_FragColor = vec4(textureColor.rgb, textureColor.r);// 方案- 5 - 设置多种贴图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);
}

http://www.ppmy.cn/embedded/112291.html

相关文章

【AWDP】 AWDP 赛制详解应对方法赛题实践 量大管饱

文章首发于【先知社区】&#xff1a;https://xz.aliyun.com/t/15535 一、AWDP概述 AWDP是什么 AWDP是一种综合考核参赛团队攻击、防御技术能力、即时策略的攻防兼备比赛模式。每个参赛队互为攻击方和防守方&#xff0c;充分体现比赛的实战性、实时性和对抗性&#xff0c;对参…

闭包+面试真题

对闭包的理解 闭包是内层函数使用外层变量 (子级可以访问父级的变量&#xff0c;但是父级不可以访问子级的) 闭包是指有权访问另一个函数作用域中变量的函数&#xff0c;创建闭包的最常见的方式就是在一个函数内创建另一个函数&#xff0c;创建的函数可以访问到当前函数的局部…

15_分布式数据结构

菜鸟&#xff1a; 老鸟&#xff0c;我最近在处理大量数据的时候遇到了瓶颈&#xff0c;单台服务器的内存和计算能力都不够用了。你知道有什么方法可以解决这个问题吗&#xff1f; 老鸟&#xff1a; 嗯&#xff0c;这种情况很常见。你可以考虑使用分布式数据结构。听说过吗&a…

Anaconda配置

2024_Anaconda更换清华源 Python项目依赖包生成requirements.txt pip freeze > requirements.txt pip install -r requirements.txtAnaconda安装以及修改环境默认位置图文教程 使用 Conda 创建和删除指定路径的虚拟环境

Vue: 创建vue项目

目录 一.创建项目 二.项目添加 三.添加成功 一.创建项目 打开本机终端输入npm create vuelatest 二.项目添加 1. 项目名称&#xff1a; Project name: one_vue 2.是否添加TypeScript支持&#xff1a;Add TypeScript? Yes 3.是否添加JSX支持&#xff1a;Add JSX Suppor…

线结构光测量系统标定--导轨

光平面标定原理可查看之前的博文《光平面标定》&#xff0c;光条中心提取可参考线结构光专栏光条中心提取系列的文章&#xff0c;相机标定参考相机标定专栏中的博文。&#xff08;欢迎进Q群交流&#xff1a;874653199&#xff09; 线结构光测量系统(指一个线结构光传感器与一个…

openssl下载和创建证书

下载&#xff1a;https://slproweb.com/products/Win32OpenSSL.html 参考&#xff1a;保姆级OpenSSL下载及安装教程-CSDN博客 生成证书 使用OpenSSL生成SSL证书的教程-CSDN博客

【R语言】删除数据框中所有行中没有大于200的数值的行

在Perl中还需要循环按行读入文件&#xff0c;而在R中&#xff0c;一行代码解决问题&#xff1a; df <- df[apply(df, 1, function(x) any(x > 200)), ]这是一个使用apply函数对数据框df进行操作的表达式。apply函数用于对数据框、矩阵或数组进行元素级别的操作。 df&am…