【Three.js基础学习】26. Animated galaxy
前言
shaders实现星系
课程回顾
使用顶点着色器为每个粒子设置动画
a属性 , u制服 ,v变化
像素比:window.devicePixelRatio
自动从渲染器检索像素比
renderer.getPixelRatio()
如何尺寸衰减, 放大缩小视角时,粒子都是同样大小的问题
gl_Position += (1.0 / - viewPosition);
下面是实现的数学解释


一、代码
这个我听的迷迷糊糊的,直接看代码中的注释吧
1.script.js
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import * as dat from 'lil-gui'
import galaxyVertexShader from './shaders/galaxy/vertex.glsl'
import galaxyFragmentShader from './shaders/galaxy/fragment.glsl'/*** Base*/
// Debug
const gui = new dat.GUI()// Canvas
const canvas = document.querySelector('canvas.webgl')// Scene
const scene = new THREE.Scene()/*** Galaxy*/
const parameters = {}
parameters.count = 200000
parameters.size = 0.005
parameters.radius = 6
parameters.branches = 3
parameters.spin = 1
parameters.randomness = 0.2
parameters.randomnessPower = 3
parameters.insideColor = '#ff6030'
parameters.outsideColor = '#1b3984'let geometry = null
let material = null
let points = nullconst generateGalaxy = () =>
{if(points !== null) // 制空{geometry.dispose()material.dispose()scene.remove(points)}/*** Geometry*/geometry = new THREE.BufferGeometry()// 这里为什么*3 因为要向各个方向发展,为什么*1只是在一个方向上拉伸const positions = new Float32Array(parameters.count * 3)const randomness = new Float32Array(parameters.count * 3)const colors = new Float32Array(parameters.count * 3)const scales = new Float32Array(parameters.count * 1)const insideColor = new THREE.Color(parameters.insideColor)const outsideColor = new THREE.Color(parameters.outsideColor)for(let i = 0; i < parameters.count; i++){const i3 = i * 3// Positionconst radius = Math.random() * parameters.radiusconst branchAngle = (i % parameters.branches) / parameters.branches * Math.PI * 2/*长时间就会发现星系在变薄,像一条丝带 ,应该避免下面代码 创建一个新的Float32Array并且在旋转后使用该属性 不应该在旋转之前添加应用随机性randomZXY*/const randomZ = Math.pow(Math.random(), parameters.randomnessPower) * (Math.random() < 0.5 ? 1 : - 1) * parameters.randomness * radiusconst randomX = Math.pow(Math.random(), parameters.randomnessPower) * (Math.random() < 0.5 ? 1 : - 1) * parameters.randomness * radiusconst randomY = Math.pow(Math.random(), parameters.randomnessPower) * (Math.random() < 0.5 ? 1 : - 1) * parameters.randomness * radius// 旋转 将数据填充到位置上positions[i3 ] = Math.cos(branchAngle) * radiuspositions[i3 + 1] = 0.0positions[i3 + 2] = Math.sin(branchAngle) * radiusrandomness[i3 ] = randomXrandomness[i3 + 1] = randomYrandomness[i3 + 2] = randomZ// Colorconst mixedColor = insideColor.clone()mixedColor.lerp(outsideColor, radius / parameters.radius)colors[i3 ] = mixedColor.rcolors[i3 + 1] = mixedColor.gcolors[i3 + 2] = mixedColor.b// Scalescales[i] = Math.random()}geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3))geometry.setAttribute('aRandomness', new THREE.BufferAttribute(randomness, 3))geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3))geometry.setAttribute('aScale', new THREE.BufferAttribute(scales, 1))/*** Material*/material = new THREE.ShaderMaterial({depthWrite: false,blending: THREE.AdditiveBlending,vertexColors: true,uniforms:{uTime: { value: 0 },uSize: { value: 30 * renderer.getPixelRatio() } // 星系顶点尺寸*像素比}, vertexShader: galaxyVertexShader,fragmentShader: galaxyFragmentShader})/*** Points*/points = new THREE.Points(geometry, material)scene.add(points)
}gui.add(parameters, 'count').min(100).max(1000000).step(100).onFinishChange(generateGalaxy).name('数量')
gui.add(parameters, 'radius').min(0.01).max(20).step(0.01).onFinishChange(generateGalaxy).name('半径')
gui.add(parameters, 'branches').min(2).max(20).step(1).onFinishChange(generateGalaxy).name('条数')
gui.add(parameters, 'randomness').min(0).max(2).step(0.001).onFinishChange(generateGalaxy).name('随机')
gui.add(parameters, 'randomnessPower').min(1).max(10).step(0.001).onFinishChange(generateGalaxy).name('随机功率')
gui.addColor(parameters, 'insideColor').onFinishChange(generateGalaxy).name('内部颜色')
gui.addColor(parameters, 'outsideColor').onFinishChange(generateGalaxy).name('外部颜色')/*** Sizes*/
const sizes = {width: window.innerWidth,height: window.innerHeight
}window.addEventListener('resize', () =>
{// Update sizessizes.width = window.innerWidthsizes.height = window.innerHeight// Update cameracamera.aspect = sizes.width / sizes.heightcamera.updateProjectionMatrix()// Update rendererrenderer.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))/*** Generate the first galaxy*/
generateGalaxy()/*** Animate*/
const clock = new THREE.Clock()const tick = () =>
{const elapsedTime = clock.getElapsedTime()// Update materialmaterial.uniforms.uTime.value = elapsedTime// Update controlscontrols.update()// Renderrenderer.render(scene, camera)// Call tick again on the next framewindow.requestAnimationFrame(tick)
}tick()
2. 顶点着色器
uniform float uTime;
uniform float uSize;attribute vec3 aRandomness;
attribute float aScale;varying vec3 vColor;/* atan(x) 弧度 反正切函数
*/void main()
{/*** Position*/vec4 modelPosition = modelMatrix * vec4(position, 1.0);// Rotatefloat angle = atan(modelPosition.x, modelPosition.z); // 获取角度 偏移的float distanceToCenter = length(modelPosition.xz); // 到中心的距离float angleOffset = (1.0 / distanceToCenter) * uTime ; // 根据时间应该旋转多少度angle += angleOffset; // 更新角度 并且 角度加上角度偏移modelPosition.x = cos(angle) * distanceToCenter; // 更新到模型上,同时乘以到中心的距离modelPosition.z = sin(angle) * distanceToCenter;// Randomness 随机modelPosition.xyz += aRandomness;vec4 viewPosition = viewMatrix * modelPosition;vec4 projectedPosition = projectionMatrix * viewPosition;gl_Position = projectedPosition;/*** Size*/gl_PointSize = uSize * aScale;gl_PointSize *= (1.0 / - viewPosition.z);/*** Color*/vColor = color;
}
3.片段着色器
varying vec3 vColor;void main()
{// // Disc// float strength = distance(gl_PointCoord, vec2(0.5));// strength = step(0.5, strength);// strength = 1.0 - strength;// // Diffuse point// float strength = distance(gl_PointCoord, vec2(0.5));// strength *= 2.0;// strength = 1.0 - strength;// Light pointfloat strength = distance(gl_PointCoord, vec2(0.5));strength = 1.0 - strength;strength = pow(strength, 10.0);// Final colorvec3 color = mix(vec3(0.0), vColor, strength);gl_FragColor = vec4(color, 1.0);
}
二、效果
shaders - 星系
总结
今天学的迷迷糊糊的,整体代码知道看得懂,思路,如何偏移以及一些数学计算很蒙!
相关文章:
【Three.js基础学习】26. Animated galaxy
前言 shaders实现星系 课程回顾 使用顶点着色器为每个粒子设置动画 a属性 , u制服 ,v变化 像素比:window.devicePixelRatio 自动从渲染器检索像素比 renderer.getPixelRatio() 如何尺寸衰减, 放大缩小视角时,粒子都是同…...
vscode使用ssh配置docker容器环境
1 创建容器,并映射主机和容器的指定ssh服务端口 2 进入容器 docker exec -it <容器ID> /bin/bash 3在容器中安装ssh服务 apt-get update apt-get install openssh-server 接着修改ssh文件信息,将容器的10008端口暴露出来允许root用户使用ssh登录 vim /…...
NLP论文速读(EMNLP 2024)|动态奖励与提示优化来帮助语言模型的进行自我对齐
论文速读|Dynamic Rewarding with Prompt Optimization Enables Tuning-free Self-Alignment of Language Models 论文信息: 简介: 本文讨论的背景是大型语言模型(LLMs)的自我对齐问题。传统的LLMs对齐方法依赖于昂贵的训练和人类偏好注释&am…...
【LeetCode】167. 两数之和 II - 输入有序数组
描述 给定一个下标从 1 开始的整数数组numbers,该数组已按非递减顺序排列,请从数组中找出满足相加之和等于目标数target的两个数。如果这两个数分别是numbers[index1]和numbers[index2],返回整数数组[index1, index2]。 只存在唯一答案&#…...
Getx:GetxController依赖管理02,Binding绑定全局控制器(懒加载Controller)
在使用GetX 状态管理器的时候,如果每个页面都手动实例化一个控制器就太麻烦了, Binding 的作用就是所有需要进行状态管理的控制器进行统一初始化 创建全局控制器Binding import package:get/get.dart; import ../controllers/counter.dart; // 同上一篇内…...
leetcode 找不同
389. 找不同 已解答 简单 相关标签 相关企业 给定两个字符串 s 和 t ,它们只包含小写字母。 字符串 t 由字符串 s 随机重排,然后在随机位置添加一个字母。 请找出在 t 中被添加的字母。 示例 1: 输入:s "abcd"…...
2025 - 生信信息学 - GEO数据分析 - RF分析(随机森林)
GEO数据分析 - RF分析(随机森林) 01 准备数据文件 #install.packages("randomForest")#引用包 library(randomForest) set.seed(123456)inputFile"diffGeneExp.txt" #输入文件 setwd("/Users/wangyang/Desktop/BCBM/02ra…...
Matlab深度学习(四)——AlexNet卷积神经网络
网络搭建参考:手撕 CNN 经典网络之 AlexNet(理论篇)-CSDN博客 在实际工程应用中,构建并训练一个大规模的卷积神经网络是比较复杂的,需要大量的数据以及高性能的硬件。如果通过训练好的典型网络稍加改进…...
etcd defrag
场景 prometheus监控告警,告警信息如下 etcd cluster "kube-etcd": database size in use on instance xx is 33.45% of the actual allocated disk space, please run defragmentation (e.g. etcdctl defrag) to retrieve the unused fragmented disk space.处理…...
golang语言整合jwt+gin框架实现token
1.下载jwt go get -u github.com/dgrijalva/jwt-go2.新建生成token和解析token文件 2.1 新建common文件夹和jwtConfig文件夹 新建jwtconfig.go文件 2.2 jwtconfig.go文件代码 /* Time : 2021/8/2 下午3:03 Author : mrxuexi File : main Software: GoLand */ package jwtC…...
数据治理、数据素养和数据质量管理:文献综述
注意:这并不是正式发表的论文,只是一篇用来交作业的文章 摘要 随着数据时代的到来,数据治理、数据素养和数据质量管理成为组织数据管理中的三大核心概念。本文基于相关研究与实践,对这三个领域进行全面综述,探讨它…...
【Linux】用户和用户组管理
管理用户 1.添加用户账号——useradd命令 【实例2-1-1】 按系统默认配置添加指定用户账号st和stu。 # 添加用户账号st [rootlocalhost ~]# useradd st # 添加用户账号stu [rootlocalhost ~]# useradd stu【实例2-1-2】添加用户账号stu01,UID为1004&am…...
游戏引擎学习第16天
视频参考:https://www.bilibili.com/video/BV1mEUCY8EiC/ 这些字幕讨论了编译器警告的概念以及如何在编译过程中启用和处理警告。以下是字幕的内容摘要: 警告的定义:警告是编译器用来告诉你某些地方可能存在问题,尽管编译器不强制要求你修复…...
如何通过对敏捷实践的调整,帮助远程团队提升研发效能?
首先明确一点,最敏捷的做法就是不要远程团队或分布式团队,远程一定比不上面对面同一地点的模式,毕竟环境不同,就不要期望远程团队和本地团队具备相同的效能,甚至期望更高。 那么,无论何种原因,…...
Ubuntu Linux使用前准备动作 配置SSH
在 Ubuntu 系统中配置 SSH 服务可以通过以下步骤进行: 1、安装ssh服务 1)打开终端(可以使用快捷键 Ctrl Alt T)。 2)运行以下命令安装 OpenSSH 服务器: sudo apt-get update:这一步是更新…...
疫情下的图书馆管理系统:Spring Boot技术
摘要 随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已逐步成熟。本文介绍了疫情下图书馆管理系统的开发全过程。通过分析疫情下图书馆管理系统管理的不足,创建了一个计算机管理疫情下图书馆管理系统的方案。文章介绍了疫情下图…...
vue3完整安装并创建项目
1、下载:https://npmmirror.com/mirrors/node/v18.19.0/node-v18.19.0-x64.msi 2、验证Nodejs是否安装成功(管理员身份运行cmd) node -v #查看nodejs的版本 v18.19.0npm -v #查看npm的版本 10.2.3 3、在D:\Program Files\nodejs路径下创建两…...
【Linux】Linux入门实操——进程管理(重点)
1. 概述 在 LINUX 中,每个执行的程序都称为一个进程。每一个进程都分配一个ID号(pid,进程号)。>windows > linux每个进程都可能以两种方式存在的。前台与后台,所谓前台进程就是用户目前的屏幕上可以进行操作的。后台进程则是实际在操作࿰…...
Linux-Apache
文章目录 Apache基础配置 🏡作者主页:点击! 🤖Linux专栏:点击! ⏰️创作时间:2024年11月19日12点20分 Apache Web服务器用来实现HTTP和相关TCP连接的处理,同时负责所提供资源的管理…...
高危,Laravel参数注入漏洞安全风险通告
今日,亚信安全CERT监控到安全社区研究人员发布安全通告,披露了Laravel 参数注入漏洞(CVE-2024-52301)。在受影响的版本中,Application.php 文件的 detectEnvironment 函数直接使用了 $_SERVER[argv],但没有检查运行环境是否为 CLI…...
ARM Fast Models MTI插件开发与性能优化实战
1. Fast Models中的Model Trace Interface架构解析在嵌入式系统仿真领域,ARM Fast Models提供的Model Trace Interface(MTI)是一套高效的仿真数据采集框架。作为一位长期从事嵌入式调试工具开发的工程师,我发现MTI的独特设计使其成…...
GDB与QEMU实现的可逆调试技术详解
1. 可逆调试技术概述可逆调试(Reversible Debugging)是一种革命性的调试技术,它允许开发者在程序执行过程中不仅能够向前执行,还能向后追溯程序状态。想象一下,如果你在调试时发现了一个内存损坏问题,传统的…...
不用OWL/RDF!Function 和 Action 在本体智能平台中的重要性体现
—— 从“语义建模”走向“可执行本体智能” 很多人初次接触企业级本体,总会陷入固有认知:将本体等同于传统知识图谱,或是OWL/RDF这类语义网标准的商业落地,执着于用标准化语法表达概念、关系与推理规则。行业内也有Palantir这类平…...
工程师着装文化变迁:从安全规范到效率优化
1. 项目概述:从“着装规范”到工程师文化观察那天早上,我像往常一样,准备去马萨诸塞州纳蒂克的MathWorks公司拜访。出门前,我习惯性地套上了长裤。七月的波士顿,夏天终于姗姗来迟,气温宜人,其实…...
OpenClaw:重新定义 AI 智能体,从对话到执行的全能 “龙虾
在 AI 技术飞速迭代的今天,大语言模型已能流畅对话、生成内容,但多数仍停留在 “只说不做” 的层面。OpenClaw(外号 “龙虾”)的出现,打破了这一僵局 —— 它是一款由奥地利工程师 Peter Steinberger 主导开发…...
运营商网络工程师视角:VoWiFi部署中的ePDG与AAA服务器配置要点及避坑指南
运营商网络工程师实战:VoWiFi部署中ePDG与AAA服务器配置的20个关键细节 当运营商开始规划VoWiFi网络时,会议室的白板上总是画满了各种接口和协议栈。但真正决定项目成败的,往往是那些容易被忽略的配置细节——比如IKEv2协商时DH组的选择会怎样…...
超声引导手术中的‘呼吸’难题:我们如何用体外标记法搞定肝部超声-CT的实时配准?
超声与CT影像实时配准:破解呼吸运动干扰的临床实战方案 在肝癌射频消融或穿刺活检手术中,影像引导的精准度直接决定治疗效果。超声凭借其实时性成为首选引导工具,但图像质量局限常需与高分辨率的CT影像融合。这一过程中,呼吸运动导…...
为什么我们的浏览器操作效率低下?如何用Shortkeys扩展实现3倍效率提升
为什么我们的浏览器操作效率低下?如何用Shortkeys扩展实现3倍效率提升 【免费下载链接】shortkeys A browser extension for custom keyboard shortcuts 项目地址: https://gitcode.com/gh_mirrors/sh/shortkeys 每天在浏览器上,我们花费大量时间…...
ComfyUI全面掌握-知识点详解——自定义节点安装与首次 AI 绘图(实操+排错)
本文为系列第 6 篇(第一章第 5 个知识点),讲解自定义节点的作用与安装方式,手把手教读者加载默认工作流、完成首次 AI 绘图,解读核心参数并排查常见问题。 目录 一、引言:自定义节点是什么?为什…...
【人生底稿 23】新疆出差记・上篇:初入边疆,三个半小时的漫长飞行
2024 年的 6 月,刚在赣州、河北、湖南的项目里连轴转完,手里的需求设计还没完全收尾,一通临时电话,打破了我短暂的节奏 —— 任务突然下达:陪客户前往新疆乌鲁木齐的甲方现场。这不是我第一次出差,却是第一…...
