Skip to content

眼睛材质 ​

眼睛在角色渲染里的比重远超它的面积——观众第一眼看的就是它,而它的视觉特征(角膜折射带来的 虹膜位移、瞳孔深度感、边缘的暗环)恰好都不是普通 PBR 材质能表现的。

EyeMaterial 用一个网格、一个材质渲染整个眼球(眼白、角膜边缘、虹膜)。

资产要求 ​

这套方案不需要遮罩贴图,各个区域是从 UV 到虹膜中心的距离解析算出来的。代价是资产必须 按约定摆放:

  • 单个眼球网格(球体或前半球罩),必须同时带法线和切线。 没有切线就没有 TBN,折射会退化成平的虹膜——这是最常见的问题。
  • UV 要把瞳孔中心放在 irisCenter(默认 (0.5, 0.5)),虹膜占据以它为中心、 半径为 irisRadius(默认 0.22)的圆盘。
  • 虹膜贴图的瞳孔在贴图中心。 眼白贴图是可选的,没有时用 scleraColor 着色。

如果虹膜位置或大小不对,先检查 UV 摆放和这两个参数,而不是去调折射。

虹膜与角膜 ​

属性默认值作用
irisCenter(0.5, 0.5)瞳孔中心在 UV 空间的位置
irisRadius0.22虹膜圆盘半径(UV 单位)
irisDepth0.06虹膜相对角膜表面的深度,决定视差强度
ior1.376角膜折射率,1.376 是人眼实测值
pupilRadius0.35瞳孔半径(相对虹膜)
pupilDilation0瞳孔缩放,可用于表现光照变化或情绪
irisColor—虹膜染色
irisBrightness—虹膜亮度
corneaSpecularStrength—角膜高光强度
corneaRoughness0.05角膜粗糙度,很低——角膜几乎是镜面

irisDepth 和 ior 共同决定视差的强弱。想要更明显的"深邃"效果就加大 irisDepth, 但过大会在斜视角下露出破绽。

角膜边缘与眼白 ​

属性默认值作用
limbalRingWidth0.15角膜边缘暗环宽度
limbalRingStrength—暗环强度
scleraColor—眼白颜色(无贴图时使用)
scleraWrap0.35眼白的环绕漫反射,软化明暗交界
scleraEdgeTint—眼白边缘染色,模拟血丝和阴影

角膜边缘暗环(limbal ring)是让眼睛显得"真"的关键细节之一。真实眼睛虹膜外缘有一圈色素 沉积,缺了它眼睛会显得平、像贴图。

眼窝遮蔽(可选) ​

裸眼球在环境光下会整体发亮,因为它不知道自己嵌在眼窝里。引擎提供两层互补的遮蔽, 默认都是关闭的。

解析式眼窝遮蔽 ​

javascript
material.socketOcclusion = true;
material.upperLidAngle = 50;   // 度
material.lowerLidAngle = 65;

用一个非对称开口建模眼睑:绕一根固定在眼球物体空间里的轴(可用 socketRotation 旋转), 上下各有一个开口角度。开口之外的方向压暗环境漫反射、环境镜面和直接光。不需要遮罩贴图、 额外 pass 或逐帧脚本。

用物体空间的好处是:这个遮蔽帧会自动跟随蒙皮和节点运动,而且垂直注视时遮蔽会跟着眼球走 ——接近真实上眼睑的行为。水平注视绕上轴转则不影响遮蔽,这也符合实际。

参数还有 socketOcclusionSoftness 和 socketOcclusionStrength 调节过渡与强度。

调不出效果先检查 vertexNormal

眼窝遮蔽的开关挂在 vertexNormal 上。如果设了 socketOcclusion = true 却看不到变化, 先确认 vertexNormal 是开启的。

屏幕空间接触遮蔽 ​

javascript
material.contactAO = true;

解析式开口是眼睑的模型,而这一层读取深度预渲染,所以跟随真实的眼睑网格—— 眨眼、不对称、睫毛都算得进去。

它压暗环境项和直接光的漫反射(因为 shadow map 分辨不出毫米级的眼睑缝隙), 但不动直接光的高光,这样角膜高光得以保留。

相关参数:contactAORadius(默认 0.006)、contactAOMinDistance、contactAOMaxDistance、 contactAOStrength、contactAOTemporalJitter。

需要深度预渲染

这一层依赖深度预渲染。Forward+ 管线总是会跑一次,所以正常情况下可用; 在没有绑定深度预渲染的场合,该项会静默地解析为无遮蔽,不会报错。

两层可以同时开:解析式提供稳定的基础遮蔽,接触遮蔽补上真实眼睑的动态细节。

相关 ​

Released under the MIT License.