基于 RadeonRays 的光线追踪全局光照实现方案

最近半年一直在做全局光照方面的工作,陆续实现了辐射度算法和光线追踪两套方案,最终由于辐射度算法的局限性(只能基于漫反射)还是使用了光线追踪的方案,是时候写个小小的总结了。

先列一下提纲吧,希望从以下几个方面讲一讲这些工作:

  • 为什么选择光线追踪
  • RadeonRays 简介
  • 实时光线追踪与离线光线追踪的区别
  • 光线追踪全局光照方案的渲染管线
  • 光线追踪方案实现过程中的经验和教训
  • 一些效果展示

为什么选择光线追踪

相信很多游戏开发者,特别是做游戏引擎的猿,会对渲染效果很痴迷,而全局光照是渲染效果呈现的一个很重要的因素,在2017GDC 中 Unity 和 AMD 发布了基于 RadeonRays 的 Progressive Lightmap 的全局光照实现方案,和 Unity 之前的 Enlighten 的方案研究对比了一下,无论在效率还是效果方面都有了很大的提升,再加上自己对于新技术的热爱(其实是 Leader 的逼迫),有了把 RadeonRays 方案移植到我们引擎的想法。其实在这之前实现了辐射度算法的方案,但是效率和效果实在是难以忍受,所以开始光线追踪的预研,半个多月之后居然移植过来简单的跑通了,极大的增强了自信心,于是继续攻克难关实现了它。后来看到报道2018GDC 中 UE4和 NVIDIA 联合发布了实时光线追踪的解决方案,DX 也适配了光线追踪的渲染管线,感觉光线追踪应该是现在的趋势。

RaydeonRays 简介

RaydeonRays 是 AMD 的一套光线追踪的解决方案,它支持三个后端:OpenCL, Vulkan,以及 Embree, OpenCL 使用支持至少 OpenCL 1.2的 GPU 和 CPU,Vulkan 支持 Vulkan 1.0以上的 GPU, Embree 支持 Intel 优化的 CPU 光线追踪设备软件。当然,在如今 GPU 性能越来越好的时代,能用 GPU 就别用 CPU 了,我选用了 GPU 的 OpenCL 方案,当然,选它也是因为 RaydeonRays 在 Github 开源了,虽然无法照搬,但是很多东西还是可以借鉴学习的。

据 Unity 所说,使用 RadeonRays 的 Lightmap 烘培方案比之前快了10-20倍,之前需要一天才能渲完的场景现在一个小时就能渲染完了,具体是真是假我也没实验过。

实时光线追踪与离线光线追踪的区别

所谓的实时光线追踪,就是随着摄像机视角的变动,后端需要实时发射追踪光线来重新计算光照信息,如果屏幕分别率很高,这个计算量是很大的,对 GPU 的性能要求是很高的,如果性能达不到游戏直接会卡死。而离线光线追踪则不会造成这种情况,即使设置了很高的光线追踪采样率,很多的反射次数,无非是烘焙 Lightmap 的时间会变长,最终还是可以渲染出效果很好的的 Lightmap 供场景使用。所以现阶段还是全局光照中的光线追踪方案占主流,NVIDIA 虽然发布了新的 TURING 架构显卡引入光线追踪框架,但是实时光线追踪真正进入游戏普及估计还是任重道远(希望能很快打脸)。

光线追踪全局光照方案的渲染管线

关于光线追踪的基本原理,其实还是比较简单的,简单来说就是向场景发射 N 条光线,然后根据碰撞点的材质进行 BXDF,BRDF 的运算,然后(根据俄罗斯轮盘)再进行漫反射,镜面反射,或者折射,如此循环直到光线逃离场景或者到达最大反射次数,最后对 N 条光线进行蒙特卡洛积分即可获得结果。对于实时光线追踪和离线光线追踪,这里发射光线的方式还是有些差异的:实时光线追踪是从视点发射光线,光线数量一般是屏幕的大小,比如屏幕是1920*1080, 则需要发射1920*1080条射线,每条射线对应一个像素点,依照需求,可能要发射多次来采样平均得到理想的结果;而对于离线光线追踪,每个静态物体都要根据光照 UV 生成 M 个 Patch(数量和 Lightmap 大小有关),每个 Patch 要向法线方向的半球发射 N 条射线(数量由用户采样数量决定),最终对 N 条射线进行蒙特卡洛积分,得到这个物体的 Lightmap。

具体的实现过程可以参照 Unity 的实现方案,贴一个他们方案的伪代码:

本来想自己画一个 PipeLine 的流程图的,但是忽然想起之前看的 UE4的视频中看到过类似的,就回头找了一下直接把他们的贴上来:

需要补充的是,对于 Miss 的光线,我做的处理是给它赋予环境球(当作天光)的颜色,而每次处理完最近的碰撞之后,需要发射阴影检测射线以及重新计算的反射光线,二手QQ买号底层的加速结构我用的 bvh,可以加包围盒也可以直接把三角形挂在上面。

光线追踪方案实现过程中的经验和教训

因为是从一穷二白的状态开始的,所以过程中遇到的坑实在是太多太多,很多可能都没记录流失了,这里就搬一下印象比较深刻,记录在案的吧。

刚开始生成 Lightmap 是逐像素的,现在想想当时的思路是太蠢了,没有合理运用好 GPU 的特性,后来用逐 Lightmap 的方式,效率提升了成百上千倍。

材质层开始没搞的很明白,结果就是 Lightmap 渲染出来效果总是不理想,比如石头边缘会漏光等等,后来仔细看了看底层的材质算法,才算弄好了。后来又恶补了一下 BRDF 的一些算法和逻辑,感觉这方面做好还是挺不容易的,最近 Google 开源了 filament 的项目代码,还有一些文档,特别是对于移动端的优化写的还是挺好的,在这里推荐一下。

随机光线的生成,开始是用的 c++ rand 方法直接在半球生成光线,后来用了 cosineSampleHemisphere 算法,最好再加个分层采样,比之前的效果噪点少一些。

一些并行的运算,只要能在 GPU 里面计算,尽量放到 GPU,放到 kernel 里面计算比 CPU 快的多得多,CPU 和 GPU 交互读取数据会比较耗费性能,这方面的操作能少做就尽量少做。

还有就是材质内存方面,尽量所有物体设置成同一属性 Instance,不然内存老是崩溃,这是底层的问题,另外在引擎客户端方面做了一些场景物体和灯光的剔除,也有改善作用。

对于 AlphaTest,开始想了好多办法,不想把 alpha 贴图传进射线检测层,但是后来效果都不好,还是乖乖传了 alpha 贴图。

一些漏光问题,很多时候是因为模型 UV 划分问题,或者 Lightmap 大小不够,像素太少导致的。

还有噪点问题,一开始采样灯光是用的随机采样,这样灯光多了很容易出现噪点,最后直接遍历所有灯光,这样虽然效率方面降低了不少,但是最后噪点基本很少,用效率换效果,最后其实效率也还可以接受,这样所有路径最终只需要遍历一次就够了。

当然还有很多服务器和各种自己粗心失误的问题,印象比较深的一次是 Github 代码改了之后找不到原版了,下的还不是 Release 版本,幸亏 Git 比 SVN 好一些,能恢复到某一时间点之前的代码,万幸啊……

一些效果展示

首先贴一个木屋的测试效果:

在左侧面还是可以看到光线追踪的反射效果的。

然后尝试渲染了一个项目比较大的场景:

光线追踪渲染出来的效果整体会更丰富生动一些,当然这个版本还是当时不成熟的版本,仔细看还是有些问题的。

最后贴一个受到 UE4启发做的一个面光效果:

面光的虚化阴影效果还是挺好的。

欢迎大家分享交流。

基于RadeonRays的光线追踪全局光照实现方案相关推荐

  1. (八)unity自带的着色器源码剖析之——————Unity3D的全局光照和阴影:下篇(unity3D中的球谐光照和SH球谐函数、unity实时阴影抗锯齿解决方案)

    一.探针基于球谐函数的全局光照 球谐光照是基于预计算辐射度传输理论实现的一种实时渲染技术.预计算辐射度传输技术能够重现在区域面光源照射下的全局照明效果.这种技术通过在运行前对场景中光线的相互作用进行预 ...

  2. 真正的全局光照:IMG DXT面向大众的光线追踪方案

    2021年,Imagination推出了世界上第一款实时的.基于硬件的光线追踪GPU解决方案,旨在最大化移动设备的视觉效果,同时具有高效性.在移动设备的面积和功率限制下,Imagination的方案克 ...

  3. Godot 4.0中的基于有向距离场SDF(Signed Distance Field)的实时全局光照技术

    原文地址 Godot官网 <Godot 4.0 gets SDF based real-time global illumination> 作者 Juan Linietsky 6月28日 ...

  4. (二十)unity shader之——————基于物理的渲染技术(PBS):下篇(PBS技术拓展:全局光照、伽马校正、HDR)

    前面两篇文章我们介绍了PBS实现的数学和理论基础,和standard shader的原理和实现,还有一些其他的渲染相关的unity技术.其中有些概念和技术没有讲的很详细,现在对这些重要的概念进行更深入 ...

  5. 计算机图形学GAMES101(十四)光线追踪(辐射度量学、渲染方程与全局光照)

    本节涉及内容: 辐射度量学(Basic radiometry) 光线的传播:反射方程以及渲染方程 全局光照 为什么要学辐射度量学? 之前使用的Whittled style光线追踪很多物理量都没有精确的 ...

  6. 【技术美术图形部分】PBR全局光照:理论知识补充

    写在前面 最近做东西的流程是这样的,想实现一个风格化森林小场景,场景体现的主体是风格化树和交互草 --> 于是用了两天时间学SpeedTree做树模型 --> 用了两天时间SD做了树干贴图 ...

  7. 实时高清渲染:全局光照(Global Illumination)[1]

    目录 基础知识: Radiance: Irradiance: Radiant flux: Radiant Intensity: Solid Angle: Lambertian surface: Lam ...

  8. 局部遮荫光伏matlab,一种基于随机蛙跳全局搜索算法的局部阴影光伏阵列MPPT控制的制作方法...

    本发明涉及一种局部阴影光伏阵列多峰MPPT控制方法,特别涉及一种基于随机蛙跳全局搜索算法的局部阴影光伏列阵多峰MPPT控制. 背景技术: 伴随太阳能发电的普及,光伏阵列的运行环境变的越来越复杂,局部遮 ...

  9. 实时全局光照RSM-Reflective Shadow Maps(RSM)

    全局光照介绍 现实世界光处于线性空间,光照效果是可以叠加的,最终的光照结果 = 直接光照 + 间接光照,结果也被称为全局光照(Global illumination).与之对比的是局部光照--仅考虑直 ...

最新文章

  1. 计算机行业2019年度投资研究手册
  2. JAVA-单例模式的几种实现方式
  3. 小程序 数据库 时间_使用云开发数据库构建更生动的小程序
  4. iOS socket 套接字编程
  5. 12行代码AC-Leecode 598. 范围求和 II——Leecode每日一题系列
  6. abap 中modify 的使用
  7. asp.net core Serilog的使用
  8. Redis radix tree源码解析
  9. java中after什么意思_Java中的即时isAfter()方法
  10. 如何查看正在使用端口号并利用任务管理器将其关闭
  11. 触发事件_SAP 通过事件触发后台JOB
  12. VMware Server 2.0下载和序列号正版
  13. POJ 3518 Prime Gap(素数)
  14. android 混淆报错记录
  15. 松翰单片机--SN8F5702学习笔记(五)PWM
  16. android动态开场,Android 开场动画
  17. vulfocus——骑士cms任意代码执行(CVE-2020-35339)
  18. 一篇文了解电商直播的优势和平台
  19. STM32CubeMonitor监控程序目标变量并导出结果为csv格式
  20. VMware 只能打开一个.vmx,无法打开第二个

热门文章

  1. leetcode-237-删除链表中的节点
  2. [TCP/IP]TCP服务端accept发生在三次握手的哪一个阶段
  3. OpenStack构架知识梳理
  4. create-react-app 构建的项目使用 mobx (说到底就是为了使用装饰器语法对 babel 做些配置...
  5. docker基础命令
  6. Git使用列表(四)
  7. linux环境变量与文件查找
  8. 【转】Compile、Make和Build的区别
  9. Nodejs入门【转载】保留备用
  10. selenium(2.4.0)中不能导出web drive 代码