头发渲染:原理与实现

版权声明

  • 本文为“优梦创客”原创文章,您可以自由转载,但必须加入完整的版权声明
  • 文章内容不得删减、修改、演绎
  • 本文视频版本:见文末

头发渲染与毛发渲染

  • 头发渲染与毛发渲染使用不同的技术
  • 头发渲染通常使用插片技术
  • 插片技术将头发建模为多个四边形面片
  • 这些面片用于渲染头发的外观
  • 例如,在《神秘海域4》中,主角的头发使用插片技术渲染
  • 黑悟空的头发也是基于此技术

插片技术的具体实现

  • 在制作头发模型时,首先将其制作成多个四边形面片
  • 这些面片构成了头发的整体形态
  • 头发的渲染效果是在这些四边形面片上实现的

头发渲染中的各向异性高光


各向异性的概念

  • 头发具有各向异性的特性
  • 各向异性指的是高光的反射方向不统一
  • 举例:球体渲染中的高光与灯光方向和视角方向的夹角有关
  • 夹角越小,高光越亮;夹角越大,高光越暗
  • 每个物体表面的方向不同,高光集中在一个小区域
  • 头发的高光则不具备这种统一的反射方向

头发的各向异性高光

  • 头发的高光是锯齿状的
  • 高光在不同方向上的反射是不一样的
  • 这使得头发具有独特的光照效果

头发渲染中的具体效果展示

  • 以“最终幻想”中的爱丽丝角色为例,展示了头发的各向异性高光
  • 头发的高光随视角变化而变化
  • 头发丝的反光效果不断扰动,表现出各向异性特征
  • 头发具有半透明效果,可以看到面部皮肤透过头发

头发的环境响应

  • 头发应该响应环境变化,例如不同的光照条件下
  • 在夕阳、西下、白天和夜晚等不同光照下,头发的反光效果不同
  • 头发在黑色、直长的情况下,反光更加明显
  • 不同的光照环境下,头发反光效果差异显著

头发模型的构建与渲染注意事项


头发模型的构建

  • 头发模型通常由四边形面片构成
  • 每一层头发面片按顺序叠加,从上至下排列
  • 美术工作流中,美术同学负责构建头发模型
  • 技术美术需要理解美术工作流,确保效果的实现

头发模型的透明与不透明区域

  • 头发模型分为两部分:不透明区域和透明区域
  • 不透明区域呈灰色,透明区域呈蓝色
  • 需要分别处理透明区域和不透明区域
  • 透明区域需要贴上头发的透明贴图,以展示丝状效果

透明头发贴图的应用问题

  • 透明贴图可能会导致渲染错误
  • 错误现象包括不透明头发覆盖透明头发
  • 渲染时可能出现锯齿状效果,影响质量
  • 这些是头发渲染中常见的问题,需在处理时注意

头发渲染处理方法


头发颜色渲染

  • 头发渲染分为两部分:颜色效果和透明度处理
  • 头发颜色渲染的构成主要基于多层结构
  • 较厚的头发部分会被表层的头发所遮挡
  • 需要实现环境遮蔽效果,模拟头发的层次感

漫反射光照与高光

  • 头发受到光线漫反射的影响,需实现漫反射光照
  • 头发的高光为各向异性高光,而非简单的圆形高光
  • 各向异性高光的效果呈现为zigzag(锯齿状)形式
  • 这种效果与头发的自然结构相符合,不能简单地用圆形高光代替

各项异性高光的实现


头发高光的物理特点

  • 头发的高光由两层构成:主要高光和次要高光
  • 主要高光呈现为发白的高光,通常出现在头发的表面
  • 次要高光则呈现为深色调,如红色或黄色
  • 主要高光的反光方向偏向发梢
  • 次要高光的反光方向偏向发根

次要高光的闪光效果

  • 次要高光通常带有闪烁的效果,这种效果在特定部分会更加明显
  • 闪光效果是为了增加头发的光泽感和动态感

渲染各向异性高光的两种模型


卡吉亚模型

  • 卡吉亚模型用于渲染头发的高光效果,但渲染结果较为单薄
  • 该模型生成的高光反射较为简单,只有单一的黄色反射
  • 这是网上常用的头发渲染方案

马施纳模型

  • 马施纳模型比卡吉亚模型更加精细,能够渲染出更真实的高光效果
  • 该模型能够产生主要高光的黄色反射以及次要高光的红色反射
  • 这种模型可以提供更丰富的光照效果,提升渲染精度

头发的透明排序


半透明渲染的问题

  • 头发的半透明渲染可能会遇到遮挡问题
  • 不透明的头发可能会遮挡住半透明的表面头发面片
  • 透明排序是半透明头发渲染中的关键问题

实现正确的透明排序

  • 为了正确处理头发的透明排序,需要将头发分层渲染
  • 头发应当从最里层往外渲染,以避免不透明部分遮挡透明部分
  • 在模型制作时,确保头发从内到外的渲染顺序
  • 这一细节将在后续进一步讲解

从后往前渲染的实现


渲染过程的步骤

  • 渲染过程需要分成多个Pass来处理头发的不同层次
  • 头发的渲染顺序是从最里层到最外层

渲染的Pass顺序

  • 第一个Pass:渲染头发的不透明部分
  • 第二个Pass:渲染头发背面的半透明部分
  • 第三个Pass:渲染头发的正面半透明部分

具体示例

  • 在渲染马尾时,首先渲染马尾的不透明部分
  • 接着渲染马尾背面的半透明部分
  • 最后渲染马尾的正面半透明部分
  • 同样的过程也适用于刘海的渲染

总结

  • 不论是马尾还是刘海,都需要分三遍渲染:不透明部分、背面半透明部分、正面半透明部分
  • 该原理是为了解决透明排序问题,确保头发层次渲染正确

透明排序在程序层面的实现

注意:本节内容是“头发渲染”的难点,文字表现力较弱,欢迎移步文末,观看本文视频版本


渲染步骤概述

为了确保头发透明部分的正确渲染,需要分为多个Pass,确保每一层头发从里到外正确渲染

第一步:渲染底层的不透明部分

  1. 开启双面渲染:确保不透明部分的头发正面和背面都被渲染
  2. 透明度测试:使用透明贴图来区分不透明和透明部分,只有透明度高于某个阈值(例如0.8)时才进行渲染
  3. 开启深度写入:对于不透明部分,保持深度写入(z-write)开启

第二步:渲染背面的半透明部分

  1. 剔除正面三角形:通过开启剔除正面三角形的设置,确保只渲染半透明部分的背面
  2. 关闭深度写入:在渲染背面半透明部分时关闭深度写入,确保正确的颜色混合

第三步:渲染正面的半透明部分

  1. 剔除背面三角形:在渲染正面半透明部分时剔除背面的三角形,只渲染正面的头发

禁用 Z-Write 的原因

在渲染半透明对象时,如果不禁用 Z-Write,前面的半透明物体会遮挡后面的不透明物体,导致颜色混合错误。禁用 Z-Write 后,GPU会允许前后物体的颜色混合。

具体原因

  • 未禁用 Z-Write:当前面的半透明物体遮挡后面的不透明物体时,前物体的颜色会覆盖后物体,导致混合错误。
  • 禁用 Z-Write:允许半透明物体的颜色与后面的物体颜色进行混合,确保正确的视觉效果。

渲染顺序

为了正确进行颜色混合,渲染顺序必须从后到前。渲染错误可能导致不一致的效果,尽管偶尔可能渲染正确。


美术层面的注意事项

尽管程序可以确保透明排序的正确性,但仍需美术同学避免头发的三角形面片穿插。穿插可能导致渲染错误,因此美术模型的制作需要确保头发不会发生穿插。

思考题


渲染多个 Pass

  • 在前面的方案中,我们需要三个 Pass 来进行头发的渲染。
  • 这种方式能够很好地分层渲染头发的各个部分。

URP 管线的限制

  • 我们知道,在 URP(Universal Render Pipeline)管线中,正常情况下只能在一个 Pass 内进行头发的渲染。

三个 Pass 的渲染实现

  • 那么,在这种情况下,我们如何在 URP 中进行三个 Pass 的渲染?
  • 关键问题在于如何跨越 URP 管线的限制,达到多 Pass 渲染的效果。

渲染状态的设置

  • 这三个 Pass 中需要设置不同的渲染状态。
  • 如何在每个 Pass 中正确设置这些状态呢?

思考和探索

  • 小伙伴们可以思考一下,在 URP 管线下,如何实现头发的渲染,解决这些问题。

透明渲染中的性能问题


透明排序问题

头发的正面与背面渲染

  • 在头发渲染时,我们通常会将头发的正面和背面都进行渲染
  • 然而,头发的背面大部分情况下是被遮挡的,只有一小部分背面能够被眼睛看见
  • 被遮挡的部分头发实际上是不可见的,但由于采用了半透明渲染,这些部分并没有被剔除

渲染开销的浪费

  • 即使某些头发部分不可见,它们仍然被渲染
  • 这种做法浪费了渲染开销,因为靠近摄像机的头发无法遮挡远离摄像机的部分
  • 导致了不必要的渲染开销,影响渲染效率

如何避免无效渲染

  • 避免这种无效渲染是我们必须考虑的第一个问题

多 Pass 渲染的开销

内置管线的多 Pass 渲染问题

  • 在头发渲染过程中,通常包含不透明的 Pass 和半透明的 Pass
  • 在内置管线下进行多 Pass 渲染时,会导致合批打断,这是一个严重的性能问题
  • 当每个角色都有多层头发时,开销会变得相当大

SRP 管线下的开销

  • 在 URP 或 HDRP 等 SRP 管线下,尽管不会有合批打断的问题,但仍然会无形中增加额外的两个 Pass
  • 如何解决这一问题是我们需要进一步探讨的

Early Z 优化无法开启

透明测试与 Early Z 的冲突

  • 显卡有一种机制可以判断前面的头发是否遮挡住后面的头发,避免不必要的渲染
  • 然而,由于开启了透明测试,这一机制无法启用
  • 在透明渲染时,透明测试会在 Shader 代码中进行,但这与提前剔除不可见头发的优化互相冲突

提前剔除不可见头发的优化问题

  • 由于透明测试的存在,显卡无法提前剔除不可见的头发,因此无法启用 Early Z 优化
  • 这种优化通常是显卡自动开启的,但在透明渲染中被禁用了
  • 结果是不可见的半透明像素仍然被渲染,导致了额外的渲染开销

渲染优化与技术实现


渲染 Pass 开销优化

优化前

  • 在优化前,马尾和刘海的渲染每个都需要三个 Pass

优化后

  • 优化后,每个马尾和刘海的渲染只需要两个 Pass,从而减少了渲染开销

Early Z 限制与 Early Z 优化

Early Z 限制

  • 关于 Early Z 的限制,我之前已经提到过,因时间关系在此不再赘述
  • 但是,优化后我们可以使 Early Z 生效,提升渲染性能

透明排序优化方案

方案选择

  • 另一种优化方式是避免透明排序,但由于这种方法需要较高的性能开销,建议优先选择让 Early Z 生效的方案
  • Early Z 优化能在减少渲染开销的同时避免透明排序带来的问题

技术实现与建议

避免照搬论文方案

  • 在实现中,不建议完全照搬 SigGraph 论文中的方法
  • 如果照搬,渲染结果可能会显得杂乱无章,如同左侧图像中的发丝散乱,效果不理想

优化后的效果

  • 通过我们项目中的优化方法,右侧图像中的头发效果更为整齐、自然

项目实践中的应用

  • 最终的效果需要在具体的项目实践中落实
  • 我们会在 TA 全栈项目中学习这些技巧,帮助大家在项目中实现更好的渲染效果

进阶内容

黑悟空头发渲染

  • 黑悟空的头发也可以采用我们项目中的方案进行渲染,调整头发颜色、主要和次要高光、发光区域等

数字人渲染进阶

  • 更多关于头发、眼睛、皮肤和服装的渲染内容,可以参考我们的 “TA 全栈项目”的数字人专题,具体请参考文末

小结与思考

参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值