我应该使用哪个 OpenGL 基元来绘制三角剖分?
Which OpenGL Primitive should I use for draw an triangulation?
我有以下图片:
我能够像下面这样进行三角测量:
我是使用 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 个数组。第一个数组包含二维顶点坐标,第二个数组包含索引。
您必须使用 glDrawElements
来绘制包含在第二个数组中的三角形图元。索引是指第一个数组的相应顶点坐标。
首先,您必须为顶点坐标创建一个浮点缓冲区,为索引创建一个整数缓冲区。最简单的方法是使用 NumPy,将嵌套列表或数组转换为数组缓冲区。
假设您有一个 vertices
的数组,格式为 [[x0, y0], [x1, y1], [x2, y2],...] 和 indices
的数组,格式为 [[a0, b0, c0], [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 来完成。但是随后列表必须 flattened 形式分别为 [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)
关于评论:
[...] I already know how to texture a plane by using glTexCoord2f
then glVertex3f
but didn't figure out how I can do it with a vao.
最简单的方法是创建一个单独的纹理坐标数组。假设您的纹理坐标 texAttr
的形式为 [[u0, v0], [u1, v1], [u2, v2],...]。
生成缓冲区很简单:
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
and enable the client state GL_TEXTURE_COORD_ARRAY
。
注意,客户端状态 GL_VERTEX_ARRAY
和 glVertexPointer
is mapped to the vertex attribute 0. See 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)
关于评论:
I d'like to displace vertex one by one [...]
可以通过glBufferSubData
更改单个顶点坐标,其中第二个参数是顶点坐标的字节偏移量。坐标 i
的偏移量将是 4*2*i
(4 是以字节为单位的浮点数大小,每个坐标由 2 个分量组成 x 和 y)。
我有以下图片:
我能够像下面这样进行三角测量:
我是使用 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 个数组。第一个数组包含二维顶点坐标,第二个数组包含索引。
您必须使用 glDrawElements
来绘制包含在第二个数组中的三角形图元。索引是指第一个数组的相应顶点坐标。
首先,您必须为顶点坐标创建一个浮点缓冲区,为索引创建一个整数缓冲区。最简单的方法是使用 NumPy,将嵌套列表或数组转换为数组缓冲区。
假设您有一个 vertices
的数组,格式为 [[x0, y0], [x1, y1], [x2, y2],...] 和 indices
的数组,格式为 [[a0, b0, c0], [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 来完成。但是随后列表必须 flattened 形式分别为 [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)
关于评论:
[...] I already know how to texture a plane by using
glTexCoord2f
thenglVertex3f
but didn't figure out how I can do it with a vao.
最简单的方法是创建一个单独的纹理坐标数组。假设您的纹理坐标 texAttr
的形式为 [[u0, v0], [u1, v1], [u2, v2],...]。
生成缓冲区很简单:
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
and enable the client state GL_TEXTURE_COORD_ARRAY
。
注意,客户端状态 GL_VERTEX_ARRAY
和 glVertexPointer
is mapped to the vertex attribute 0. See 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)
关于评论:
I d'like to displace vertex one by one [...]
可以通过glBufferSubData
更改单个顶点坐标,其中第二个参数是顶点坐标的字节偏移量。坐标 i
的偏移量将是 4*2*i
(4 是以字节为单位的浮点数大小,每个坐标由 2 个分量组成 x 和 y)。