我有以下图片:
我使用python的triangle库做到了。我的三角测量结果存储在一个dict
对象中,如下所示:
>>> triangulation["vertices"]
array([[ 23. , 282. ],
[ 24. , 254. ],
[ 30. , 239. ],
[ 43. , 219. ],
[ 60. , 204. ], ... And so on ...
>>> triangulation["triangles"]
array([[ 89, 106, 105],
[ 99, 35, 86],
[110, 68, 87],
[ 47, 66, 83],
[ 72, 82, 74], ... And so on ...
现在,我想使用OpenGL将此纹理分割为网格。我想知道我应该使用哪种原语?我认为TRIANGLE_STRIP
是正确的解决方案,但它是一个复杂的三角测量,很明显只有一个TRIANGLE_STRIP是不够的。
你有2个阵列。第一个数组包含2维顶点坐标,第二个数组包含索引。
你必须使用glDrawElements
来绘制第二个数组中包含的三角形基元。索引指的是第一个数组的相应顶点坐标。
首先,您要为顶点坐标创建浮点缓冲区,并为索引创建一个积分缓冲区。最简单的方法是使用NumPy将嵌套列表或数组转换为数组缓冲区。
假设你有[[x0,y0],[x1,y1],[x2,y2],......]形式的vertices
数组和[[a0,b0,c0]形式的indices
数组],[a1,b1,c1],[a2,b2,c2],...],然后可以像这样创建缓冲区:
import numpy as np
vertex_array = np.array(vertices, dtype=np.float32)
no_of_indices = len(indices) * 3
index_array = np.array(indices, dtype=np.uint32)
使用ctypes
而不是NumPy可以做到同样的事情。但是这些列表必须分别以[x0,y0,x1,y1,x2,y2,...]的形式展平[a0,b0,c0,a1,b1,c1,a2,b2,c2,.. ]:
vertex_array = (ctypes.c_float * len(flat_vertices))(*flat_vertices)
no_of_indices = len(flat_indices) * 3
index_array = (ctypes.c_uint32 * no_of_indices)(*flat_indices)
创建顶点数组对象。见Vertex Specification:
vao = glGenVertexArrays(1)
glBindVertexArray(vao)
ibo = glGenBuffers(1)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo)
glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_array, GL_STATIC_DRAW)
vbo = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, vbo)
glBufferData(GL_ARRAY_BUFFER, vertex_array, GL_STATIC_DRAW)
glVertexAttribPointer(0, 2, GL_FLOAT, False, 0, None)
glEnableVertexAttribArray(0)
glBindBuffer(GL_ARRAY_BUFFER, 0)
glBindVertexArray(0)
如果要绘制三角形图元,则绑定顶点数组对象并调用glDrawElements
就足够了:
glBindVertexArray(vao)
glDrawElements(GL_TRIANGLES, no_of_indices, GL_UNSIGNED_INT, None)
关于评论:
[...]我已经知道如何使用
glTexCoord2f
然后使用glVertex3f
对飞机进行纹理处理,但是没有弄清楚如何用vao来做到这一点。
最简单的方法是创建一个单独的纹理坐标数组。假设你有[[u0,v0],[u1,v1],[u2,v2],......]形式的纹理坐标texAttr
。生成缓冲区很简单:
texAttr_array = np.array(texAttr, dtype=np.float32)
如果你有一个着色器程序,那么你要添加纹理坐标属性:
EG
layout (location = 0) in vec2 vertex;
layout (location = 1) in vec2 texAttr;
并定义通用顶点属性数据的数组。
vao = glGenVertexArrays(1)
glBindVertexArray(vao)
# [...] index buffer
vbo = glGenBuffers(2)
glBindBuffer(GL_ARRAY_BUFFER, vbo[0])
glBufferData(GL_ARRAY_BUFFER, vertex_array, GL_STATIC_DRAW)
glBindBuffer(GL_ARRAY_BUFFER, vbo[1])
glBufferData(GL_ARRAY_BUFFER, texAttr_array, GL_STATIC_DRAW)
glVertexAttribPointer(0, 2, GL_FLOAT, False, 0, None)
glEnableVertexAttribArray(0)
glVertexAttribPointer(1, 2, GL_FLOAT, False, 0, None)
glEnableVertexAttribArray(1)
glBindBuffer(GL_ARRAY_BUFFER, 0)
glBindVertexArray(0)
如果使用兼容性配置文件和固定功能属性,则需要指定glTexCoordPointer
并启用客户端状态GL_TEXTURE_COORD_ARRAY
。
注意,客户端状态GL_VERTEX_ARRAY
和glVertexPointer
被映射到顶点属性0.请参阅What are the Attribute locations for fixed function pipeline in OpenGL 4.0++ core profile?:
vao = glGenVertexArrays(1)
glBindVertexArray(vao)
# [...] index buffer
vbo = glGenBuffers(2)
glBindBuffer(GL_ARRAY_BUFFER, vbo[0])
glBufferData(GL_ARRAY_BUFFER, vertex_array, GL_STATIC_DRAW)
glBindBuffer(GL_ARRAY_BUFFER, vbo[1])
glBufferData(GL_ARRAY_BUFFER, texAttr_array, GL_STATIC_DRAW)
glVertexPointer(2, GL_FLOAT, 0, None)
glEnableClientState(GL_VERTEX_ARRAY)
glTexCoordPointer(2, GL_FLOAT, 0, None)
glEnableClientState(GL_TEXTURE_COORD_ARRAY)
glBindBuffer(GL_ARRAY_BUFFER, 0)
glBindVertexArray(0)
请注意,如果您不使用着色器,则必须启用二维纹理
glEnable(GL_TEXTURE_2D)
关于评论:
我喜欢逐个取代顶点[...]
单个顶点坐标可以通过glBufferSubData
更改,其中第二个参数是到顶点坐标的字节偏移量。坐标i
的偏移量为4*2*i
(4是浮点数的大小,以字节为单位,每个坐标由2个分量x和y组成)。