百科问答小站 logo
百科问答小站 font logo



如何评价 NVIDIA RTX Technology? 第1页

  

user avatar   nvidiaying-wei-da 网友的相关建议: 
      

谢邀。


“光线追踪就是未来,且一直会如此!”几十年来,当图形开发者被问及实时光线追踪是否可行时,这句话一直都是他们的口头禅。

大家似乎都同意前半句的说法:光线追踪就是未来。因为光线追踪是我们所知道的唯一能够渲染真正意义上具有照片级真实感图像的技术。电影业无法接受在图像质量上的妥协,这一领域中所采用的所有离线渲染器都是基于光线追踪,这并非偶然。光栅化多年来取得了巨大的进步,并且即使到如今也仍在发展,但它在所能计算的效果类型上有着根本性的限制。要想真正让图形效果再上一层楼,就需要新的底层技术。这就是光线追踪的用武之地,这也是为什么实时光线追踪一直是游戏玩家和游戏开发者的梦想。

那么光线追踪会不会总是未来的梦想,而永远不会在当下实现呢?在GDC 2018上,NVIDIA推出了RTX,其基于NVIDIA Volta GPU及未来GPU的超高性能,将赋力NVIDIA所支持的所有光线追踪API。同时,微软也宣布将光线追踪纳入其行业标准DirectX API中。

这两种技术构成了强大的组合,我们可以自信地回答上述问题:未来已来!这种说法毫不夸张:现在领先的游戏工作室已经开始采用RTX,通过DirectX开发即将推出的游戏。光线追踪在游戏中的应用不再是梦想。它此时此刻正在发生,且将迎来一个实时图形的新时代。


关于实时光线追踪的演示,大家可观看以下几个视频:

https://www.zhihu.com/video/974987051536461824

星球大战短片——在NVIDIA RTX上运行的虚幻引擎(Unreal Engine)实时光线追踪演示


https://www.zhihu.com/video/974987303555350528

NVIDIA RTX实时光线追踪演示


https://www.zhihu.com/video/974989613518000128

运行于NVIDIA RTX的EA Project PICA实时光线追踪演示


下面我们将从微软的DXR API以及NVIDIA的RTX技术两方面带大家了解实时光线追踪的实现。


了解DirectX Raytracing API

微软公布的DirectX Raytracing(DXR)API是DirectX 12的自然扩展。它将光线追踪完全集成到DirectX中,并使其能够与光栅化和计算共同发挥作用,而非将其替代。

API概述

与早期版本的DirectX 12相同,DXR API的重点在于通过提供应用程序重要的底层访问控制来提供高性能。其中的一些设计决策就反映了这一点:

  • 所有与光线追踪相关的GPU工作都通过应用程序所规划的命令列表和队列进行调度。因此,光线跟踪与其他工作(如光栅化或计算)紧密结合,且可通过多线程应用程序高效地进入队列。
  • 光线追踪着色器以工作项目网格的形式进行调度,与计算着色器类似。这样就让这一工具能够利用GPU的大规模并行处理吞吐量,并根据给定的硬件相应地执行低层工作项的调度。
  • 应用程序仍有责任在必要时进行GPU工作与资源的显式同步,与光栅化和计算一样。这使开发者能够对光线追踪、光栅化、计算工作和内存传输之间的最大重叠进行优化。
  • 光线追踪和其他调度类型共享所有资源,例如纹理、缓冲区和常量。从光线追踪着色器访问资源时无需进行转换、重复或映射。
  • 保存光线追踪特定数据的资源完全由应用程序管理,如加速结构和着色器表(请参阅下文)。不存在隐形的“幕后”内存分配或传输。
  • Shader编译为显式,因此可以完全在应用程序控制下进行编译。着色器可被单独编译或批量编译。如有需要,编译可以跨多个CPU线程并行开展。

DXR为DirectX引入了三个新概念,这也是应用程序必须管理的:

  1. 光线跟踪管线状态对象包含在光线追踪调度期间执行的编译后的着色器代码。
  2. 加速结构包含用于加速光线追踪本身的数据结构,即搜索光线与场景几何体之间的交点。
  3. 着色器表定义了光线追踪着色器与其资源(纹理、常量等)、以及场景几何体之间的关系。


光线追踪管线

传统的光栅图形管线定义了许多着色器类型:顶点着色器(vertex shader)、几何着色器(geometry shader)、像素着色器(pixel shader)等。与其类似,光线追踪管线也包括五类新的着色器,它们在不同的阶段发挥作用:

  • Ray generation着色器是光线追踪调度中最先调用的。Ray generation着色器与计算着色器相比,新增了调用全新HLSL函数TraceRay()的功能,该功能可将单一光线投射到场景中,搜索交点,触发进程中的其它着色器。Ray generation着色器可以多次调用TraceRay()
  • TraceRay()在光线和场景之间找到潜在交点时,会调用Intersectionany hit着色器。Intersection着色器会确定光线是否与单一的几何图元相交 - 例如球体、细分曲面、或任何你能编写的基本图元类型!当然,最常见的类型是三角形,API会通过高度调优的内置intersaction着色器为其提供特别的支持。一旦找到交点,就可能会采用any hit着色器来进一步处理,也可能放弃。Any hit着色器通常都会通过执行纹理查找来进行alpha测试,并根据texel的值来决定是否放弃这一交点。
  • TraceRay()完成对光线场景交点的搜索,就会根据搜索结果调用closest hitmiss着色器。大多数着色都是通过closest hit着色器进行的,包括材质评估、纹理查找等。Miss着色器可用于进行环境查找等。closest hit和miss着色器都可以通过调用TraceRay()本身来递归地进行光线追踪。

由这些着色器构建的管线定义了单一光线编程模型。在语义上,每个GPU线程一次处理一条光线,且无法与其他线程通信或查看当前正被处理的其他光线。这能够简化开发者的工作,同时让特定供应商能够围绕API进行优化。

不同着色器类型相互通信的主要方式是ray payloadray payload只是一个用户定义的结构,作为inout参数传递给TraceRay()。Any hit、closest hit和miss着色器都能够读取并写入ray payload,进而将其计算结果传回给TraceRay()的调用者。

示例

为了更清楚地解释上述着色器,让我们来看一些简单的示例:

追踪主要光线的基础ray generation着色器

       // An example payload struct. We can define and use as many different ones as we like. struct Payload {     float4 color;     float  hitDistance; };  // The acceleration structure we'll trace against. // This represents the geometry of our scene. RaytracingAccelerationStructure scene : register(t5);  [shader("raygeneration")] void RayGenMain() {     // Get the location within the dispatched 2D grid of work items     // (often maps to pixels, so this could represent a pixel coordinate).     uint2 launchIndex = DispatchRaysIndex();      // Define a ray, consisting of origin, direction, and the t-interval     // we're interested in.     RayDesc ray;     ray.Origin = SceneConstants.cameraPosition.     ray.Direction = computeRayDirection( launchIndex ); // assume this function exists     ray.TMin = 0;     ray.TMax = 100000;      Payload payload;      // Trace the ray using the payload type we've defined.     // Shaders that are triggered by this must operate on the same payload type.     TraceRay( scene, 0 /*flags*/, 0xFF /*mask*/, 0 /*hit group offset*/,               1 /*hit group index multiplier*/, 0 /*miss shader index*/, ray, payload );      outputTexture[launchIndex.xy] = payload.color; }      

以上代码显示了被追踪的主要光线的简单情况,即光线从虚拟相机发送到场景中。当然,ray generation着色器决不局限于此。将ray generation基于光栅化g-buffer数据(例如追踪反射)是另一种常见用例。这通常成本较低,因为许多引擎总会生成一个g-buffer。这也是光线追踪如何与光栅化互补、而非替代它的一个很好的例子。

Closest hit着色器将重心可视化

       // Attributes contain hit information and are filled in by the intersection shader. // For the built-in triangle intersection shader, the attributes always consist of // the barycentric coordinates of the hit point. struct Attributes {     float2 barys; };  [shader("closesthit")] void ClosestHitMain( inout Payload payload, in Attributes attr ) {     // Read the intersection attributes and write a result into the payload.     payload.color = float4( attr.barys.x, attr.barys.y,                             1 - attr.barys.x - attr.barys.y, 1 );      // Demonstrate one of the new HLSL intrinsics: query distance along current ray     payload.hitDistance = RayTCurrent(); }      

状态对象

当使用传统的光栅化时,只要求正绘制的当前对象所需的着色器在GPU上处于工作状态。因此,光栅化管线对象相对较小,包含单一组的顶点着色器、像素着色器等。与光线追踪相比,这是一个很重要的区别,因为我们有权随意将光线射入场景,这意味着它们可以照射到任何对象!因此,用于可能被光线照射到的所有对象的所有着色器都必须位于GPU上并做好执行准备。

DXR中,将着色器组合在一起执行的机制就是状态对象(state objects)。在应用程序层面,光线追踪管线状态对象可以被视为二进制可执行文件,其源自为场景编译的所有着色器的链接步骤。在创建状态对象时就指定了不同着色器之间的关系。例如,intersection、any hit和closest hit三个着色器都被捆绑到了hit组中。应用程序会在从命令列表中调用DispatchRays()时指定将要被执行的管线状态对象。应用程序可以创建任意数量的管线状态对象,并且还可以重新使用预编译着色器来实现。

加速结构

光线追踪需要空间搜索数据结构来有效地计算光线与场景中几何体的交点。应用程序使用新的命令列表方法BuildRaytracingAccelerationStructure()来显式构建这些数据结构。NVIDIA RTX包含精心优化的构建算法,能够以极快的速度产出高质量的结果,从而能够实时构建并更新这些结构。应用程序可进一步优化不同类型内容的加速结构,如静态与动画。

场景中的所有几何体都由两层加速结构来表示。底层加速结构由几何图元构建而成,例如三角形。这些构建的输入图元通过一个或多个几何描述符来指定。几何描述符包括一个顶点和一个索引缓冲区,使得其粒度与光栅化中的一个draw call大致相当。

顶层加速结构是基于对底层结构的引用而构建的。我们称这些引用为实例描述符(instance descriptor)。每个实例描述符还包括一个转换矩阵以将其定位到场景中,以及相对于着色器表的偏移量以查找材料信息(请参见下文)。请注意,在我们之前的ray generation着色器示例中,TraceRay()的“场景”参数是顶层加速结构 - 它表示交点搜索的“入口点”。

由顶层和底层定义的双层结构可实现高效的刚体动画和实例化。顶层加速结构通常足够小,能够以非常低的成本构建。

着色器表

我们已经探讨了光线追踪管线——指定存在于场景中的着色器,以及加速结构——指定几何体。着色器表是将两者联系在一起的数据结构。换句话说,它定义了哪个着色器与场景中的哪个对象相关联。此外,它还包含有关每个着色器所访问资源的信息,例如纹理、缓冲区和常量。

在应用程序层面,着色器表只是由应用程序全权管理的一大块GPU内存。应用程序负责分配资源,填充有效数据,将其传输到GPU,并正确地将其与光线追踪调度同步,就像任何其他GPU内存资源一样。应用程序也可以自由地维护多个着色器表,例如对其进行多缓冲,对一个进行更新,同时用另一个进行渲染。

布局

着色器表是一批大小一致的记录。每条记录都将着色器(或hit组)与一组资源相关联。通常场景中每个几何对象都有一条记录,所以着色器表通常有数千条目。

一条记录以一个不透明的着色器标识符开始,应用程序通过从已编译的着色器进行查询以获取该标识符。其后包含着色器资源的根表(root table),其布局由着色器的本地根签名(local root signature)定义。一如既往地,根签名可以包含常量、描述符表和根描述符的任意组合。然而,使用光线追踪,应用程序可直接访问根表内存(而不是使用“setter”方法),从而实现非常高效的更新。由于它只是“内存”,所以甚至可以通过GPU着色器来更新着色器表!

索引

还记得我们在从实例描述符构建顶层加速结构时,探讨了着色器表偏移量?现在就开始明白了吧,只要TraceRay()找到交点,系统就会使用这些偏移量来定位正确的着色器表记录。然后,它可以绑定记录中定义的资源,并为相交的几何体执行合适的intersection、any hit或closest hit着色器。

通过以上内容带大家快速了解了一下DirectX Raytracing API。在这里,我们讲到的只是冰山一角。您还可以阅读Microsoft关于DXR的博客文章,浏览更多的示例代码,更深入地探索微软的API。或者在微软的DXR开发者支持论坛上寻找答案。有关NVIDIA RTX光线追踪技术的更多信息,请参阅NVIDIA GameWorks 光线追踪页面


开发准备指南

为着手开发由RTX加速的DirectX Raytracing应用,您需要具备:

  • NVIDIA Volta GPU
  • NVIDIA驱动程序396或更高版本
  • Windows 10 RS4
  • 微软DXR开发包,包括支持DXR的D3D运行时、HLSL编译器和标头

为完成设置,我们还推荐采用NVIDIA NSight Graphics,这也是与RTX技术一同发布的,并具有一流的DXR支持。

请注意,DXR是Windows 10 RS4的DirectX实验性功能,仅针对开发者。这意味着必须在Windows中启用开发者模式才能运行DXR应用程序。(设置→更新与安全→面向开发者)。

探寻未来之路

DXR是推进光线追踪广为采用的关键一步。将这一功能融入DirectX将使更多的开发者能够尝试采用以前为高端内容创建应用程序所用的技术。如今,DXR仍然是面向开发者的功能,但随着更多图形编程人员尝试采用光线追踪,DXR成为主流的可能性也将会增加。包括Epic、Remedy和Electronic Arts在内的公司已经开始尝试在其游戏引擎中添加实时光线追踪功能。

查看NVIDIA在Github上的DXR教程,其中包括示例代码和完整文档。您还可以使用NVIDIA的渲染原型框架Falcor(更新即将推出)对DXR展开探索。想要采用NVIDIA RTX和DXR进行开发的开发者可直接向NVIDIA垂询更多信息




  

相关话题

  如何评价英伟达(NVIDIA)官方正式宣布将以 400 亿美元收购安谋(ARM)? 
  为什么游戏机采用A卡在PC上优化反而不如N卡? 
  为什么《轩辕剑七》试玩版的画面看起来缺乏立体感? 
  英伟达 (NVIDIA) 创始人黄仁勋是一个什么样的人? 
  如何看待 NVIDIA 470.05 版本驱动疑似解除限制 RTX 3060 挖矿? 
  如何评价英伟达CUDA平台将不再支持Mac OS?如今CUDA与METAL相比各自有什么优势与劣势? 
  卖掉首发的 RTX 3070 有望不添钱换 3080 Ti 吗? 
  如何评价NVIDIA RTX 4090 显卡? 
  如何评价 NVIDIA 发布的 DGX-1? 
  如何评价摩尔线程发布基于 MUSA 统一系统架构发布的 GPU? 

前一个讨论
游戏里有哪些神奇的操作是被意外发现的?
下一个讨论
如何评价日剧《unnatural》第十集?





© 2025-04-10 - tinynew.org. All Rights Reserved.
© 2025-04-10 - tinynew.org. 保留所有权利