植被包裹法线
全库目录221
本文目录10
叶片几何各自朝向不同,光照就像一堆板片。包裹法线从树冠代理体积取得方向,让叶片共同表达团块明暗。离线代理生成、空间变换与各LOD写回共同决定受光是否连贯。
植被的包裹法线
树冠、灌木这类资产由大量交叉面片构成。用面片自身的几何法线做光照,每一片叶子各自朝向不同,受光结果零碎生硬——看起来是一堆板片,而不是一团有体积的树冠。
美术期望的效果是让整棵树像一个柔软的实体一样受光。做法是把法线“揉”成一个包裹整个树冠的体积法线:位于树冠左侧的叶片,无论自身朝向如何,法线都大致朝左外方。
平滑后的法线离线写入网格法线通道。运行时继续读取该通道,无需额外的法线平滑或映射计算。沿法线扩张的描边也会使用这些法线,但宽度、尖角和轮廓质量仍需单独验证。
椭球代理的法线场
树冠接近单个团块时,可先使用可直接求值的椭球。中心为c,三个正半轴为a、b、c_z,均在同一对象空间且使用同一长度单位。隐式面为 F(p)=((x-cx)/a)^2+((y-cy)/b)^2+((z-cz)/c_z)^2-1,其法线方向来自梯度:
对内部叶片也可取同一方向场。沿中心射线投影到椭球只改变梯度长度,不改变归一化方向。中心点的梯度为零,需要指定备用方向,例如对象Up。半轴(2,1,1)、点(2,1,0)得到normalize(0.5,1,0),不能用normalize(p-center)代替,否则会把椭球当成球体。
这个方法无需建代理网格,但不能贴合多团树冠。若需要局部凹凸,才继续构建下述几何代理。
代理网格生成
生成流程
难点在于如何得到那个“包裹体”的形状。一条可行的管线分五步:
一、生成包裹小球。遍历原始网格的每个三角形,以最长边中点为球心,以三个顶点到球心的最大距离乘以不小于1的缩放系数为半径生成小球,间距过近时可合并,但合并后仍需检查覆盖。只用最长边的一半不能保证包含第三个顶点,等边三角形就是反例。这些小球共同构成包裹树冠的碰撞壳——它们是形状的粗略采样,不需要精确。
二、生成代理网格。以包围盒中心生成一个 UV 球体网格并合并重复顶点,然后让每个顶点朝中心投射射线:命中小球就把顶点吸附到命中点,未命中时保留稳定的原代理位置或采用邻域补洞。得到的是一个贴合树冠外形的团块代理。
这一步的本质是用射线投射把离散的小球壳转换成连续的封闭网格。保留球体连接关系可以维持闭合拓扑,但顶点吸附仍可能造成退化三角形、自交和局部折叠。初始球应包住小球集合,沿射线选进入集合的最近正向交点;从内部发射或把未命中顶点全部收拢到中心都会破坏这个边界模型。生成后检查面积、法线朝向和自交。
三、平滑代理网格。对代理网格做网格平滑,常用 Taubin 平滑——它交替进行正负两个方向的位移,在去除高频噪声的同时抑制整体收缩,比单纯的 Laplacian 平滑更能保持体积。迭代次数与滤波系数共同影响平滑尺度,并不保证严格保持体积。
对于均匀邻接权重,delta[i]=average(p[j], j in neighbours[i])-p[i]。先同时计算全部delta,再写 p1=p+lambda*delta(p);第二遍重新计算p1的邻域,写 p2=p1+mu*delta(p1),其中lambda为正、mu为负。两遍都应读独立输入快照,原地逐点更新会使结果依赖顶点遍历顺序。边界、硬边和固定锚点可保留;参数需要结合网格谱与迭代次数检查稳定性。
平滑后重算法线。要让顶部受光更统一,可以朝上方向收拢;先把法线与上方向变换到同一空间,再插值和归一化。写回对象空间通道时还要转换回对象空间。
四、可选的半球化。把代理网格顶点向其包围球位置插值,再叠加一次法线朝上的收拢。适合需要更圆润体积感的树种。
五、映射法线。对原始植被网格的每个顶点,在代理网格上找最近的顶点,直接拷贝其法线。完整计算是在同一空间最小化每个代理顶点的平方距离,再取最小索引。它会产生最近邻区域边界,代理过稀时明暗分块;可用空间索引加速,或查询代理三角形最近点并按该点重心坐标插值三个法线,再归一化。法线插值和为零时使用稳定备用方向。
所有 LOD 层级都要一起处理,否则 LOD 切换时光照会突变——这是最容易遗漏的一点。
例如三角形顶点(0,0,0)、(2,0,0)、(1,1.5,0),最长边为前两点,球心取(1,0,0)。三个顶点到球心距离分别为1、1、1.5,因此半径至少1.5才能覆盖;只用半边长1会漏掉顶点3。若代理最近顶点法线分别向左、向上,原叶片点移动到最近邻分界两侧时会突然切换方向,表现为树冠明暗块状。
改查最近三角形并插值时,例如重心权重(0.5,0.25,0.25),代理三个单位法线为(1,0,0)、(0,1,0)、(0,0,1),结果先为(0.5,0.25,0.25),归一化约为(0.8165,0.4082,0.4082)。它连续追踪代理表面方向,但与原叶片真实几何朝向并不相同,其他几何判定继续使用原数据。
法线空间与切线
若代理在世界空间求值,而资产保存对象空间法线,设对象到世界的线性矩阵为M,则对象法线可由 normalize(Mᵀ*n_world) 恢复,因为正向法线变换使用M的逆转置。这个转换要求M可逆。非均匀缩放下直接用逆矩阵处理法线方向会错。
改写法线后,已有切线不一定垂直于新法线。切线空间法线贴图要求重新构建正交基或重新生成切线,并保留镜像UV手性。需要原几何法线的遮罩、碰撞或背面规则应继续读取相应几何数据;包裹方向只用于约定的艺术化着色。
写回资产
法线必须落到资产文件里,不能只改运行时实例。两类资产的处理方式不同:
- 专用植被格式:直接解析二进制文件,按顶点布局的偏移量覆写法线、切线、副法线的浮点数据。需要准确掌握该格式的顶点布局;
- 通用网格格式:用导出器把修改后的网格写成新文件,重新导入后替换预制体中的网格引用。
第一种精确但依赖格式细节,格式版本变化会失效;第二种通用但要经过一次完整的导入流程,可能引入其他属性的变化。
边界
这套方法的适用前提是资产形态接近团块。树冠、灌木、草丛适合;藤蔓、垂柳这类狭长或分散的形态,包裹体无法表达真实形状,平滑后的法线会指向错误方向。
另外,法线被覆写后就不再表达真实几何朝向。如果项目中有其他效果依赖原始法线(例如某些基于法线的遮罩),需要提前确认冲突。
验证方法
显示原法线与代理方向,旋转光源检查团块明暗。检查代理退化、自交及未命中点,所有LOD写回同一空间并重导入核对。该方向是艺术化着色数据,不代表实际几何垂直关系。
CPU参考ellipsoid_normal检查椭球梯度与中心退化,smooth_step检查同步邻域读取和固定边界,见 reference.py,运行 python -B 知识库/examples/revision_06_08/test_reference.py。未执行代理球壳、最近面查询、资产导出或引擎光照;这些仍为尚未验证。
相关主题
参考资料
- Gabriel Taubin,A Signal Processing Approach to Fair Surface Design,SIGGRAPH1995:2026-10-22核读第2节、图1与离散Laplacian公式(6),正负两步低通滤波;本文椭球法线为隐式面梯度的独立推导。
- 空间变换维护法线逆转置与非均匀缩放的证明。
- 代理球壳与资产写回是本文提出的离线流程,需要独立做覆盖、自交与格式验收;不归因为某个引擎的既有实现。