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角膜粗糙度,很低——角膜几乎是镜面

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

角膜边缘与眼白

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

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

眼窝遮蔽(可选)

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

解析式眼窝遮蔽

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

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

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

参数还有 socketOcclusionSoftnesssocketOcclusionStrength 调节过渡与强度。

调不出效果先检查 vertexNormal

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

屏幕空间接触遮蔽

javascript
material.contactAO = true;

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

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

相关参数:contactAORadius(默认 0.006)、contactAOMinDistancecontactAOMaxDistancecontactAOStrengthcontactAOTemporalJitter

需要深度预渲染

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

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

相关

Released under the MIT License.