创建公司网站用什么软件,做彩票网站代理赚钱吗,网站建设管理员角色设置,营销策划公司名字简单大气目录
Optix v6
基本构成组件
射线与求交
纹理
三角Mesh
Optix v7结构
基本构成组件
管线
着色器绑定表(SBT)
第一个例子
第二个例子 全局光照(GI)有很多种解决方案#xff0c;比如VXGI、Lumen、DDGI、SSGI、IBL、PRT、SurfelsGI等#xff0c;其中#xff0c;越来…目录
Optix v6
基本构成组件
射线与求交
纹理
三角Mesh
Optix v7结构
基本构成组件
管线
着色器绑定表(SBT)
第一个例子
第二个例子 全局光照(GI)有很多种解决方案比如VXGI、Lumen、DDGI、SSGI、IBL、PRT、SurfelsGI等其中越来越火的Nvidia的RTX技术也是软硬件结合的实时光追解决方案。 Optix的缺点是就像D3D或者OpenGL代码比较难以理解。更难的问题在于Optix的资料太少没有多少可以用来参考或者学习的资料尤其是比较通俗的中文资料。笔者在广泛搜集和阅读源码后撰写了Optix v6和Optix v7两个系列文章。其中Optix v6来自于对官方源码结合用户手册的解读Optix v7来自于对一个已有教程的解读。见[Optix v6-v7 - 应用与代码构建]。
Optix v6
基本构成组件
主要的对象模型有
Context用于运行 Optix 引擎的实例。ProgramCUDA 函数编译为 NVIDIA PTX 虚拟汇编语言 (virtual assembly language)。Variables一种变量用于将数据传入 Optix 程序。Buffer绑定到一个变量的多维数组。TextureSamplerBuffer 的插值机制。Geometryray 可以相交的基元比如三角形或者用户自定义类型。Material材质程序当 ray 相交与基元相交时执行。GeometryInstance绑定 Geometry 和 Material。GroupNode一系列安排在层次结构 (hierarchy) 中的对象。TransformNode一个层次节点 (hierarchy node) 用于变换几何和 ray。SelectorNode可编程层次节点用来选择去遍历的子对象。AccelerationStructure绑定到层次节点 (hierarchy node) 的加速结构对象。
组件程序有
Ray generation programs光追管线的入口由每个像素样本或者用户自定义的任务比如一些自定义的特殊算法来调用。Exception programs异常控制。Closest hit programs当 ray 找到最近交点时调用在该程序中执行比如材质着色等程序。Any hit programs当 ray 找到一个新的潜在的最近交点时调用比如对于计算阴影时有用。Intersection programs实现一个 ray 和基元交点测试在 traversal 时调用。Bounding box programs计算基元的世界空间包围盒当构建一个新的加速结构时调用。Miss programs当追踪的光线错过了所有几何结构时调用。Attribute programs当与内置三角形相交时调用用于为任何命中和最近命中的程序提供三角形特定属性。
主机可以对VariablesrtDeclareVariable进行赋值并在GPU设备上访问这些值。
主机上申请BufferrtBuffer然后用于在GPU设备上访问Buffer里的值或者计算并往Buffer里面填充值。
GPU启动渲染需要一个入口程序一般就是光线生成程序我们可以在一个Context里设置多个入口程序并在发射时根据情况选择使用哪个入口程序。
射线与求交
发射启动后如果光线检测到与最近的基元求交得到了交点就会调用该物体绑定的closest-hit程序如果与任意一个物体相交比如在阴影计算时就会调用any-hit程序。如果与任何基元都没有交点就会调用miss程序。
进行光线追踪时一般都是这样调用
rtTrace(top_object, ray, payload);
其中第一个参数表示加速结构最顶层ray就是光线payload就是光线携带的信息比如根据BRDF当前的光衰减量或者光此时反弹的次数等。计算阴影着色时的射线和计算辐射度的射线都用rtTrace(...)来追踪。
每个基元类型都需要绑定一种求交程序内置的三角形可以不用绑定以及设置该基元的包围盒。
然后为每种基元设计closest-hit程序和any-hit程序并且绑定到材质对象中。之后再把材质对象和基元绑定在一起。绑定好的基元和材质叫做几何实例(GeometryInstance)。多个几何实例可以构成一个几何组(GeometryGroup)。
对于射线遍历过程中发现的每个潜在的最近交点都会执行 any-hit program。执行程序的交点可能不会沿着射线相交顺序排序但如果需要最终可以枚举射线与场景的所有交点。不过在计算阴影光线时一般会给采样射线的负载Payload设置一个衰减值当衰减值到0则终止射线的遍历否则就忽略交点
if(optix::luminance(prd_shadow.attenuation) importance_cutoff)rtTerminateRay();
elsertIgnoreIntersection();
纹理
纹理的定
义看着跟CUDA有一些区别但其实基本过程都是一致的只不过Optix 7的函数名跟CUDA都是基本一样的。
纹理需要在.cu文件里用rtTextureSampler声明然后在主机上通过Context创建然后初始化。
纹理并不会和材质绑定在一起因此哪怕是相同的材质类型如果纹理不同也需要分别实现不同的closest-hit程序。
三角Mesh
三角mesh可以自己写求交程序也可以用optix自己内置的程序但是如果我们用内置的程序的话如果额外提供了法向量贴图那么就需要实现attribute程序来计算着色法向量。attribute程序在closest-hit和any-hit程序执行之前执行更新法向量等信息。
注意每个不同的mesh都有自己的indexBuffer以及vertexBuffer自定义求交程序时必须给一个参数primIdx使得程序可以知道是与Buffer里哪个三角形获得了交点。
如果实例化的对象们的材质不同假设总共涉及三种材质那么就需要所有的实例化对象都包含这三种材质并通过函数预先指定我们需要哪种材质。
Optix v7结构
Optix v7的结构就复杂了很多。尤其是引入了着色器绑定表/发射参数等概念。
Optix v6中相机等参数都是使用rtDeclareVariable变量定义的纹理/三角顶点数组等信息也都是通过全局变量来设置比如rtBuffer/rtTextureSampler/rtDeclareVariable。在Optix v7中这些内容都被列入了着色器绑定表里。
基本构成组件
Moudle会包含各种类型的程序Moudle的创建需要两个很重要的参数结构
OptixPipelineCompileOptions
OptixModuleCompileOptions
moudles定义了一些特性这些特性来自于上面两个参数结构设置的属性这些特性相当于给绑定到管线里的progrmas进行一些设置比如第二个参数结构可以设置最大追踪深度/是否用离焦模糊等。用于创建链接到单个管线中的程序组的所有moudles都必须使用相同的第一个参数结构即单个管线里的所有程序最大追踪深度等属性都必须是一样的。同一管线内的模块可能会有不同的第二个参数结构。
因此如果我们想进行二次光线追踪来获得一幅图像且两次光追用不同的管线就需要设置两组管线并且为其配置不同的Moudles。
管线
一个管线里可以有多个采样射线生成程序Raygen可以有多个Miss程序以及多个Hitgroup程序。每个Hitgroup程序都包含了closest-hit和any-hit程序。
着色器绑定表(SBT)
着色器绑定表可以理解为当响应了closest-hit或者any-hit程序以后执行计算时需要访问的数据比如使用哪个纹理/访问顶点数组。其实实际上当物体与射线有交点时去执行哪个closest-hit或者哪个any-hit程序时根据物体绑定的SBT来决定的。
在构建加速结构时每个OptixBuildInput对象比如代表一个球体或者代表一个mesh组都对应一个物体ID。
当我们只有一种发射的射线类型时每个物体绑定的一个SBT该SBT对应一个Hitgroup程序就可以了。如果有两种发射的射线类型而且每个物体都要实现对两种射线类型不同的着色计算那么就需要两种类型的SBT分别绑定两个不同的Hitgroup程序。当此时求交时是第一个SBT那么第一个Hitgroup程序响应当此时求交时是第二个SBT那么第二个Hitgroup程序响应。
sbt.hitgroupRecordBase属性设置了Hitgroup的SBT的地址。用以GPU程序响应求交程序后访问SBT。
当设置有两种采样射线类型且需要访问两种不同的SBT时采样辐射度射线/采样阴影的射线时所有OptixBuildInput对象对应的SBT都应该是两个而不能有的是2个有的是1个否则就会在optixTrace(...)时因为SBT strideoptixTrace(...)是对整个场景的所有加载进去的物体进行光追不一致而导致访问错误。我们再给两个例子加深一下印象。
现在假设有三个closest-hit程序与三个any-hit程序设名字分别为 __closesthit_1__closesthit_2__closesthit_3__anyhit_1__anyhit_2__anyhit_3
hitgroup程序也有3个分别绑定了上面的三组closest-hit和any-hit程序
hitgroup_1
hitgroup_2
hitgroup_3
以上的假设并不会直接用到仅仅是作为一些场景罢了。
第一个例子
假设我们只有一种类型的相机采样射线。
假如我们加载了5个meshes每个mesh都包括不同数量的三角形。
假设初始化了5个hitgroup SBT。因为我们要设置optixTrace(...)的SBT offset为0且SBT stride为1每个mesh绑定的SBT数量都是1个也就是说第一个mesh相当于绑定了第一个hitgroup SBT第二个mesh相当于绑定了第二个hitgroup SBT以此类推。
不同的SBT可以绑定不同的hitgroup程序。
第二个例子
假如我们加载了5个meshes每个mesh都包括不同数量的三角形。
假设初始化了10个hitgroup SBT设为HitgroupRecord[10]。我们希望追踪相机射线或者阴影射线时响应不同的求交程序closest-hit程序与any-hit程序。
我们要设置optixTrace(...)的SBT stride为2每个mesh绑定的SBT数量都是2个也就是说
当optixTrace(...)的SBT offset为0时当相机射线与mesh[0]有交点那么此时响应的Hitgroup SBT就是HitgroupRecord[0]当相机射线与mesh[1]有交点那么此时响应的Hitgroup SBT就是HitgroupRecord[2]当相机射线与mesh[2]有交点那么此时响应的Hitgroup SBT就是HitgroupRecord[3]以此类推。
当optixTrace(...)的SBT offset为1时当相机射线与mesh[0]有交点那么此时响应的Hitgroup SBT就是HitgroupRecord[1]当相机射线与mesh[1]有交点那么此时响应的Hitgroup SBT就是HitgroupRecord[3]当相机射线与mesh[2]有交点那么此时响应的Hitgroup SBT就是HitgroupRecord[5]以此类推。
第一个mesh相当于绑定了第一个和第二个hitgroup SBT第二个mesh相当于绑定了第二个和第四个hitgroup SBT以此类推。根据optixTrace的SBT offset参数来设置meshes应该去响应哪个SBT。