<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>粒子渲染 on 文艺技术笔记</title>
        <link>https://wenyiblog.top/tags/%E7%B2%92%E5%AD%90%E6%B8%B2%E6%9F%93/</link>
        <description>Recent content in 粒子渲染 on 文艺技术笔记</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>zh-cn</language>
        <copyright>文艺技术笔记 | 软件工程师文艺</copyright>
        <lastBuildDate>Tue, 30 Jun 2026 16:00:00 +0800</lastBuildDate><atom:link href="https://wenyiblog.top/tags/%E7%B2%92%E5%AD%90%E6%B8%B2%E6%9F%93/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>Three.js 黑洞渲染实录：四轮迭代从硬边过渡到物理级光影</title>
        <link>https://wenyiblog.top/2026/06/threejs-black-hole-rendering/</link>
        <pubDate>Tue, 30 Jun 2026 16:00:00 +0800</pubDate>
        
        <guid>https://wenyiblog.top/2026/06/threejs-black-hole-rendering/</guid>
        <description>&lt;h2 id=&#34;为什么要用-threejs-做黑洞&#34;&gt;&lt;a href=&#34;#%e4%b8%ba%e4%bb%80%e4%b9%88%e8%a6%81%e7%94%a8-threejs-%e5%81%9a%e9%bb%91%e6%b4%9e&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;为什么要用 Three.js 做黑洞？
&lt;/h2&gt;&lt;p&gt;2024 年《星际穿越》十周年重映带火了一波黑洞可视化热潮。从科普教育到天文数据可视化，再到互动艺术装置，&amp;ldquo;在浏览器里渲染一个黑洞&amp;quot;的需求正在变得真实。&lt;/p&gt;
&lt;p&gt;Three.js 作为 WebGL 生态最成熟的 3D 框架，天然适合做这件事——它提供了完整的渲染管线、后处理栈和自定义 shader 入口。但黑洞不是普通天体，它的视觉特征几乎全部来自&lt;strong&gt;广义相对论效应&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;事件视界（Event Horizon）：光线无法逃逸的边界&lt;/li&gt;
&lt;li&gt;引力透镜（Gravitational Lensing）：背景星光被弯曲&lt;/li&gt;
&lt;li&gt;光子环（Photon Ring）：在 1.5 倍史瓦西半径处绕行的光&lt;/li&gt;
&lt;li&gt;吸积盘（Accretion Disk）：高速旋转的炽热物质&lt;/li&gt;
&lt;li&gt;多普勒频移：朝向观察者运动的物质偏蓝，远离的偏红&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这些效果在传统 3D 渲染中没有现成方案。标准光照模型、PBR 材质、环境贴图全部失效。你需要的是一套&lt;strong&gt;完全自定义的 shader 管线&lt;/strong&gt;。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;本文记录一个真实项目的四轮迭代过程，从最初的&amp;quot;黑色球体&amp;quot;到最终的物理级光影效果，拆解每一步的决策逻辑和参数调优细节。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;第一轮迭代硬边黑洞&#34;&gt;&lt;a href=&#34;#%e7%ac%ac%e4%b8%80%e8%bd%ae%e8%bf%ad%e4%bb%a3%e7%a1%ac%e8%be%b9%e9%bb%91%e6%b4%9e&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;第一轮迭代：硬边黑洞
&lt;/h2&gt;&lt;h3 id=&#34;最朴素的起点&#34;&gt;&lt;a href=&#34;#%e6%9c%80%e6%9c%b4%e7%b4%a0%e7%9a%84%e8%b5%b7%e7%82%b9&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;最朴素的起点
&lt;/h3&gt;&lt;p&gt;第一轮的目标很简单：在场景中放一个&amp;quot;黑洞&amp;rdquo;。做法也极其直接——创建一个球体几何体，赋予纯黑材质，关闭光照响应。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-glsl&#34; data-lang=&#34;glsl&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// fragment shader - 第一版&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;gl_FragColor&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;vec4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;用 &lt;code&gt;MeshBasicMaterial&lt;/code&gt; 配 &lt;code&gt;color: 0x000000&lt;/code&gt; 就能达到同样效果。一个纯黑色的球悬浮在星空中，从概念上讲没错——事件视界确实是一个&amp;quot;看不见&amp;quot;的球面。&lt;/p&gt;
&lt;h3 id=&#34;问题暴露&#34;&gt;&lt;a href=&#34;#%e9%97%ae%e9%a2%98%e6%9a%b4%e9%9c%b2&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;问题暴露
&lt;/h3&gt;&lt;p&gt;但效果&lt;strong&gt;极其虚假&lt;/strong&gt;。原因有三：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;问题&lt;/th&gt;
					&lt;th&gt;表现&lt;/th&gt;
					&lt;th&gt;根本原因&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;边缘太硬&lt;/td&gt;
					&lt;td&gt;球体轮廓锐利如剪纸&lt;/td&gt;
					&lt;td&gt;没有大气散射过渡&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;无引力透镜&lt;/td&gt;
					&lt;td&gt;背景星星不被扭曲&lt;/td&gt;
					&lt;td&gt;缺少光线偏折计算&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;无深度感&lt;/td&gt;
					&lt;td&gt;黑洞像一个平面贴纸&lt;/td&gt;
					&lt;td&gt;缺少周围光学效应&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;在真实物理中，黑洞周围的光线会被极端引力弯曲。观察者看到的不是一个&amp;quot;黑色球&amp;quot;，而是一个被扭曲的背景星空包裹的暗区。边缘处存在一个明亮的光子环，再往外是吸积盘发出的辐射光。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;一个没有引力透镜效果的黑洞，就像一张没有阴影的纸片人——形似而神不似。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;决策必须上自定义-shader&#34;&gt;&lt;a href=&#34;#%e5%86%b3%e7%ad%96%e5%bf%85%e9%a1%bb%e4%b8%8a%e8%87%aa%e5%ae%9a%e4%b9%89-shader&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;决策：必须上自定义 shader
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;MeshBasicMaterial&lt;/code&gt; 的渲染管线完全绕过了 vertex/fragment shader 的自定义空间（虽然技术上可以注入，但不如从头写清晰）。第一轮的核心收获是确认了方向：&lt;strong&gt;需要用 &lt;code&gt;ShaderMaterial&lt;/code&gt; 接管整个渲染流程&lt;/strong&gt;。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;第二轮迭代加入光子环&#34;&gt;&lt;a href=&#34;#%e7%ac%ac%e4%ba%8c%e8%bd%ae%e8%bf%ad%e4%bb%a3%e5%8a%a0%e5%85%a5%e5%85%89%e5%ad%90%e7%8e%af&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;第二轮迭代：加入光子环
&lt;/h2&gt;&lt;h3 id=&#34;光子环的物理背景&#34;&gt;&lt;a href=&#34;#%e5%85%89%e5%ad%90%e7%8e%af%e7%9a%84%e7%89%a9%e7%90%86%e8%83%8c%e6%99%af&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;光子环的物理背景
&lt;/h3&gt;&lt;p&gt;在广义相对论中，距离黑洞中心 1.5 倍史瓦西半径处存在一个&amp;quot;光子球&amp;quot;（Photon Sphere）。光子在这个距离上可以做不稳定的圆形轨道运动。对于远处观察者来说，这意味着在事件视界边缘会看到一个&lt;strong&gt;极其明亮的光环&lt;/strong&gt;——光子环。&lt;/p&gt;
&lt;p&gt;光子环不是物理实体，它是光线在极端引力场中的几何效应。要在 shader 中模拟它，核心思路是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;计算视线方向与黑洞中心的距离（impact parameter）&lt;/li&gt;
&lt;li&gt;根据距离判断光线偏折角度&lt;/li&gt;
&lt;li&gt;在光子环半径附近增强亮度&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;shader-实现思路&#34;&gt;&lt;a href=&#34;#shader-%e5%ae%9e%e7%8e%b0%e6%80%9d%e8%b7%af&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Shader 实现思路
&lt;/h3&gt;&lt;p&gt;在 fragment shader 中，对每个像素执行以下逻辑：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-glsl&#34; data-lang=&#34;glsl&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;float&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dist&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;length&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;viewDir&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;blackHoleCenter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;float&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;photonRadius&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;1.5&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;schwarzschildRadius&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// 光线偏折近似&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;float&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;deflection&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;schwarzschildRadius&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;max&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dist&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.001&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// 光子环亮度&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;float&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ringGlow&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;exp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pow&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dist&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;photonRadius&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ringSharpness&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;2.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这里的 &lt;code&gt;ringSharpness&lt;/code&gt; 是控制光子环宽度的关键参数。值越大，环越窄越锐利；值越小，环越宽越发散。&lt;/p&gt;
&lt;h3 id=&#34;参数调优过程&#34;&gt;&lt;a href=&#34;#%e5%8f%82%e6%95%b0%e8%b0%83%e4%bc%98%e8%bf%87%e7%a8%8b&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;参数调优过程
&lt;/h3&gt;&lt;p&gt;光子环的调参是第二轮最耗时的部分。以下是几个关键参数的迭代记录：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;参数&lt;/th&gt;
					&lt;th&gt;初始值&lt;/th&gt;
					&lt;th&gt;最终值&lt;/th&gt;
					&lt;th&gt;调优依据&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;ringSharpness&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;5.0&lt;/td&gt;
					&lt;td&gt;18.0&lt;/td&gt;
					&lt;td&gt;太宽会像雾，太窄会闪烁&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;ringBrightness&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;2.0&lt;/td&gt;
					&lt;td&gt;4.5&lt;/td&gt;
					&lt;td&gt;需要在 bloom 后处理中保持可见&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;deflectionStrength&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;0.5&lt;/td&gt;
					&lt;td&gt;1.2&lt;/td&gt;
					&lt;td&gt;过大会导致整个画面扭曲&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;innerFade&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;0.0&lt;/td&gt;
					&lt;td&gt;0.3&lt;/td&gt;
					&lt;td&gt;事件视界边缘需要微弱的过渡&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;引力透镜的简化处理&#34;&gt;&lt;a href=&#34;#%e5%bc%95%e5%8a%9b%e9%80%8f%e9%95%9c%e7%9a%84%e7%ae%80%e5%8c%96%e5%a4%84%e7%90%86&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;引力透镜的简化处理
&lt;/h3&gt;&lt;p&gt;完整的引力透镜需要求解测地线方程（geodesic equation），这在实时渲染中计算量过大。项目中采用的方案是&lt;strong&gt;解析近似&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;对于距离黑洞较远的光线，使用弱场近似（偏折角 ∝ 1/r）&lt;/li&gt;
&lt;li&gt;对于近距离光线，使用经验公式插值&lt;/li&gt;
&lt;li&gt;背景星空用 cube map 采样，根据偏折后的方向重新查找&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这个近似在视觉上已经足够 convincing。普通用户不会去验证测地线解的精度，他们关心的是&amp;quot;看起来像不像&amp;quot;。&lt;/p&gt;
&lt;h3 id=&#34;第二轮效果&#34;&gt;&lt;a href=&#34;#%e7%ac%ac%e4%ba%8c%e8%bd%ae%e6%95%88%e6%9e%9c&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;第二轮效果
&lt;/h3&gt;&lt;p&gt;加入光子环后，黑洞从一个&amp;quot;黑色贴纸&amp;quot;变成了一个有光学特征的暗区。边缘的亮环给出了明确的&amp;quot;这是一个引力场&amp;quot;的视觉暗示。但整体仍然缺乏真实感——因为缺少了黑洞最具标志性的视觉元素：&lt;strong&gt;吸积盘&lt;/strong&gt;。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;第三轮迭代吸积盘&#34;&gt;&lt;a href=&#34;#%e7%ac%ac%e4%b8%89%e8%bd%ae%e8%bf%ad%e4%bb%a3%e5%90%b8%e7%a7%af%e7%9b%98&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;第三轮迭代：吸积盘
&lt;/h2&gt;&lt;h3 id=&#34;为什么选择粒子系统而非几何面片&#34;&gt;&lt;a href=&#34;#%e4%b8%ba%e4%bb%80%e4%b9%88%e9%80%89%e6%8b%a9%e7%b2%92%e5%ad%90%e7%b3%bb%e7%bb%9f%e8%80%8c%e9%9d%9e%e5%87%a0%e4%bd%95%e9%9d%a2%e7%89%87&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;为什么选择粒子系统而非几何面片
&lt;/h3&gt;&lt;p&gt;吸积盘的经典渲染方式是用一个扁平的圆盘几何体，贴上噪声纹理，旋转动画。这个方案的问题在于：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;边缘太规整&lt;/strong&gt;：几何面片的边界是数学上完美的圆或椭圆，而真实吸积盘的物质分布是湍流态的&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;缺乏体积感&lt;/strong&gt;：面片是二维的，无法表现吸积盘的厚度变化和湍流结构&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;无法表现粒子轨迹&lt;/strong&gt;：吸积盘中的物质沿螺旋线向内运动，面片无法自然表达这种动力学&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;粒子渲染优于曲线渲染，这是项目中确立的核心审美原则。粒子系统天然具有有机、模糊、非几何的质感，更接近真实天体物理中的等离子体视觉效果。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;最终方案：&lt;strong&gt;用 GPU 粒子系统模拟吸积盘&lt;/strong&gt;。每个粒子代表一小团等离子体，沿开普勒轨道运动，速度随半径变化。&lt;/p&gt;
&lt;h3 id=&#34;粒子运动学&#34;&gt;&lt;a href=&#34;#%e7%b2%92%e5%ad%90%e8%bf%90%e5%8a%a8%e5%ad%a6&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;粒子运动学
&lt;/h3&gt;&lt;p&gt;吸积盘中的物质运动遵循开普勒定律：内圈快、外圈慢。在 shader 中，每个粒子的角速度为：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-glsl&#34; data-lang=&#34;glsl&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;float&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;angularVelocity&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sqrt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;G&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;M&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pow&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;radius&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;3.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;float&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;angle&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;initialAngle&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;angularVelocity&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;为了增加视觉丰富度，还叠加了：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;径向漂移&lt;/strong&gt;：粒子缓慢向内螺旋（模拟吸积过程）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;垂直扰动&lt;/strong&gt;：用 Perlin 噪声给粒子一个 z 方向的偏移，模拟盘的厚度&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;湍流扰动&lt;/strong&gt;：用 simplex noise 给速度加随机分量&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;多普勒频移的颜色处理&#34;&gt;&lt;a href=&#34;#%e5%a4%9a%e6%99%ae%e5%8b%92%e9%a2%91%e7%a7%bb%e7%9a%84%e9%a2%9c%e8%89%b2%e5%a4%84%e7%90%86&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;多普勒频移的颜色处理
&lt;/h3&gt;&lt;p&gt;这是吸积盘渲染中最有趣的部分。由于吸积盘高速旋转，朝向观察者运动的一侧会蓝移（频率升高），远离的一侧会红移（频率降低）。&lt;/p&gt;
&lt;p&gt;实现方式是在 fragment shader 中根据粒子的速度矢量与视线方向的点积来计算频移量：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-glsl&#34; data-lang=&#34;glsl&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;float&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dopplerShift&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dot&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;velocity&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;viewDirection&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;speedOfLight&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;vec3&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;baseColor&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;temperatureToColor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;temperature&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;vec3&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;shiftedColor&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;baseColor&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dopplerShift&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;shiftStrength&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;shiftStrength&lt;/code&gt; 控制频移的夸张程度。物理上真实的频移量很小，视觉上几乎看不出来。为了审美效果，通常会把这个值放大 5-10 倍。&lt;/p&gt;
&lt;h3 id=&#34;噪声纹理的选择&#34;&gt;&lt;a href=&#34;#%e5%99%aa%e5%a3%b0%e7%ba%b9%e7%90%86%e7%9a%84%e9%80%89%e6%8b%a9&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;噪声纹理的选择
&lt;/h3&gt;&lt;p&gt;吸积盘的纹理细节决定了它的&amp;quot;质感&amp;quot;。测试了几种方案：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;噪声类型&lt;/th&gt;
					&lt;th&gt;效果&lt;/th&gt;
					&lt;th&gt;取舍&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Perlin noise&lt;/td&gt;
					&lt;td&gt;平滑连续&lt;/td&gt;
					&lt;td&gt;太规则，缺乏湍流感&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Simplex noise&lt;/td&gt;
					&lt;td&gt;各向同性&lt;/td&gt;
					&lt;td&gt;好一些，但仍偏平滑&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Worley noise&lt;/td&gt;
					&lt;td&gt;细胞状结构&lt;/td&gt;
					&lt;td&gt;太离散&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;fBm（分形布朗运动）&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;多尺度湍流&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;最终选择&lt;/strong&gt;&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;fBm 通过叠加多个频率和振幅递减的噪声层，产生了从大尺度旋涡到小尺度湍流的完整频谱。这正是吸积盘磁流体动力学湍流的视觉特征。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-glsl&#34; data-lang=&#34;glsl&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;float&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fbm&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;vec2&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;float&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;float&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;amplitude&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;float&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;frequency&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mo&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;6&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;amplitude&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;noise&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;frequency&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;frequency&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;2.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;amplitude&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id=&#34;第三轮效果&#34;&gt;&lt;a href=&#34;#%e7%ac%ac%e4%b8%89%e8%bd%ae%e6%95%88%e6%9e%9c&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;第三轮效果
&lt;/h3&gt;&lt;p&gt;吸积盘加入后，整个场景的视觉信息量暴增。黑洞不再是一个孤立的暗球，而是一个动态的、有物质流入的天体系统。旋转的盘面、颜色渐变、粒子轨迹，一切都指向&amp;quot;这是一个活的天体&amp;quot;。&lt;/p&gt;
&lt;p&gt;但画面仍然缺少最后一步——&lt;strong&gt;光影层次&lt;/strong&gt;。粒子很亮，但亮度是&amp;quot;平&amp;quot;的，没有 bloom 的光晕，没有体积光的深度暗示。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;第四轮迭代物理级光影&#34;&gt;&lt;a href=&#34;#%e7%ac%ac%e5%9b%9b%e8%bd%ae%e8%bf%ad%e4%bb%a3%e7%89%a9%e7%90%86%e7%ba%a7%e5%85%89%e5%bd%b1&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;第四轮迭代：物理级光影
&lt;/h2&gt;&lt;h3 id=&#34;bloom辉光后处理&#34;&gt;&lt;a href=&#34;#bloom%e8%be%89%e5%85%89%e5%90%8e%e5%a4%84%e7%90%86&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Bloom（辉光后处理）
&lt;/h3&gt;&lt;p&gt;Bloom 是让高亮区域&amp;quot;溢出&amp;quot;到周围像素的后处理效果。对于黑洞场景，光子环和吸积盘的高温区域都需要强烈的 bloom 来模拟光的高动态范围。&lt;/p&gt;
&lt;p&gt;Three.js 的 &lt;code&gt;UnrealBloomPass&lt;/code&gt; 提供了三个核心参数：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;参数&lt;/th&gt;
					&lt;th&gt;作用&lt;/th&gt;
					&lt;th&gt;项目取值&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;threshold&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;亮度阈值，超过此值才产生 bloom&lt;/td&gt;
					&lt;td&gt;0.6&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;strength&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;bloom 强度&lt;/td&gt;
					&lt;td&gt;1.8&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;radius&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;bloom 扩散半径&lt;/td&gt;
					&lt;td&gt;0.4&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;调参的关键平衡：&lt;code&gt;threshold&lt;/code&gt; 太低会导致整个画面泛白，太高则只有最亮的像素有 bloom，效果不明显。&lt;code&gt;strength&lt;/code&gt; 和 &lt;code&gt;radius&lt;/code&gt; 需要配合——高强度小半径产生锐利的光晕，低强度大半径产生柔和的氛围光。&lt;/p&gt;
&lt;h3 id=&#34;体积光volumetric-light&#34;&gt;&lt;a href=&#34;#%e4%bd%93%e7%a7%af%e5%85%89volumetric-light&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;体积光（Volumetric Light）
&lt;/h3&gt;&lt;p&gt;体积光模拟光线在介质中散射的效果。对于黑洞场景，它的作用是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;给吸积盘增加&amp;quot;厚度&amp;quot;和&amp;quot;密度&amp;quot;感&lt;/li&gt;
&lt;li&gt;在光子环周围产生光线散射的暗示&lt;/li&gt;
&lt;li&gt;增强整体的&amp;quot;在介质中观察&amp;quot;的氛围&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;实现上使用&lt;strong&gt;径向模糊&lt;/strong&gt;（Radial Blur）的近似方案：从黑洞中心向外做射线采样，累积亮度。这比真正的体积渲染（raymarching）计算量小几个数量级，视觉效果却非常接近。&lt;/p&gt;
&lt;h3 id=&#34;后处理管线&#34;&gt;&lt;a href=&#34;#%e5%90%8e%e5%a4%84%e7%90%86%e7%ae%a1%e7%ba%bf&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;后处理管线
&lt;/h3&gt;&lt;p&gt;最终的后处理栈由以下 pass 组成：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;RenderPass&lt;/strong&gt;：基础场景渲染&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;UnrealBloomPass&lt;/strong&gt;：辉光效果&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;自定义 VolumetricPass&lt;/strong&gt;：体积光&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;FXAA / SMAA&lt;/strong&gt;：抗锯齿&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ToneMappingPass&lt;/strong&gt;：HDR 到 LDR 的色调映射&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;VignettePass&lt;/strong&gt;：暗角，聚焦视觉中心&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;每个 pass 的顺序很重要。Bloom 必须在色调映射之前，因为它需要 HDR 数据才能正确工作。抗锯齿在 bloom 之后，否则 bloom 会模糊掉锯齿边缘。&lt;/p&gt;
&lt;h3 id=&#34;色调映射的选择&#34;&gt;&lt;a href=&#34;#%e8%89%b2%e8%b0%83%e6%98%a0%e5%b0%84%e7%9a%84%e9%80%89%e6%8b%a9&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;色调映射的选择
&lt;/h3&gt;&lt;p&gt;测试了三种色调映射算法：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Reinhard&lt;/strong&gt;：简单但高光压缩过度，光子环细节丢失&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ACES Filmic&lt;/strong&gt;：电影级色调曲线，高光保留好，暗部有层次&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AgX&lt;/strong&gt;：新一代算法，色彩保真度更高&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;最终选择 &lt;strong&gt;ACES Filmic&lt;/strong&gt;，它在保持光子环高亮细节的同时，让暗部的星空背景也有足够的层次感。&lt;/p&gt;
&lt;h3 id=&#34;最终效果对比&#34;&gt;&lt;a href=&#34;#%e6%9c%80%e7%bb%88%e6%95%88%e6%9e%9c%e5%af%b9%e6%af%94&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;最终效果对比
&lt;/h3&gt;&lt;p&gt;四轮迭代的效果对比：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;迭代&lt;/th&gt;
					&lt;th&gt;视觉特征&lt;/th&gt;
					&lt;th&gt;核心问题&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;第一轮&lt;/td&gt;
					&lt;td&gt;纯黑球体&lt;/td&gt;
					&lt;td&gt;无光学效应，像贴纸&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;第二轮&lt;/td&gt;
					&lt;td&gt;黑球 + 光子环&lt;/td&gt;
					&lt;td&gt;有光学暗示，但缺乏物质&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;第三轮&lt;/td&gt;
					&lt;td&gt;光子环 + 吸积盘粒子&lt;/td&gt;
					&lt;td&gt;信息量足够，但光影平淡&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;第四轮&lt;/td&gt;
					&lt;td&gt;Bloom + 体积光 + 后处理&lt;/td&gt;
					&lt;td&gt;物理级光影，有机模糊质感&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;从&amp;quot;一个黑色球&amp;quot;到&amp;quot;一个发光的、有引力透镜效应的、有旋转吸积盘的天体系统&amp;quot;，四轮迭代的核心驱动力是&lt;strong&gt;不断追问&amp;quot;缺少什么&amp;quot;&lt;/strong&gt;。每一轮解决一个主要问题，同时暴露下一个问题。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;关于审美偏好为什么粒子渲染是更优解&#34;&gt;&lt;a href=&#34;#%e5%85%b3%e4%ba%8e%e5%ae%a1%e7%be%8e%e5%81%8f%e5%a5%bd%e4%b8%ba%e4%bb%80%e4%b9%88%e7%b2%92%e5%ad%90%e6%b8%b2%e6%9f%93%e6%98%af%e6%9b%b4%e4%bc%98%e8%a7%a3&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;关于审美偏好：为什么粒子渲染是更优解
&lt;/h2&gt;&lt;p&gt;在黑洞渲染项目中，有一个贯穿始终的审美决策：&lt;strong&gt;粒子渲染优于曲线渲染&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;这个决策的根源在于真实天体物理的视觉本质。吸积盘不是固体，不是面片，不是曲线——它是一团高速旋转的等离子体，由无数微观粒子组成。用粒子系统来渲染它，在概念上就是正确的。&lt;/p&gt;
&lt;h3 id=&#34;有机模糊质感&#34;&gt;&lt;a href=&#34;#%e6%9c%89%e6%9c%ba%e6%a8%a1%e7%b3%8a%e8%b4%a8%e6%84%9f&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;有机模糊质感
&lt;/h3&gt;&lt;p&gt;粒子渲染天然具有一种&amp;quot;有机模糊&amp;quot;的质感：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;粒子之间没有硬边界，靠密度叠加形成连续感&lt;/li&gt;
&lt;li&gt;长曝光效果可以通过粒子拖尾（motion trail）自然实现&lt;/li&gt;
&lt;li&gt;每个粒子可以独立闪烁，产生湍流态的视觉节奏&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;相比之下，用 NURBS 曲线或参数曲面来渲染吸积盘，会得到数学上完美但视觉上&amp;quot;太干净&amp;quot;的结果。真实的天体不会这么干净。&lt;/p&gt;
&lt;h3 id=&#34;纯光效--glow-无几何&#34;&gt;&lt;a href=&#34;#%e7%ba%af%e5%85%89%e6%95%88--glow-%e6%97%a0%e5%87%a0%e4%bd%95&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;纯光效 / Glow 无几何
&lt;/h3&gt;&lt;p&gt;项目后期进一步去掉了吸积盘的几何骨架，只保留纯光效。粒子不渲染为小球或点，而是渲染为&lt;strong&gt;带 bloom 的光点&lt;/strong&gt;。最终画面上看不到任何&amp;quot;几何体&amp;quot;，只有光的密度分布。&lt;/p&gt;
&lt;p&gt;这种&amp;quot;无几何&amp;quot;的渲染风格与长曝光天文摄影的视觉语言高度一致——你看到的不是一颗颗星星，而是光在时间上的累积。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;追求有机模糊质感，拒绝过度清晰的几何边界，是这个项目最核心的审美原则。它决定了从 shader 参数到后处理栈的每一个选择。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;性能考量与取舍&#34;&gt;&lt;a href=&#34;#%e6%80%a7%e8%83%bd%e8%80%83%e9%87%8f%e4%b8%8e%e5%8f%96%e8%88%8d&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;性能考量与取舍
&lt;/h2&gt;&lt;p&gt;实时渲染黑洞最大的性能瓶颈在两个地方：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;引力透镜的背景采样&lt;/strong&gt;：每个像素需要重新计算光线方向并采样 cube map，相当于全屏做一次方向重映射&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;粒子数量&lt;/strong&gt;：吸积盘需要至少 50 万粒子才能形成足够密度的视觉效果&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;项目中的优化策略：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;引力透镜计算放在 fragment shader 中，利用 GPU 并行性&lt;/li&gt;
&lt;li&gt;粒子运动计算在 vertex shader 中完成，避免 CPU-GPU 数据传输&lt;/li&gt;
&lt;li&gt;后处理使用半分辨率渲染，bloom 和体积光在低分辨率下计算后上采样&lt;/li&gt;
&lt;li&gt;吸积盘粒子使用 &lt;code&gt;THREE.Points&lt;/code&gt; + &lt;code&gt;BufferGeometry&lt;/code&gt;，单次 draw call&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在 GTX 1060 级别的显卡上，1080p 分辨率可以稳定 60fps。移动端（WebGL 2.0 支持的设备）可以跑到 30fps，需要降低粒子数量到 10 万并关闭体积光。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;从项目中学到的三件事&#34;&gt;&lt;a href=&#34;#%e4%bb%8e%e9%a1%b9%e7%9b%ae%e4%b8%ad%e5%ad%a6%e5%88%b0%e7%9a%84%e4%b8%89%e4%bb%b6%e4%ba%8b&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;从项目中学到的三件事
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;第一，shader 调参是一门经验科学。&lt;/strong&gt; 没有&amp;quot;正确答案&amp;quot;，只有&amp;quot;看起来对&amp;quot;。光子环的宽度、多普勒频移的强度、bloom 的阈值，这些参数的最终值都是在视觉测试中反复微调得到的。物理公式给出的是起点，审美判断决定终点。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第二，迭代比规划更重要。&lt;/strong&gt; 四轮迭代不是在项目开始前就规划好的。每一轮都是在前一轮的基础上&amp;quot;发现问题、解决问题&amp;quot;。如果你一开始就试图做&amp;quot;完美的黑洞渲染器&amp;quot;，大概率会陷入过度工程化的泥潭。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第三，审美原则是技术决策的锚点。&lt;/strong&gt; &amp;ldquo;粒子渲染优于曲线渲染&amp;rdquo;、&amp;ldquo;有机模糊优于几何清晰&amp;rdquo;——这些审美原则不是装饰性的偏好，它们直接决定了技术方案的走向。当面临&amp;quot;用面片还是粒子&amp;quot;、&amp;ldquo;用曲线还是光点&amp;quot;的选择时，审美原则就是决策依据。&lt;/p&gt;
&lt;p&gt;黑洞渲染是一个很好的案例：它的物理基础足够硬核（广义相对论），但它的视觉呈现又完全依赖审美判断。在这个项目中，技术和审美不是两条平行线，而是同一条线的两面。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;总结&#34;&gt;&lt;a href=&#34;#%e6%80%bb%e7%bb%93&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;总结
&lt;/h2&gt;&lt;p&gt;从四轮迭代的完整路径来看，Three.js 黑洞渲染的核心挑战不在于框架能力，而在于如何将广义相对论的光学效应转化为实时可计算的 shader 逻辑。第一轮确认了自定义 shader 的必要性，第二轮用解析近似解决了引力透镜的计算成本问题，第三轮通过粒子系统实现了吸积盘的有机质感，第四轮用完整的后处理管线赋予了画面物理级的光影层次。&lt;/p&gt;
&lt;p&gt;每一步的参数调优都没有标准答案，最终值来自反复的视觉测试和审美判断。&amp;ldquo;粒子渲染优于曲线渲染&amp;rdquo;、&amp;ldquo;有机模糊优于几何清晰&amp;rdquo;——这些原则贯穿了整个项目的技术决策。&lt;/p&gt;
&lt;p&gt;如果你对 WebGL 可视化、天文渲染或 shader 调优感兴趣，欢迎访问 &lt;a class=&#34;link&#34; href=&#34;https://wenyiblog.top&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;文艺技术笔记&lt;/a&gt; 获取更多技术文章。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;本文在写作过程中使用了 AI 工具作为辅助，内容基于真实项目经验整理。&lt;/p&gt;
&lt;/blockquote&gt;
</description>
        </item>
        
    </channel>
</rss>
