[sig16]《神秘海域4》中的volumetric-based materials

NaughtyDog在SIGGRAPH16分享了他们在《神秘海域4》中采用的体积渲染技术,用于处理布料和头发。文章详细介绍了他们如何通过高效的近似计算,克服PS4早期硬件限制,实现物理正确且高质量的视觉效果。项目中包含了大量trick,但始终保持对物理模型的尊重,确保结果的准确性和一致性。

在这里插入图片描述

siggraph16,naughtydog的TA带来的很不错的处理衣服和头发的volumetric渲染的文章。

项目经验和心路历程
实际在我接触到的大部分开发者眼里,大家会觉得naughtydog这样的引领业界的公司,一定是从“一个英明决策到另一个英明决策”,然后砍瓜切菜般一A到底的把牛逼游戏做出来。
实际上作者在本文中也反复提及,中间走了不少弯路,有错误的预判,有失败的尝试,中间一度感到失去希望,还在团队确实牛逼,彼此也非常暖心的互奶,作品出来之后,还是叫好叫座的。
最后也是意识到again做一个demo和一个需要任何时候都好看,都高帧数不卡顿的游戏是非常不同的。
so this is the reality.

本来项目立项是在ps4早期,所以项目组希望达到一个非常“纯物理”的渲染,实际开发中也是颇有雄心的做了各种物理正确的渲染和计算。
但是实际是机能明显还是不够强劲,所以本文更多的是讲一些以更加高效的方式进行近似逼近。
一定程度上也反映了游戏开发之道,就是“高效近似的艺术”,使用各种技术的组合来以n倍效率达到原本使用昂贵计算才能做到的事情,进而超越了时代的限制。
同时本文中讲得很多“失败的尝试”,对于其他学习者来说也非常的珍贵,我们也可以看到作者的思考方式,做事方式。
虽然naughtydog的做法中也是各种trick,但是naughtydog是知道什么是对的,完备做法应该是什么样的,在这个基础上进行近似,这样的有意为之的方式,可以保持结果的近似度非常高,且有很好的自洽,看似奇胜,实则正和。
实际开发中,有些开发者在不知其所以然的情况下,各种trick,耍小聪明,最后会是让团队吃亏了。

cloth
在这里插入图片描述
开发fabric系统的时候,考虑的点:

  • 不同的reflection model
  • 不同的scattering
  • 细节的tiling处理
  • volumetric self-shadow
    macro weave structure
    这里的做法很不错,它是预先生成好一系列的纤维类型,然后做好tiling贴图,然后供美术使用:
    在这里插入图片描述
    (工具界面看起来虽然比较圡,功能还是很强大的,可以让美术预先选择不同的基础纹理)
    在这里插入图片描述
    maya里面建模不同的纹理
    在这里插入图片描述
    生成小的tiling贴图
    在这里插入图片描述
    然后tiling走起,又快又好,简直优秀。

然后说为啥不用高大上的scan技术,真实照相机一扫,那才上流么?
在这里插入图片描述
因为这样的预先生成的方式,可以以这样的组合方式来进行,达到开发效率高,资源俭省的优势,同时质量也很好。
中间可以也有一个非常犀利的各种组合出衣服的材质编辑的展示。

shader模型
丝绸类的,对比过ggx anisotropic和kajiya kay,最后ggx理论上和效果上都更牛逼,但是实际玩家看起来差别不大,最后还是kajiyakay了。
不同材质的,使用的“ready at dawn”的。

散射处理
在这里插入图片描述
使用了一个非常省的方式,达到一个不错的模拟:
在这里插入图片描述

hair render
开始也想尝试使用纯geometry,然后做正确透明排序的方式,但是最后发现还是不行。
头发依旧是hair card:
在这里插入图片描述
在这里插入图片描述
在透明处理上是dither alpha+taa来处理,不过问了在naughtydog工作的同事,说alpha blend也是有的。。
然后这部分技术比较直接,简单过下:
unify normal
使用这种unify的normal来处理头发插片之间的过渡,整体光照更加一致,同时也让backlit更好
在这里插入图片描述
在这里插入图片描述

cooked shadow
在这里插入图片描述
cook shadow信息,然后结合realtime shadow来让头发的shadow信息正确。

scatter
这里包括直接光的scatter和backlit的scatter
在这里插入图片描述
scatter部分是有physically based的光照模型,包含Single Reflection ®, Double Transmission (TT), Transmission-Reflection-Transmission (TRT) ,但是作者表示这个还是太费了,最后使用了fabric部分的scatter模拟,也还ok。
physical model在ue4现在代码里也有,确实计算量多好多倍。

shader package
这是一个从动画电影工业中借鉴来的概念,在动画片制作中,shader artist会制作一组shader package,
在这里插入图片描述
然后把相关的实现做好,暴露出来少量的参数,然后给其他美术使用,同时在开发的过程中,不停的增补。
其实这个对应的就是ue这种的material graph,做得过程中,shader的内部并不向美术开放,属于一个黑盒的状态。
任何的修改都需要以需求,以及对shader负责的人来一起迭代完成,这里的好处就是,始终能够对于这种关键的shader package保持质量和效率的最佳实现。

ppt链接:http://advances.realtimerendering.com/s2016/The%20Process%20of%20Creating%20Volumetric-based%20Materials%20in%20Uncharted%204.pptx

<think>我们正在分析一个宏定义:`#define SIG_WEB_ENDPLAY (SIGRTMAX - 2)` 这个宏定义的作用是将标识符 `SIG_WEB_ENDPLAY` 定义为 `(SIGRTMAX - 2)` 的值。 ### 解释: 1. **`SIGRTMAX`**: - 在 Linux 系统中,`SIGRTMAX` 是一个预定义的宏,它表示**实时信号(real-time signal)的最大编号**。 - 实时信号是 POSIX 标准中的一部分,编号范围是从 `SIGRTMIN` 到 `SIGRTMAX`。这些信号可以用于应用程序自定义,并且具有排队能力(即多个相同信号可以被排队而不会丢失)。 2. **`(SIGRTMAX - 2)`**: - 这个表达式表示取实时信号的最大编号减去2,因此 `SIG_WEB_ENDPLAY` 被定义为一个具体的实时信号编号。 - 例如,如果 `SIGRTMAX` 的值为 64(在某些系统上),那么 `SIG_WEB_ENDPLAY` 的值就是 62。 3. **自定义信号的目的**: - 这里定义了一个自定义信号 `SIG_WEB_ENDPLAY`,从名称推测,它很可能用于表示“网页播放结束”事件。 - 在程序中,我们可以使用这个信号来通知进程某个与网页播放相关的任务已经结束(例如,视频播放完成、音频流结束等)。 4. **使用场景**: - 在之前的代码中,我们见过:`signal(SIG_WEB_ENDPLAY, sigact_play_end);`,这表示当进程收到 `SIG_WEB_ENDPLAY` 信号时,会调用处理函数 `sigact_play_end`。 - 通过这个宏定义,我们知道了 `SIG_WEB_ENDPLAY` 的具体信号值来源于实时信号的高端(靠近最大值)。 ### 注意事项: - 实时信号的范围是系统定义的,通常从 `SIGRTMIN`(一般是一个较小的数,如34)到 `SIGRTMAX`(如64)。不同系统可能有不同的范围。 - 选择 `SIGRTMAX - 2` 是为了避免与系统其他部分可能使用的实时信号冲突(因为通常从低编号开始使用)。这样定义可以确保使用的是实时信号中较高编号的信号。 - 实时信号的优势在于它们支持排队,即如果同一个信号多次发送,而进程尚未处理,这些信号会被排队并按顺序处理(而标准信号可能会被合并,只传递一次)。 ### 示例: 假设在某个系统中: ```c #include <signal.h> printf("SIGRTMIN=%d, SIGRTMAX=%d\n", SIGRTMIN, SIGRTMAX); ``` 可能输出:`SIGRTMIN=34, SIGRTMAX=64` 那么 `SIG_WEB_ENDPLAY` 的值将是 62。 §§相关问题§§ 1. 实时信号(SIGRTMIN 到 SIGRTMAX)与标准信号(如SIGINT)有哪些主要区别? 2. 为什么选择使用 `SIGRTMAX - 2` 而不是一个固定的数字来定义自定义信号? 3. 在Linux系统中,如何查看当前系统的 `SIGRTMIN` 和 `SIGRTMAX` 的具体数值? 4. 使用实时信号时,如何确保信号处理函数的重入安全性和线程安全性? 5. 除了 `SIG_WEB_ENDPLAY`,还有哪些常见的自定义信号命名和用途? </think>### 解释 `#define SIG_WEB_ENDPLAY (SIGRTMAX - 2)` 这行代码是一个 **C/C++ 宏定义**,用于为自定义信号 `SIG_WEB_ENDPLAY` 赋予具体的信号编号值。核心解析如下: 1. **`SIGRTMAX` 的含义** - `SIGRTMAX` 是 Linux/Unix 系统中预定义的宏,表示**实时信号的最大编号**(Real-time Signal Maximum)。 - 实时信号范围是 `SIGRTMIN` 到 `SIGRTMAX`(通常是 `34~64`,具体值因系统而异)。 - 这类信号支持排队(多个相同信号不会被丢弃),适用于高可靠性场景。 2. **`(SIGRTMAX - 2)` 的赋值逻辑** - 将 `SIG_WEB_ENDPLAY` 定义为实时信号区域的**倒数第3个信号**(最大编号减2)。 - 例如:若 `SIGRTMAX = 64`,则 `SIG_WEB_ENDPLAY = 62`。 - **设计意图**: - 优先使用高编号信号,避免与常用标准信号(如 `SIGINT=2`)冲突 - 保留 `SIGRTMAX` 和 `SIGRTMAX-1` 给更高优先级功能使用 3. **与之前代码的关联** 该宏使 `SIG_WEB_ENDPLAY` 成为有效信号,使得 `signal(SIG_WEB_ENDPLAY, sigact_play_end)` 能够正确绑定信号处理函数。 4. **实时信号的优势** - 支持信号排队(即使处理函数未返回,新信号也不会丢失) - 可携带附加数据(通过 `sigqueue` 而非 `kill` 发送) - 优先级排序(编号越大优先级越高) ### 典型使用场景 ```c // 发送信号示例(其他进程或线程) sigqueue(target_pid, SIG_WEB_ENDPLAY, (union sigval){.sival_ptr = data}); // 接收处理函数 void sigact_play_end(int sig, siginfo_t *info, void *context) { void *custom_data = info->si_value.sival_ptr; // 提取附加数据 // 处理播放结束逻辑 } ```
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值