zoukankan      html  css  js  c++  java
  • WebGPU+光线追踪Ray Tracing 开发三个月总结

    大家好~这三个月以来,我一直在学习和实现“基于WebGPU的混合光线追踪实时渲染”的技术,使用了Ray Tracing管线(如.rgen、.rmiss等着色器)。
    现在与大家分享和介绍我目前的学习成果,希望对大家有所帮助!谢谢!

    通过国外的开源项目,可在WebGPU中使用Ray Tracing管线

    这三个月我对Ray Tracing的研究有了质的突破,主要归功于我发现的WebGPU Node开源项目!
    该作者首先在dawn-ray-tracing开源项目中对“dawn项目:Chrome对WebGPU的实现"进行了扩展,加入了光追的API;
    然后在WebGPU Node开源项目中,底层封装了Vulkan SDK,上层使用了dawn-ray-tracing项目,提供了WebGPU API,实现了在Nodejs环境中使用WebGPU API和Ray Tracing管线来实现硬件加速的光线追踪(电脑需要使用nvdia的RTX显卡)!

    相关介绍参见:
    Real-Time Ray-Tracing in WebGPU

    搭建运行环境

    显卡需要为GeForce RTX(如RTX 2060s)

    有两种方法来搭建运行环境:
    1、给Chrome浏览器打补丁,使其与下载DXR驱动(DirectX Raytracing)关联,从而在该浏览器中运行
    详见该作者最近写的开源项目:chromium-ray-tracing
    (我目前没有运行成功)

    2、在这里下载并安装版本为Windows 451.74的Vulkan Driver,然后在你项目中安装webgpu的npm包:“yarn add webgpu@0.1.16”,就可以在nodejs中调用vulkan 1.2版本的Ray Tracing API了!!!

    参考示例:webgpu-examples
    使用方法: clone 项目,然后在项目根目录执行“npm install”,接着在项目根目录执行“node . ay-tracingindex.mjs”运行光追示例。

    注意:要在requestAdapter中指定preferredBackend为“Vulkan”(因为如果为D3D12,会有bug),相关代码为:

      let adapter = await GPU.requestAdapter({
        window,
        preferredBackend: "Vulkan"
      });
    

    应用场景

    考虑到WebGPU还没有正式发布,并且可能在三年内浏览器都不会支持Ray Tracing管线,所以我把渲染放到云端,这样就可以在云端自行搭建环境(如使用WebGPU Node开源项目),然后通过网络传输将渲染结果传输到客户端,从而在客户端浏览器不支持的情况下仍能显示光追渲染的画面。

    因此,我的应用场景为:
    1、云渲染
    2、云游戏

    这两个应用场景有不同的需求:
    “云渲染”属于离线渲染,我们关心的是:

    • 画质要好
    • 渲染时间可以长点

    因此:

    • 每帧可采样多次,即n spp(n >= 30)
    • 支持多种渲染效果,如“焦射”(causicts)等
    • 全局光照可使用n次bounce(n >= 2)

    “云游戏”属于实时渲染,我们关心的是:

    • 画质可以差点
    • 渲染时间要短(每帧30ms以内)

    因此:

    • 每帧只采样一次,即1 spp
    • 全局光照只使用一次或两次bounce
    • 对“焦射”(causicts)等场景用性能好的方案达到接近的渲染效果,通过牺牲画质来减少渲染时间

    介绍我目前的实现方案

    主要技术框架是“实时混合光线追踪”,主要包含下面的pass:
    1、gbuffer pass
    创建gbuffer
    2、ray tracing pass
    直接从gbuffer中获取world position、diffuse等数据,用来计算直接光照,从而减少了每个像素发射的光线数量;
    每个像素发射1个shadow ray,用来计算直接光照的阴影;
    如果只用1个bounce来计算全局光照的话,每个像素发射1个indirect ray+1个shadow ray,用来计算间接光照。
    3、denoise pass
    基于BMFR算法来实现降噪,具体可参考本文后面的“实现降噪Denoise”部分。
    4、taa pass
    使用taa来抗锯齿

    相关代码可见我的开源项目:
    WebGPU-RTX

    介绍我学习的整个流程,分享相关资料

    了解光线追踪的相关领域

    我通过下面的文章进行了初步的了解:
    一篇光线追踪的入门
    光线追踪与实时渲染的未来
    实时光线追踪技术:业界发展近况与未来挑战
    Introduction to NVIDIA RTX and DirectX Ray Tracing
    如何评价微软的 DXR(DirectX Raytracing)?

    实现第一个光追的Demo

    通过学习下面的资料:
    Ray Tracing in One Weekend
    Ray Tracing: The Next Week
    Ray Tracing in One Weekend和Ray Tracing: The Next Week的详解
    基于OpenGL的GPU光线追踪

    我参考资料中的代码,用WebGL 2实现一个Demo:

    该场景的红圈中是一个球,附近有一个球形光源和一个矩形光源

    因为没有进行降噪,所以噪点太多了哈哈!

    相关代码可见我的开源项目:
    Wonder-RayTrace

    学习和实现Ray Tracing管线

    通过学习NVIDIA Vulkan Ray Tracing Tutorial教程,我用 js语言+WebGPU Node开源项目 基于Ray Tracing管线依次实现了阴影、反射等基础渲染效果。

    该教程使用了VK_KHR_ray_tracing扩展,而WebGPU Node开源项目也使用了该扩展(Vulkan SDK),因此该教程的shader代码几乎可以直接用到该开源项目中。

    教程代码

    用Reason重写

    我用Reason语言重写了示例代码,提炼了一个基础架构。

    学习GBuffer+Ray Tracing混合管线

    因为我希望优先减少渲染时间,所以我要通过混合管线来进行实时渲染。

    我通过A Gentle Introduction To DirectX Raytracing教程来学习和实现。

    教程代码下载

    我学习了该教程的第一篇到第11篇,分别实现了创建GBuffer、使用Lambertian材质渲染、多光源的阴影等内容。

    实现降噪Denoise

    教程的第9篇通过每个像素对每个光源发射一个shadow ray,最后累加并计算平均值,实现了多光源的阴影。

    教程的第11篇对第9篇进行了改进:为了减少每个像素发射的shadow ray的数量,每个像素只随机向一个光源发射一个shadow ray。
    这样会导致噪点,如下图所示:

    我们可以通过累计采样数来不断逼近无噪点的图片(如该教程的第6篇一样),但这样需要经过长时间后才会收敛,所以只适合“云渲染”这种离线渲染的应用场景。

    累加一定帧数后,结果如下图所示:

    实现taa

    降噪算法通常需要先实现“帧间的数据复用”,而TAA抗锯齿也需要实现“帧间数据复用”的技术;而且降噪算法会使用TAA作为最后一个pass来抗锯齿。所以我决定先实现taa,将其作为实现降噪算法的铺垫。

    我参考了下面的资料来实现taa:
    DX12渲染管线(2) - 时间性抗锯齿(TAA)相关代码
    Unity Temporal AA的改进与提高相关代码
    unit Temporal Anti-Aliasing

    实现BMFR降噪算法

    为了能应用于“云游戏”这种实时渲染的应用场景,我们需要快速降噪。因此我实现了BMFR算法来降噪。

    降噪前场景:

    降噪后场景:

    我参考了下面的资料:
    BLOCKWISE MULTI-ORDER FEATURE REGRESSION FOR REAL-TIME PATH TRACING RECONSTRUCTION
    参考代码

    学习蒙特卡罗积分(monte carlo)的理论

    教程的第11篇随机向一个光源发射一个shadow ray,这其实已经使用了蒙特卡罗积分的理论。

    我们可以通过下面的资料深入学习该理论,了解概率密度函数(pdf)、重要性采样等相关概念,为我们后面实现全局光照打下理论基础:
    【RAY TRACING THE REST OF YOUR LIFE 超详解】 光线追踪 3-1 蒙特卡罗 (一)【RAY TRACING THE REST OF YOUR LIFE 超详解】 光线追踪 3-7 混合概率密
    光线追踪器Ray Tracer:进阶篇

    实现全局光照

    通过学习教程的第12篇,我实现了one bounce的全局光照。

    更多参考资料:
    Global Illumination and Path Tracing
    Global Illumination and Monte Carlo

    这里我遇到的问题主要是处理indirect specular noise:噪点不稳定,导致降噪后不稳定(高光周围有明显波动)。
    我首先以为是pdf写错了,结果修改了pdf后还是没有改进;
    然后希望通过clamp等方法移除这些高光的fireflies噪点,结果影响到了画质;
    最后采用了“采样indirect specular/diffuse多次”来稳定噪点。这适用于“云渲染”的离线渲染,但不适用于“云游戏”的实时渲染。

    基于GGX模型,实现disney BRDF

    通过学习教程的第14篇,我引入了pbr材质,实现了GGX模型,加入了多bounce的全局光照。

    我对教程代码进行了改进:
    在.rgen着色器中使用for循环而不是递归来实现的多bounce;
    实现了disney BRDF,在pbr材质中有diffuse、roughness、metallic、specular这几个参数。

    更多参考资料:
    基于物理着色(二)- Microfacet材质和多层材质
    基于物理着色(三)- Disney和UE4的实现
    基于物理的渲染(PBR)白皮书 | 迪士尼原则的BRDF与BSDF相关总结
    WebGPU-Path-Tracer 实现了disney BRDF

    目前的渲染效果

    我目前的实现需要改进的地方

    在Ray Tracing pass中支持纹理

    使用bindless texture或者virtual texture来实现

    扩展disney BRDF,实现BSDF,支持透明、折射效果

    增加后处理

    如gamma矫正等

    在云端环境下多线程渲染

    云端天然具有并行的优势,因此可将渲染任务分配到多个显卡/服务器中执行。

    改进降噪效果

    BMFR对高光specular处理得不好。
    为了应用在“云渲染”中,需要提高画质。因此可考虑:

    • 改进BMFR对specular的处理
      BMFR论文中已有相关的讨论
    • 使用专门对多个spp采样进行降噪的降噪器来替代BMFR
      因为BMFR主要是针对1 spp采样,所以需要使用针对蒙托卡罗积分路径追踪的降噪器来替代

    改进indirect specular/diffuse noise

    现在我通过增加spp来增加噪点的稳定性,这在“云游戏”中行不通,因为只能有1 spp。因此可考虑:

  • 相关阅读:
    死锁
    Hibernate—01
    POI
    线程 Thread
    SSH页面整合_01
    cnblogs安家了
    漫画:天堂里没有程序员!
    我又愿中国青年都只是向上走,不必理会这冷笑和暗箭!!!!!!!!
    一位信息系统项目管理培训老师写的《论婚姻项目管理》值得看一下!
    程序员保持健康的方法和经验
  • 原文地址:https://www.cnblogs.com/chaogex/p/13199224.html
Copyright © 2011-2022 走看看