<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>cg on PlumePHP</title><link>https://plumephp.com/categories/cg/</link><description>Recent content in cg on PlumePHP</description><generator>Hugo</generator><language>zh-CN</language><lastBuildDate>Sat, 17 Oct 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://plumephp.com/categories/cg/index.xml" rel="self" type="application/rss+xml"/><item><title>Vulkan 描述符集与着色器编程：资源绑定与 SPIR-V 实战</title><link>https://plumephp.com/vulkan-descriptor-shader/</link><pubDate>Tue, 01 Sep 2026 00:00:00 +0000</pubDate><guid>https://plumephp.com/vulkan-descriptor-shader/</guid><description>深度解析 Vulkan Descriptor Set Layout、Pool、Uniform Buffer、Image/Sampler 绑定机制，涵盖 SPIR-V 编译流程、Push Constants 实战及 Pipeline Layout 设计要点。</description></item><item><title>16.3 交付卷三</title><link>https://plumephp.com/cg-shade-16-3-deliverable-handoff-volume3/</link><pubDate>Thu, 15 Oct 2026 21:50:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-16-3-deliverable-handoff-volume3/</guid><description>卷二的收尾交付：接口契约写清卷一封了装配/深度/覆盖、卷二封了着色链（片元颜色的来源），卷三只替换「直接光照求值」为渲染方程的积分估计；另给出三条轴的参数扰动扫描——强度偏移 1 个 Q16.16 单位即产生首次可见差异（128 像素），超采样 N=4 才收敛，10 条软告警不硬失败、exit 0。</description></item><item><title>16.2 三种消费的联调</title><link>https://plumephp.com/cg-shade-16-2-three-host-integration/</link><pubDate>Thu, 15 Oct 2026 21:35:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-16-2-three-host-integration/</guid><description>同一份 scene_spec.json 在 Python 定点、TypeScript 定点、浏览器 WebGL2 三处消费：S 与 P 成片 sha256 逐字节相同（0d997343…，43731 覆盖像素），S 与 W 按声明容差比对为 MAE 0.5067、PSNR 47.03 dB、覆盖归属差 0.0781‰；负例（片元颜色 ×0.5）MAE 21.3528 被同一判据拒绝。</description></item><item><title>16.1 着色管线的装配</title><link>https://plumephp.com/cg-shade-16-1-shading-pipeline-assembly/</link><pubDate>Thu, 15 Oct 2026 21:20:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-16-1-shading-pipeline-assembly/</guid><description>把卷二前面十五节的环节首尾相接成一条从规格到成像的链：S 层在 320x240 场景上逐级核对十二个缓冲契约，w 不变量 487/487 成立、重心权重和违反 0 次、覆盖 43731 像素，成片 sha256 与卷二基线逐字节一致；P 层用 BigInt 重算同一链路复现同一摘要，负例（顶点顺序交换）必须让摘要分叉。</description></item><item><title>12.3 CPU 与 GPU 的比对</title><link>https://plumephp.com/cg-shade-12-3-cpu-gpu-comparison/</link><pubDate>Thu, 15 Oct 2026 21:00:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-12-3-cpu-gpu-comparison/</guid><description>把同一份场景交给 WebGL2 渲染，再与 S 层定点基线逐像素比对：MAE 0.5073、PSNR 46.95 dB、覆盖归属差异 0.08‰，与 12.1 的 CPU 浮点镜像 0.4963 落在同一噪声地板上。不一致像素按「共享边归属 0.0% / 插值精度 11.3% / 舍入 88.6%」三类归因，并如实交代本机后端是 ANGLE/SwiftShader 软件实现，不是真实 GPU。</description></item><item><title>12.2 图像 digest 与误差度量</title><link>https://plumephp.com/cg-shade-12-2-image-digest-error/</link><pubDate>Thu, 15 Oct 2026 20:30:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-12-2-image-digest-error/</guid><description>sha256 是「全等判据」，只在「全等是合理期望」时成立——浮点实现的 sha256 与基线不同，而它的 MAE 只有 0.4963。本节给出 MAE / RMSE / PSNR / 最大通道差四个标量的定义与各自盲区：整幅 +1 与 4 像素 +64 的 MAE 完全相同，只有 RMSE 与最大通道差分得开；覆盖归属差异与颜色误差是两条独立判据，必须分两栏报告。</description></item><item><title>12.1 浮点的容差口径</title><link>https://plumephp.com/cg-shade-12-1-float-tolerance/</link><pubDate>Thu, 15 Oct 2026 20:00:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-12-1-float-tolerance/</guid><description>逐位相等在两个宿主之间不可能，容差必须可声明、可复算。本节把容差写成三条同时成立的判据——覆盖归属差异 ≤ 20‰、MAE ≤ 1.0、PSNR ≥ 30 dB，逐条给出阈值出处，并用同一份整数基线量出噪声地板与三条穿越点：太松会漏掉 2% 的全局偏置，太紧会把噪声本身判成错。</description></item><item><title>10.3 色调与调色</title><link>https://plumephp.com/cg-shade-10-3-grading/</link><pubDate>Thu, 15 Oct 2026 19:00:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-10-3-grading/</guid><description>调色的整数形态是查表：对比度绕 128 旋转、色温用逐通道偏置，合成三张 256 项的一维 LUT；饱和度写成 luma + (s·(in-luma) &gt;&gt; 16)。本节量化 8 位 LUT 的往返代价与三维 LUT 的节点数误差，并给出 W 层浮点着色器与 S 层整数结果的声明容差比对（含被拒绝的负例）。</description></item><item><title>10.2 Bloom 与泛光</title><link>https://plumephp.com/cg-shade-10-2-bloom/</link><pubDate>Thu, 15 Oct 2026 18:40:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-10-2-bloom/</guid><description>泛光不是「把亮的地方涂糊」，而是一条四步整数链：Rec.601 亮度做整数阈值提取亮部、每级减半的 2×2 盒式降采样、整数双线性上采样、以及权重和恰好为 ONE 的合并。本节扫描级数 2/4/6、阈值 64/96/128、强度 0.25~2.0，并给出金标准泛光帧的 sha256。</description></item><item><title>10.1 卷积与模糊</title><link>https://plumephp.com/cg-shade-10-1-convolution-blur/</link><pubDate>Thu, 15 Oct 2026 18:20:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-10-1-convolution-blur/</guid><description>后处理的第一步是用核卷积。本节把卷积写成全整数：Q16.16 核权重之和必须恰好等于 ONE，否则整帧会整体偏亮或偏暗；边界有 clamp/wrap/mirror 三种；半径 r 的二维核拆成两次一维可分离卷积，半径 8 时实测快 8.86 倍。Python 与 TypeScript 在四个半径下的模糊缓冲 sha256 逐字节相同。</description></item><item><title>《计算机图形学》卷三《光线追踪与全局光照》目录</title><link>https://plumephp.com/cg-trace-toc/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-toc/</guid><description>《计算机图形学》卷三《光线追踪与全局光照》目录：16 章 48 节，把光还原成一个可估计的积分——光线求交与 BVH、阴影反射折射、蒙特卡洛积分与方差、路径追踪与渲染方程、重要性采样与多重重要性采样、辐射度与光子映射、体积渲染与 ray marching、SDF、收敛度量与停止准则，最后做跨语言数值一致与三卷总收官。本页给出分工、六档可运行性口径、卷三新基线与全书 16 章 48 节完整清单。</description></item><item><title>《计算机图形学》卷三《光线追踪与全局光照》附录 A · 渲染算法公式、参数表与数据集索引</title><link>https://plumephp.com/cg-trace-appendix-a/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-appendix-a/</guid><description>《计算机图形学》卷三《光线追踪与全局光照》附录 A：全卷共用的定点常数表（EPSILON、TRI_STRIDE、BVH 叶子容量、SplitMix64 的四个常数）、光追中间量的实测位宽上界（为什么 TS 侧必须全程 BigInt）、十个渲染算法的整数形式速查、采样与收敛参数表、三卷基线 sha256 与误差汇总，以及各章产物的数据集索引与复现命令。所有数字来自本机实跑。</description></item><item><title>1.1 光线的表示与求交</title><link>https://plumephp.com/cg-trace-01-1-ray-representation-intersection/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-01-1-ray-representation-intersection/</guid><description>光线就是 o + t·d，求交就是把这个参数式代进一个隐式方程解出 t。本节用同一条探针光线对球、地面、三角形三种原语各求一次交：76800 条主光线归一化残差最大 5 Q16.16，命中 43731 个像素，三种 F(p) 残差分别是 712、0、-29。</description></item><item><title>1.2 相机与主光线</title><link>https://plumephp.com/cg-trace-01-2-camera-primary-ray/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-01-2-camera-primary-ray/</guid><description>相机三根基向量必须从 mat_look_at 的视图矩阵取行（第 0/1/2 行即 s / u / -f）。底座原先取列，把 up 的 z 与 back 的 y 各反一号，相机是歪的。判据是主光线命中掩码与卷一光栅化覆盖掩码的逐像素差：取行 43731 只差 4 个，取列 21519 差 22212。像素再经 NDC 与 4:3 宽高比合成主光线方向。</description></item><item><title>1.3 递归与深度限制</title><link>https://plumephp.com/cg-trace-01-3-recursion-depth-limit/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-01-3-recursion-depth-limit/</guid><description>底座的 trace 把 depth 一路传下去，却不把入射方向传给 shade。本节写一个与它逐字同构、只多传一个 dirv 的 trace_rec，给着色器加一层受深度门控的镜面反射：深度 1 的输出与卷三基线 sha256 逐字节相同（退化为直接光照），每加一层 MAE 与变化像素都单调下降。</description></item><item><title>10.1 噪声的构造</title><link>https://plumephp.com/cg-trace-10-1-noise-construction/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-10-1-noise-construction/</guid><description>噪声在本章不是纹理而是几何的生成器，所以同一个 (ix, iz, seed) 必须给出同一个整数。本节用同一个 32 位混合哈希派生出值噪声与梯度噪声：128 点扫描线上均值 31041、标准差 14919，16384 个格点低 16 位的碰撞率 117.4‰，整数插值与 float64 参照的最大偏差只有 1 个 Q16.16。</description></item><item><title>10.2 分形与地形</title><link>https://plumephp.com/cg-trace-10-2-fractal-terrain/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-10-2-fractal-terrain/</guid><description>一个 octave 的噪声撑不起地形，fBm 按 gain^k 的振幅把它叠起来。本节用左移采样坐标实现 lacunarity=2、用 Q16.16 连乘 gain，全程整数：4 层高度场幅 132654，octaves=1 时逐位等于底座值噪声，与 8 层参照解的最大偏差 7551，结构函数斜率收敛到 0.533。</description></item><item><title>10.3 程序化场景的生成</title><link>https://plumephp.com/cg-trace-10-3-procedural-scene/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-10-3-procedural-scene/</guid><description>程序化场景要能当资产用，靠的不是看起来像，而是可断言：同一 seed 必须给出同一场景。本节把 fBm 位移与噪声分档材质接进既有 scene_spec，基线帧 sha256 逐字节锚定 213b4130…，程序化场景的几何 digest 与帧 sha256 在同 seed 重跑下不变、换 seed 必变。</description></item><item><title>11.1 SDF 的构造与布尔运算</title><link>https://plumephp.com/cg-trace-11-1-sdf-construction-boolean/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-11-1-sdf-construction-boolean/</guid><description>距离场要被 sphere tracing 当步长信任，必须同时满足下界性与 Lipschitz 界。本节用 40000 对随机点估计八个场的 Lipschitz 常数：球、盒、平面、交、差都落在 1000.0‰ 附近，高度场却到 1084.1‰；下界性实测球/盒/平面/并集的最大 f-d_true 恰为 0，高度场 648 个采样点里 426 个高估，最坏 3909 Q16.16。</description></item><item><title>11.2 ray marching 求交</title><link>https://plumephp.com/cg-trace-11-2-sdf-ray-marching/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-11-2-sdf-ray-marching/</guid><description>sphere tracing 每一步走多远由场值自己决定，于是三件事必须量：迭代次数怎么分布、容差 eps 取多少、步长放大到几倍会出事。3072 条主光线的实测是解析命中 2048、marching 命中 1995、真漏交 0；无地面场景里场放大 1.1 倍只穿透不漏交，1.25 倍漏交 303.0303‰，1.5 倍直接 1000‰。</description></item><item><title>11.3 SDF 的法线与软阴影</title><link>https://plumephp.com/cg-trace-11-3-sdf-normal-soft-shadow/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-11-3-sdf-normal-soft-shadow/</guid><description>有了求交点，法线靠差分、软阴影靠沿光取样，两者都不是免费午餐：差分步长 h 太大会跨过棱角、太小会被定点量化吃掉，实测中心差分在 h=64 时均值 0.0342 度；软阴影有一个系统性平面偏置 k*sin(theta)，k 必须超过 1/sin(theta)≈1.732 才能让开阔地面回到满亮度。</description></item><item><title>12.1 噪声与收敛的度量</title><link>https://plumephp.com/cg-trace-12-1-noise-convergence-metric/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-12-1-noise-convergence-metric/</guid><description>噪声不是「看起来脏」这种观感描述，而是一个可算的整数：同一像素在 N 个样本下是个随机变量。本节先把面光源半径取 0、N = 1 退化回卷三基线的逐字节锚点，再用 256 样本扫掠与 8 批参考解量出收敛速率——实测 log-log 斜率 -0.5027，理论值 -0.5。</description></item><item><title>12.2 参考解与误差</title><link>https://plumephp.com/cg-trace-12-2-reference-error/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-12-2-reference-error/</guid><description>误差只在有参考解时才有意义，可参考解本身也是估计量。本节用四条互相独立的量法给它造不确定度：批均值的标准误、对半拆、换种子族的第二条参考解、以及只取全程无遮挡像素的确定性网格求积。实测 1024 样本/像素的参考解相对标准误 0.005729，对半拆比值 2.045、换族比值 2.219，都与理论吻合。</description></item><item><title>12.3 采样的停止准则</title><link>https://plumephp.com/cg-trace-12-3-stopping-criterion/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-12-3-stopping-criterion/</guid><description>知道每个像素的误差量级之后，就可以让它自己决定什么时候停。本节实测三条停止准则（逐像素方差、相对误差阈值、预算上限）各跑两个最小样本数版本，量出各自停在哪、总样本数、最终误差，以及两种失效模式——四样本全零会让方差估计变成 0，于是最早停、错得最狠。</description></item><item><title>13.1 求交的容差边界</title><link>https://plumephp.com/cg-trace-13-1-intersection-tolerance-bound/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-13-1-intersection-tolerance-bound/</guid><description>把 Möller–Trumbore 的误差写成一条闭式不等式，在 43731 条命中主光线上逐条核对：界恒成立，最紧处实测/界 = 0.746916。改一处舍入规则，41254 条命中的 t 就会分叉。真正决定自交的是垂直误差 Δt·sinθ，最大 241.47 LSB，而非沿光线的 Δt。</description></item><item><title>13.2 累积的确定性</title><link>https://plumephp.com/cg-trace-13-2-accumulation-determinism/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-13-2-accumulation-determinism/</guid><description>一张图是几万次累加拼出来的：整数加法三序零差异，破坏结合律的是 fmul 的截断（结合律反例 1005/4096）。重排三角形重建 BVH 后图像摘要一字不变而访问节点数变了；全局 RNG 流下换遍历顺序 3049/3072 像素改变，逐像素流则逐字节相同。</description></item><item><title>13.3 跨语言对照</title><link>https://plumephp.com/cg-trace-13-3-cross-language-comparison/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-13-3-cross-language-comparison/</guid><description>同一份 scene_spec.json 交给 Python 与 TypeScript，像素缓冲 sha256 同为 213b4130…、五个计数逐条相同。把相机基从行换成列，命中像素从 43731 掉到 21519，两侧却依旧逐字节相同——跨语言一致抓不到「两边一起错」。再把 BigInt 换成 Number，右移只有 32 位，命中像素静默变成 8484。</description></item><item><title>14.1 两条路径的等价与分歧</title><link>https://plumephp.com/cg-trace-14-1-two-paths-equivalence/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-14-1-two-paths-equivalence/</guid><description>光栅化与光追是两条完全独立的成像路径：一个在屏幕 Q6 空间用整数边函数判覆盖，一个在世界空间用 Möller–Trumbore 求交。同一份场景下两条路径的覆盖掩码各 43731 像素、逐像素对称差 4 个，且这 4 个全落在到最近正向边距离为 0 Q6 的轮廓边上；采样点挪半个像素，同一判据立刻变差到 160。</description></item><item><title>14.2 CPU 与 GPU 的差异</title><link>https://plumephp.com/cg-trace-14-2-cpu-gpu-difference/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-14-2-cpu-gpu-difference/</guid><description>把 CPU 定点与浏览器 WebGL2 之间的差异拆成三类可归因的来源：光栅化规则（顶左规则与子像素精度）、插值方式（屏幕空间仿射对透视校正）、浮点精度（Q6/Q16.16 对 float32）。每类配一个只动一个变量的实验，并用 MAE ≤ 1.0、PSNR ≥ 30 dB、覆盖归属差异 ≤ 20‰ 三条声明容差加一个必须被拒绝的负例来收口。</description></item><item><title>14.3 一致性的判据</title><link>https://plumephp.com/cg-trace-14-3-consistency-criteria/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-14-3-consistency-criteria/</guid><description>把三类判据摆在同一帧上：跨语言逐字节一致（sha256 相等，0 容忍）、跨路径像素掩码一致（光追命中掩码对光栅化覆盖掩码的对称差等于 4 个像素）、跨宿主声明容差（MAE ≤ 1.0 / PSNR ≥ 30 dB / 覆盖差 ≤ 20‰）。再给出反直觉的结论：判据一抓不到「两侧同错」。</description></item><item><title>15.1 帧序列与动画输出</title><link>https://plumephp.com/cg-trace-15-1-frame-sequence-animation/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-15-1-frame-sequence-animation/</guid><description>离线渲染的成片是一串图，不是一张图。本节把共用相机参数接上一条纯整数相机路径，16 帧逐帧渲染并落盘 PNG 序列，用 ffmpeg 合成 GIF/MP4；实测单帧约 1.6-2.0 s、总耗时 29.1 s，逐帧重跑 16/16 帧 sha256 相同。</description></item><item><title>15.2 性能的度量与剖析</title><link>https://plumephp.com/cg-trace-15-2-performance-profiling/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-15-2-performance-profiling/</guid><description>一帧 6.7 秒，时间到底花在哪？本节把 320x240 基线的单帧耗时拆成主光线求交、阴影光线求交、着色算术、光线生成、命中处理五块，用计数而不是直觉解释它；实测阴影光线求交独占 53.68%，比主光线求交还贵，因为阴影光线大多要遍历到底去证明这一点没被挡住。</description></item><item><title>15.3 参数与质量的取舍</title><link>https://plumephp.com/cg-trace-15-3-quality-tradeoff/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-15-3-quality-tradeoff/</guid><description>把分辨率、每像素样本数、最大弹射深度、BVH 叶子容量四条旋钮各转一遍，用「相对参考解的 MAE」对「本机墙钟」给出取舍表；实测样本数在 9 spp 之后饱和（MAE 只再降 1.5463 倍），叶子容量的遍历代价在 leaf=4 处取到最小值，未达预期的组合以软告警列出。</description></item><item><title>16.1 渲染器的全链路回放</title><link>https://plumephp.com/cg-trace-16-1-full-chain-replay/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-16-1-full-chain-replay/</guid><description>把 config/scene_spec.json 到像素缓冲的八级链路逐级重放：规格摘要、相机基行口径、76800 条主光线方向摘要、BVH 511 节点高 9、命中 43731 像素、阴影光线 77211（遮挡 1357）、遍历 3238333 节点，末级 sha256 与卷三基线逐字节相同，P 层在 BigInt 里复现每一级摘要。</description></item><item><title>16.2 三卷一致性总检</title><link>https://plumephp.com/cg-trace-16-2-three-volume-consistency/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-16-2-three-volume-consistency/</guid><description>把三卷基线的 sha256、计数与容差判据并成一张表：卷一顶点光栅化 bac65977…、卷二逐像素 0d997343…、卷三主光线 213b4130…，三者命中或覆盖都是 43731 像素；再引第 13.3 与第 14.3 节的实测锚给出反直觉结论——列口径真 bug 下两个语言实现仍逐字节相同，只有掩码对称差（4 对 22212）抓得出来。</description></item><item><title>16.3 交付与后续</title><link>https://plumephp.com/cg-trace-16-3-delivery-and-next/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-16-3-delivery-and-next/</guid><description>卷三的交付账本：三卷基线 .rgb 的 sha256 逐个复核，六条计数恒等式（主光线 76800、BVH 访问 3238333 = 主光线 + 阴影光线、掩码对称差 4）逐条对账，六档可运行性各写清证明了什么；另给出已证明 4 条与未证明 5 条（真实 GPU、生产级材质、硬件光追 API 等），以及三条扰动轴的软告警。</description></item><item><title>2.1 球、平面与三角形</title><link>https://plumephp.com/cg-trace-02-1-sphere-plane-triangle/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-02-1-sphere-plane-triangle/</guid><description>三条解析求交原语——光线-球、光线-平面、光线-三角形的闭式解，连同方向与平面平行、交点在光线背后、方向与三角形共面三个退化情形一律返回 None 的口径；再用真实场景量出解析球与八面体细分网格之间的面化误差，看清网格近似在离线光追里的真实代价。</description></item><item><title>2.2 Möller–Trumbore 与数值稳定性</title><link>https://plumephp.com/cg-trace-02-2-moller-trumbore-stability/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-02-2-moller-trumbore-stability/</guid><description>Möller–Trumbore 的除法链在 Q16.16 定点下的量级实测（原始乘积到 2^49、除法分子到 2^39，故 TS 侧必须全程 BigInt）；det 趋近 0 时相对误差从 0.061‰ 涨到 46.1426‰ 的扫描，以及真实命中里为什么不能按 det 大小做 epsilon 剔除。</description></item><item><title>2.3 容差与自交</title><link>https://plumephp.com/cg-trace-02-3-epsilon-self-intersection/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-02-3-epsilon-self-intersection/</guid><description>自交与容差的边界分析：EPSILON 被两条可测量的边界夹住——下界是地形自交在 eps&gt;=16 清零，上界是场景里最小的可见几何间隙 174 Q16.16；实测丢遮挡在 eps=256 起出现，并解释为什么偏移要沿法线而不是沿光线，以及球自交为何清不干净。</description></item><item><title>3.1 包围盒与 BVH</title><link>https://plumephp.com/cg-trace-03-1-aabb-bvh/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-03-1-aabb-bvh/</guid><description>把 896 个三角形收进一棵扁平整数数组的 BVH：叶子 9 个整数、内部节点 10 个，left 等于负一是整棵树唯一的类型标签。本节立起两条不变量——父盒包含两个子盒、叶盒包含它引用的每个三角形，再把 slab 判据逐轴展开到方向分量为 0 的退化分支，全部落到实跑输出。</description></item><item><title>3.2 BVH 的构建</title><link>https://plumephp.com/cg-trace-03-2-bvh-build/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-03-2-bvh-build/</guid><description>本节拆开 BVH 的构建：划分轴为什么按最长轴选、中位数划分平均花掉 SAH 最优代价的多少倍、叶子容量从 1 扫到 32 时每条光线的访问与测试各是多少，以及排序键的除法为什么必须走 floorDiv 才能在两个宿主上复现同一棵树、而不是只复现节点数。</description></item><item><title>3.3 BVH 的遍历与代价</title><link>https://plumephp.com/cg-trace-03-3-bvh-traversal-cost/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-03-3-bvh-traversal-cost/</guid><description>把 BVH 打开、关掉、再只去掉 best_t 收缩：三个模式跑同一条代码路径、同一批 76800 条主光线，用可逐条复现的整数计数（访问节点数、三角形测试数）与逐像素比对，回答加速结构到底省掉了什么、又省得够不够多；全部结论只建立在计数上，不做速度断言。</description></item><item><title>4.1 硬阴影与阴影光线</title><link>https://plumephp.com/cg-trace-04-1-hard-shadow-ray/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-04-1-hard-shadow-ray/</guid><description>硬阴影只有「被挡住」和「没被挡住」两种结果，判据是一条从命中点指向光源的阴影光线。本节把 `off` 是沿法线的偏移向量、不是起点这件事讲透：写错一行，77211 条阴影光线的遮挡数会从 1357 涨到 77210，画面只剩环境光。最后用一张方向光掩码数出像素层面的真阴影 839 个。</description></item><item><title>4.2 镜面反射与折射</title><link>https://plumephp.com/cg-trace-04-2-reflection-refraction/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-04-2-reflection-refraction/</guid><description>反射方向 r = d - 2(d·n)n 与 Snell 折射在 Q16.16 下逐位算清：4096 组随机单位向量的单位性偏差最大 55；eta = 1.5 时 3061 组全内反射；临界角公式与整数扫描在水 / 玻璃 / 金刚石三档互证到 1–2 LSB。菲涅尔 x^5 的平方链与逐次相乘实测不逐位相同（429/4096 差 1 LSB）。</description></item><item><title>4.3 递归的光线树</title><link>https://plumephp.com/cg-trace-04-3-recursive-ray-tree/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-04-3-recursive-ray-tree/</guid><description>光线树把「反射的光线还能再反射」显式组织成一棵按深度分层的树：depth 只是透传给着色器的参数，形状由着色器决定。实测每层光线 76800 / 44877 / 9232 / 6881 / 6269，代价随深度亚线性增长（每主光线 2.686 → 3.236 条），而在某一层截断会引入单边偏差而非无偏估计。</description></item><item><title>5.1 积分与估计</title><link>https://plumephp.com/cg-trace-05-1-integral-estimator/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-05-1-integral-estimator/</guid><description>蒙特卡洛积分把「算一个积分」换成「估一个积分」：无偏估计量的均值收敛到真值，偏差则永远停在那里。本节讲清无偏性成立的条件，逐位核对 SplitMix64 的掩码语义——漏掉 `&amp; RNG_MASK` 会让输出涨到 191 位、Q16.16 采样当场失效；再用 3 分箱卡方量出取模的量化偏置：值域 2^4 时 χ² = 15677，而 64 位拒绝采样只有 1.301。</description></item><item><title>5.2 方差与收敛</title><link>https://plumephp.com/cg-trace-05-2-variance-convergence/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-05-2-variance-convergence/</guid><description>估计量的方差是 σ²/N，误差只能按 1/√N 降。本节把这条定律量成一个小数：7 档 N × 2048 条独立子流，log-log 最小二乘拟合出斜率 −0.4978，落在 −0.5 ± 0.03 内；再把 pdf 写错成 1.1，总误差被常数偏差压平到 −0.2638，而方差那条纹丝不动。</description></item><item><title>5.3 分层与低差异序列</title><link>https://plumephp.com/cg-trace-05-3-stratified-low-discrepancy/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-05-3-stratified-low-discrepancy/</guid><description>分层把立方体切成 4×4 格子，低差异序列让点自己避开彼此：同一个 d 球占比积分上，4096 个 Halton 点抵得上 7.4 万个随机点，log-log 斜率从 −0.4980 陡到 −0.7103。但这份红利随维度迅速蒸发，8 维时优势只剩 1.4 倍。</description></item><item><title>6.1 渲染方程</title><link>https://plumephp.com/cg-trace-06-1-rendering-equation/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-06-1-rendering-equation/</guid><description>渲染方程把一个像素的颜色写成第二类 Fredholm 积分方程：出射辐亮度等于自发光加上半球上入射辐亮度的积分。本节逐项拆解它，再用 Neumann 级数展成「每次弹射一项」的几何级数——双板腔真值 1.199936，截断 K 项的相对偏差恰为 (ab)^K；灯箱实测第一阶占 0.592314，第 8 阶之后只剩 0.00781676。</description></item><item><title>6.2 路径采样</title><link>https://plumephp.com/cg-trace-06-2-path-sampling/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-06-2-path-sampling/</guid><description>路径追踪把渲染方程改写成可估计的形式：方向按余弦加权采样，权重退化成 albedo 的连乘，一条路径就是一个样本。本节用确定性 SplitMix64 走完整条路径，量出 maxDepth 从 1 抬到 16 时平均亮度从 26032.93 爬到 33362.13，再用俄罗斯轮盘赌把每条路径的求交次数从 12.1170 砍到 2.7717。</description></item><item><title>6.3 无偏性与偏差</title><link>https://plumephp.com/cg-trace-06-3-unbiasedness-bias/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-06-3-unbiasedness-bias/</guid><description>截断与轮盘赌都会让图像偏离参考解，但只有一个是错的：maxDepth 硬截断丢掉 (ab)^K 的尾部能量，是偏差；俄罗斯轮盘赌的权重补偿保持期望不变，只放大方差。本节用双板腔把两条曲线分开量，截断偏差从 0.44442655 降到 0.00010173 后被定点地板挡住，轮盘赌标准差从 0.459160 涨到 5.258522。</description></item><item><title>7.1 概率密度与权重</title><link>https://plumephp.com/cg-trace-07-1-pdf-weight/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-07-1-pdf-weight/</guid><description>蒙特卡洛估计量只有一个形状 `f/p`，方差全由采样用的概率密度 `p` 决定。本节先在半球上把 `p` 归一数清楚——漏掉 `1/π` 的 `cosθ` 会得 π 而不是 1；再用 `f(x)=2x` 量三条 pdf：匹配的 `2x` 让权重恒为 1、方差恰为 0，反匹配的 `2(1−x)` 把最大权重推到 255。最后把 `fdiv` 的截断误差与除零边界摆出来。</description></item><item><title>7.2 余弦加权与光源采样</title><link>https://plumephp.com/cg-trace-07-2-cosine-light-sampling/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-07-2-cosine-light-sampling/</guid><description>同一个直接光照积分有两条采样路径：余弦/BRDF 采样与光源采样（NEE），后者要把面积测度换成立体角测度，雅可比是 `p_ω = r²/(A·cosθ_l)`。本节把总辐射功率固定、只让光源半径从 0.15 变到 0.50，量出两条路径的方差交叉：小光源下光源/余弦方差比 0.065，大光源下 6.732。</description></item><item><title>7.3 多重重要性采样</title><link>https://plumephp.com/cg-trace-07-3-multiple-importance-sampling/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-07-3-multiple-importance-sampling/</guid><description>余弦采样与光源采样各有一半场景吃亏，MIS 的做法是两条都采、再按权重函数拼起来。本节量出平衡启发式 `p_i/Σp_j` 与幂启发式 `p_i²/Σp_j²` 在三种光源尺寸下的方差：小光源与较优单路径打平（1.0447），中等与大光源分别降到 0.9053 与 0.6341；权重归一残差 ≤ 1，而幂启发式在 pdf &lt; 1/256 时下溢成 0+0。</description></item><item><title>8.1 间接光照</title><link>https://plumephp.com/cg-trace-08-1-indirect-lighting/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-08-1-indirect-lighting/</guid><description>直接光只算一次命中，剩下的能量全在多次弹射里。本节把渲染方程展开成按弹射次数排列的级数：0 次弹射差 41.4%，16 次才收敛到 0.49%。再对照自发光面积光源与环境常数两种源项——环境常数把均值调准到万分之零点二，却把漫反射像素的亮度标准差压到参考解的 45.1%。</description></item><item><title>8.2 辐射度方法</title><link>https://plumephp.com/cg-trace-08-2-radiosity/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-08-2-radiosity/</guid><description>辐射度把腔体切成有限块，用形状因子矩阵把渲染方程变成线性方程组，一次解到底。本节量三件事：质心近似 cosθi·cosθj·Aj/(πr²) 的行和缺口在 n=2 时高达 17880 ulp（27.3%），不做行归一化解会整体偏低 15~23%；Jacobi 25 轮、Gauss-Seidel 14 轮收敛到同一残差。</description></item><item><title>8.3 光子映射</title><link>https://plumephp.com/cg-trace-08-3-photon-mapping/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-08-3-photon-mapping/</guid><description>光子映射把能量当成粒子：从光源发射、在场景里弹、命中处记一笔，最后用 k 近邻密度估计在着色点还原辐照度。本节量出三个数：记录条件写成 b&gt;=1 会让天花板直接项占比从 28% 掉到 18%；r² 掉到 3 ulp 时 1/r² 的凸性把估计值推高到 +63.3%；参考解自己的噪声底就有 14.11% 的 L1。</description></item><item><title>9.1 体积渲染方程</title><link>https://plumephp.com/cg-trace-09-1-volume-rendering-equation/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-09-1-volume-rendering-equation/</guid><description>体积渲染方程把表面方程里「只在表面取值」的积分换成沿路径连续取值。本节用定点整数把三件事写成可断言的数：透射率 exp(-σ_t s) 的整数 LUT 与浮点 exp 差 2262 ppm、Henyey–Greenstein 相函数的归一化与各向异性、以及单次散射相对所有阶求和漏掉多少。</description></item><item><title>9.2 ray marching</title><link>https://plumephp.com/cg-trace-09-2-ray-marching/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-09-2-ray-marching/</guid><description>把 9.1 的连续积分换成沿光线取 N 个样点的求和，就得到 ray marching。本节把步长与误差的关系量成三张表：中点法二阶收敛直到定点地板、透射率链式累乘的偏差随 N 漂到 −5.17%、一阶近似在 σ_t·Δs ≥ 1 时透射率塌成 0 的条带阈值，以及双层介质里误差的震荡。</description></item><item><title>9.3 体积阴影与散射</title><link>https://plumephp.com/cg-trace-09-3-volume-shadow-scattering/</link><pubDate>Thu, 15 Oct 2026 18:00:00 +0800</pubDate><guid>https://plumephp.com/cg-trace-09-3-volume-shadow-scattering/</guid><description>介质里的阴影光线不再回答「挡不挡」，而是给出一条透射率曲线；几何遮挡由 BVH 求交单独判成「乘以 0」。本节把步进搬进带遮挡体的场景，量体积阴影的解析与步进对照、单次散射与二阶散射的差（贡献 18.14%、代价近 20 倍），以及各向异性相函数一次渲染重加权出的七档 g。</description></item><item><title>4.3 软阴影与 PCF</title><link>https://plumephp.com/cg-shade-04-3-soft-shadow-pcf/</link><pubDate>Thu, 15 Oct 2026 16:30:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-04-3-soft-shadow-pcf/</guid><description>在深度图上取 N x N 邻域逐个做整数遮蔽比较，可见度=(N^2-occ)/N^2，把硬边界摊成半影。8 顶点 / 4 三角形的极简场景里，N=1/3/5/7 的半影像素为 0/1103/2146/3059，与 N=15 参考的可见度 MAE 为 0.12926/0.11639/0.10724/0.09882，整帧 114.1 到 403.1 ms，收益按 1/N 递减。</description></item><item><title>4.2 分辨率、偏差与走样</title><link>https://plumephp.com/cg-shade-04-2-shadow-bias-aliasing/</link><pubDate>Thu, 15 Oct 2026 16:15:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-04-2-shadow-bias-aliasing/</guid><description>把阴影偏差解析地推出来：深度 1 LSB 对应 80 个 Q16.16 世界单位，纹素世界尺寸 20480、tan(theta)=1.4142，故解析上界 28963，而实测每像素所需偏差中位数只有 1、p95 184。再扫出偏差权衡曲线：bias 从 0 加到 4096，自遮挡从 22360 降到 0，阴影脱离从 17 升到 459；分辨率 64² 到 512² 自遮挡降 38 倍。</description></item><item><title>4.1 阴影贴图的原理</title><link>https://plumephp.com/cg-shade-04-1-shadow-map-principle/</link><pubDate>Thu, 15 Oct 2026 16:00:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-04-1-shadow-map-principle/</guid><description>把 487 顶点 / 896 三角形的烛影山谷用光源正交矩阵投到 256x256 深度图，再在主相机逐像素插值出光源空间坐标 (lu,lv,ld)，整数比对 ld-map&gt;bias 判定遮蔽：深度图覆盖 11409 纹素、光源趟剔除 192 三角形、主视图 43731 像素、硬阴影 1360 像素（31.1‰）。P 层与 S 层像素缓冲逐字节相同，W 层按声明容差收敛。</description></item><item><title>《计算机图形学》卷二《着色、光照与纹理》目录</title><link>https://plumephp.com/cg-shade-toc/</link><pubDate>Thu, 15 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-toc/</guid><description>《计算机图形学》卷二《着色、光照与纹理》目录：16 章 48 节，只替换卷一封版的着色环节——逐顶点 Lambert 改为插值法线后逐像素求值，把光照模型、BRDF 与能量守恒、法线贴图、阴影、环境光遮蔽、微表面 PBR、sRGB 与色调映射、程序化纹理与后处理全部写成可逐像素断言的整数。本页给出分工、六档可运行性口径、卷二新基线与全书 16 章 48 节完整清单。</description></item><item><title>《计算机图形学》卷二《着色、光照与纹理》附录 A · 着色公式、材质参数表与数据集索引</title><link>https://plumephp.com/cg-shade-appendix-a/</link><pubDate>Thu, 15 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-appendix-a/</guid><description>《计算机图形学》卷二《着色、光照与纹理》附录 A：全卷共用的 Q16.16 定点常数表（1/π、9/π、3/π）、逐像素层的量级上界推导、六个着色公式的整数形式速查（Lambert、Phong、Blinn-Phong、GGX、Smith、Schlick）、材质参数表、能量守恒残差汇总，以及各章产物的数据集索引与复现命令。所有数字来自本机实跑。</description></item><item><title>1.1 Lambert 与漫反射</title><link>https://plumephp.com/cg-shade-01-1-lambert-diffuse/</link><pubDate>Thu, 15 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-01-1-lambert-diffuse/</guid><description>卷一封版了几何到像素的骨架，卷二只换着色环节。本节从 N·L 的几何含义出发，把 Lambert 漫反射写成纯整数点积加一次算术右移：66 个方向实测受光 30、背光 36，去掉 max(0, N·L) 后出现 81 个负通道，而钳制版所有通道落在 [0, 200]。</description></item><item><title>1.2 Phong 与高光</title><link>https://plumephp.com/cg-shade-01-2-phong-specular/</link><pubDate>Thu, 15 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-01-2-phong-specular/</guid><description>Phong 高光要构造反射向量 R = 2(N·L)N − L 再算 R·V 的幂次，Blinn-Phong 改用半步向量 H。本节用 66 个观察方向实测两者的叶宽、最大差与运算量，把 x^32 的平方链（5 次 fmul）与 31 次逐次相乘逐位比对，并推翻「Blinn-Phong 不会照亮背面」这句流传很广的话。</description></item><item><title>1.3 着色频率与插值</title><link>https://plumephp.com/cg-shade-01-3-shading-frequency/</link><pubDate>Thu, 15 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-01-3-shading-frequency/</guid><description>同一份场景、同一套顶点变换、同一个 Lambert 公式，只把「插值颜色」换成「插值法线再逐像素求值」：覆盖掩码与深度缓冲逐像素相同（几何封版），颜色却有 41261 个像素不同（537.2526‰），MAE 3.5764、PSNR 37.06 dB、最大通道差 48。</description></item><item><title>11.1 时间抗锯齿</title><link>https://plumephp.com/cg-shade-11-1-temporal-antialiasing/</link><pubDate>Thu, 15 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-11-1-temporal-antialiasing/</guid><description>时间抗锯齿的全部机制可以压成三个整数：帧间权重 w = ONE//(k+1)、确定性的 Halton 子像素抖动、历史帧的 3×3 邻域裁剪。本节在解析圆盘上实测——静止相机下 1→16 帧的 MAE 从 1.9163 收敛到 0.3881；每帧微动 0.25 px 时，裁剪把重影误差从 9.2405 压到 4.929。</description></item><item><title>11.2 抖动与蓝噪声</title><link>https://plumephp.com/cg-shade-11-2-dithering-blue-noise/</link><pubDate>Thu, 15 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-11-2-dithering-blue-noise/</guid><description>抖动不减少量化误差，它把误差从低频的「带状」搬到高频的「噪声」。本节把 0..255 的斜坡量化到 8 级，比较无抖动、Bayer 有序抖动、Floyd–Steinberg 误差扩散与 16×16 蓝噪声：总误差几乎不变，低频带状分量从 6.4844 压到 1.2 上下；蓝噪声更把阈值矩阵的低频功率占比压到同尺寸白噪声的 1/243。</description></item><item><title>11.3 抗锯齿的度量</title><link>https://plumephp.com/cg-shade-11-3-antialias-metric/</link><pubDate>Thu, 15 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-11-3-antialias-metric/</guid><description>把「哪个抗锯齿方案更好」写成一条可复算的判据：先用参考解的梯度阈值圈出边缘像素，只在边缘上算 MAE，再配上 PSNR。64×64 圆盘的 296 个边缘像素上，无抗锯齿 → 4 spp SSAA → 8 帧 TAA → 16 spp SSAA 三级判据全部成立，而把覆盖率乘 0.5 的错实现被同一条判据拒绝。</description></item><item><title>13.1 材质的表示与继承</title><link>https://plumephp.com/cg-shade-13-1-material-representation/</link><pubDate>Thu, 15 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-13-1-material-representation/</guid><description>材质是六个定点参数而非浮点结构体。继承用不动点松弛解析，与输入顺序无关：叶子 gold_trim_dark 逐字段来源确定，解析 digest 074b01f1… 在打乱输入后不变，自指父指针报错；叶子材质驱动一帧，改被继承字段帧变、改旁系帧不变。</description></item><item><title>13.2 着色变体</title><link>https://plumephp.com/cg-shade-13-2-shader-variants/</link><pubDate>Thu, 15 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-13-2-shader-variants/</guid><description>材质的每个开关都让着色器分叉：4 开关理论 16 组合、实际只用 9；8 开关理论 256、实际 23，爆炸比 11.13×。变体键用整数位编码去重，与 frozenset、关键词串去重同数；键漏掉 shadow 位则去重数从 9 塌缩到 7。逐个渲染实际变体，不同键必给不同帧。</description></item><item><title>13.3 材质的数据驱动</title><link>https://plumephp.com/cg-shade-13-3-material-data-driven/</link><pubDate>Thu, 15 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-13-3-material-data-driven/</guid><description>一份材质表 JSON 驱动三种宿主：Python 建材质对象、TypeScript 建同构对象、HTML 内联同一条材质。三处解析的六个字段逐字段相同（对账表 S/W/P 三列一致），规范 digest c456c8c1… 两侧相同；改一个字段后帧 digest 与内联值同步变化，四次扰动全部同步。</description></item><item><title>14.1 光源类型与表示</title><link>https://plumephp.com/cg-shade-14-1-light-types/</link><pubDate>Thu, 15 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-14-1-light-types/</guid><description>三种光源共用一套光照方向构造与衰减接口：方向光无衰减、点光源 r²/(r²+d²)、聚光再乘锥软化。同一场景下受光像素 959.8‰ / 953.3‰ / 70.1‰；衰减的两种整数写法在 178/1280 个距离上分叉、最大差 1 个 Q16.16，d=range 处恰好 0.5。</description></item><item><title>14.2 光照的批处理与代价</title><link>https://plumephp.com/cg-shade-14-2-light-batching-cost/</link><pubDate>Thu, 15 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-14-2-light-batching-cost/</guid><description>点光源衰减改成有限支撑的 (r²−d²)/(r²+d²)，才让「哪些光源影响哪个像素」成为一条整数谓词。两级剔除：逐像素距离阈值 + 16×16 网格分桶。N=64 时循环 3031360→380842、完整求值恒为 72576、两版逐字节相同；代价模型 25702400→4498256 ops（比例 0.1750）。</description></item><item><title>14.3 光照的调试视图</title><link>https://plumephp.com/cg-shade-14-3-light-debug-view/</link><pubDate>Thu, 15 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-14-3-light-debug-view/</guid><description>把光照拆成环境 / 漫反射 / 镜面 / 衰减四张灰度图，再加一张合成图。故意把衰减写成 r²/(r²+d)（分母忘了平方），衰减通道 43731/43731 个像素全变、最大差 47042，而环境 / 漫反射 / 镜面三通道逐字节相同——缺陷被精确定位到衰减那一行。</description></item><item><title>15.1 跨语言着色对照</title><link>https://plumephp.com/cg-shade-15-1-cross-language-shading/</link><pubDate>Thu, 15 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-15-1-cross-language-shading/</guid><description>同一份场景规格在 Python 与 TypeScript 两条 CPU 路径下产出逐字节相同的像素缓冲。把着色器写成可参数化形式，五个负例各只动一处口径——降精度改用除法、插值后不归一化、逐项钳制、1/π 取 20860、albedo 四舍五入——每个都让 sha256 分叉，七个摘要两两不同，退化档复现卷二基线。</description></item><item><title>15.2 中间缓冲的着色验证</title><link>https://plumephp.com/cg-shade-15-2-intermediate-buffer-verify/</link><pubDate>Thu, 15 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-15-2-intermediate-buffer-verify/</guid><description>把逐像素着色器的四张中间缓冲各自单独导出并断言：法线模长落在 [65533, 65537]、albedo 通道在 [70,220]、深度沿单三角形单调、覆盖率与解析解逐像素相同（43731 像素、差异 0）。法线图与 albedo 图编码后的 sha256 由 TypeScript 侧逐字节复现。</description></item><item><title>15.3 偏差的定位方法</title><link>https://plumephp.com/cg-shade-15-3-deviation-localization/</link><pubDate>Thu, 15 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-15-3-deviation-localization/</guid><description>给定一张「错了的图」，按二分定位法逐级比对覆盖率、法线、albedo 与最终颜色四张缓冲，把偏差锁到管线的某一段。差异数字本身就是线索：等于覆盖像素数说明逐像素操作出问题，只有几十个说明舍入或常数出问题。五个负例各定位到对应阶段，并对「插值后漏归一化」做一次完整演练，从法线图差异 43731 一路定位到漏掉的那一行。</description></item><item><title>2.1 BRDF 与能量守恒</title><link>https://plumephp.com/cg-shade-02-1-brdf-energy-conservation/</link><pubDate>Thu, 15 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-02-1-brdf-energy-conservation/</guid><description>把 BRDF 的半球反射率写成固定的 512 方向整数估计：cosθ_k=(2k+1)/128 是精确有理数、方位只用 {0,±1,±√2/2}，全程无浮点三角函数。∫cosθ dω 的估计逐位等于 π（残差 0），Lambert 能量 65533（999.9542‰），残差 3。</description></item><item><title>2.2 常见 BRDF 的定点化</title><link>https://plumephp.com/cg-shade-02-2-brdf-fixed-point/</link><pubDate>Thu, 15 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-02-2-brdf-fixed-point/</guid><description>把 Lambert、Phong、Blinn-Phong 三种 BRDF 写成全整数：1/π=20861，Phong 归一化 9/π=187749，Blinn 归一化 3/π=62583，指数 (R·V)^16 用 4 次平方。实跑能量：Lambert 65533、归一化 Phong 65321、归一化 Blinn 69886（超过 ONE），未归一化 Phong 只 22800。</description></item><item><title>2.3 材质的组合与混合</title><link>https://plumephp.com/cg-shade-02-3-material-blend/</link><pubDate>Thu, 15 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-02-3-material-blend/</guid><description>材质的线性混合只要满足不变量 w_A+w_B==ONE 就仍能量守恒（五组权重实测 65533/65479/65426/65373/65321 全 ≤ ONE，权重和 =2·ONE 时涨到 130854）；清漆层朴素相加 78640 越界、按 (1-F) 缩放后 60946 守恒。并用混合材质渲染一帧，跨宿主 sha256 逐字节相同。</description></item><item><title>3.1 法线的变换</title><link>https://plumephp.com/cg-shade-03-1-normal-transform/</link><pubDate>Thu, 15 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-03-1-normal-transform/</guid><description>法线不能直接用模型矩阵 M 变换：非均匀缩放 diag(2,1,1) 下 (M·t)·(M·n) 实测 +3.0000 而非 0，改用逆转置 (M⁻¹)ᵀ 后恒为 +0.0000；纯旋转时两者相等，错误只在非均匀缩放下暴露。4096 个单位法线扫描给出归一化后的模长不变量 |n| ∈ [ONE−5, ONE]。</description></item><item><title>3.2 切线空间</title><link>https://plumephp.com/cg-shade-03-2-tangent-space/</link><pubDate>Thu, 15 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-03-2-tangent-space/</guid><description>切线空间从三角形的三个顶点位置与三个 UV 解出：标准 UV 下 denom=65536、T=(2,0,0)、B=(0,0,2)，手性 w=-1；把 u 反向令 denom=-65536 后 T 翻成 (-1,0,0)、w 变 +1。相邻面平均出的切线 T_avg=(1,0.5,0) 模长 1.1180、n·T_avg=0.5，Gram-Schmidt 后回到正交单位基。</description></item><item><title>3.3 法线贴图的解压与重建</title><link>https://plumephp.com/cg-shade-03-3-normal-map-reconstruction/</link><pubDate>Thu, 15 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-03-3-normal-map-reconstruction/</guid><description>把 32x32 的 8 位法线贴图还原成 128x128 世界法线：解压 n=(v&lt;&lt;17)/255-ONE 后未归一化模长落在 [0.9905,1.0024]，归一化后偏差最大 2，与连续法线夹角最大 0.7753°。W 层用 WebGL2 片元着色器做同一件事，与 S 层按声明容差比对 MAE 0.5068 / PSNR 51.08 dB / 覆盖差异 0‰，负例被同一判据拒绝。</description></item><item><title>5.1 环境光遮蔽</title><link>https://plumephp.com/cg-shade-05-1-ambient-occlusion/</link><pubDate>Thu, 15 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-05-1-ambient-occlusion/</guid><description>环境光遮蔽衡量一个点周围半球有多大比例能看见天空，是环境光里最便宜的一阶近似。本节先构造一个能解析求解的最小场景——平面上方悬一个球，正下方那点的遮蔽恰为 1 减去 r/h 的平方——再用一组固定的 64 条整数方向做逐像素数值估计，量出它与解析值的误差、整幅 AO 图的 MAE，最后把 AO 作为乘性项接进着色，并在 TypeScript 侧复现同一张 AO 图。</description></item><item><title>5.2 SSAO 的采样与噪声</title><link>https://plumephp.com/cg-shade-05-2-ssao-sampling-noise/</link><pubDate>Thu, 15 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-05-2-ssao-sampling-noise/</guid><description>SSAO 从深度缓冲重建视空间位置与法线，再在半球上撒一组固定方向做遮挡估计。方向集固定会让误差呈低频带纹，把它按一张确定性的 4×4 旋转表逐像素转开，误差被打散成高频噪声，再用 3×3 盒式模糊压回去。本节量出 4/8/16/32/64 采样的收敛曲线、旋转前后的粗糙度，以及模糊对内部像素误差的削减，并在 TypeScript 侧逐字节复现。</description></item><item><title>5.3 环境贴图与球谐</title><link>https://plumephp.com/cg-shade-05-3-envmap-spherical-harmonics/</link><pubDate>Thu, 15 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-05-3-envmap-spherical-harmonics/</guid><description>环境贴图把整个天空的入射光存下来，球谐用 9 个系数（L0/L1/L2）把它压成可解析重建的方向函数。本节用整数 Fibonacci 格点做投影，得到 9 个 Q16.16 系数，重建辐照度与直接积分只差 2‰；但太阳圆盘这类高频特征装不进 9 个系数，L2 带被它拉偏，反而在低频背景上引入振铃。</description></item><item><title>6.1 微表面理论</title><link>https://plumephp.com/cg-shade-06-1-microfacet-theory/</link><pubDate>Thu, 15 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-06-1-microfacet-theory/</guid><description>微表面理论把镜面反射拆成 D、G、F 三个因子：GGX 分布 D 决定高光形状，Smith 几何项 G 补偿微面互相遮挡，Schlick 菲涅尔 F 决定反射比例。本节在 Q16.16 里把它们写成纯整数，用投影圆盘方向集验证 ∫D(n·h)dω≈1，并量出 alpha=0.25 时镜面波瓣的半高全宽是 40.74 度。</description></item><item><title>6.2 金属度-粗糙度工作流</title><link>https://plumephp.com/cg-shade-06-2-metalness-roughness/</link><pubDate>Thu, 15 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-06-2-metalness-roughness/</guid><description>金属度-粗糙度工作流只用两个标量描述一个表面：基础色在绝缘体时是漫反射 albedo、在金属时是镜面 F0，粗糙度平方后映射成 GGX 的 alpha。本节扫过粗糙度 0/0.25/0.5/0.75/1，量出 NDF 峰值从 809 掉到 0.32、半高角从 0.76 度张到 90 度，并说明为什么高光宽度要用 NDF 半高角而不是 BRDF 的半高全宽。</description></item><item><title>6.3 能量守恒的验证</title><link>https://plumephp.com/cg-shade-06-3-energy-conservation-check/</link><pubDate>Thu, 15 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-06-3-energy-conservation-check/</guid><description>6.1 的 BRDF 和 6.2 的参数映射都默认反射能量不超过入射能量，但 BRDF 本身给不出这个保证。本节把 ∫f·cosθ·dω≤1 变成一个可跑的整数实验：GGX 各粗糙度的残差表、alpha=1 处的解析锚点 1-ln2、单次弹射丢掉 69.3% 能量、Kulla-Conty 补偿把它补回 1，以及 kD=1-F 为什么守不住掠射角。</description></item><item><title>7.1 线性空间与 sRGB</title><link>https://plumephp.com/cg-shade-07-1-linear-srgb/</link><pubDate>Thu, 15 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-07-1-linear-srgb/</guid><description>把 sRGB 传递函数固化成整数查找表：解码表 256 项一次生成后冻结，编码用整数二分在边界表上反查，Python 与 TypeScript 读同一份整数故逐位一致。实测 8 位往返残差 0 灰度级、线性往返最大误差 292 Q16.16，并给出线性段与幂段的分段边界。</description></item><item><title>7.2 色调映射</title><link>https://plumephp.com/cg-shade-07-2-tone-mapping/</link><pubDate>Thu, 15 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-07-2-tone-mapping/</guid><description>把 Reinhard、扩展 Reinhard（白点）与 ACES filmic 近似三条色调映射曲线写成全整数，喂同一份《烛影山谷》HDR 辐射度（曝光 6.0 后 max 4.33），实测输出曲线与 8 位直方图：Reinhard 均值 165.89 不裁剪、扩展 Reinhard 裁掉 156 像素、ACES 均值 213.43。</description></item><item><title>7.3 色彩管理的整数化</title><link>https://plumephp.com/cg-shade-07-3-color-management-integer/</link><pubDate>Thu, 15 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-07-3-color-management-integer/</guid><description>把 sRGB 接进卷二着色链路并量出代价：8 位量化误差最大 218 Q16.16、均值 40.10，往返不变量残差 0 灰度级；线性域取中点与 sRGB 域取中点最多差 61 灰度级；端到端「线性着色 + 编码」与「直接在 sRGB 域着色」MAE 15.57、PSNR 24.28 dB。</description></item><item><title>8.1 纹理坐标与寻址模式</title><link>https://plumephp.com/cg-shade-08-1-wrap-addressing/</link><pubDate>Thu, 15 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-08-1-wrap-addressing/</guid><description>UV 是一对 Q16.16 定点数，落格子就是一次算术右移。本节把 wrap / clamp / mirror / border 四种寻址全做成整数运算——位与、钳位、向下取整的模、越界短路——再用一张自描述纹理把采样结果反查回 texel：64 列里只有 12 列四种模式给出同一结果。</description></item><item><title>8.2 过滤与 mipmap 的构造</title><link>https://plumephp.com/cg-shade-08-2-filter-mipmap-build/</link><pubDate>Thu, 15 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-08-2-filter-mipmap-build/</guid><description>从最近邻到三线性：双线性用四个 Q16.16 权重累加后一次 &gt;&gt; 32 降精度；mip 链是逐级 (a+b+c+d) &gt;&gt; 2，奇数尺寸要决定最后一行列是保留还是截断；LOD 用整数位长求 floor(log2)。对 4×4 超采样参考解，最近邻 MAE 54.41、mipmap 14.15、三线性 10.56。</description></item><item><title>8.3 各向异性过滤</title><link>https://plumephp.com/cg-shade-08-3-anisotropic-filtering/</link><pubDate>Thu, 15 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-08-3-anisotropic-filtering/</guid><description>像素足迹是 UV 空间的平行四边形，过滤核取它的内切椭圆，半轴比就是各向异性比。本节从 UV 梯度算出椭圆、构造 ripmap，再量 N=1/2/4/8 的采样曲线：MAE 25.99 降到 19.76 且收益递减，ripmap 单次查表 11.00，代价是显存 ×3.88。</description></item><item><title>9.1 值噪声与 Perlin</title><link>https://plumephp.com/cg-shade-09-1-value-noise-perlin/</link><pubDate>Thu, 15 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-09-1-value-noise-perlin/</guid><description>站内那篇讲的是大地形 LOD、分块与流式加载的工程实现，本节把噪声函数本身拆成可逐值断言的整数。值噪声与 Perlin 共用同一个整数哈希，只在格点上放标量值还是梯度向量：128×128 实测两者均值 32138 与 98，相邻差分均值 4703.5 与 7464.1，功率谱峰值分别落在第 0 与第 2 个频带。</description></item><item><title>9.2 分形噪声与 fBm</title><link>https://plumephp.com/cg-shade-09-2-fractal-fbm/</link><pubDate>Thu, 15 Oct 2026 14:00:00 +0800</pubDate><guid>https://plumephp.com/cg-shade-09-2-fractal-fbm/</guid><description>单层噪声太规整，fBm 把它叠成分形。本节用整数实现 octaves / lacunarity / gain 三个旋钮，在 0.125 世界单位步长上扫描 1/2/4/8 层：归一化粗糙度 0.0405 → 0.0509 → 0.0714 → 0.0918 单调上升，方差反而从 13653 降到 8481；再做整数域扭曲，看细节被拧成条带。</description></item></channel></rss>