OpenGL 索引和数组纹理

Posted

技术标签:

【中文标题】OpenGL 索引和数组纹理【英文标题】:OpenGL Indexed and Array texture 【发布时间】:2013-12-08 08:51:08 【问题描述】:

我有一个关于 glDraw(arrays)(elements) 的问题。问题是,大多数人说元素由于顶点重用和缓存而更有效,但我尝试渲染地形,每个顶点具有相同的位置不同的纹理坐标。这使得每个顶点都是独一无二的,对吧?因此,如果我没有任何顶点重用,我是否应该更喜欢数组,因为与我不仅需要提供顶点数据还需要提供索引缓冲区的元素相比,它更容易实现并一次性渲染缓冲区? 有没有一种方法可以渲染地形以使其能够使用元素?我只是不知道如何正确地纹理地形,也许这就是问题所在。

我可以想象人物的渲染模型使用元素会很好,因为我可以提供一个纹理文件,并且每个顶点位置不需要更多的 tex 坐标。但是地形应该用数组来渲染?

什么时候应该选择数组,什么时候选择元素?

【问题讨论】:

【参考方案1】:

对于地形glDrawElements 是可行的方法,假设您有一个简单的 2d 网格,并且您在顶点着色器上置换它或将高度作为顶点属性发送。对于这种网格,它比glDrawArrays 快​​得多。

对于纹理:我不知道你是想用一个大纹理来纹理地形,还是混合在一起的多个纹理,例如简单的草图案,或者随着高度的增加将草混合到雪中。

第一个非常简单:假设地形的宽度为 W,高度为 H。您在整个地图上使用一个大纹理。然后一个顶点的纹理坐标为:

vec2 TexCoord = vec2(VertexPos.x/W,VertexPos.z/H);

第二次有点变化:

如果你的 texture 是一个简单的草 tile,或者你想覆盖整个地形的任何东西,那么一个顶点的纹理坐标是:

vec2 TexCoord = vec2(VertexPos.x/XdirectionTileSize,VertexPos.z/ZdirectionTileSize);

XdirectionTileSizeZdirectionTileSize 是一种模式的尺寸。例如,您想以 1 米 * 1 米的分辨率在地形上获取草纹理,并且您的顶点彼此相距 2 米,然后将它们设置为 0.5 (1/2)。

对于更多纹理,您可以定义更多平铺尺寸,以及一个大纹理贴图,每种颜色定义一种材质。示例:红色是草,蓝色是雪,绿色是沙子,alpha 是岩石。然后你像这样混合纹理:(你可以获取这个大的材质贴图就像一个大的纹理)

color = materialmap.r*grass + materialmap.b*snow + materialmap.g*sand + materialmap.a*rock;

最后,我最喜欢的地形纹理方法是程序着色器喷射。我不会在这里写。例如 Frostbite Engine (Battlefields) 使用这个。这是一个非常好的演示文稿的链接:Terrain Rendering in Frostbite Using Procedural Shader Splatting。简而言之,这就像掩蔽。将高度、法线、坡度渲染到 FBO 纹理中,并像在延迟渲染/着色中一样使用它。

为了质量:如果您的 texcoords 是在一个顶点位置在平面(.xy、.xz)上的着色器中计算的,它会随着斜率的增加而扭曲纹理。这个问题的解决方案是三平面纹理。页面底部:Generating Complex Procedural Terrains Using the GPU。简而言之:它将纹理从 3 个平面(xz、xy、yz)投影到地形,并将它们与法线混合/混合。

当然,您可以混合使用这些纹理方法。我知道它不能直接回答您的问题,但我认为您不应该将纹理坐标作为顶点属性传递。用大纹理、瓷砖或飞溅来定义它们要容易得多。哦,我希望你使用着色器;)。

【讨论】:

这很有帮助!您间接回答了我的一个大问题,如何使用元素或数组有效地渲染地形。谢谢!

以上是关于OpenGL 索引和数组纹理的主要内容,如果未能解决你的问题,请参考以下文章

通过opengl中的纹理传递数组数据

在OpenGL ES(Android)中使用带纹理的索引缓冲区有什么意义吗?

opengl vbo 纹理

OpenGL纹理操作--glGenTextures

OpenGL纹理操作--glGenTextures

OpenGL - 纹理显示不正确(夹紧?)