如何使用 glDrawArrays 和 glVertexPointer?

Posted

技术标签:

【中文标题】如何使用 glDrawArrays 和 glVertexPointer?【英文标题】:How to work with glDrawArrays and glVertexPointer? 【发布时间】:2019-05-21 22:18:06 【问题描述】:

我需要将我的程序从glVertex 重新编写为glDrawArrays,并且我正在尝试使用这些功能进行整理。你能解释一下为什么这段代码不起作用以及如何改变它,所以它绘制了 2 个三角形吗?

import pyglet
import pyglet.gl as pgl


win = pyglet.window.Window(1300, 1000, resizable=True)



@win.event
def on_draw():

    array = [100, 100, 0,
             500, 300, 0,
             900, 100, 0,
             100, 300, 0,
             500, 500, 0,
             900, 300, 0]


    pgl.glClearColor(0.3, 0.3, 0.3, 0.0)
    pgl.glEnableClientState(pgl.GL_VERTEX_ARRAY)
    pgl.glVertexPointer(3, pgl.GL_FLOAT, 18, (pgl.GLubyte * len(array))(*array))

    pgl.glDrawArrays(pgl.GL_TRIANGLES, 0,18)
    pgl.glDisableClientState(pgl.GL_VERTEX_ARRAY)



pyglet.app.run()

【问题讨论】:

【参考方案1】:

缓冲区中的数据类型必须与glVertexPointer定义顶点数据数组时指定的类型相对应。 由于集合类型为GL_FLOAT,因此数组数据的类型必须为GLfloat

data = (pgl.GLfloat * len(array))(*array)

glVertexPointer(和类似函数)的第三个参数(stride)指定连续属性之间的字节偏移量。 由于每个顶点由 3 个分量 (x, y, z) 组成,并且一个分量的大小为 GLfloat 的大小,因此 stride 必须为 3*4 = 12。 由于缓冲区是紧密打包的,stride 也可以设置为 0。这是glVertexPointer(和类似功能)提供的特殊情况。如果stride设置为0,则由sizetype参数自动计算。

pgl.glVertexPointer(3, pgl.GL_FLOAT, 0, data)

最终代码:

import pyglet
import pyglet.gl as pgl

win = pyglet.window.Window(1300, 1000, resizable=True)

@win.event
def on_draw():

    array = [100, 100, 0,
             500, 300, 0,
             900, 100, 0,
             100, 300, 0,
             500, 500, 0,
             900, 300, 0]


    pgl.glClearColor(0.3, 0.3, 0.3, 0.0)
    pgl.glEnableClientState(pgl.GL_VERTEX_ARRAY)
    data = (pgl.GLfloat * len(array))(*array)
    pgl.glVertexPointer(3, pgl.GL_FLOAT, 0, data)

    pgl.glDrawArrays(pgl.GL_TRIANGLES, 0, 18)
    pgl.glDisableClientState(pgl.GL_VERTEX_ARRAY)

pyglet.app.run()

【讨论】:

如果我想输入顶点的数组坐标 (x,y,z)、法线坐标 (x1,y1,z1) 和纹理坐标 (x2,y2,z2)参数步幅为 9? @PopeyeTheSailor 否,如果类型为GLfloat,则步幅为 9*4 = 36。对于法线向量,您必须为数据指针添加 3*4 = 12 的偏移量,并且到纹理坐标的偏移量为 6*4=24。

以上是关于如何使用 glDrawArrays 和 glVertexPointer?的主要内容,如果未能解决你的问题,请参考以下文章

我应该使用几个 glDrawArrays() 还是将所有顶点收集到一个大 glDrawArrays 调用?

PyOpenGL - 最小 glDrawArrays 示例

不同形状的OpenGL glDrawArrays

glDrawArrays 导致内存不足

通过 gldrawarrays 和 GL_POINTS 溺水时得到带有白色边框的点

尝试在 C++ 中使用 glDrawArrays 时出错