光线追踪应该算是终极显卡杀手了,尽管拥有高端的画质,但是对性能的要求实时渲染的领域始终是望而生畏。不过,很多全局光照的算法都是基于光线追踪的基础上简化而来的,了解光线追踪还是有必要的。
1.光线的描述:
r(t) = o + t d,o是起点,d是单位方向向量,t是时间也可以说是变量,r(t)就是射线。
2.光线和物体求交:
光线和物体的交点,就是这根光线的可见点。如果物体的表面由隐函数F(x, y, z)=0表示,这个F是个通用的符号,例如如果物体是个球,则:
x2 + y2 +z2- r2 = 0,代入x,y,z的值
(Ox+t*dx)2+(Oy+t*dy)2+ (Oz+t*dz)2 - r2 = 0,求出t值,找出近交点。这种求交方式如果不进行处理,每一根光线都得跟场景中所以物体进行就交,这样就没法玩了。
3.场景结果优化:
4.光的分布:光关于对倾斜面的cosine衰减和距离平方的反比衰减,这个是点光源的。
5.可见性:判断光是否被遮挡了,在光与点之间建立一条射线,对所有物体进行碰撞。如果,有碰撞判断碰到的点与光源,那个离渲染点近。
6.镜面反射:镜面反射的是物体也不是光源,要做到这种效果,就必须在渲染点上向多个方向发出射线,而不是仅仅往光源的方向发出射线。
7.传播介质:由于介质也会对光造成一定的影响,甚至是改变光的方向,例如大气散射之类的。
总结:光线追踪的原理是比较简单的,但是在运用上算法的效率不具备收敛性,这是它很难适应市场的主要原因。动不动为了求交就来个全场景遍历,即便是增加了场景管理等优化措施也是很消耗的,再者为此增加了场景管理的负担。可见,光线追踪就是一个华丽的负担。
尽管如此,却依旧可以尝试,简化,把算法简化到效率和效果都可接受的范围,谁如果能够在效果上找到折中的点,谁就是赢家。
目前光线追踪比较成熟的技术还是在CPU端实现的,因为这个设计到使用包围盒之类的东西简化计算的问题,当然空间划分也是其中一部分。
2.基于KD-Tree的场景空间划分:
光线跟踪渲染的主要运算操作耗费在光线与场景求交的过程中,而对空间的划分可以防止不必要的遍历,从而减少浪费。当前主要使用的空间划分技术有基于空间划分的均匀网格,八叉树,KD-Tree等,效果较理想的是KD-Tree。
KD-Tree的优点:
1.KD-Tree是一种特殊的BSP树,它将BSP划分中的任意分割平面退化为轴对齐的分割平面,这样就降低了BSP生成时的几何体元分割操作。但是它却同样具有BSP树的优良特征,即一定程度上的启发式空间划分,这样可以使得到的最终划分二叉树尽可能地平衡,这样就降低了最坏情况下的光线与划分结构之间的求交次数,进而提升的效率。
2.由于KD-Tree是一种二叉树,因此在遍历的时间就要比八叉树等非二叉树的划分结构更简单,这也推广了它的使用范围。
3.最后,很重要的一点是由于二叉树遍历的简易性可以使它们比较容易移植于不支持堆栈递归结构的GPU之中。
KD-Tree的创建:
KD-Tree的创建过程是一个自顶向下的递归过程,从根结点开始执行向下的空间划分,空间划分过程中最主的操作就是对分割平面的选取。分割平面是轴对齐的,然后在此基础上对分割面进行定位,定位的基本原则是得到的tree尽量平衡,也就是分割面两边的几何体元(三角形)最好一样多。
针对于分割时,分割面可能与三角形体元有三种关系:与分割面相交,在分割面左边,在分割面右边。分割面相交时可以选择对体元进行分割,也可以把其算做某一边,一般选择后面这种处理方式来简化计算。
在确定分割平面位置的时候,使用体元的AABB包围盒在分割平面法向量上的位置来作为分割平面的潜在位置。这样的好处是分割面潜在位置被确定,接下来只需要选择最优的潜在位置即可。
创建KD树主要的工作是确定分割面,在分割面的选取上,是直接把体元在分割面法向量上的位置作为潜在位置。这里需要注意的是,每一个AABB包围盒会确定两个潜在点。
叶子节点的确定,有两种方式,一种是当节点里面的体元数到达一定数量的时候,确定为叶子节点。一种方式是分割的层次到达一定的程度后,确定为叶子节点。
细节优化:1.在创建KD-tree的时候,前面几个级别使用均匀分割,因为体元多使用精确的分割会占用大量计算的时间。当体元数量达到一定数值的时候,使用精确分割来减少tree的不均匀。2.将KD-Tree信息、场景原始几何数据,分别归类存放于不同纹理之中,通过纹理参照在需要进行同类型数据的访问。这样一方面可以利用纹理提供的虚拟cache提高数据访问时的效率,另一方面相关数据的打包存放又减少了相同数据的重复访问次数,减少了访问的延时。
KD-Tree的遍历:
在CPU中tree的深度遍历可以用堆栈进行很好的解决,但是GPU中无堆栈。在遍历的时候,需要解决两个问题,一个是子遍历完要回到父,另一个就是对遍历过的子要设置一个已遍历的状态来进行描述。
总结:光线追踪就两个重点,一个是场景的管理,另一个是求交和光照计算。光线追踪算法本身并不复杂,只是效率不高而已。其中,使用KD之类的场景管理,嵌入到GPU时并不是太容易,需要使用更通用计算的API来实现,DX11是不行的。
相关推荐
酸射线示踪剂实时光线追踪渲染器 这是一个实时光线追踪渲染器; 设计用于 Oculus Rift 的概念验证。自 SDK 0.6.0 起,不再维护此项目。特征: 三角形网格的 OpenCL 光线追踪器。 简单的朗伯材质...(即将推出纹理...
Foveated实时光线追踪在 DirectX 光线追踪器的开发过程中,计算复杂度被认为对于目标系统规范来说太高了。 因此,注视点——过去曾被用于提高光栅化性能——被认为适用于优化性能而不损害感知场景质量的目的。 使用 ...
--- ****UNDER CONSTRUCTION**** ---
现在 返回 rttexturesamplergetglimageid rtbuffergetglboid 和 成功 的 RT _ RT _ INVALID _ VALUE ( 在 除了 设置 该 ID 为 0 来 输出 ) ) 当 被 非 GL 缓冲器 / 采样器 。 最终用户 许可 协议 ( EULA ) 提醒 ...
迷你RT 我的第一个光线追踪
请参阅文档: : 简短的我的项目包含一个光线追踪脱机渲染器。 这是我上交的,但是我将其扩展到路径跟踪之类的功能。 使用部分后面列出了有关我想做的其他事情的完整列表。 我的raytracer功能包括: 球面射线相交平面...
迷你RT 我的第一个光线追踪项目
RTXplay 一个用于体验NVIDIA实时光线追踪概念的实验室。 该实验室打算将RTOW提供的光线跟踪器迁移到OptiX光线跟踪引擎,从而利用Turing微体系结构引入的新RT核。建造由于缺乏适当的硬件开发,测试已分别在Windows和...
参考: [1]“一种用于光线追踪的快速体素遍历算法” J. Amanatides 和 A. Woo。 欧洲图形学, 87(3), 1987 [2] 该算法的其他实现可从 Web 获得: - ...
一维水平层状介质中直达波的射线追踪。 更多详情请参考https://github.com/TcheL/RT1D
光线追踪C# demo(raytracing in one week && raytracing in the next week)
matlab求导代码光线追踪实施说明 此存储库包含IONORT-IONV在意大利开发的IONOsphere射线追踪。 我已经使用VSCode上的“ Comment Translate”插件将代码注释从意大利语翻译为英语。 我还提供了用于理解该存储库中所...
光线追踪器用C ++实现的光线跟踪器。 它遍历由基于Lua的DSL描述的场景文件。 这是为滑铁卢大学CS 488课程的一个项目编写的。 检查该以查看使用光线跟踪器渲染的某些图像!建造与使用在src目录中运行make来编译程序。...
在本文中,我们通过测量验证的光线追踪(RT)仿真对5 GHz频段的受阻车辆到车辆(V2V)通道进行建模。 首先,我们通过集成三个关键通道功能来建立一个逼真的V2V RT仿真器:小规模结构(例如路灯柱,交通标志),由其...
用 C++ 编写的完全可定制和可配置的全局照明光线追踪器。 H-RT 是一个研究项目,旨在比较流行和不太流行的光反射模型。 您可以在(Mercurial 存储库)获取 H-RayTracer 的源代码:https://bitbucket.org/bayger/hrt