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

news2024/9/26 5:18:52

上图

在这里插入图片描述



着色器设置点材质时,在顶点着色器中,最好设置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 * 3
		
		const 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)) / 5
		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
		
		position[current] = Math.cos(branchAngel) * distance + randomX
		position[current + 1] = 0 + randomY
		position[current + 2] = Math.sin(branchAngel) * distance + randomZ
		
		const mixColor = galaxyColor.clone()
		mixColor.lerp(outGalaxyColor, distance / params.radius)
		// 设置颜色
		colors[current] = mixColor.r
		colors[current + 1] = mixColor.g
		colors[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
	// })
	//#endregion

	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()

// ---------------------------------------------------------------------------

//#region

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.01

const clock = new THREE.Clock()
function animate() {
	// controls.update()
	const elapsedTime = clock.getElapsedTime()
	material.uniforms.uTime.value = elapsedTime
	requestAnimationFrame(animate)
	renderer.render(scene, camera)
}
animate()

window.addEventListener('resize', () => {
	camera.aspect = window.innerWidth / window.innerHeight
	camera.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.coloradmin.cn/o/2125916.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

FIDAVL:基于视觉语言模型的假图像检测与归因 !

FIDAVL:基于视觉语言模型的假图像检测与归因 &#xff01; 这份完整版的大模型 AI 学习资料已经上传CSDN&#xff0c;朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】 作者提出了FIDAVL&#xff1a;使用视觉语言模型进行虚假图像检测。FIDAVL是一…

基于 ROS 的Terraform托管服务轻松部署Qwen-VL-Chat

介绍 Qwen-VL是阿里云研发的大规模视觉语言模型&#xff08;Large Vision Language Model&#xff09;。Qwen-VL可以以图像、文本、检测框作为输入&#xff0c;并以文本和检测框作为输出。在Qwen-VL的基础上&#xff0c;利用对齐机制打造出基于大语言模型的视觉AI助手Qwen-VL-…

什么是嵌入式?行业前景如何?

目录 什么是嵌入式&#xff1f; 主要特点 常见应用场景 1. 工业自动化 2. 交通运输 3. 智能家居 4. 消费电子 5. 医疗设备 6. 航空航天 7. 物联网&#xff08;IoT&#xff09; 8. 能源管理 行业前景如何&#xff1f; 市场需求强劲 物联网&#xff08;IoT&#xff09;的爆发 汽车…

vue3的基本使用(步骤,架构模式,调试工具,指令)

1.基本使用步骤 a.导入vue.js的script脚本文件&#xff08;自动为window对象挂载vue构造函数&#xff09; b.在页面中声明一个将要被vue控制的Dom区域 c.创建vue实例对象 <body><div id"app">{{msg}}</div> </body> </html> <s…

树形弹窗选择框/vue2/Element/弹框选择

前言 此类选择器根据vueelementUI实现&#xff0c;使用vue3的可以根据此案例稍作改动即可实现&#xff0c;主要功能有弹出选择、搜索过滤、搜索结果高亮等&#xff0c;此选择器只支持单选&#xff0c;如需多选可在此基础进行改造。 效果图 代码实现 使用时&#xff0c;props-…

文件备份的方法有哪些?应该怎么弄?分享六个高效便捷的电脑文件备份方法

我们的电脑中存储了大量重要文件&#xff0c;如照片、文档、视频以及重要资料等。 然而&#xff0c;面对突如其来的硬件故障、病毒攻击或人为误操作&#xff0c;这些数据仿佛都悬于一线。 虽然说可以选择的恢复方法有很多&#xff0c;但是没有任何一个方法可以做到100%的&…

【Mysql】记录sql在执行过程中很慢

在改之前的测试脚本,之前写了一些sql,这次准备顺手把sql也调整一下,因为虽然sql能用&#xff0c;但是写的十分拉跨 附sql 分析过程: 1. 初步推测慢主要是因为left join了好几张表。 然后我去查了也跟开发求证过sql在执行过程中是"先联表&#xff0c;再执行查询条件"…

SCADA|KingSCADA运行报错:加载网络服务失败

哈喽,你好啊,我是雷工! 今天要运行KingSCADA程序时报错:加载 网络服务失败 ,导致无法运行。 解决问题思路及过程记录如下: 01 问题描述 如下图所示,报加载 网络服务失败 ; 02 处理过程 软件运行信息窗口中会有详细的运行信息,可以先查看软件的信息窗口。 也可以在日…

bluez SPP使用

然后退出bluetoothctl&#xff0c;执行rfcomm listen /dev/rfcomm0 1&#xff0c;如果已被使用&#xff0c;则执行rfcomm release 0(执行该命令会有数据回显&#xff0c;既手机收到开发板发来的相同数据&#xff0c;若要关闭回显需要加上参数-r&#xff0c;开启raw mode) 手机上…

项目中常用注解整理

Mybatis/MybatisPlus TableName //用来将指定的数据库表和 JavaBean 进行映射TableId(type IdType.AUTO) //标记为数据库中的主键TableField(existfalse) //标记为数据库中不存在的字段&#xff0c;防止报错Paramparam标签提供了对某个函数的参数的各项说明&#xff0c;包括参…

CTF 竞赛密码学方向学习路径规划

目录 计算机科学基础计算机科学概念的引入、兴趣的引导开发环境的配置与常用工具的安装Watt Toolkit&#xff08;Steam&#xff09;、机场代理Scoop&#xff08;Windows 用户可选&#xff09;常用 Python 库SageMathLinux小工具 yafuOpenSSL Markdown编程基础Python其他编程语言…

@老板:图纸防泄密方法有哪些?图纸防泄密高招分享

图纸&#xff0c;就像是企业的秘密武器设计图纸&#xff0c;里面藏着产品的精髓和创新的火花。一旦这些图纸落入竞争对手之手&#xff0c;就像是自家的独门秘籍被外人偷学&#xff0c;后果不堪设想。因此&#xff0c;保护图纸不泄密&#xff0c;是每个企业都必须认真对待的大事…

【QT】常用类

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;折纸花满衣 &#x1f3e0;个人专栏&#xff1a;QT 目录 &#x1f449;&#x1f3fb;QMediaPlayer&#x1f449;&#x1f3fb;QMediaPlaylistsetPlaybackMode &#x1f449;&#x1f3fb;QDir&#x1f449;…

stm32驱动HX711称重传感器 c++代码分享

一、HX711模块介绍 HX711模块是一种专门用于称重传感器的放大器模块。它的主要功能是将测得的微小电压信号放大到可以被微控制器读取的范围。 HX711模块通常配合称重传感器一起使用&#xff0c;例如压力传感器、负载细胞等。它采用24位的模数转换器&#xff08;ADC&#xff09…

交叉熵函数与kl散度的区别

公式上的区别 手动计算的方式展示如何实现这两个损失函数 交叉熵损失函数 import torch import torch.nn.functional as F# 模型的输出 logits 和真实标签 target logits torch.tensor([[2.0, 0.5, 0.1], [0.3, 2.5, 0.8]], requires_gradTrue) target torch.tensor([0, 1])…

测试开发基础——软件测试中的bug

二、软件测试中的Bug 1. 软件测试的生命周期 软件测试贯穿于软件的整个生命周期 需求分析 测试计划 测试设计与开发 测试执行 测试评估 上线 运行维护 用户角度&#xff1a;软件需求是否合理 技术角度&#xff1a;技术上是否可行&#xff0c;是否还有优化空间 测试角度…

某郊到家:互联网时代下的按摩服务革新

在快速发展的时代背景下&#xff0c;一群具有前瞻性的企业家在2018年勇敢地进军了按摩服务行业&#xff0c;引领了一场对传统模式的革新。他们不仅在竞争激烈的市场中站稳脚跟&#xff0c;还成功地在不断变化的市场环境中确立了自己的位置。 创新的商业模式和持续的努力&#x…

【2024】前端学习笔记2-有序列表-无序列表-描述列表

学习笔记 有序列表:ol基本使用:嵌套使用扩展:使用CSS改变序号类型无序列表:ul基本使用扩展:使用CSS改变符号类型扩展:使用CSS定制列表样式描述列表:dl基本使用扩展:使用CSS定制类型格式总结有序列表:ol 有序列表由<ol>标签包裹一组<li>(列表项)标签组成…

区块链之变:揭秘Web3对互联网的全面改变

随着技术的进步&#xff0c;区块链 逐渐从一个相对小众的概念演变为重塑互联网结构的核心力量。特别是 Web3 的兴起&#xff0c;标志着互联网进入了一个新的发展阶段。这一变革不仅仅是技术的升级&#xff0c;更是对互联网功能、数据控制和用户体验的全面重新定义。本文将详细探…

数学建模笔记—— 回归分析

数学建模笔记—— 回归分析 回归分析1. 回归分析的一般步骤2. 一元线性回归分析2.1 具体过程2.1.1 确定回归方程中的解释变量和被解释变量2.1.2 确定回归模型和建立回归方程2.1.3 利用回归直线进行估计和预测2.1.4 对回归方程进行各种检验(补充)1. 回归直线的拟合优度2. 显著性…