我对glDraw(数组)(元素)有疑问。问题是,大多数人说由于顶点重用和缓存,元素更有效,但我尝试渲染一个地形,每个顶点具有相同的位置不同的纹理坐标。这会使每个顶点唯一吗?因此,如果我没有任何顶点重用,我应该更喜欢数组,因为它更容易实现并且一次性渲染缓冲区与我需要提供的元素不仅需要提供顶点数据而且还需要提供索引缓冲区? 有没有办法渲染地形,使其能够使用元素?我只是不知道如何正确地纹理地形,也许这就是问题。
我可以想象渲染人物模型对元素很好,因为我可以提供一个纹理文件,而且每个顶点位置不需要更多的tex坐标。但地形应该用数组渲染吗?
我应该何时选择数组和元素?
答案 0 :(得分:3)
对于地形glDrawElements
是可行的方法,假设您有一个简单的2d网格,并在顶点着色器上移位它或将高度作为顶点属性发送。对于这种网格,它比glDrawArrays
快得多。
对于纹理:我不知道你是否想要将一个大的或更多的纹理混合在一起来构造地形,例如简单的草图案,或者随着高度增加而混合到雪中的草。
第一个非常简单:假设你的地形宽度为W,高度为H.你在整个地图上使用一个大纹理。然后一个顶点的纹理坐标为:< / p>
vec2 TexCoord = vec2(VertexPos.x/W,VertexPos.z/H);
对于第二个它改变了一点:
如果你的纹理是一个简单的草 tile ,或者你想覆盖整个地形的任何东西,那么顶点的纹理坐标是:
vec2 TexCoord = vec2(VertexPos.x/XdirectionTileSize,VertexPos.z/ZdirectionTileSize);
XdirectionTileSize
和ZdirectionTileSize
是一种模式的维度。例如,你想在1米* 1米分辨率的地形上获取草纹理,并且你的顶点彼此相距2米,然后将它们设置为0.5(1/2)。
对于更多纹理,您可以定义更多的图块大小,以及一个大的纹理贴图,每种颜色定义一种材质。例如:红色是草,蓝色是雪,绿色是沙子,阿尔法是岩石。然后你像这样混合纹理 :(你可以获取这个大的材质地图就像一个大纹理)
color = materialmap.r*grass + materialmap.b*snow + materialmap.g*sand + materialmap.a*rock;
最后,我最喜欢的地形纹理方法是程序着色器splatting 。我不会在这里写。例如Frostbite Engine(Battlefields)使用它。这是一个非常好的演示文稿的链接:http://dice.se/publications/terrain-rendering-in-frostbite-using-procedural-shader-splatting/。简而言之就像掩盖一样。将高度,法线,斜率渲染为FBO纹理,并在延迟渲染/着色中使用它。
对于质量:如果您的texcoords是在平面上具有顶点位置(.xy,.xz)的着色器中计算的,则它会随着斜率的增加而扭曲纹理。这个问题的解决方案是三平纹理。页面底部:http://http.developer.nvidia.com/GPUGems3/gpugems3_ch01.html。简而言之:它将纹理从3个平面(xz,xy,yz)投射到地形,并将它们与法线混合/混合。
当然你可以混合使用这些纹理方法。我知道它不能直接回答你的问题,但我认为你不应该将纹理坐标作为顶点属性传递。使用大纹理,瓷砖或喷溅来定义它们要容易得多。哦,我希望你使用着色器;)。