我被这项任务卡住了,不知道如何解决。我需要绘制带有纹理的图块网格,我的世界代表一个图块网格,其中每个图块的宽度和高度均等于1。绘制时,我计算了一个顶点缓冲区,其中包含可在相机看到的图块的顶点,例如屏幕上:
(所以我所有这些顶点都有一个VBO)
另外,我有一个包含索引的元素缓冲区,并使用GL_TRIANGLE_STRIP模式绘制它们:
实际结果:
在这一步上,一切工作都很好,但是接下来,我需要在每个正方形上映射他从网络收到的纹理,所有纹理都不同。我该怎么办?我正在使用 OpenGL ES 2.0 和C++。
最佳答案
好吧,如果其他问答对它的解释不够好,让我尝试一下。
问题确实在于您正在使用triangle strip。三角带有很多用途,最重要的原因是减少用于存储顶点的数据量:
The primary reason to use triangle strips is to reduce the amount of data needed to create a series of triangles. The number of vertices stored in memory is reduced from 3N to N+2, where N is the number of triangles to be drawn.
(Wikipedia)
只需简单地重用先前三角形中的数据,三角形带即可实现这一神奇的性能。它从上一个三角形获取两个顶点,并从另一个三角形获取一个顶点,这使您可以在该组点上形成一个新的三角形。如果所有顶点都形成一个连续的表面,并且每个顶点作为第一个三角形的一部分和下一个三角形的一部分,则每个顶点都有意义。
例如对于一系列顶点:
0: (0,0)
1: (0,1)
2: (1,0)
3: (1,1)
我们最终以1---3
|\ |
| \ |
| \|
0---2
因此,确实,三角形是由索引(0,1,2)和(1,2,3)形成的。即使我们添加纹理,它仍然有效。假设纹理与四个图块一样大,我们可能会得到:
0: (0,0) (0 , 0)
1: (0,1) (0 , 0.5)
2: (1,0) (0.5, 0)
3: (1,1) (0.5, 0.5)
4: (2,0) (1 , 0)
5: (2,1) (1 , 0.5)
结果:1---3---5
|\ |\ |
| \ | \ |
| \| \|
0---2---4
要观察的关键顶点是2和3。对于顶点2,纹理坐标为(0.5,0),该坐标同时是第二个三角形的右边缘和第三个三角形的左边缘。这个顶点自然在位置和纹理上都属于它们。现在,考虑一个瓦片 map ,其中每个正方形可以是一个不同的瓦片。通常,这可以通过带有方形瓷砖的纹理图集来实现,每种类型的瓷砖仅以不同的偏移量存储。
因此,第一对三角形的纹理坐标可能是相同的,而第二对三角形的纹理坐标可能具有说(+5,+5)的偏移量(假设现在的纹理例如是100x100,因为这样更容易读书)。
那么现在顶点2和3会发生什么呢?它们的纹理坐标不能同时为0.5 和 5。它们只是两个三角形的不同顶点,碰巧在位置上彼此相邻,但在纹理方面完全分开。现在,重用先前顶点的所有属性的三角带成为障碍。
这就是爆炸开始的地方。您不需要单独的三角形,而无需将几何图形绘制为三角形带。您仍然可以在一个drawcall中绘制它们,但是您将不得不承受一些额外的数据重复:
-- triangle 0
0: (0,0) (0 , 0)
1: (0,1) (0 , 0.5)
2: (1,0) (0.5, 0)
-- triangle 1
3: (0,1) (0 , 0.5)
4: (1,0) (0.5, 0)
5: (1,1) (0.5, 0.5)
-- triangle 2
6: (1,0) (5 , 5)
7: (1,1) (5 , 5.5)
8: (2,0) (5.5, 5)
-- triangle 3
9: (1,1) (5 , 5.5)
10: (2,0) (5.5, 5)
11: (2,1) (5.5, 5.5)
这是原始数据,但我知道很难跟踪,因此让我们使用索引并再次查看。假设位置保持不变(0-5),第一个三角形的纹理坐标为t0
到t3
,第二个三角形的纹理坐标为u0
到u3
。现在:0: 0 t0
1: 1 t1
2: 2 t2
3: 1 t1
4: 2 t2
5: 3 t3
6: 2 u0
7: 3 u1
8: 4 u2
9: 3 u1
10: 4 u2
11: 5 u3
!现在,发现关键的区别要容易一些:位置2
与第一个三角形的texcoord t2
结合出现,但在第二个三角形中与位置u0
结合出现。同样,位置3
分别与t3
和u1
交互。这是因为顶点2是第一个三角形的第三个顶点,但是第二个三角形的第一个顶点,依此类推。就是这样!现在,您只需要编写代码来生成这样的布局,就可以随意设置VBO(请记住,位置的顶点属性可能与图块的VBO完全不同,而无需重写即可更新图块内容瓷砖本身),您就完成了。
请记住,正如我之前提到的,所有这些仍然在一次调用中绘制。整个VBO由GPU尽可能快地进行线性处理,这将导致非常好的性能,考虑到我们正在处理的数据类型和内存大小,略高的内存使用量可以忽略不计。当今的典型GPU。
我有几句话是后记。
关于c++ - 纹理映射到瓷砖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59858065/