我有以下图像:
我使用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是不够的。
答案 0 :(得分:4)
您有2个数组。第一个数组包含二维顶点坐标,第二个数组包含索引。
您必须使用glDrawElements
来绘制第二个数组中包含的三角形图元。索引指的是第一数组对应的顶点坐标。
首先,您需要为顶点坐标创建一个浮点缓冲区,并为索引创建一个积分缓冲区。最简单的方法是使用NumPy将嵌套列表或数组转换为数组缓冲区。
假设您有一个vertices
数组,其格式为 [[x0,y0],[x1,y1],[x2,y2],...] 和以{em> [[a0,b0,c0],[a1,b1,c1],[a2,b2,c2],...] 形式的indices
数组,然后缓冲区可以这样创建:
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)
如果有着色器程序,则必须添加纹理坐标属性:
例如
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 )。