opengl 如何使用PyGLM中的数据初始化缓冲区对象的数据存储?

khbbv19g  于 2022-11-23  发布在  其他
关注(0)|答案(2)|浏览(196)

我使用PyGLMPyOpenGL
我在Vertex Shader中指定了以下Shader Storage Buffer

layout(std430, binding = 1) buffer MVP
{
    mat4 u_proj;
    mat4 u_view;
    mat4 u_model;
} mvp_data;

我已经初始化了模型、视图和投影矩阵:

model = glm.mat4(1)
view  = glm.lookAt(glm.vec3(0,-3,0), glm.vec3(0,0,0), glm.vec3(0,0,1))
proj  = glm.perspective(glm.radians(90), self.__vp_size[0]/self.__vp_size[1], 0.1, 100)

如何使用glBufferData(或glNamedBufferData)创建和初始化缓冲区对象的数据存储

ssbo = glGenBuffers( 1 )
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo )
glBufferData(GL_SHADER_STORAGE_BUFFER, 3*16*4, ???, GL_STATIC_DRAW )

分别由glBufferSubData(或glNamedBufferSubData)初始化

ssbo = glGenBuffers( 1 )
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo )
glBufferData(GL_SHADER_STORAGE_BUFFER, 3*16*4, None, GL_STATIC_DRAW )
glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, ???, ???);

由于SSBO包含3个(紧密封装)mat4,因此缓冲区的大小为3 * 16 * 4(3个4x4矩阵,元素数据类型为float)。
因此,缓冲区的初始化可以通过NumPy数组来完成。
但是如何将PyGLM矩阵有效地分配给NumPy数组呢?

buffer_data = numpy.zeros(3*16, dtype=numpy.float32)

??? buffer_data = model, view, proj

glBufferData(GL_SHADER_STORAGE_BUFFER, buffer_data.nbytes, buffer_data, GL_STATIC_DRAW)

或者有没有一个更有效的解决方案,而不复制数据到一个NumPy数组?

pw136qt2

pw136qt21#

最后我自己找到了解决办法。
应当注意,Shader Storage Buffer由344=48个紧密封装的浮点数组成。
PyGlm提供了方便的函数glm.value_ptrglm.sizeofglm.value_ptr对应于glm::value_ptrglm.sizeof的工作方式与 glm 数据类型的c++ sizeof operator类似。
此函数可与PyOpenGLglBufferSubData Package 一起使用,以更新缓冲区数据:

glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0,                      glm.sizeof(glm.mat4), glm.value_ptr(model))
glBufferSubData(GL_SHADER_STORAGE_BUFFER, 1*glm.sizeof(glm.mat4), glm.sizeof(glm.mat4), glm.value_ptr(view))
glBufferSubData(GL_SHADER_STORAGE_BUFFER, 2*glm.sizeof(glm.mat4), glm.sizeof(glm.mat4), glm.value_ptr(proj))

一个glm.mat4类型的对象可以被赋值给numpy.array,其形状为(4, 4),类型为np.float32。因此,3个矩阵可以被赋值给numpy.array的元素,其形状为(3, 4, 4)

buffer_data = np.empty([3, 4, 4], dtype=np.float32)
buffer_data[0] = model
buffer_data[1] = view
buffer_data[2] = proj

此数组可用于一次更新整个缓冲区数据:

buffer_size = buffer_data.size * buffer_data.itemsize
glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, buffer_size, buffer_data)

或者,对于缓冲区对象的数据存储的初始glBufferData创建和初始化:

glBufferData(GL_SHADER_STORAGE_BUFFER, buffer_data, GL_DYNAMIC_DRAW)

从PyGLM 2.0.0版开始,有一种更简单的方法来解决这个问题。请参见Using Arrays
PyGLM的数组类型是在2.0.0版本中引入的,以减少要求用户在glm之外还使用numpy的可能性。它主要是为了提供一种将多个glm类型示例(如vectors)传递给外部C函数(如glBufferData)的方法。

buffer_data = glm.array(model, view, proj)
glBufferData(GL_SHADER_STORAGE_BUFFER, buffer_data.nbytes, buffer_data.ptr, GL_STATIC_DRAW)
ws51t4hk

ws51t4hk2#

有一种方法可以一次更新所有数据,而完全不需要使用numpy。
在PyGLM文档中,它表示(https://github.com/Zuzu-Typ/PyGLM/wiki/Using-arrays):
PyGLM的数组类型是在2.0.0版本中引入的,以减少要求用户在glm之外还使用numpy的可能性。它主要是为了提供一种将多个glm类型示例(如vectors)传递给外部C函数(如glBufferData)的方法。
你可以做的就是用glm.数组 Package 矩阵,如下所示:

buffer_data = glm.array(model, view, proj)

然后更新数据,如下所示:

glBufferData(GL_SHADER_STORAGE_BUFFER, buffer_data.nbytes, buffer_data.ptr, GL_STATIC_DRAW)

注意:nbytesptr是在glm.array的成员中建立的,您可以使用它们来代替glm.sizeofglm.value_ptr

相关问题