<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>刘耀宇的博客</title>
        <link>https://liuyaoyu.top/</link>
        <description>先吃面吧</description>
        <lastBuildDate>Sun, 28 Jun 2026 00:44:43 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en-US</language>
        <copyright>All rights reserved 2026, NotionNext</copyright>
        <item>
            <title><![CDATA[从ue5 BRDF看UE shader分支选择]]></title>
            <link>https://liuyaoyu.top/article/example-36</link>
            <guid>https://liuyaoyu.top/article/example-36</guid>
            <pubDate>Mon, 12 Jan 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[从ue5 BRDF看UE shader分支选择]]></description>
            <content:encoded><![CDATA[<div id="notion-article" class="mx-auto overflow-hidden "><main class="notion light-mode notion-page notion-block-2e6a18473e718046890fe68723dad555"><div class="notion-viewport"></div><div class="notion-collection-page-properties"></div><div class="notion-text notion-block-2eca18473e71802b9668cc392d3c06e8">我们先来看ue的一段BRDF:</div><div class="notion-text notion-block-2eca18473e7180f7bca1c8ccdc2fa944">除了传统的#if SHADING_PATH_MOBILE</div><div class="notion-text notion-block-2eca18473e71803d90e2d62af8ba8d5f">这种宏分支外，我们还能看到if (bHasAnisotropy)   以及 BRANCH<b> 关键字</b></div><div class="notion-text notion-block-2eca18473e7180629c8fdc4079410bb6">这两者为什么怎么用？</div><div class="notion-text notion-block-2eca18473e7180b8a6f5cd0b8c16a3e5">在shader内少使用if 动态分支是每个TA都知道，但是往往忽略了 <b>相干性（Coherence）</b></div><div class="notion-text notion-block-2eca18473e7180f289a5e71c22b95641">我们看这句：</div><div class="notion-text notion-block-2eca18473e7180719001fc7c4450390b">如果这个材质开启了各向异性（Anisotropy），那么这个 Draw Call 绘制的所有像素，其 <code class="notion-inline-code">bHasAnisotropy</code> 几乎都是 true。</div><div class="notion-text notion-block-2eca18473e71800fb765ee7b45be23f6">再说个通俗的例子：如果if（guffer.roughness&gt;0.8） 这个动态分支</div><div class="notion-text notion-block-2eca18473e71809e8478fcb0897b111a">如果确实roughness要么是0.9  要么是0.7  那么他的消耗其实是很低的 （一致性分支）</div><div class="notion-text notion-block-2eca18473e71800e8422e8fa81a25630">最怕的就是这个roughness是较为随机的，这才是if 动态分支真正害怕</div><div class="notion-text notion-block-2eca18473e7180f7b19ecf3083aacad3">这种分支会让 GPU 的并行线程「分化」，一部分走 if，一部分走 else，严重降低并行效率，是性能杀手</div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-2eca18473e7180f391b9cd1aa8507bd1" data-id="2eca18473e7180f391b9cd1aa8507bd1"><span><div id="2eca18473e7180f391b9cd1aa8507bd1" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2eca18473e7180f391b9cd1aa8507bd1" title="用动态分支减少变体数量"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">用动态分支减少变体数量</span></span></h2><div class="notion-text notion-block-2eca18473e7180c6a331f2f64de798c4">那么为什么不直接用宏来实现bHasAnisotropy的分支？</div><div class="notion-text notion-block-2eca18473e7180a0a3b1d94cfa9df103">比如定义一个这个的宏  然后#define HASANISOTROPY ？</div><div class="notion-text notion-block-2eca18473e7180028917f11ddd3087bb">这是因为：减少变体</div><div class="notion-text notion-block-2eca18473e71806ca683d168bc881846">每增加一个宏开关，Shader 的变体数量就会翻倍（2的n）</div><div class="notion-text notion-block-2eca18473e71803585d2e7c40a7467b8">UE 将一些<b>不是极其昂贵</b>或者<b>逻辑复杂</b>的特性，放在运行时用 <code class="notion-inline-code">BRANCH</code> 来处理。这样多个材质可以共享同一个编译出来的二进制文件（PSO），只是运行时的逻辑路径不同</div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-2eca18473e7180719e1dc41c57234ead" data-id="2eca18473e7180719e1dc41c57234ead"><span><div id="2eca18473e7180719e1dc41c57234ead" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2eca18473e7180719e1dc41c57234ead" title="BRANCH关键字"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">BRANCH关键字</span></span></h2><div class="notion-text notion-block-2eca18473e7180eea219ce7eb096215c">Branch 是DX11 + 的 HLSL 高级编译指令，是给 GPU 的分支执行「明确的指令」，作用是告诉 GPU：这个 if/else 分支，按「动态分支」的方式执行。</div><div class="notion-text notion-block-2eca18473e7180208744f4b8c0a9c8cf">如果不写这个关键字 就是默认模式flatten</div><div class="notion-text notion-block-2eca18473e7180d39f94d7adca23055f">使用if else  是真的会把两个代码都跑一遍  然后丢弃不需要的代码</div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-2eca18473e7180af8bb7fecdac24cec2" data-id="2eca18473e7180af8bb7fecdac24cec2"><span><div id="2eca18473e7180af8bb7fecdac24cec2" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2eca18473e7180af8bb7fecdac24cec2" title="那 一致性条件 起到了什么作用？"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">那 一致性条件 起到了什么作用？</span></span></h3><div class="notion-text notion-block-2eca18473e71802395a4c9c57ed3d768">既然 [branch] 是跳转，为什么大家还要强调 一致性 呢？这就涉及到 GPU 的 <b>Warp（线程束）</b> 机制了：</div><ul class="notion-list notion-list-disc notion-block-2eca18473e71809fa633de4c2b9fad2d"><li><b>如果条件一致（比如 0 或 1）</b>： 整个 Warp（比如 32 个像素）都要跳。这时候 GPU 效率极高，因为它直接让这 32 个线程一起“飞”过不用的代码段。这就是<b>最理想的动态分支</b>。</li></ul><ul class="notion-list notion-list-disc notion-block-2eca18473e7180d397aae73cdf7d5a91"><li><b>如果条件不一致（分歧）</b>： 如果 Warp 里有 16 个像素想走 if，16 个想走 else。 这时 [branch] 就会变慢：它必须先带着 16 个线程跑 if（另外 16 个发呆），再带着剩下的 16 个跑 else（前 16 个发呆）。 <b>注意：</b> 即使这种情况下，它依然比 flatten 好，因为它至少在某一时刻只跑了一半的指令量，而 flatten 是全量跑</li></ul><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-2eca18473e7180359b94e93917620bb7" data-id="2eca18473e7180359b94e93917620bb7"><span><div id="2eca18473e7180359b94e93917620bb7" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2eca18473e7180359b94e93917620bb7" title="总结：BRANCH 和 条件一致性"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">总结：BRANCH 和 条件一致性</span></span></h2><div class="notion-text notion-block-2eca18473e71802487e6ee738b897ac3">好了  就这么简单  BRANCH  和 一致性的条件   形成了<b>黄金组合</b></div></main></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[基于houdini理解Billboard算法]]></title>
            <link>https://liuyaoyu.top/article/example-35</link>
            <guid>https://liuyaoyu.top/article/example-35</guid>
            <pubDate>Mon, 12 Jan 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[如题]]></description>
            <content:encoded><![CDATA[<div id="notion-article" class="mx-auto overflow-hidden "><main class="notion light-mode notion-page notion-block-2e6a18473e71809ca3c7ed28e4c06f94"><div class="notion-viewport"></div><div class="notion-collection-page-properties"></div><div class="notion-text notion-block-2e6a18473e71804b9315c87755af04e1">较为简单的矩阵计算，但是温故以下：</div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-2e6a18473e718050b34fdf88b0459f14" data-id="2e6a18473e718050b34fdf88b0459f14"><span><div id="2e6a18473e718050b34fdf88b0459f14" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2e6a18473e718050b34fdf88b0459f14" title="前言"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">前言</span></span></h2><div class="notion-text notion-block-2e6a18473e7180f4a35be3db949c2b9a">这个算法其实直观性较差，尝试用houdini进行拆建：</div><div class="notion-text notion-block-2e6a18473e71803988f6cd1f299b3969">在houdini中，我们常常要让copytopoints的对象（位置不同 ）同时面向 另一个一个对象，并且是随动的</div><div class="notion-text notion-block-2e6a18473e71802b800df9381fd1230d">这个和bb的是一样的，我们的做法是：</div><div class="notion-text notion-block-2e6a18473e7180b283c6c9b17d4ce658">计算目标中心  和 目标对象（以下简称R对象）的归一化向量</div><div class="notion-text notion-block-2e6a18473e71803dbad7d708cbe8e062">基于这个归一化向量创建一个矩阵</div><div class="notion-text notion-block-2e6a18473e718030b871c96856ca440c">然后通过 点坐标*矩阵的 方式 来改变点的位置。我们在shader中实现一下：</div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-2e6a18473e7180f9a038d8b0db2a1200" data-id="2e6a18473e7180f9a038d8b0db2a1200"><span><div id="2e6a18473e7180f9a038d8b0db2a1200" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2e6a18473e7180f9a038d8b0db2a1200" title="最垃圾链路（局部空间完成旋转）"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">最垃圾链路（局部空间完成旋转）</span></span></h2><div class="notion-text notion-block-2e6a18473e7180f09d60f34e514f3581">这贼垃圾，纯脑洞，得把摄像机转到局部空间，纯闲的</div><div class="notion-text notion-block-2e6a18473e7180279c1ee7c2ba97d6b4">并且你需要自己建立矩阵，用cross的方式</div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-2e6a18473e718053a264c2a3e73f1a8e" data-id="2e6a18473e718053a264c2a3e73f1a8e"><span><div id="2e6a18473e718053a264c2a3e73f1a8e" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2e6a18473e718053a264c2a3e73f1a8e" title="常规链路（view空间完成旋转）"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">常规链路（view空间完成旋转）</span></span></h2><div class="notion-text notion-block-2e6a18473e7180e782a3d463dd1edad0">这个是unity 等引擎用的</div><div class="notion-text notion-block-2e6a18473e71809c89d7c123d9ac05a0"><b>步骤 1：面片局部坐标→View 空间</b></div><div class="notion-text notion-block-2e6a18473e7180728f67cc6eabbecdbb">P_view = P_l × world矩阵 × view矩阵（先转世界，再转 View 空间）。</div><div class="notion-blank notion-block-2e6a18473e7180f8ad70d69b9bfa8418"> </div><div class="notion-text notion-block-2e6a18473e7180849652e00d173ba827"><b>步骤 2：在 View 空间构建 “朝向相机的旋转矩阵 R_view”</b></div><div class="notion-text notion-block-2e6a18473e71801aa4d4c4ecddce48e7">View 空间中相机在原点(0,0,0)，且：</div><div class="notion-text notion-block-2e6a18473e718059ac9bf2b9b4e9aabd">相机前向是 View 空间的-Z轴（forward_view = (0,0,-1)，固定不变）；</div><div class="notion-text notion-block-2e6a18473e7180b9a8acd8ffac733f04">相机右向是 View 空间的X轴（right_view = (1,0,0)）；</div><div class="notion-text notion-block-2e6a18473e7180599790f90a2055223f">相机上向是 View 空间的Y轴（up_view = (0,1,0)）；→ 旋转矩阵R_view = [right_view, up_view, forward_view]（单位矩阵，甚至可以省略旋转，直接用 View 空间的 X/Y 轴偏移）。</div><div class="notion-text notion-block-2e6a18473e7180e3a7cff9879ffc9ba4"><b>步骤 3：View 空间旋转 + 转裁切空间</b></div><div class="notion-text notion-block-2e6a18473e7180069dd8fcb0ca20143c">View 空间旋转：P_view_rot = P_view × R_view（对 View 空间的面片顶点旋转，本质是对齐相机 X/Y 轴）；</div><div class="notion-text notion-block-2e6a18473e71803d9145e475cd3b825a">View→裁切：P_clip = P_view_rot × proj矩阵。</div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-2e6a18473e718017b8daedefe09e773e" data-id="2e6a18473e718017b8daedefe09e773e"><span><div id="2e6a18473e718017b8daedefe09e773e" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2e6a18473e718017b8daedefe09e773e" title="优化后链路（NX用世界空间+世界空间旋转偏移）"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">优化后链路（NX用世界空间+世界空间旋转偏移）</span></span></h2><div class="notion-text notion-block-2e6a18473e71804e9eeae52f97a4bfc8"><b>步骤 1：局部顶点 → 局部方向向量（剥离位置，只保留偏移）</b></div><div class="notion-text notion-block-2e6a18473e71809b830bf310563cdc44">P_l = 面片中心局部坐标(0,0,0) + 局部偏移向量V_l</div><div class="notion-text notion-block-2e6a18473e718080aeb1c2cdd7409b95">因为面片的中心就是（0，0，0）</div><div class="notion-text notion-block-2e6a18473e71801bac1ef6ea215e3f35">所以 局部偏移向量V_l = 顶点坐标</div><div class="notion-text notion-block-2e6a18473e7180f58d9cf07926759f51">代码里用的是(借用uv)：</div><div class="notion-text notion-block-2e6a18473e718049bd3fdebe6885d8d8">local_position_offset = float3((input.texcoord0.x-0.5)*2.0, 0.0, (input.texcoord0.y-0.5)*2.0);</div><div class="notion-blank notion-block-2e6a18473e718080b779f9f290c2ebd9"> </div><div class="notion-text notion-block-2e6a18473e718036a175ff5309d7c53a"><b>步骤 2：局部偏移向量 → 世界空间旋转后的偏移向量</b></div><div class="notion-text notion-block-2e6a18473e7180a4958fcef540f1aaeb">local_position_offset 和 旋转矩阵 进行 mul</div><div class="notion-text notion-block-2e6a18473e7180f18e4ecaaf3c75a63f">这个旋转矩阵可以借用view矩阵进行构建：</div><div class="notion-text notion-block-2e6a18473e7180709e17e1807afd4c6b">一个是view_up ，一个是view_right，因为local_position_offset 有一个分量是0 所以没必要弄第三个</div><div class="notion-text notion-block-2e6a18473e71806bb752cb2a05c288e6">world_camera_facing_offset = (local_position_offset.x * view_up + local_position_offset.z * view_right) × s</div><div class="notion-text notion-block-2e6a18473e718045ab42f5e51c672777">（这里不用mul 直接用矩阵的乘法的拆开  节省这个指令）</div><div class="notion-text notion-block-2e6a18473e718097916fcf1a0c8b38c2">s是scale是缩放</div><div class="notion-text notion-block-2e6a18473e7180bcb268e8008beff8e9">这一步完成了旋转和转化到世界空间（这个旋转矩阵来自view转化矩阵  view 矩阵的前 3 列（<code class="notion-inline-code">Cam_R/Cam_U/Cam_F</code>）的<b>空间属性是世界空间</b>—— 因为它们描述的是 “相机的右 / 上 / 前方向在世界空间中指向哪里  即但它的<b>列向量数据</b>是 “世界空间的相机方向”   所以这个旋转矩阵同时把偏移转化到世界空间）</div><div class="notion-blank notion-block-2e6a18473e7180288a1dc357b7da9eda"> </div><div class="notion-text notion-block-2e6a18473e7180e4a004e43919658f80"><b>步骤三：世界坐标+世界空间旋转后的偏移向量</b></div><div class="notion-text notion-block-2e6a18473e7180b0819adf3698dca4c4">这个不难  世界坐标 + 世界坐标的偏移就是  新的坐标</div><div class="notion-blank notion-block-2e6a18473e7180c38e9ae1a3c8d0881e"> </div></main></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[描边outline（屏幕空间描边）]]></title>
            <link>https://liuyaoyu.top/article/example-34</link>
            <guid>https://liuyaoyu.top/article/example-34</guid>
            <pubDate>Sat, 29 Nov 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[后处理描边]]></description>
            <content:encoded><![CDATA[<div id="notion-article" class="mx-auto overflow-hidden "><main class="notion light-mode notion-page notion-block-2baa18473e71803e907bd8972ade017b"><div class="notion-viewport"></div><div class="notion-collection-page-properties"></div><div class="notion-text notion-block-2e6a18473e7180daa26ce41ab731989c">在项目里，描边是在后处理实现</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2e6a18473e71807d8c97ef391b16ffcb"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://tuchuang.imgliuyaoyu.top/picture/miaobiao1.png?spaceId=f6ca1847-3e71-81fd-991d-0003208a348b&amp;t=2e6a1847-3e71-807d-8c97-ef391b16ffcb" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-2e6a18473e718067930af726fedea758">我们先来聊聊我们熟悉的方案：对模型物体进行顶点偏移扩大，这个方案前向渲染，对模型顶点做向外偏移，渲染一个扩大的 “轮廓网格”（通常用纯色），再渲染原模型，靠两层叠加形成描边 —— 这种方案需要为每个要描边的模型单独处理（改 Shader / 加轮廓网格）。</div><div class="notion-text notion-block-2e6a18473e718003b73ae32b81071082"><b>屏幕空间后处理描边</b>（属于 “像素级描边”）：完全脱离模型 / 顶点，在场景渲染完成后，对「屏幕纹理 + 深度纹理」做像素级计算，识别出需要描边的<b>屏幕像素区域</b>并着色 —— 全程在 2D 屏幕空间操作，不碰任何 3D 模型 / 顶点，这是两者最核心的区别。</div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-2e6a18473e71803a8ccaf323b57fb857" data-id="2e6a18473e71803a8ccaf323b57fb857"><span><div id="2e6a18473e71803a8ccaf323b57fb857" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2e6a18473e71803a8ccaf323b57fb857" title="输入贴图："><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">输入贴图：</span></span></h2><table class="notion-simple-table notion-block-2e6a18473e7180f98e57f68f935a5d01"><tbody><tr class="notion-simple-table-row notion-block-2e6a18473e71800baaa8f74c4e8170ad"><td class="" style="width:120px"><div class="notion-simple-table-cell">输入资源</div></td><td class="" style="width:120px"><div class="notion-simple-table-cell">类型</div></td><td class="" style="width:714.9999847412109px"><div class="notion-simple-table-cell">作用（核心：判定描边的核心依据）</div></td></tr><tr class="notion-simple-table-row notion-block-2e6a18473e71809890bcd2fd5e7a3add"><td class="" style="width:120px"><div class="notion-simple-table-cell">t_tex0（Texture0）</div></td><td class="" style="width:120px"><div class="notion-simple-table-cell">2D 纹理</div></td><td class="" style="width:714.9999847412109px"><div class="notion-simple-table-cell">描边掩码纹理 / 目标纹理：▸ 核心作用：标记 “需要描边的物体区域”—— 需要描边的物体像素值≠0（比如纯色 / ID 值），不需要的 = 0；▸ 举例：若只想给角色描边，渲染场景时会单独输出 “角色区域为白色、其他区域为黑色” 的纹理作为t_tex0。</div></td></tr><tr class="notion-simple-table-row notion-block-2e6a18473e7180b7a18ae7df4babade5"><td class="" style="width:120px"><div class="notion-simple-table-cell">t_tex1（Texture1）</div></td><td class="" style="width:120px"><div class="notion-simple-table-cell">2D 纹理</div></td><td class="" style="width:714.9999847412109px"><div class="notion-simple-table-cell">原场景颜色纹理：▸ 非 FrameBuffer Fetch 模式下，作为原场景的基础颜色，最终描边会叠加到这个纹理上；▸ 若启用 FrameBuffer Fetch（移动端 Metal 优化），则直接读取帧缓冲，无需传入t_tex1。</div></td></tr><tr class="notion-simple-table-row notion-block-2e6a18473e7180e8acc7e4d8656eada7"><td class="" style="width:120px"><div class="notion-simple-table-cell">t_scene_depth</div></td><td class="" style="width:120px"><div class="notion-simple-table-cell">深度纹理</div></td><td class="" style="width:714.9999847412109px"><div class="notion-simple-table-cell">场景深度缓冲：▸ 记录每个屏幕像素的深度值（距离相机的距离）；▸ 用于 “深度过滤”（比如outline_depth_threshold_clip_player参数：过滤掉过远 / 过近的物体，避免给背景 / 超近物体描边）。</div></td></tr><tr class="notion-simple-table-row notion-block-2e6a18473e7180cba9e0f705d39d1523"><td class="" style="width:120px"><div class="notion-simple-table-cell">u_rt_size</div></td><td class="" style="width:120px"><div class="notion-simple-table-cell">float4</div></td><td class="" style="width:714.9999847412109px"><div class="notion-simple-table-cell">渲染目标（RT）的尺寸（宽 / 高 + 1 / 宽、1 / 高）：用于计算屏幕空间的采样偏移（描边宽度）。</div></td></tr><tr class="notion-simple-table-row notion-block-2e6a18473e7180ea8641dd2a3f97c902"><td class="" style="width:120px"><div class="notion-simple-table-cell">width</div></td><td class="" style="width:120px"><div class="notion-simple-table-cell">float</div></td><td class="" style="width:714.9999847412109px"><div class="notion-simple-table-cell">描边宽度：控制邻域采样的偏移量，值越大描边越宽。</div></td></tr><tr class="notion-simple-table-row notion-block-2e6a18473e71805fa160ec3ea34fe351"><td class="" style="width:120px"><div class="notion-simple-table-cell">outline_depth_threshold_clip_player</div></td><td class="" style="width:120px"><div class="notion-simple-table-cell">float</div></td><td class="" style="width:714.9999847412109px"><div class="notion-simple-table-cell">深度阈值：过滤不需要描边的深度区域（比如值 = 0.9 时，深度值超过 0.9 的像素不描边，避免给远处物体描边）。</div></td></tr></tbody></table><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2e6a18473e718083a2add9f8a45eae45"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://tuchuang.imgliuyaoyu.top/picture/miaobiao2.png?spaceId=f6ca1847-3e71-81fd-991d-0003208a348b&amp;t=2e6a1847-3e71-8083-a2ad-d9f8a45eae45" alt="notion image" loading="lazy" decoding="async"/></div></figure><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-2e6a18473e718024a06be8314d073009" data-id="2e6a18473e718024a06be8314d073009"><span><div id="2e6a18473e718024a06be8314d073009" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2e6a18473e718024a06be8314d073009" title="这个tex怎么来的？（tex0判定需要描边物体的核心）"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">这个tex怎么来的？（tex0判定需要描边物体的核心）</span></span></h2><ol start="1" class="notion-list notion-list-numbered notion-block-2e6a18473e71803381a6f4657dfc0241" style="list-style-type:decimal"><li>渲染场景时，先执行一个 “预处理 Pass”：</li><ol class="notion-list notion-list-numbered notion-block-2e6a18473e71803381a6f4657dfc0241" style="list-style-type:lower-alpha"><li>对<b>需要描边的物体</b>（比如角色、交互道具），渲染到<code class="notion-inline-code">t_tex0</code>时输出 “非 0 值”（比如白色、物体 ID、纯色）；</li><li>对<b>不需要描边的物体</b>（比如场景、背景、水体），渲染到<code class="notion-inline-code">t_tex0</code>时输出 “0 值”（黑色）；</li></ol></ol><ol start="2" class="notion-list notion-list-numbered notion-block-2e6a18473e718087930bf28d24f5fff1" style="list-style-type:decimal"><li>后处理 Pass 中，Shader 采样<code class="notion-inline-code">t_tex0</code>，只有 “非 0 值区域的边缘” 会被判定为 “需要描边的边缘”，最终生成描边。</li></ol><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-2e6a18473e71806e9b1ff5d51a49adab" data-id="2e6a18473e71806e9b1ff5d51a49adab"><span><div id="2e6a18473e71806e9b1ff5d51a49adab" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2e6a18473e71806e9b1ff5d51a49adab" title="Ps:"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">Ps:</span></span></h2><div class="notion-text notion-block-2e6a18473e71802f90c3d423e84a8984">顶点阶段不处理任何模型，只针对 “全屏四边形”（后处理的标准做法：用一个覆盖整个屏幕的四边形作为渲染载体）做操作：</div><ol start="1" class="notion-list notion-list-numbered notion-block-2e6a18473e71808c998effcaf3797370" style="list-style-type:decimal"><li>接收全屏四边形的顶点坐标（input_position）和 UV 坐标（input_texcoord0，范围 0~1，对应屏幕像素）；</li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-2e6a18473e718047999fcdd70ef39947" style="list-style-type:decimal"><li>计算采样偏移量：u_rt_size.zw是1/屏幕宽、1/屏幕高（归一化的像素尺寸），乘以width（描边宽度），得到 “单个像素的偏移量”（_v_0）；</li></ol><ol start="3" class="notion-list notion-list-numbered notion-block-2e6a18473e7180b0b69fc4ba27ee7b52" style="list-style-type:decimal"><li>生成 5 个采样坐标：</li><ol class="notion-list notion-list-numbered notion-block-2e6a18473e7180b0b69fc4ba27ee7b52" style="list-style-type:lower-alpha"><li>_Varying_texcoord0：当前像素的 UV（中心坐标）；</li><li>_Varying_texcoord1/_Varying_texcoord2：当前像素<b>上下</b>偏移后的 UV；</li><li>_Varying_texcoord3/_Varying_texcoord4：当前像素<b>左右</b>偏移后的 UV；→ 这 5 个坐标是为像素阶段 “邻域采样” 做准备（检测上下左右像素的差值）。</li></ol></ol><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-2e6a18473e718041bff6fea6e1e9c20f" data-id="2e6a18473e718041bff6fea6e1e9c20f"><span><div id="2e6a18473e718041bff6fea6e1e9c20f" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2e6a18473e718041bff6fea6e1e9c20f" title="Vs"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">Vs</span></span></h2><div class="notion-text notion-block-2e6a18473e718010a43ed4e4e28760a6">对每个像素做：</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2e6a18473e718026a2cbd5372ed11b6c"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://tuchuang.imgliuyaoyu.top/picture/miaobiao3.png?spaceId=f6ca1847-3e71-81fd-991d-0003208a348b&amp;t=2e6a1847-3e71-8026-a2cb-d5372ed11b6c" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-2e6a18473e7180e08314d38ac571505a">具体步骤：</div><ol start="1" class="notion-list notion-list-numbered notion-block-2e6a18473e7180b9b8cde70c34f9c049" style="list-style-type:decimal"><li><b>邻域采样</b>：用顶点阶段生成的 5 个 UV，采样t_tex0（描边掩码纹理），得到 5 个像素值：</li><ol class="notion-list notion-list-numbered notion-block-2e6a18473e7180b9b8cde70c34f9c049" style="list-style-type:lower-alpha"><li>_p_4：当前像素的 t_tex0 值；</li><li>_p_5/_p_6/_p_7/_p_8：上下左右四个方向偏移后的 t_tex0 值；</li></ol></ol><ol start="2" class="notion-list notion-list-numbered notion-block-2e6a18473e7180f590aedceacc5fd42f" style="list-style-type:decimal"><li><b>边缘检测（核心！判定哪里需要描边）</b>：</li><ol class="notion-list notion-list-numbered notion-block-2e6a18473e7180f590aedceacc5fd42f" style="list-style-type:lower-alpha"><li>计算 “当前像素” 与 “上下左右像素平均值” 的差值：_p_4 - (((_p_5 + _p_6) + _p_7) + _p_8) * 0.25f；</li><li>用sign(length(差值))判断是否为边缘：▸ 若差值≠0 → sign返回 1 → 判定为 “物体边缘”（需要描边）；▸ 若差值 = 0 → sign返回 0 → 非边缘（不需要描边）；→ 本质：t_tex0中 “需要描边的物体区域” 和 “背景区域” 的交界像素，差值会显著变大，从而被判定为边缘。</li></ol></ol><ol start="3" class="notion-list notion-list-numbered notion-block-2e6a18473e718040ae92c564359fb10a" style="list-style-type:decimal"><li><b>深度过滤（筛选需要描边的物体）</b>：</li><ol class="notion-list notion-list-numbered notion-block-2e6a18473e718040ae92c564359fb10a" style="list-style-type:lower-alpha"><li>采样深度纹理t_scene_depth，得到当前像素的深度值_p_10；</li><li>适配深度范围（SYSTEM_DEPTH_RANGE_NEGATIVE/USE_REVERSED_Z）：处理不同 API（D3D/OpenGL）的深度值范围差异（0~1 或 - 1~1）；</li><li>用outline_depth_threshold_clip_player过滤：1.0f - step(...) → 深度值超过阈值的像素，描边强度置 0（不描边）。</li></ol></ol><ol start="4" class="notion-list notion-list-numbered notion-block-2e6a18473e7180328035d776fc03af64" style="list-style-type:decimal"><li><b>描边叠加 + 输出</b>：</li><ol class="notion-list notion-list-numbered notion-block-2e6a18473e7180328035d776fc03af64" style="list-style-type:lower-alpha"><li>取邻域采样的最大值_p_11（强化边缘对比度）；</li><li>把边缘检测得到的描边颜色，叠加到原场景颜色（_p_0，来自t_tex1/FrameBuffer Fetch）上；</li><li>最终输出_entryPointOutput：叠加描边后的屏幕像素颜色。</li></ol></ol></main></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Hlod基础知识]]></title>
            <link>https://liuyaoyu.top/article/example-33</link>
            <guid>https://liuyaoyu.top/article/example-33</guid>
            <pubDate>Mon, 10 Nov 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[大世界相关]]></description>
            <content:encoded><![CDATA[<div id="notion-article" class="mx-auto overflow-hidden "><main class="notion light-mode notion-page notion-block-2a7a18473e71802f9cd2e9d811db3eee"><div class="notion-viewport"></div><div class="notion-collection-page-properties"></div><div class="notion-text notion-block-2baa18473e71802f9bc2dd9554670cc5">这个东西还是在修bug 看到的</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2baa18473e7180f09aa7ed89fdb326c0"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://tuchuang.imgliuyaoyu.top/picture/bzdsd1.png?spaceId=f6ca1847-3e71-81fd-991d-0003208a348b&amp;t=2baa1847-3e71-80f0-9aa7-ed89fdb326c0" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-2baa18473e7180f0879cdf2db94ef7ab"><b>那么什么是hlod？</b></div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2baa18473e71801495dafe93341aad7e"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://tuchuang.imgliuyaoyu.top/picture/bzdsd2.png?spaceId=f6ca1847-3e71-81fd-991d-0003208a348b&amp;t=2baa1847-3e71-8014-95da-fe93341aad7e" alt="notion image" loading="lazy" decoding="async"/></div></figure><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-2baa18473e71801cb8c6e6e03cc706e5" data-id="2baa18473e71801cb8c6e6e03cc706e5"><span><div id="2baa18473e71801cb8c6e6e03cc706e5" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2baa18473e71801cb8c6e6e03cc706e5" title="是什么？"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">是什么？</span></span></h2><div class="notion-text notion-block-2baa18473e71807a9b33f542b7e03f85">HLOD（分层细节级别）的核心机制正是将远距离的多个零散物体 &quot;集群化&quot;，生成一个低多边形代理模型来替代逐个渲染</div><div class="notion-text notion-block-2baa18473e71809b8b30fb6b7e83f30f">普通的 LOD 是针对单个模型（比如一棵树、一块石头）的优化。而 HLOD 是针对一群物体的优化。</div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-2baa18473e7180ec800ec5062617fc9e" data-id="2baa18473e7180ec800ec5062617fc9e"><span><div id="2baa18473e7180ec800ec5062617fc9e" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2baa18473e7180ec800ec5062617fc9e" title="怎么做？"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">怎么做？</span></span></h2><div class="notion-text notion-block-2baa18473e718031becaec92bd55954a">HLOD 合并是一个<b>两步流程</b>：</div><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-2baa18473e7180e4b055e432ee291d7b" data-id="2baa18473e7180e4b055e432ee291d7b"><span><div id="2baa18473e7180e4b055e432ee291d7b" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2baa18473e7180e4b055e432ee291d7b" title="1️⃣ 第一步：生成集群（Generate Clusters）"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">1️⃣ 第一步：生成集群（Generate Clusters）</span></span></h4><ul class="notion-list notion-list-disc notion-block-2baa18473e7180e8a8e6dff1ff879df1"><li>在场景中划定区域（HLOD Volume），将区域内的静态物体（如树木、石头）分组</li></ul><ul class="notion-list notion-list-disc notion-block-2baa18473e71809f9a95dff8e42c2e61"><li>这些物体必须设置为 &quot;Static&quot;（静态），且不能是骨骼动画网格（Skeletal Mesh）</li></ul><ul class="notion-list notion-list-disc notion-block-2baa18473e718017b161f4fea5d31195"><li>集群会按照<b>空间距离</b>和<b>屏幕尺寸</b>自动分组，确保同一集群内的物体在远距离观察时 &quot;看起来像一个整体&quot;</li></ul><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-2baa18473e718009bfc6cce6053c8953" data-id="2baa18473e718009bfc6cce6053c8953"><span><div id="2baa18473e718009bfc6cce6053c8953" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2baa18473e718009bfc6cce6053c8953" title="2️⃣ 第二步：生成代理网格（Generate Proxy Meshes）"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">2️⃣ 第二步：生成代理网格（Generate Proxy Meshes）</span></span></h4><div class="notion-text notion-block-2baa18473e7180babd29e4e8482569a9"><b> 烘焙</b>：</div><ul class="notion-list notion-list-disc notion-block-2baa18473e718085a82eeae236f998a9"><li>将集群内所有物体的网格合并，生成一个<b>全新的低多边形网格</b>（通常只有原模型总面数的 5-20%）</li></ul><ul class="notion-list notion-list-disc notion-block-2baa18473e7180828c0ad87a48daf854"><li>同时将这些物体的材质和纹理<b>合并为一张大纹理</b>（Atlas Texture）</li></ul><ul class="notion-list notion-list-disc notion-block-2baa18473e7180fb8436cf9cfeb50da2"><li>最终生成一个<b>单一的 Static Mesh</b>，替代集群内的所有原始模型</li></ul><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-2baa18473e7180fea252dac348522d2f" data-id="2baa18473e7180fea252dac348522d2f"><span><div id="2baa18473e7180fea252dac348522d2f" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2baa18473e7180fea252dac348522d2f" title="特殊点"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">特殊点</span></span></h2><table class="notion-simple-table notion-block-2baa18473e71800e8fa5d2eec981c652"><tbody><tr class="notion-simple-table-row notion-block-2baa18473e7180cfb8a0fad6e34e4f04"><td class="" style="width:120px"><div class="notion-simple-table-cell">特性</div></td><td class="" style="width:120px"><div class="notion-simple-table-cell">HLOD 合并</div></td><td class="" style="width:120px"><div class="notion-simple-table-cell">普通 Actor 合并</div></td></tr><tr class="notion-simple-table-row notion-block-2baa18473e7180aaac84c6adb934c98a"><td class="" style="width:120px"><div class="notion-simple-table-cell"><b>合并范围</b></div></td><td class="" style="width:120px"><div class="notion-simple-table-cell">只对远距离物体生效，近距仍用原始模型</div></td><td class="" style="width:120px"><div class="notion-simple-table-cell">永久合并，远近都用同一个模型</div></td></tr><tr class="notion-simple-table-row notion-block-2baa18473e7180fe93bdefb7a0f960ce"><td class="" style="width:120px"><div class="notion-simple-table-cell"><b>细节处理</b></div></td><td class="" style="width:120px"><div class="notion-simple-table-cell">生成多级 LOD（从高细节到低细节），根据距离自动切换</div></td><td class="" style="width:120px"><div class="notion-simple-table-cell">只有一个合并后的模型，无 LOD 切换</div></td></tr><tr class="notion-simple-table-row notion-block-2baa18473e71803399cdc465e26f25f9"><td class="" style="width:120px"><div class="notion-simple-table-cell"><b>纹理处理</b></div></td><td class="" style="width:120px"><div class="notion-simple-table-cell">自动生成纹理图集，优化渲染性能</div></td><td class="" style="width:120px"><div class="notion-simple-table-cell">可选择合并材质，但通常保留多个材质</div></td></tr><tr class="notion-simple-table-row notion-block-2baa18473e7180739965e7d4f0a66ab8"><td class="" style="width:120px"><div class="notion-simple-table-cell"><b>适用场景</b></div></td><td class="" style="width:120px"><div class="notion-simple-table-cell">仅用于开放世界的远景优化（如山体植被、城市建筑群）</div></td><td class="" style="width:120px"><div class="notion-simple-table-cell">适用于任何场景的静态物体优化</div></td></tr><tr class="notion-simple-table-row notion-block-2baa18473e7180c0b29fef83b8cdc946"><td class="" style="width:120px"><div class="notion-simple-table-cell"><b>性能影响</b></div></td><td class="" style="width:120px"><div class="notion-simple-table-cell">仅远距离节省性能，近距无额外开销</div></td><td class="" style="width:120px"><div class="notion-simple-table-cell">无论远近都减少 Draw Call，但增加单个模型复杂度</div></td></tr></tbody></table><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-2baa18473e7180509a36c9c54946b8c1" data-id="2baa18473e7180509a36c9c54946b8c1"><span><div id="2baa18473e7180509a36c9c54946b8c1" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2baa18473e7180509a36c9c54946b8c1" title="脚本"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">脚本</span></span></h2><div class="notion-text notion-block-2baa18473e7180bd9f9ec1fb30bf2264">可以通过 ue 脚本插件完成</div><div class="notion-text notion-block-2baa18473e718011aa84da0d40671473">用户鼠标右键文件夹，即可批量为文件夹下子关卡生成hlod资源</div><div class="notion-text notion-block-2baa18473e7180d88dfaf316b517723b">这个具体问ai 很简单的脚本</div></main></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[关于米氏散射]]></title>
            <link>https://liuyaoyu.top/article/example-32</link>
            <guid>https://liuyaoyu.top/article/example-32</guid>
            <pubDate>Sat, 29 Nov 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[雾的物理现象]]></description>
            <content:encoded><![CDATA[<div id="notion-article" class="mx-auto overflow-hidden "><main class="notion light-mode notion-page notion-block-2baa18473e7180b0af10e7f63e45dff1"><div class="notion-viewport"></div><div class="notion-collection-page-properties"></div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-2baa18473e71801f87f3ea7692d733b6" data-id="2baa18473e71801f87f3ea7692d733b6"><span><div id="2baa18473e71801f87f3ea7692d733b6" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2baa18473e71801f87f3ea7692d733b6" title="现实现象："><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">现实现象：</span></span></h2><ol start="1" class="notion-list notion-list-numbered notion-block-2baa18473e718093bc66c3e0411e5524" style="list-style-type:decimal"><li>云 雾 雾霾 能看见就是米氏散射的原因（无差别散射所有颜色的光）</li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-2baa18473e7180a2b95aef8181fac539" style="list-style-type:decimal"><li>你注意一下。当你正对着太阳看，然后太阳旁边的云就是发出很白很亮的光，当你背对着太阳看云，你会看到云就不会那么亮那么白，这也是米氏散射。</li></ol><div class="notion-text notion-block-2baa18473e71800b9ea8e807c3b28970">再比如，你开车如果雾天。你开远光灯，前面的雾会更白茫茫一片，更看不清。</div><div class="notion-text notion-block-2baa18473e7180409f5afc23deb86db0">这是因为，车灯（尤其是远光灯）发出的强光，在驾驶人视野前方的雾滴上发生了剧烈的前向散射（米氏散射的核心特征）</div><ol start="1" class="notion-list notion-list-numbered notion-block-2baa18473e71806fb664de971bbe0ebc" style="list-style-type:decimal"><li>波长。波长越长（黄、红光），穿透力越强，被散射得越少。现实现象就是：雾灯氏黄的。 还有晚霞氏黄色红色的。因为此时光的路径长，到人眼这里只有红光和黄光能穿透了。</li></ol><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-2baa18473e718063b9ddcd973d8bb16b" data-id="2baa18473e718063b9ddcd973d8bb16b"><span><div id="2baa18473e718063b9ddcd973d8bb16b" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2baa18473e718063b9ddcd973d8bb16b" title="相关代码："><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">相关代码：</span></span></h2><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2baa18473e7180d89ca8d1da18c67e16"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://tuchuang.imgliuyaoyu.top/picture/adafdadd1.png?spaceId=f6ca1847-3e71-81fd-991d-0003208a348b&amp;t=2baa1847-3e71-80d8-9ca8-d1da18c67e16" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-2baa18473e7180e89aa7ddabfb043d33"> </div></main></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[高度指数雾]]></title>
            <link>https://liuyaoyu.top/article/example-31</link>
            <guid>https://liuyaoyu.top/article/example-31</guid>
            <pubDate>Sat, 29 Nov 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[指数雾]]></description>
            <content:encoded><![CDATA[<div id="notion-article" class="mx-auto overflow-hidden "><main class="notion light-mode notion-page notion-block-2baa18473e7180dba782f94a01ccf0eb"><div class="notion-viewport"></div><div class="notion-collection-page-properties"></div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-2baa18473e718016a45afd82c0bffbd7" data-id="2baa18473e718016a45afd82c0bffbd7"><span><div id="2baa18473e718016a45afd82c0bffbd7" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2baa18473e718016a45afd82c0bffbd7" title="1.前言"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">1.前言</span></span></h2><div class="notion-text notion-block-2baa18473e7180e2a684fc5180ceee3d">重点是模拟真实雾的高度分布和距离衰减，随着高度的增加，雾的密度会下降</div><div class="notion-text notion-block-2baa18473e71800b8c8eccb382b57afd">公式核心为：雾密度 = 基础密度 × exp(- 高度衰减系数 × (目标高度 - 雾的基准高度))</div><div class="notion-text notion-block-2baa18473e71803f9359e8d2fa3395fa">这是整个雾效计算的物理基础，所有后续步骤都围绕这个密度模型展开。</div><div class="notion-text notion-block-2baa18473e718076b6d1df5175d9cba5">exp(x) 是单调递增</div><div class="notion-text notion-block-2baa18473e718045863bc91145fbe341">exp（-x）是单调递减</div><div class="notion-text notion-block-2baa18473e718040a2acf2eff2d6adb7">具体说 当目标高度 &gt; 基准高度 则雾越淡（x项为负 单调递减）</div><div class="notion-text notion-block-2baa18473e71800693e0cf41146844bd">当目标高度 &lt; 基准高度 则雾越浓（x项为正 单调递增）</div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-2baa18473e71801fabfccfb8e656e25e" data-id="2baa18473e71801fabfccfb8e656e25e"><span><div id="2baa18473e71801fabfccfb8e656e25e" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2baa18473e71801fabfccfb8e656e25e" title="总雾density的计算"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">总雾density的计算</span></span></h3><div class="notion-text notion-block-2baa18473e71802c993df7d8fb61a9af">总雾量 = 积分项 × 调整后的路径长度（RayLength）× 雾密度基础项（RayOriginTerms）</div><div class="notion-text notion-block-2baa18473e7180a9a798d349ab34c205">（总雾量 = 单位路径积累量 × 路径长度 x  起点浓度）</div><ul class="notion-list notion-list-disc notion-block-2baa18473e7180f0b669e1ba3e6c9360"><li>雾衰减因子 = max(-12.7, 雾高度衰减系数 × 调整后射线Y方向)</li></ul><ul class="notion-list notion-list-disc notion-block-2baa18473e7180b3b613daa10266ffc7"><li>单位路径积分 = (1.0 - 2^(-雾衰减因子)) / 雾衰减因子</li></ul><ul class="notion-list notion-list-disc notion-block-2baa18473e7180319eb9c5743ae47593"><li>积分泰勒近似 = ln(2) - 0.5 × (ln(2))² × 雾衰减因子</li></ul><ul class="notion-list notion-list-disc notion-block-2baa18473e718006be18e8ccad5aab67"><li>有效单位积分 = 如果 |雾衰减因子| &gt; 极小值 则 单位路径积分 否则 积分泰勒近似</li></ul><div class="notion-text notion-block-2baa18473e718029b50ff042f572aa68">关于这个单位路径积分：</div><div class="notion-text notion-block-2baa18473e7180649a7ec278928b60e6">类似:总水量 = 水源压力 × 流量调整系数 × 水管长度</div><div class="notion-text notion-block-2baa18473e71804c87bdfc84b5f745f5">就是 单位路径积分 这个系数本身就包含了 “连续变化” 的信息，所以不用再除以总长度求平均，直接乘总长度就能得到总累积值</div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-2baa18473e7180ccb4fefe77fa05e35f" data-id="2baa18473e7180ccb4fefe77fa05e35f"><span><div id="2baa18473e7180ccb4fefe77fa05e35f" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2baa18473e7180ccb4fefe77fa05e35f" title="2.计算步骤："><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">2.计算步骤：</span></span></h2><div class="notion-text notion-block-2baa18473e71808eaef3d30a7cfc377e">本质上是计算，从相机到渲染点的路径长度（路径越长，叠加的浓度越大）</div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-2baa18473e718014bb25f0ba1b6cb0bf" data-id="2baa18473e718014bb25f0ba1b6cb0bf"><span><div id="2baa18473e718014bb25f0ba1b6cb0bf" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2baa18473e718014bb25f0ba1b6cb0bf" title="向量准备："><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">向量准备：</span></span></h3><div class="notion-text notion-block-2baa18473e718031bc25c91a0ad74ac8">为此我们需要准备：</div><div class="notion-text notion-block-2baa18473e7180c4b118e67a5232e52b">1.相机到渲染的向量（WorldPositionRelativeToCamera），长度（CameraToReceiverLength）</div><div class="notion-text notion-block-2baa18473e7180c2a66ffa91e26a7832">2.处理雾的起始距离（ExcludeDistance）：强制让雾从指定距离后生效（避免近距离物体被雾遮挡），这个其实就是把相机起点往 那个路径方向 偏移一下</div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-2baa18473e7180058fade49663ce0451" data-id="2baa18473e7180058fade49663ce0451"><span><div id="2baa18473e7180058fade49663ce0451" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2baa18473e7180058fade49663ce0451" title="积分雾的总浓度计算（核心）"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">积分雾的总浓度计算（核心）</span></span></h3><div class="notion-text notion-block-2baa18473e718040b276c44e09c7ba89">雾的 density 由「路径长度 × 路径上的雾密度积分」决定。这里要 计算积分，兼顾性能和精度：</div><ol start="1" class="notion-list notion-list-numbered notion-block-2baa18473e71806da9d6f605b583028e" style="list-style-type:decimal"><li>计算射线起点的雾密度（RayOriginTerms）：基于调整后射线起点的高度，计算指数衰减项（exp2(-Exponent2)），再乘以基础密度（u_fog_info_raw.y），代表射线起点处的雾密度系数（max (-12.7) 是为了避免exp2溢出）。</li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-2baa18473e718039b6f7f707023f068b" style="list-style-type:decimal"><li>计算积分项（LineIntegral）：针对指数密度模型，积分公式为 [1 - exp(-Falloff)] / Falloff（Falloff是高度衰减系数 × 射线方向 Z 分量），表示 “单位路径长度上的雾密度积分”；</li></ol><ol start="3" class="notion-list notion-list-numbered notion-block-2baa18473e718085a2dbe3d6baf0676d" style="list-style-type:decimal"><li>处理边界情况：当Falloff接近 0（射线几乎水平）时，用泰勒展开近似积分（避免除零错误）；</li></ol><ol start="4" class="notion-list notion-list-numbered notion-block-2baa18473e718018abcfc5d26ed95d21" style="list-style-type:decimal"><li>总雾量 = 积分项 × 调整后的路径长度（RayLength）× 雾密度基础项（RayOriginTerms）。</li></ol><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2baa18473e7180acab57ce2239acb8c4"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://tuchuang.imgliuyaoyu.top/picture/wuqigaodu1.png?spaceId=f6ca1847-3e71-81fd-991d-0003208a348b&amp;t=2baa1847-3e71-80ac-ab57-ce2239acb8c4" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-2baa18473e71805899c8f344fd5e902c">伪代码如下：</div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-2baa18473e718050a566ef0f033dd45e" data-id="2baa18473e718050a566ef0f033dd45e"><span><div id="2baa18473e718050a566ef0f033dd45e" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2baa18473e718050a566ef0f033dd45e" title="计算雾的混合因子和颜色"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">计算雾的混合因子和颜色</span></span></h3><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-2baa18473e71808eb5d0d67ea8741b0e" data-id="2baa18473e71808eb5d0d67ea8741b0e"><span><div id="2baa18473e71808eb5d0d67ea8741b0e" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2baa18473e71808eb5d0d67ea8741b0e" title="获取基础雾颜色"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">获取基础雾颜色</span></span></h4><div class="notion-text notion-block-2baa18473e71802a81fadd15b9dae684">这里有个函数GetFogColor ，依据距离获取雾的颜色</div><div class="notion-text notion-block-2baa18473e718068a7e9c5365ccb1302">half3 GetFogColor(float dis_to_camera)</div><div class="notion-text notion-block-2baa18473e7180a98f8cedc6757d29d6">{</div><div class="notion-text notion-block-2baa18473e718061ad1ed517be3e59c8">half3 Isvlmfog_ambient = half3(u_ambient.rgb * u_atmosphere_param.y); //环境光适配因子</div><div class="notion-text notion-block-2baa18473e7180cbb276d0230f9f48f6">half linear_factor = smoothstep(u_fog_near_color.w * u_camera_info.y, u_camera_info.y * max(u_fog_near_color.w + 0.001, u_fog_color.w), dis_to_camera);</div><div class="notion-text notion-block-2baa18473e7180ebbe47fc82607eff3e">half3 fog_color = lerp(half3(u_fog_near_color.rgb), half3(u_fog_color.rgb), linear_factor) * Isvlmfog_ambient;</div><div class="notion-text notion-block-2baa18473e71801aaa64d1a446d4f48c">//fog_color = u_fog_near_color.rgb;</div><div class="notion-text notion-block-2baa18473e7180eea0b6d69d185fc32a">return fog_color;</div><div class="notion-text notion-block-2baa18473e71804c9788cc91de3565b9">}</div><div class="notion-text notion-block-2baa18473e71803c9c06eb1c367862cb">里面的近雾色 和 远雾色  是美术通过引擎进行调节的</div><div class="notion-text notion-block-2baa18473e7180628492eb310016acf5">u_ambient.rgb 是场景的环境光</div><div class="notion-text notion-block-2baa18473e718076a28fe51b6ed7262c">u_atmosphere_param.y：环境光对雾的影响强度（0 = 雾色不受环境光影响，1 = 雾色完全贴合环境光）</div><div class="notion-text notion-block-2baa18473e7180e5acebe6f4b65e7a7b">相乘就是Isvlmfog_ambient，即影响雾的环境光底色</div><div class="notion-text notion-block-2baa18473e718005b411d7b901732d2a">所以就是美术可调的远近雾色 叠加 环境光影响</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-2baa18473e7180a9bfa8f51402608332" data-id="2baa18473e7180a9bfa8f51402608332"><span><div id="2baa18473e7180a9bfa8f51402608332" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2baa18473e7180a9bfa8f51402608332" title="获取雾的定向散射颜色"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">获取雾的定向散射颜色</span></span></h4><div class="notion-text notion-block-2baa18473e71806083acd01849571587">其实就是米氏散射拉</div><div class="notion-text notion-block-2baa18473e7180a6ab71ee3d75302767">这个颜色不是雾本身的底色，而是 “雾反射了特定方向光源的颜色”，且只在 “视线与光源方向接近” 时才明显</div><div class="notion-text notion-block-2baa18473e7180f885c2dd9c565dc1f9"><a class="notion-link" href="https://mcnw7y8qdp0f.feishu.cn/wiki/NR6fwOZiHioxhHkz7BAcxziznbc" target="_blank" rel="noopener noreferrer">关于米氏散射</a></div><div class="notion-text notion-block-2baa18473e71808fb165e938cda2ba45">要算这个也要分几步：</div><div class="notion-text notion-block-2baa18473e7180edb4fbe008a34c5991"><b>1.先算光源方向</b></div><div class="notion-text notion-block-2baa18473e718026881edcec05e5c9ae">代码里用的这个：</div><div class="notion-text notion-block-2baa18473e71806a89e9ebf966e7d625"><code class="notion-inline-code">FogStruct_InscatteringLightDirection</code>  其中xyz是光源的世界空间方向  w是定向散射的生效起始距离</div><div class="notion-text notion-block-2baa18473e71808cbc65f7f50c2164f5"><b>2.计算 散射强度：视线与光源方向越近，散射越强</b></div><div class="notion-text notion-block-2baa18473e718067bdd1e5d7cb41a34d">这个类似那个sss的计算，就是逆光的时候强度最大呗。dot（-v，L）</div><div class="notion-text notion-block-2baa18473e71805fa310c8cd2fffe327">然后    pow(..., max(2.0, 雾散射指数×30.0))）  就是最低都得是2的pow</div><div class="notion-text notion-block-2baa18473e718004aebadd74f4d335fb">视线正对光源（逆光）时，散射最强；视线背向光源时，散射最弱（几乎没有）。</div><div class="notion-text notion-block-2baa18473e7180bf86ebf6d07dba70c3"><b>3.计算 “散射颜色”：光源颜色 × 雾的散射特性</b></div><ul class="notion-list notion-list-disc notion-block-2baa18473e7180a581d6d8c66c53e053"><li>先算米氏散射颜色（mie_color）：混合 定向光源颜色（比如太阳的白色 / 橙黄色）和 雾的米氏散射底色（u_mie_color），模拟雾滴对不同波长光线的散射差异（比如雾对红光散射弱、蓝光散射强，但定向散射时更偏向光源颜色，这是米氏散射的原理 <a class="notion-link" href="https://mcnw7y8qdp0f.feishu.cn/wiki/NR6fwOZiHioxhHkz7BAcxziznbc" target="_blank" rel="noopener noreferrer">关于米氏散射</a></li></ul><ul class="notion-list notion-list-disc notion-block-2baa18473e71802bb26eca5309b356a6"><li>再乘「散射强度」和「大气散射开关」：控制定向散射的 浓淡 和 是否启用；</li></ul><ul class="notion-list notion-list-disc notion-block-2baa18473e7180de8a02fb30dbcaf103"><li>最后用「定向散射积分」控制生效范围：只有雾的有效路径长度超过 “定向散射起始距离” 时，才会叠加这个颜色（避免近距离雾过亮）。</li></ul><div class="notion-text notion-block-2baa18473e71804ebacbf7a68e3b3b4f">最终雾色 = 基础雾色 × (1 - 雾透射因子) + 定向散射颜色</div><div class="notion-text notion-block-2baa18473e7180c1bb8ace18bf8b488d">其实就是雾的底色 + 雾的散射的光（逆光最大的米氏散射的颜色）</div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-2baa18473e7180e6a888f4e593b4cce7" data-id="2baa18473e7180e6a888f4e593b4cce7"><span><div id="2baa18473e7180e6a888f4e593b4cce7" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2baa18473e7180e6a888f4e593b4cce7" title="3.入口："><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">3.入口：</span></span></h2><div class="notion-text notion-block-2baa18473e718030b204d3c4a2455d10">先是这个入口</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2baa18473e7180ecabc1d6ca138733c7"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://tuchuang.imgliuyaoyu.top/picture/wuqigaodu2.png?spaceId=f6ca1847-3e71-81fd-991d-0003208a348b&amp;t=2baa1847-3e71-80ec-abc1-d6ca138733c7" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-2baa18473e71808fa2b0daa5814095f4">重点还是GetExponentialHeightFog函数</div><div class="notion-text notion-block-2baa18473e71803f8359eeccec56f6a6">伪代码如下：</div><div class="notion-text notion-block-2baa18473e7180fab7bfc71a508e465d">函数 核心指数高度雾计算(相机世界位置, 目标点相对相机向量, 初始排除距离) -&gt; 雾颜色+混合因子:</div><div class="notion-text notion-block-2baa18473e71801b8428ed4d9e29f467">// 注：所有「全局参数」均对应原代码的全局变量，括号内标注原代码变量名</div><div class="notion-text notion-block-2baa18473e718063a5c7c544f50c3a05">最小雾不透明度 = 0.0  // 原代码：const half MinFogOpacity = 0.0</div><div class="notion-text notion-block-2baa18473e71801d84e5fe2190992e2a">// ===================== 第一步：射线预处理（算清“雾计算的路径基础”）=====================</div><div class="notion-text notion-block-2baa18473e7180f88e68ee4e077c735c">// 目的：把“相机→目标点”的射线属性算透，为后续雾量积分做准备</div><div class="notion-text notion-block-2baa18473e7180528eadf6d753257e08">相机到目标点向量 = 目标点相对相机向量  // 原代码：CameraToReceiver = WorldPositionRelativeToCamera</div><div class="notion-text notion-block-2baa18473e7180aa968af750bc62821b">射线长度平方 = 点积(相机到目标点向量, 相机到目标点向量)  // 原代码：CameraToReceiverLengthSqr</div><div class="notion-text notion-block-2baa18473e718084938eee1588de657b">射线长度倒数 = 1.0 / 平方根(射线长度平方)  // 原代码：CameraToReceiverLengthInv = rsqrt(...)</div><div class="notion-text notion-block-2baa18473e71808d9e77e2d46d0a2432">射线总长度 = 射线长度平方 × 射线长度倒数  // 原代码：CameraToReceiverLength（等价于sqrt(平方)，优化性能）</div><div class="notion-text notion-block-2baa18473e71808081d4edc95689c6a1">射线单位向量 = 相机到目标点向量 × 射线长度倒数  // 原代码：CameraToReceiverNormalized（方向标准化）</div><div class="notion-text notion-block-2baa18473e718083b2e4c2b1293435dd">// ===================== 第二步：雾生效距离处理（控制“雾从哪里开始出现”）=====================</div><div class="notion-text notion-block-2baa18473e7180b484dedd183be93a77">// 目的：避免近距离物体被雾遮挡，只让雾在「指定距离后」生效</div><div class="notion-text notion-block-2baa18473e7180b3adb7db0f010ed4c1">// 最终雾生效起始距离 = 取初始值、全局配置值的最大值（原代码：ExcludeDistance = max(ExcludeDistance, max(u_fog_info.x,0.001))）</div><div class="notion-text notion-block-2baa18473e7180e4919ec1d662cfefb0">最终雾生效起始距离 = 最大值(初始排除距离, 最大值(全局参数.雾起始距离, 0.001))  // 全局参数.雾起始距离 = 原代码u_fog_info.x</div><div class="notion-text notion-block-2baa18473e7180a8af56d5feec8be8b6">交点在射线上的比例 = 最终雾生效起始距离 × 射线长度倒数  // 原代码：ExcludeIntersectionTime（射线参数t：0=相机，1=目标点）</div><div class="notion-text notion-block-2baa18473e71801c9aaeec9a57090f02">相机到交点的Y分量 = 交点在射线上的比例 × 相机到目标点向量.y  // 原代码：CameraToExclusionIntersectionZ（注意原代码变量名写Z但实际用y，伪代码修正为Y更准确）</div><div class="notion-text notion-block-2baa18473e71806eb2f2f0fbffd47335">交点的世界高度 = 相机世界位置.y + 相机到交点的Y分量  // 原代码：ExclusionIntersectionZ（生效距离处的高度，雾密度核心关联值）</div><div class="notion-text notion-block-2baa18473e7180a6a49ac90a603a3d51">交点到目标点的Y分量 = 相机到目标点向量.y - 相机到交点的Y分量  // 原代码：ExclusionIntersectionToReceiverZ（调整后射线的Y方向长度）</div><div class="notion-text notion-block-2baa18473e71806ab39bdd9300d2edf0">调整后射线长度 = (1.0 - 交点在射线上的比例) × 射线总长度  // 原代码：RayLength（仅计算“生效距离→目标点”的雾量，前面的路径无雾）</div><div class="notion-text notion-block-2baa18473e7180678177c73e88eef995">调整后射线Y方向 = 交点到目标点的Y分量  // 原代码：RayDirectionZ（实际是Y方向，伪代码修正命名）</div><div class="notion-text notion-block-2baa18473e7180f09383f54025cdb0e2">// ===================== 第三步：起点雾密度计算（算“生效距离处的雾浓淡基准”）=====================</div><div class="notion-text notion-block-2baa18473e7180118fcde2caf1516ad7">// 目的：基于“高度衰减模型”，计算雾生效起点的密度（高度越低，密度越大）</div><div class="notion-text notion-block-2baa18473e7180e38df4d7f710fcc626">// 高度指数项：max(-12.7)避免exp2溢出（原代码：Exponent2 = max(-12.70f, u_fog_info.z * (...)）</div><div class="notion-text notion-block-2baa18473e7180df8869f3354b5f6877">高度指数项 = 最大值(-12.7, 全局参数.雾高度衰减系数 × (交点的世界高度 - 全局参数.雾基准高度))</div><div class="notion-text notion-block-2baa18473e7180e6b51cf8324c9e81f2">// 全局参数.雾高度衰减系数 = 原代码u_fog_info.z；全局参数.雾基准高度 = 原代码u_fog_info_raw.x</div><div class="notion-text notion-block-2baa18473e718075b21cf282f63de1a2">射线起点雾密度项 = 全局参数.雾基础密度 × 2^(-高度指数项)  // 原代码：RayOriginTerms = u_fog_info_raw.y * exp2(-Exponent2)（exp2(x)=2^x，这里明确负号，和原代码完全一致）</div><div class="notion-text notion-block-2baa18473e7180308563e1ef16ba0c71">// 全局参数.雾基础密度 = 原代码u_fog_info_raw.y</div><div class="notion-text notion-block-2baa18473e7180e69e08da64d85853e8">// ===================== 第四步：路径雾量积分（核心！算“路径上的总雾浓”）=====================</div><div class="notion-text notion-block-2baa18473e7180159ff8c1d09112ef67">// 目的：用数学解析解计算“射线穿过雾的总雾量”，既快又准</div><div class="notion-text notion-block-2baa18473e71806992cbea40834f9335">// 雾衰减因子：反映射线方向对雾密度的影响（原代码：Falloff = max(-12.70f, u_fog_info.z * RayDirectionZ)）</div><div class="notion-text notion-block-2baa18473e718024abe7ecfc2678603e">雾衰减因子 = 最大值(-12.7, 全局参数.雾高度衰减系数 × 调整后射线Y方向)</div><div class="notion-text notion-block-2baa18473e7180a7a676cb49546e11dc">// 解析解积分：单位长度路径上的雾密度总和（原代码：LineIntegral = (1.0f - exp2(-Falloff)) / Falloff）</div><div class="notion-text notion-block-2baa18473e7180c6afcff19a3e7d0d63">单位路径积分 = (1.0 - 2^(-雾衰减因子)) / 雾衰减因子</div><div class="notion-text notion-block-2baa18473e7180f9a0cad6aea9dfeb66">// 泰勒展开：处理雾衰减因子≈0（射线水平）的情况，避免除零错误（原代码：LineIntegralTaylor）</div><div class="notion-text notion-block-2baa18473e71805cb6aac25ddf950a14">积分泰勒近似 = 自然对数(2.0) - 0.5 × (自然对数(2.0))² × 雾衰减因子</div><div class="notion-text notion-block-2baa18473e7180dbbe86d8f9f5647eec">// 选择稳定的积分方案（原代码：abs(Falloff) &gt; FLT_EPSILON2 ? LineIntegral : LineIntegralTaylor）</div><div class="notion-text notion-block-2baa18473e71809aaee2fcb200ea3c2e">如果 绝对值(雾衰减因子) &gt; 极小值:  // 极小值=原代码FLT_EPSILON2（避免除零）</div><div class="notion-text notion-block-2baa18473e7180d7b176e51241815b73">有效单位积分 = 单位路径积分</div><div class="notion-text notion-block-2baa18473e7180a38435eb2997f99e43">否则:</div><div class="notion-text notion-block-2baa18473e718071a425e64542462890">有效单位积分 = 积分泰勒近似</div><div class="notion-text notion-block-2baa18473e7180988e8ae44c24622b21">// 总雾量积分：起点密度 × 单位积分 × 路径长度（原代码：ExponentialHeightLineIntegral = ...）</div><div class="notion-text notion-block-2baa18473e7180f2883bfd09cf9923a6">总雾量积分 = 射线起点雾密度项 × 有效单位积分 × 调整后射线长度  // 核心结果：雾的总浓度</div><div class="notion-text notion-block-2baa18473e7180c68e45e5bacd2e5411">// ===================== 第五步：雾颜色计算（算“雾该是什么颜色”）=====================</div><div class="notion-text notion-block-2baa18473e7180709d11e9b20b6fcbb2">// 1. 基础雾色：按距离取雾的基础颜色（原代码：dis_to_camera = length(...)，实际就是射线总长度）</div><div class="notion-text notion-block-2baa18473e7180cc86a4e19d5964d7ef">目标点到相机距离 = 射线总长度  // 复用前面计算结果，优化性能（原代码逻辑一致）</div><div class="notion-text notion-block-2baa18473e71807d9868d8c760330a8b">基础雾颜色 = 调用GetFogColor(目标点到相机距离)  // 原代码：GetFogColor(dis_to_camera)（外部函数：按距离返回雾色，比如远→蓝）</div><div class="notion-text notion-block-2baa18473e718064a2c7d76a3472edcf">// 2. 定向散射颜色（可选：模拟阳光等定向光在雾中的散射，比如逆光雾更亮）</div><div class="notion-text notion-block-2baa18473e7180d9b611f3b205590242">定向散射颜色 = (0, 0, 0)  // 默认无定向散射</div><div class="notion-text notion-block-2baa18473e71801dafaac1b8fec80269">如果 启用定向光雾散射:  // 原代码：#if SUPPORT_FOG_DIRECTIONAL_LIGHT_INSCATTERING</div><div class="notion-text notion-block-2baa18473e7180528c3ccf525a0ca490">定向散射起始距离 = 全局参数.光源方向.w  // 原代码：FogStruct_InscatteringLightDirection.w（定向散射生效距离）</div><div class="notion-text notion-block-2baa18473e7180b4bf44cbe50eb02c7f">// 米氏散射颜色：模拟雾滴对光线的散射（原代码：mie_color = lerp(u_dir_color.rgb, u_mie_color.rgb*..., u_mie_color.a)）</div><div class="notion-text notion-block-2baa18473e7180aca1b8f78f21f24e08">米氏散射颜色 = 线性插值(全局参数.定向光颜色, 全局参数.米氏颜色×全局参数.米氏颜色, 全局参数.米氏颜色.a)</div><div class="notion-text notion-block-2baa18473e71800fb087e507e90dcc96">// 全局参数.定向光颜色=原代码u_dir_color.rgb；全局参数.米氏颜色=原代码u_mie_color</div><div class="notion-text notion-block-2baa18473e718029af98dd6abd91d5ad">// 散射强度：视线与光线方向越近，散射越强（原代码：pow(saturate(dot(...)), max(2.0, u_fog_info.y*30.0))）</div><div class="notion-text notion-block-2baa18473e718076a428c46b3bcb52cd">视线与光线夹角余弦 = 饱和值(点积(射线单位向量, 全局参数.光源方向.xyz))  // 夹角余弦∈[0,1]，越近越亮</div><div class="notion-text notion-block-2baa18473e718047b86def36fe41167f">散射强度 = 视线与光线夹角余弦 ^ 最大值(2.0, 全局参数.雾散射指数 × 30.0)  // 幂次集中散射效果（原代码u_fog_info.y=雾散射指数）</div><div class="notion-text notion-block-2baa18473e71800d93bee4362a8b5241">// 定向散射基础色：米氏颜色×强度×开关（原代码：Isvlmfog_inscatter = u_atmosphere_param.w）</div><div class="notion-text notion-block-2baa18473e7180589e45f43e0078035e">定向散射基础 = 米氏散射颜色 × 散射强度 × 全局参数.大气散射开关  // 全局参数.大气散射开关=原代码u_atmosphere_param.w</div><div class="notion-text notion-block-2baa18473e71807ea593d7d4c68708f8">// 定向散射有效积分：只在“定向散射起始距离后”生效（原代码：DirExponentialHeightLineIntegral）</div><div class="notion-text notion-block-2baa18473e7180759af8fc3542f11d1d">定向散射积分 = 射线起点雾密度项 × 有效单位积分 × 最大值(调整后射线长度 - 定向散射起始距离, 0.0)</div><div class="notion-text notion-block-2baa18473e7180309e88c89a494885a2">定向散射透射因子 = 饱和值(2^(-定向散射积分))  // 散射越强，透射因子越小</div><div class="notion-text notion-block-2baa18473e7180b8968fc0bac87751a8">定向散射颜色 = 定向散射基础 × (1.0 - 定向散射透射因子)  // 透射越少，散射颜色越明显</div><div class="notion-text notion-block-2baa18473e7180d79039fcf5d385370d">// ===================== 第六步：透射因子计算（算“物体被雾挡多少”）=====================</div><div class="notion-text notion-block-2baa18473e7180f6966efab369e2b224">// 目的：控制物体与雾的混合比例（原代码：ExpFogFactor = max(saturate(exp2(-...)), MinFogOpacity)）</div><div class="notion-text notion-block-2baa18473e7180bebaa9c47f4809f58d">雾透射因子 = 最大值(饱和值(2^(-总雾量积分)), 最小雾不透明度)</div><div class="notion-text notion-block-2baa18473e71804386c1c643190fa38f">// 逻辑：总雾量越大 → 2^(-总雾量)越小 → 透射因子越接近0 → 物体越透明，雾越明显</div><div class="notion-text notion-block-2baa18473e718074beddff002b5a7517">// ===================== 第七步：结果合成（输出“最终雾色+混合因子”）=====================</div><div class="notion-text notion-block-2baa18473e718054aa2dce30a947f950">// 最终雾色 = 基础雾色×雾可见比例 + 定向散射色（原代码：FogColor = (InscatteringColor)*(1-...) + DirectionalInscattering）</div><div class="notion-text notion-block-2baa18473e71809e8ce7e14140e7a866">最终雾颜色 = 基础雾颜色 × (1.0 - 雾透射因子) + 定向散射颜色</div><div class="notion-text notion-block-2baa18473e7180c5a699e3816ca1c3fc">// 1-雾透射因子：雾的可见比例（透射因子越小，雾越明显）</div><div class="notion-text notion-block-2baa18473e7180cf8319f3531b422ec6">// 返回格式：RGB=雾颜色，A=透射因子（原代码：return half4(FogColor, ExpFogFactor)）</div><div class="notion-text notion-block-2baa18473e7180f393d4fe15f090a40f">返回 (最终雾颜色.r, 最终雾颜色.g, 最终雾颜色.b, 雾透射因子)</div></main></div>]]></content:encoded>
        </item>
    </channel>
</rss>