在任何视觉图形的场景中,为了让用户获得更真实的体验,阴影往往发挥着重要作用。不过,它们长期以来一直是实时应用程序中在速度和质量方面最难完成的功能之一。随着硬件的改进和硬件加速光线追踪技术的普及,开发人员获得了比以往任何时候都更准确、更快地渲染阴影的能力。在Imagination,我们相信光线追踪在未来实时渲染中的潜力,并一直在寻求可能的界限突破。

这篇博文将简要介绍如何生成具有硬阴影的完全光线追踪场景,以及Khronos Vulkan光线追踪扩展的高级概述。对于那些已经阅读了我们之前《Vulkan中的环境遮挡》的读者来说,这是很好的后续内容,从完全通过光栅化的光照技术到现在使用完整的光线追踪。正如《Vulkan中的环境遮挡》一样,我们的PowerVR SDK中有一个完全光线追踪硬阴影的代码示例,您可以在空闲时间探索。


当前的阴影技术

在过去十年中,实时渲染阴影的流行方法是使用阴影贴图。这是场景从光源视角再次渲染到离屏深度缓冲区(称为阴影贴图)的地方,然后在着色过程中对阴影贴图进行采样,以使用深度比较计算可见性。虽然这种方法已经成功地应用于许多应用中,但它也有一些缺点。

最常见的问题是阴影锯齿——这是在阴影贴图的分辨率过低的地方,导致出现块状阴影。虽然可以通过使用更高分辨率的阴影贴图来解决,但会增加内存占用和带宽利用率,可能会对性能产生负面影响,尤其是在移动设备上。即使使用更高分辨率的阴影贴图,某些微观细节也很难保留,这要后续的屏幕空间阴影通道来细化。但是,在使用光线追踪时,可以在屏幕上为每个像素分配一条光线,这将产生像素完美的硬阴影。


光线追踪管线

光线生成

当在命令缓冲区调用 vkCmdTraceRaysKHR ,将为当前绑定的光线追踪流水线调用用户定义的光线生成着色器。追踪光线的命令允许开发人员为调度的线程设置各种参数。我们的演示是完全光线追踪的,这意味着最好为屏幕上的每个像素分配一个光线生成着色器线程。

每次调用光线生成着色器都必须指定将主光线发射到场景中所需的变量。光线需要有原点(视点)和行进方向。可以通过将逆视图矩阵应用于(0,0,0,1)来计算原点。要计算方向,需要当前像素的屏幕空间位置。可以使用 gl_LaunchIDEXT 从光线生成着色器查询分派坐标。使用此内置扩展,屏幕空间坐标和光线方向可以按如下方式计算:

const vec2 pixelCenter = vec2(gl_LaunchIDEXT.xy) + vec2(0.5);
const vec2 inUV = pixelCenter / vec2(gl_LaunchSizeEXT.xy);
vec2 screenspace = inUV * 2.0 - 1.0;vec4 target = mInvProjectionMatrix * vec4(screenspace.xy, 1, 1);
vec4 direction = mInvViewMatrix * vec4(normalize(target.xyz), 0);

从这里,我们可以使用 traceRayEXT 函数将主光线发射到场景中。然后,它将遍历加速结构,在该结构中,它将命中或错过场景中的几何体,并调用相应着色器组。执行的着色器组将取决于其命中内容,并将像素颜色存储在有效负载结构中。“未命中”着色器只是将光线的颜色设置为硬编码的清除颜色。

命中组着色器

一旦光线与场景中的对象发生碰撞,就会执行命中着色器。顶点缓冲区、索引缓冲区和材质等模型数据都附着到“命中组”着色器。光线追踪扩展允许我们获取命中对象的实例ID。在本演示中,每个模型都是唯一的,因此实例ID直接对应于模型ID。模型ID可用于查找上述缓冲区。

// Since each object is unique in this scene, instance ID is enough to identify which buffers to look up
uint objID = gl_InstanceID;// indices of the triangle we hit
ivec3 ind = ivec3(indices[nonuniformEXT(objID)].i[3 * gl_PrimitiveID + 0], //indices[nonuniformEXT(objID)].i[3 * gl_PrimitiveID + 1], //indices[nonuniformEXT(objID)].i[3 * gl_PrimitiveID + 2]); //// Vertices of the hit triangle
Vertex v0 = vertices[nonuniformEXT(objID)].v[ind.x];
Vertex v1 = vertices[nonuniformEXT(objID)].v[ind.y];
Vertex v2 = vertices[nonuniformEXT(objID)].v[ind.z];

gl_PrimitiveID 可以用来告诉我们使用哪些索引来查找命中的顶点,然后使用重心插值系数在它们之间进行插值,该插值系数来自命中着色器中声明为 hitAttributeEXT 类型的全局变量。然后,我们使用世界矩阵将插值顶点值转换到世界空间,并旋转法线值。

// Get the interpolation coefficients
const vec3 barycentrics = vec3(1.0 - attribs.x - attribs.y, attribs.x, attribs.y);// Interpolate the position and normal vector for this ray
vec4 modelNormal = vec4(v0.nrm * barycentrics.x + v1.nrm * barycentrics.y + v2.nrm * barycentrics.z, 1.0);
vec4 modelPos = vec4(v0.pos * barycentrics.x + v1.pos * barycentrics.y + v2.pos * barycentrics.z, 1.0);// Transform the position and normal vectors from model space to world space
mat4 worldTransform = transforms[nonuniformEXT(objID)];
vec3 worldPos = (worldTransform * modelPos).xyz;// Don't translate the normal vector, only rotate and scale
mat3 worldRotate = mat3(worldTransform[0].xyz, worldTransform[1].xyz, worldTransform[2].xyz);
vec3 worldNormal = worldRotate * modelNormal.xyz;

使用击中点的法线和世界位置,我们可以计算光线相对于场景中静态光源的Phong照明分量。然后,我们使用一个新的命中和未命中组从该点向光源发射另一条光线。我们可以将次光线的最大长度设置为击中点和光源之间的距离。如果光线在这个距离内与加速度结构中的任何物体碰撞,我们可以得出结论,在碰撞点和光源之间有一个物体,因此该点处于阴影中。如果次光线未击中距离集内的任何对象,则会执行“未命中”着色器,我们可以假定该点不在阴影中。

在这个图中,我们可以看到两个例子。光线从视口(1)发射,第一条光线击中点3,第二条光线发射,在到达光源的途中不会击中任何几何体。视点的第二条光线在点4处照射,但在到达光源的过程中,在点5处再次发生碰撞。因此,我们可以得出结论,点4在阴影中,但点3不在阴影中。


优化

虽然光线追踪阴影提供了比传统方法更高的逼真度,但它们仍然不完全完美。因此,就实时计算而言,光线追踪算法需要更多的硬件,这是一个明显的缺点。除此之外,还可以采取一些不同的优化措施来改进本文概述的技术。

阴影检查

我们可以减少第一组用来检查硬阴影的二次光线的数量;这是通过首先检查已计算的Phong光照分量来完成的。如果由于曲面背向光源,光照分量已为0,则检查硬阴影没有意义,因为该点已处于黑暗中。

这将光线预算从屏幕上像素数的大约1.8倍减少到大约1.5倍。这显然取决于场景和其中的对象,因为它随未命中场景的主光线的比例以及通过或未通过阴影检查的主光线的比例而变化。

混合渲染

一般来说,光线追踪核心将比传统的光栅化流水线慢(至少目前是这样)。有几个可能的原因,但主要的原因是光线追踪硬件仍然相对较新,因此与光栅化相比,GPU仍然没有为其投入更多的空间。这意味着可以计算一个标准的G缓冲区,并使用位置附件来定位从哪个位置发射阴影检查光线。G缓冲区在《Vulkan中的环境遮挡》中有介绍,所以如果你还没有看到,一定要看一看。简而言之,G缓冲区可以替代主光线,从而产生更好的任务重叠和更小的光线预算。


结束

虽然完全光线追踪的硬阴影在写这篇博文的时候可能不是最佳解决方案,但它们仍然提供了传统流水线难以模拟的细节和准确性。一如既往,我们强烈建议大家看看PowerVR SDK及其代码示例,以了解我们如何实现这些技术和实现这些算法的确切机制。我们也总是通过支持门户或论坛发送电子邮件。

如果您有兴趣了解更多关于各种图形技术的信息,请查看我们的文档网站,或者在SDK Github中探索我们的其他代码示例。

https://docs.imgtec.com/

https://github.com/powervr-graphics/Native_SDK

英文链接:https://developer.imaginationtech.com/blog/vulkan-fully-ray-traced-hard-shadows/

声明:本文为原创文章,转载需注明作者、出处及原文链接。


欢迎加入Imagination GPU与人工智能交流2群

入群请加小编微信:eetrend89

(添加请备注公司名和职称)

推荐阅读

Vulkan同步机制和图形-计算-图形转换的风险

Imagination Technologies 是一家总部位于英国的公司,致力于研发芯片和软件知识产权(IP),基于Imagination IP的产品已在全球数十亿人的电话、汽车、家庭和工作场所中使用。获取更多物联网、智能穿戴、通信、汽车电子、图形图像开发等前沿技术信息,欢迎关注 Imagination Tech !

Vulkan完全光线追踪硬阴影相关推荐

  1. 浅谈高性能计算(HPC)

    高性能计算(HPC)利用超级计算机和并行处理技术,快速完成耗时较长的任务或同时完成多个任务.HPC市场既是一个传统的市场,又是一个新兴的.高速发展的市场.定位高端用户.标杆项目,影响力大.平民化趋势. ...

  2. Imagination在GDC 2022上推出下一代移动游戏解决方案

    借助于O3DE引擎展示采用硬件加速的全域光照光线追踪解决方案 英国伦敦- 2022年3月23日-Imagination Technologies在"2022游戏开发者大会(GDC 2022) ...

  3. 反射大师怎么使用_大师赛锦鲤将获得2080游戏主机?三娘冲了!

    三娘的2372篇推送ᕱ⑅ᕱ 少年狂,挑剑竞锋芒!第五届<剑网3>竞技大师赛-俱乐部争锋赛今日火热开战,即日起至3月23日每晚19:00锁定官方直播间,八家职业俱乐部强者出征,一同决战沙场! ...

  4. OptiX资料学习笔记1——简介

    OptiX资料学习笔记1--简介 OptiX引擎的现状 目前有三种开源的API支持NVIDIA的光线追踪功能,分别为: DirectX Raytracing (DXR) DX的光线追踪API Vulk ...

  5. 将HLSL射线追踪到Vulkan

    将HLSL射线追踪到Vulkan Bringing HLSL Ray Tracing to Vulkan Vulkan标志 DirectX光线跟踪(DXR)允许您使用光线跟踪而不是传统的光栅化方法渲染 ...

  6. Imagination 推新款GPU IP,首次实现桌面级光线追踪效果

    游戏界被炒得最热的概念可能就是光线追踪技术了,不仅仅是PC端的游戏.光线追踪所展示出来的画面效果也确实惊艳,可以让我们感叹到图像技术达到的一个新高度. 但是实际上,光线追踪并不是一个新技术.10年前, ...

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

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

  8. 实时光线追踪技术:业界发展近况与未来挑战

    最近阅读了SIGGRAPH 2019中 EA SEED团队带来的,关于实时光线追踪一篇很赞的技术分享[1]. 本文将以此为引子,对实时光线追踪技术的发展近况,当前业界面对的挑战,以及未来的研究方向进行 ...

  9. 光线追踪技术 清华大学 pdf_实时光线追踪技术:业界发展近况与未来挑战

    最近阅读了SIGGRAPH 2019中 EA SEED团队带来的,关于实时光线追踪一篇很赞的技术分享[1]. 本文将以此为引子,对实时光线追踪技术的发展近况,当前业界面对的挑战,以及未来的研究方向进行 ...

最新文章

  1. 007-迅雷定时重启AutoHotkey脚本-20190411
  2. 20145234黄斐《Java程序设计》第五周
  3. Java程序员面试中的多线程问题1
  4. StarlingMVC Framework 原理。。。
  5. 【白话科普】10s 从零看懂 H5
  6. 还要让你的家人等多久?五年后,你在做什么?
  7. 九大神招,让Python里数据分析神器Jupyter,完美升华
  8. redis 命令行 操作
  9. http://snaps.php.net,科技常识:Windows下编译PHP和memcache扩展教程
  10. cruzer php sandisk 闪迪u盘量产工具_sandisk cruzer 32G U盘量产工具下载
  11. 如何用计算机计算幅度,用自然语言的方式做计算:Numi 计算器
  12. 基于Patachmatch的stereo matching笔记(二):《DeepPruner》
  13. Visio 画图去掉页边距的解决办法
  14. 计算机网络ping用法,Ping命令及用法详解
  15. TM影像各波段及波段组合情况
  16. 雷克萨斯品牌舆情监测-危机后,如何重新赢得消费者的认可?
  17. 单体测试使用Assert.assertThat(expected,Matcher matcher)来对比结果和预期
  18. php和mysql入门
  19. mysql实现layui分页_LayUI
  20. html异步加载页面,Jquery异步加载页面(load)

热门文章

  1. 惠普笔记本电脑关闭功能键
  2. 稳态视觉诱发电位SSVEP简介
  3. fatfs文件系统的宏定义使用
  4. 音视频学习(一)——PTZ控制原理
  5. EasyGBS定制项目添加“设备标签”模块的代码实现分享
  6. java开发工程师面试经历
  7. 使用TensorFlow训练神经网络识别MNIST数据一
  8. 软件需求工程 高校教学平台 软件概要设计说明书
  9. 奇易群控模拟器v3.1.2绿色版
  10. win7系统中Fiddler根证书创建失败的解决方法