计算机图形学 E06:从一张图反推光源强度
给定一张被点光源照亮的平面图,如果几何、反射率和光源位置都已知,能否反推出光源有多亮?这个问题只剩一个未知数,仍然足以检查梯度是否正确、步长为何影响收敛,以及图像完全匹配时参数是否唯一。 实验固定 Lambert 平面,只恢复非负光强 s。目标图由已知强度 3 生成,求解器只接收像素观测和已知系数。三个初值、三档步长都运行 40 次更新;另用全饱和图保留多解反例。 哪些量已知,哪个量待求 平面位于 z=0,法线为 +Z,反射率 ρ=0.7,点光源位于 (0,0,2)。32×32 个像素对应 [−1.5,1.5]² 内的格点中心。所有点都无遮挡,V=1;没有间接反射、噪声或曝光变化。 第 19 篇的 Lambert BRDF 为 ρ/π。点光源辐射强度除以距离平方,再乘入射余弦,得到表面接受的照度贡献。因此像素线性输出为: Ii(s)=sai,ai=ρπmax(0,ni⋅ℓi)ri2Vi.I_i(s)=s a_i,\qquad a_i=\frac{\rho}{\pi}\frac{\max(0,n_i\cdot\ell_i)}{r_i^2}V_i. Ii(s)=sai,ai...
计算机图形学 E05:目标可达,关节为什么仍然不动
两根长度为 1 的杆,从原点伸向目标 (1,1)。给定关节角度,末端位置很容易计算;反过来给定末端位置,应该把两个关节转到哪里?这就是一个最小的逆运动学问题。 第 30 篇先指定骨骼姿态,再用权重带动网格。本篇向前多走一步:从目标位置求姿态。实验同时保留解析解和迭代解,检查“够不着”“迭代没有求到”和“杆长发生变化”这三种不同情况。一个可达目标,也可能让梯度迭代从第一步就停住。 先把杆长放进参数化 肩关节位于原点,两杆长度为 l₁、l₂,肩角为 θ₁,肘角 θ₂ 相对第一根杆定义。角度使用弧度,位置使用统一的模型长度单位。肘位置 q 和末端 p 是: q=l1(cosθ1sinθ1),p=q+l2(cos(θ1+θ2)sin(θ1+θ2)).q=l_1\begin{pmatrix}\cos\theta_1\\\sin\theta_1\end{pmatrix},\qquad p=q+l_2\begin{pmatrix}\cos(\theta_1+\theta_2)\\\sin(\theta_1+\theta_2)\end{pmatrix}. q=l1(cosθ1sin...
计算机图形学 E04:射线怎样进入 GPU 工作队列
一批相机射线完成第一次求交后,有些已经得到环境颜色,有些还需反射。继续扫描全部射线很容易实现;把仍需计算的射线集中到队列,则能让下一阶段直接读取存活任务。代价是增加状态存储、原子分配与阶段切换。 这个选择可以在两个镜面组成的小场景里验证。实验保持光路与画质相同,对照全量扫描和队列消费,检查容量不足、陈旧计数与尾线程错误。真实 GPU 结果与 CPU 参考一致;本次计时存在大量量化零,不能据此判断队列具有稳定速度收益。 两次反射给出可手算的参考 第 23 篇区分了理想镜面与连续方向采样。本实验只保留确定性镜面,最多反射两次;没有随机 BSDF、MIS、Russian roulette 或 BVH,也没有使用硬件光追接口。它实现的是波前组织方式中的“保存射线、压缩存活任务、分阶段继续追踪”。 图像为 128×128,实际发射 N=16,381 条像素中心射线,最后三个像素留作黑色占位。射线从 (x,y,2) 沿 (0,0,−1) 发出,x、y 按像素中心均匀分布在 (−1,1)。第一块镜面位于 x+z=0,只保留 −1≤x<0、|y|<1 的区域。 使用未归一化法线也能计算反射,但...
计算机图形学 E03:一层介质为什么越斜越暗
一层厚度固定的吸收介质,正面观察和倾斜观察会有不同透射。厚度没有改变,射线在介质内部走过的距离却变长了。如果直接给所有像素乘同一个“透明度”,便丢掉这个几何条件。 本篇选择均匀纯吸收作为第 19–24 篇表面传输的扩展。有限盒子给出真实介质路径,解析指数透射检查分段算法;粗步长产生负透射的失败结果也保存。实验没有入射散射、发光、完整光谱或景深。 从局部损失到指数透射 设沿射线传播的辐亮度为 L(s),均匀吸收系数为 σ_a,单位为距离单位的倒数。没有沿途发光与散射进入时,一个微小距离 ds 的局部变化为 dL=−σ_a L ds。负号表示能量离开当前光束,系数非负。 将方程除以 L 并从 0 积分到 d: logL(d)L(0)=−σad,T(d)=L(d)L(0)=e−σad.\log\frac{L(d)}{L(0)}=-\sigma_a d, \qquad T(d)=\frac{L(d)}{L(0)}=e^{-\sigma_a d}. logL(0)L(d)=−σad,T(d)=L(0)L(d)=e−σad. σ_a d 必须无量纲。若世界长度从米改成厘米,吸收系...
计算机图形学 E02:透明叠面与会失效的历史颜色
两层半透明颜色交换绘制顺序,交叠区会变色。一个白色矩形移开后,上一帧的白色如果仍参与平均,原本露出的棋盘会留下尾迹。这两个问题都涉及多个样本的组合,但有效条件不同:透明合成依赖前后层次,时间抗锯齿依赖历史样本是否仍对应当前表面。 本篇将它们分别验证。真实 WebGPU 绘制两层半透明矩形并读回浮点附件;C++ 用带抖动的运动场景、运动向量和深度拒绝检查 TAA。解析面积覆盖率提供图像参考,亚像素速度另保留一次效果变差的实验。 alpha 需要和颜色存储一起定义 取未预乘的线性颜色 C 与 alpha α。预乘颜色 c=αC;透明红 C=(1,0,0)、α=0.5 存为 (0.5,0,0,0.5)。若存的是 (1,0,0,0.5),却把它当预乘输入,颜色会过亮。 alpha 可以在此表示像素内覆盖比例与不透明程度的综合权重,但它不自动包含厚度、折射方向或波长相关的吸收。第 23 篇的玻璃路径不是把物体画成一层低 alpha 就能替代的。 source-over 中,前层占去 α_s,后层只贡献剩余部分。预乘形式为: co=cs+(1−αs)cb,αo=αs+(1−αs)αb.c_...
计算机图形学 E01:同一个球的网格与距离场
一个单位球可以保存为三角形,也可以保存成函数 f(p)=‖p‖−1。两种表示都能产生球形画面,但它们的误差来自不同位置:网格先离散曲面,距离场沿射线反复查询。增加三角形和增加查询预算,分别改变什么?把球压成椭球后,同一个函数还能给出安全步长吗? 本实验复用第 17、18 篇的射线和 BVH,用解析球交点检查实际等值面网格与 sphere tracing。薄板和非均匀缩放另设反例。结果保留步数耗尽、薄结构消失,以及旧三角形求交核在共享边上的数值异常。 零集合与距离是两个要求 隐式曲面只要求 f(p)=0 描述边界。球内负、球外正,可以表达内外关系;函数值的大小却未必是到曲面的距离。将 f 乘以 100,零集合没有改变,直接拿函数值推进射线就可能跨过整个物体。 真实有符号距离 d(p) 的绝对值,是 p 到边界上最近点的欧氏距离,符号区分内外。单位球的最近边界点沿径向,因此 d(p)=‖p‖−1。中心取 −1,球面取 0,点 (2,0,0) 取 1,这三个手算值进入检查器。 球面外一点的距离为 d,半径 d 的开球内没有边界。单位方向射线从该点前进 d,不会穿过边界。这是 sphe...
计算机图形学 35:用三个场景检验 SAH 分割
把一组图元按数量切成两半,会得到高度较均衡的树;这是否就是一棵适合射线的树?左右两个盒子可能包含几乎相同的空间,一条射线仍要进入两边。树的高度没有直接说明一条射线要测试多少图元。 本篇把“更好的分割能减少遍历工作”写成可反驳的小项目:固定第 34 篇验收过的显式栈遍历,比较数量中位数分割和 12 桶 SAH。均匀、不均两簇、重叠三组场景都检查最近命中、图像、工作量、构建成本和遍历时间,不预设每一组都会加速。 研究问题怎样落到代码上 第 18 篇已有数量中位数建树:求当前组的完整包围盒,选择跨度最大的轴,按图元包围盒质心沿该轴排序,用 nth_element 分成数量相近的两组。两个及以下图元成为叶子。 它控制了树高,却没有直接优化孩子包围盒面积。假设 56 个图元集中在左边,另 8 个在远处右边。数量二分的第一刀可能把左簇分到两侧,右孩子于是同时包含近簇与远簇。两侧各有 32 个图元,不意味着两侧容易被射线排除。 SAH 选择不同的目标:估计进入孩子以后还需付出的求交工作,比较分裂与保持叶子哪个更便宜。它是一个成本模型,不是所有相机射线的精确耗时方程。本文复现这个模型的有限桶版...
计算机图形学 34:一次优化怎样同时检查画质和时间
把递归遍历改成显式栈,画面仍是两个盒子,是否就能接受这次优化?黑色背景占据大半张图,一次漏掉小物体未必容易发现;单次运行快几毫秒,也可能来自测量顺序。优化需要同时回答两个问题:程序是否仍计算同一个结果,这个结果用了多少时间。 本篇复用第 33 篇的场景,选择 BVH 最近命中查询作为待研究的热点。基线和对照使用同一棵树,只改变保存待访问节点的方式。这个小实验测量一个 CPU 查询内核,不能据此宣称整个渲染器的主要瓶颈已经确定。 有界问题先固定输入 场景冻结在 tick=120,即固定步模拟完成一秒的位置。仍是地面、移动盒与静止盒,共 26 个三角形;相机和点光源保持上一章的配置。图像为 128×128,每个像素只有一个中心样本。 射线由上一章的权威 float32 VP 矩阵反投影近、远端得到。世界坐标为右手系,Y 向上;图像原点在左上角。射线命中范围、几何法线、反射率、点光源与人工填充项都没有另外设一组参数。 本篇的问题是:在相同 BVH 上,递归调用与显式待访问栈能否得到相同最近命中,CPU 耗时分布有什么差别?它不比较光栅与光追,不改变每像素样本数,也不讨论一个 API ...
计算机图形学 33:同一场景的三种观察方式
一个盒子用软件光栅器画出来,用 CPU 射线求交画出来,再交给 GPU 显示,三幅图相近是否就足以证明三个程序处理了同一个场景?盒子的位置、相机的近远平面、点光源衰减、显示编码,只要有一项不同,比较就可能混入另外一个问题。 本篇把前面的几何、光栅、BVH、照明和固定步模拟接到一份场景数据上。先冻结三个确定时刻,对照共同的直接照明;再单独打开 CPU 阴影,解释画面变化;最后在真实 WebGPU 页面中播放同一条运动轨迹并编辑参数。每种观察方式都有明确的比较范围。 场景数据怎样成为共同输入 场景包含一块地面和两个轴向盒子,共 26 个三角形。图像为 128×128,正交相机的位置是 (5,4,7),观察目标是 (0,0.7,0),半高 3.2,近、远距离为 1 和 20。世界坐标沿用右手系,Y 向上;图像数组原点位于左上角。 地面对象编号为 1,两盒编号为 2、3;材质编号在这个小场景中与对象编号相同。对象 2 沿 X 运动,对象 3 静止。各面使用向外的单位几何法线,没有插入另一套平滑法线或纹理。 可编辑的源文件是 examples/computer-graphics/proj...
计算机图形学 32:模拟怎样稳定地显示
一个弹簧在每帧收到的时间间隔不同,运动结果会不会跟着显示帧率变化?一个高速质点在一步之后已经落到地面以下,把位置拉回地面、反转速度,是否就完成了正确的反弹? 这两个问题都涉及时间,但需要分别处理。固定步长规定动力学怎样推进,显示插值决定怎样观察离散状态;碰撞还要确定事件发生在步内哪个时刻。本篇沿用上一章的单弹簧,再加入一个能求解析撞击时间的点—平面模型。 显示一帧,不等于积分一步 上一章的质量、刚度与初态保持不变:m=1 kg、k=4 N/m、x=1 m、v=0。速度先更新的半隐式 Euler 需要固定步长 h,且当前弹簧的稳定条件是 0<h<1 秒。如果把每帧收到的时间间隔直接作为 h,渲染负载、暂停和显示频率都会改变离散轨迹。 解决当前复现问题的方法是保留一个时间累积器。收到显示帧的经过时间 Δt,就把它加入积压;只要积压至少有一个完整 h,就执行一次固定积分并减去 h。一帧可以执行零步、一步或多步。 这里不依赖浮点数是否恰好能表示 1/120。FixedSpringClock 使用每秒 72,000 个整数时间单位,一个物理步为 600 单位,即 h=1/12...











