我现在一直在研究游戏引擎中地形系统的不同方法,试图熟悉这项工作。许多细节看起来很简单,但我对一个细节感到困惑。
出于性能原因,许多地形解决方案利用着色器生成部分或全部几何体,例如顶点着色器以生成LoD的位置或曲面细分着色器。起初我认为这些方法专门用于不关心物理模拟的渲染。
我之所以这么说是因为我理解了着色器,因此着色器计算的结果通常在帧结束时被丢弃。因此,如果您严重依赖着色器,那么几何信息将在您访问之前消失并将其发送到另一个系统(例如在CPU上运行的物理)。
所以,我对着色器有误吗?您可以存储它们的结果,生成要由其他系统访问的几何体吗?或者我是否被迫将地形几何保留在CPU上并将着色器留给其他细节?
答案 0 :(得分:2)
您了解着色器的部分是正确的,即:在一帧之后,数据将作为最终合成图像存储在后备缓冲区中。
BUT:使用变换反馈,可以将变换后的几何体捕获到顶点缓冲区并重复使用。变换反馈在顶点/几何/细化着色器之后发生,因此您可以使用几何着色器生成地形(或其可见部分一次),将其推送到变换反馈并存储它。 这样,您可以在地形上使用CPU碰撞检测!你甚至可以将它与tesselation结合起来。
你会喜欢这个:http://andrew-flower.com/assets/projects/defter-thesis-f9a659feea18ffe347b24e3bbfc054d8.pdf
对于LOD和Tesselation:LOD不是Tesselation的先决条件。您可以使用Tesselation允许一些更复杂的效果,通过递归细分粗糙几何来添加细节。将它与LOD链接只是一个非常好的优化,避免了基于RAM内存的LOD网格级别,因为你只需要你的“基础网格”并细分它(虽然这将是一个不令人满意的优化imho)。
现在有关GPU和CPU专有地形的更深入信息。
如NVidia文章中所述 - (https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch01.html):
1.2 Marching Cubes和密度函数从概念上讲,地形表面可以用一个函数完整描述,称为 密度函数。对于3D空间中的任何点(x,y,z),该函数 生成单个浮点值。这些值会有所不同 空间 - 有时是积极的,有时是消极的如果值是 积极的,那么太空中的那个点就在坚固的地形内。
如果值为负,则该点位于空白处 (如空气或水)。正面和负面之间的界限 密度值为零的值是地形的表面。 我们希望在这个表面构建一个多边形网格。
使用着色器
用于生成地形的密度函数必须可用于碰撞检测着色器,并且必须填充包含碰撞位置的输出缓冲区(如果有)...
<强> CUDA 强>
请参阅:https://www.youtube.com/watch?v=kYzxf3ugcg0
这里有人使用CUDA,基于NVidia的文章,但是暗示相同: 在CUDA中,执行碰撞检测时,必须共享密度函数。
然而,这将使变换反馈技术难以实现。Shaders和CUDA都暗示至少在一个位置重新采样/重新计算密度,仅用于单个物体的碰撞检测。
通常,这意味着以顶点/索引缓冲区对的形式存储RAM内存的几何体集,这些对象由着色器管道定期处理。由于您拥有此处提供的数据,因此您很可能还有一个碰撞网格,它是您的地形的简化表示,您可以根据该地形执行碰撞。
或者,您可以在地形上使用一组碰撞器,标记允许路径,这是在早期的PS1最终幻想游戏中执行的(实际上并没有真正的地形)我们今天了解地形。)
这个简短的答案既不深入也不完整。我只是想让你深入了解几十种解决方案中使用的一些概念。
更多阅读:http://prideout.net/blog/?tag=opengl-transform-feedback