计算机图形学 09:法线怎样决定明暗
把模型横向拉长两倍,轮廓变化正确,高光却可能出现在错误位置。顶点位置和法线若都乘同一个缩放矩阵,程序不会报错,但法线已经不再垂直于表面。
本篇先用点积定位这个问题,再用同一个32三角形曲面比较平面与平滑着色。几何、覆盖与光源不变,只改变着色法线;所有颜色仍在线性域计算,最后沿用第04篇的sRGB输出。
法线保存的是垂直关系
三角形顶点为时,两条边、位于表面内。非退化三角形的单位几何法线为:
交换顶点绕序会改变叉积符号。零面积三角形没有唯一的面方向,本系列仍拒绝对零向量归一化,不通过更换分母掩盖退化几何。
顶点上还可以存一组用于着色的法线。它们可以来自原始光滑曲面,也可以由相邻面按明确权重平均。几何法线描述三角形本身,着色法线描述希望使用的局部朝向;两者用途不同,不能因为数组都只有三个分量就相互替代。
例如,一个球面由少量平面三角形近似时,面法线在每片内恒定,而顶点法线可以指向球心外侧。插值后的着色看起来更平滑,但三角形的真实位置和轮廓没有改变。
同乘缩放矩阵的反例
取切向量、法线,两者点积为零。将x方向放大两倍,线性矩阵为。切向量必须随几何变为。
若法线也直接乘A,得到,于是:
这不是单位长度问题。把两个结果各自归一化,非零点积仍不会变成零;方向已经错了。只在着色前补一个normalize无法修复错误的变换。
要求新法线继续满足。令,则:
因此仿射变换的法线使用线性部分的逆转置。当前例子得到,与点积恰为零。检查器实际输出错误路径3、正确路径0,比较发生在归一化之前,便于手算。
A仅取模型或模型视图变换的三阶线性部分,不含投影。平移不改变切向量,也不进入这个法线矩阵。若法线在世界空间、光方向却在相机空间,即使两个向量都归一化,点积也没有正确的几何含义。
旋转、剪切与奇异情况
纯旋转矩阵满足,所以,法线恰好能与方向使用相同矩阵。这解释了为什么某些程序旋转时正常,一旦非均匀缩放就出错。只用旋转测试,无法证明法线处理普遍正确。
累计实现transform_normal用三阶矩阵列向量的叉积构造逆转置作用,不额外引入通用矩阵库。若A的列为a、b、c,行列式,则:
除对角缩放外,实验还检查的剪切。原切向量变成,法线应变成,点积仍为零。这项检查能暴露“只对每个分量除缩放值”的不完整实现。
零缩放会使矩阵奇异,逆不存在。接口拒绝零行列式、非有限矩阵和非仿射矩阵;运算得到非有限法线也拒绝。它没有实现近奇异矩阵的条件数估计,因此不承诺极端尺度下的数值稳定性。
负行列式还会改变朝向。代数恒等式表明,变换后重新叉积的几何法线可能与直接逆转置的法线反向。镜像模型需要连同顶点绕序、外侧约定和剔除策略处理。本次图像没有镜像,不用它证明镜像路径已经验收。
余弦项与经验高光
设单位法线为n,单位光方向l从表面指向光源。对正面受光的一侧,漫反射余弦因子为。这里先把它称为因子,避免将一个无量纲余弦误当成完整辐射亮度。
Lambert反射模型的BRDF为,最终出射光还依赖入射光及其方向积分。当前直接光教学式把光强等常量折入系数,计算;它不包含完整照明积分,也没有处理间接反射和遮挡。下一篇才加入阴影。
经验高光使用Blinn–Phong形式。单位视线v也从表面向外,半程向量,高光因子为:
本实现对背光或背向视线的表面关闭这个直接高光。l与v相反时,和向量可能为零,也不能归一化。参数p控制高光集中程度,不等于一个已经标定的物理粗糙度。
取、、p=4。因为h=l,漫反射因子为0.5,高光为。实际检查结果为0.5与0.0625000000000001,误差在阈值内。反向光源样本的高光为零。
这个经验式没有被声明为能量守恒的完整材质。随意叠加任意大的漫反射和高光系数,可能让反射能量失去物理解释。当前系数只是固定图像对照条件,不能据此推导真实材料参数。
同一块曲面,两种着色
实验取单位球面前部的一块网格。x范围为[-0.75,0.75],间隔0.375;y范围为[-0.5,0.5],间隔0.25。25个顶点的位置为:
每个网格四边形拆成两个三角形,共32片。顶点着色法线取,其长度为1。模型位于相机前方−Z区域,面法线朝+Z。
采用正交投影,屏幕位置为,w均为1。这使本篇能单独观察法线插值;一般透视相机仍须像第07篇UV那样先按1/w修正权重,再对插值法线归一化。
平面版本每个三角形使用一个几何法线。平滑版本按屏幕重心权重组合三个顶点法线,再归一化。单位向量的线性平均一般不是单位向量,例如与的平均长度只有,所以最后一步不能省。
光方向为归一化的(-1,1,2),正交视线为(0,0,1),高光指数32。线性颜色固定为:
第一项只是教学底色,不冒充环境光的物理计算。各分量最大不超过0.89,因此本实验不触发高光压缩,直接进行一次sRGB编码。
两张图来自实际C++输出,原始尺寸256×256,经sips转换PNG。第一张可见三角形面片,第二张出现连续高光;外侧仍是相同矩形裁取范围,并不是生成了更多几何。
数值证据能排除哪些误判
两个版本共享同一次覆盖判断,共写入24,576个样本,即192×128。24,190个像素的最终RGB不同。这个差异数不评价哪种风格更好,只确认法线改变确实影响了着色,而不是误把相同图像当成对照。
平滑法线的最大为。它验证当前样本归一化后的长度,不证明法线等于精确球面在每个像素处的法线。顶点法线在三角形内插值仍是近似,几何表面本身也是分片平面。
本实验没有比较投射阴影、曲面细分或透视投影的法线图。平滑着色改变的是光照输入,不会修复粗糙轮廓、错误深度或遮挡关系。若误把着色法线用于几何可见性,可能制造另一类错误。
在仓库根目录运行:
1 | |
输出目录须存在。累计检查复跑00–09,原始结果在writing-plans/computer-graphics/evidence/09-cpu.txt,两张图为lighting-flat.ppm和lighting-smooth.ppm。实验确定性运行,没有随机种子、性能计时或GPU结论。
练习与自检
练习一:把缩放改为,法线直接乘A再归一化,与逆转置再归一化是否一致?这个结果能否推广到非均匀缩放?
答案:正的均匀缩放只改变长度,两条路径归一化后方向相同。非均匀缩放会改变分量比例,正文的点积3与0反例已说明不能推广。负缩放还涉及朝向,需另行处理。
练习二:将所有顶点法线都替换成各自面法线,再进行插值,能否让低多边形轮廓变圆?为什么相同面的三个相同法线插值后仍保持平面着色?
答案:不会改变顶点位置与覆盖,轮廓不变。同一面三份相同法线的加权和仍为原法线,因为权重和为1;归一化也不改变方向。要改变轮廓需要修改几何,不能只更换着色输入。
系列导航与资料
前篇:08:怎样减少锯齿与纹理闪烁。系列入口。下一篇:10:光源看不见的地方怎样变暗。
PBRT 4ed §3.10.3 Normals、§3.10.7 Handedness,法线逆转置及变换朝向。§6.5 Triangle Meshes与§9.2 Diffuse Reflection用于核对几何与着色法线、Lambert反射的边界。
Microsoft Specular Lighting,核对半程向量与高光指数。来源记录见evidence/research-09-11.md,法线变换和高光页面于2026-09-20再次查阅。上述手算样本、网格与颜色参数由本系列独立选定。





