'How to initialize a buffer object's data store with data from PyGLM?
I have specified the following Shader Storage Buffer in the Vertex Shader:
layout(std430, binding = 1) buffer MVP
{
mat4 u_proj;
mat4 u_view;
mat4 u_model;
} mvp_data;
I have initialized the model, view and projection matrix:
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)
How can the buffer object's data store be created and initialized using glBufferData
(or glNamedBufferData
)
ssbo = glGenBuffers( 1 )
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo )
glBufferData(GL_SHADER_STORAGE_BUFFER, 3*16*4, ???, GL_STATIC_DRAW )
respectively initialized by glBufferSubData
(or 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, ???, ???);
Since the SSBO contains 3 (tightly packed) mat4
, the size of the buffer is 3 * 16 * 4 (3 4x4-matrices with element data type float
).
So the initialization of the buffer can be done by a NumPy array.
But how the PyGLM matrices can be effectively assigned to the NumPy array?
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)
Or is there an even more efficient solution, without an copying the data to a NumPy array?
Solution 1:[1]
Finally I found the solution myself.
It should be noted, that the Shader Storage Buffer consists of 344=48 tightly packed floats.
PyGlm provides the handy functions glm.value_ptr
and glm.sizeof
. glm.value_ptr
corresponds to the glm::value_ptr
. glm.sizeof
works like c++ sizeof
operator for the glm data types.
This functions can be used with the glBufferSubData
wrapping of PyOpenGL to updates the buffer data:
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))
A object of type glm.mat4
can be assigned to a numpy.array
with shape (4, 4)
of type np.float32
. So the 3 matrices can be assigned to the elements of a numpy.array
with shape (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
This array can be used to updates the entire buffer data at once:
buffer_size = buffer_data.size * buffer_data.itemsize
glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, buffer_size, buffer_data)
Or for the initial glBufferData
creation and initialization of the buffer object's data store:
glBufferData(GL_SHADER_STORAGE_BUFFER, buffer_data, GL_DYNAMIC_DRAW)
Since PyGLM version 2.0.0 there is a simpler way to l this. See Using Arrays:
PyGLM's array type was introduced in version 2.0.0 to reduce the likelihood of requiring users to also use numpy besides glm. It's mainly intended to provide a way of passing multiple glm type instances (such as vectors) to external C functions (such as glBufferData).
buffer_data = glm.array(model, view, proj)
glBufferData(GL_SHADER_STORAGE_BUFFER, buffer_data.nbytes, buffer_data.ptr, GL_STATIC_DRAW)
Solution 2:[2]
There is a way to update all the data at once without having to use numpy at all.
In the PyGLM docs, it says (https://github.com/Zuzu-Typ/PyGLM/wiki/Using-arrays):
PyGLM's array type was introduced in version 2.0.0 to reduce the likelihood of requiring users to also use numpy besides glm. It's mainly intended to provide a way of passing multiple glm type instances (such as vectors) to external C functions (such as glBufferData).
What you can do is to wrap the matrices with a glm.array like this:
buffer_data = glm.array(model, view, proj)
Then update the data like this:
glBufferData(GL_SHADER_STORAGE_BUFFER, buffer_data.nbytes, buffer_data.ptr, GL_STATIC_DRAW)
Note: nbytes
and ptr
are built in members of glm.array, and you use them instead of glm.sizeof
and glm.value_ptr
.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Rabbid76 |