代码之家  ›  专栏  ›  技术社区  ›  Sun Bear

如何将C++或GLM结构作为一个麻木数组来表达?

  •  1
  • Sun Bear  · 技术社区  · 8 年前

    我想将下面的结构表示为numpy数组。

    struct UniformBufferObject {
        glm::mat4 model;
        glm::mat4 view;
        glm::mat4 proj;
    };
    

    此后,numpy阵列将作为GLSL布局读入:

    layout(binding = 0) uniform UniformBufferObject {
        mat4 model;
        mat4 view;
        mat4 proj;
    } ubo;
    

    在上述声明中, mat4

    下面,我创建了一个python列表,然后将其转换为一个具有4x4形状的numpy数组(w/o复制),其中每个元素都是一个 dtype=float32 .

    问题: 我下一步应该做什么来代表 UniformBufferObject

    >>> model = [0.1, 0.1, 0.1, 1, 0.1, 0.1, 0.1, 1, 0.1, 0.1, 0.1, 1, 0.1, 0.1, 0.1, 0,]
    >>> view = [0.2, 0.2, 0.2, 1, 0.2, 0.2, 0.2, 1, 0.2, 0.2, 0.2, 1, 0.2, 0.2, 0.2, 0,]
    >>> proj = [0.3, 0.3, 0.3, 1, 0.3, 0.3, 0.3, 1, 0.3, 0.3, 0.3, 1, 0.3, 0.3, 0.3, 0,]
    >>> modeln = np.asarray(model, dtype= 'f4').reshape(4,4)
    >>> viewn = np.asarray(view, dtype= 'f4').reshape(4,4)
    >>> projn = np.asarray(proj, dtype= 'f4').reshape(4,4)
    >>> modeln
    array([[0.1, 0.1, 0.1, 1. ],
           [0.1, 0.1, 0.1, 1. ],
           [0.1, 0.1, 0.1, 1. ],
           [0.1, 0.1, 0.1, 0. ]], dtype=float32)
    >>> viewn
    array([[0.2, 0.2, 0.2, 1. ],
           [0.2, 0.2, 0.2, 1. ],
           [0.2, 0.2, 0.2, 1. ],
           [0.2, 0.2, 0.2, 0. ]], dtype=float32)
    >>> projn
    array([[0.3, 0.3, 0.3, 1. ],
           [0.3, 0.3, 0.3, 1. ],
           [0.3, 0.3, 0.3, 1. ],
           [0.3, 0.3, 0.3, 0. ]], dtype=float32)
    >>> 
    
    1 回复  |  直到 7 年前
        1
  •  1
  •   Rabbid76    7 年前

    如果在GLSL a中 Uniform block 是这样指定的

     layout(binding = 0) uniform UniformBufferObject {
         mat4 model;
         mat4 view;
         mat4 proj;
     } ubo;
    

    那么OpenGL不能保证th块中的成员是按连续顺序存储的。OpenGL对元素的内存布局、对齐方式或顺序没有任何保证。

    要实现定义良好的顺序和内存布局 memory layout qualifier std140 要使用的ahs。这个 ARB_uniform_buffer_object :

    layout(std140, binding = 0) uniform UniformBufferObject {
        mat4 model;
        mat4 view;
        mat4 proj;
    } ubo;
    

    有关布局的详细说明,请访问:

    如果是上述均匀块体,则 std140 float S 在一行中,大小为192字节

    mat4 model     byte offset   0: size in bytes  64 = 4*4*sizeof(float)
    mat4 view      byte offset  64: size in bytes  64 = 4*4*sizeof(float)
    mat4 proj      byte offset 128: size in bytes  64 = 4*4*sizeof(float)
    --------------------------------------------------------------------
                                    size in bytes 192 = 3*4*4*sizeof(float)
    

    要创建与此内存布局对应的缓冲区,请使用平面 numpy.array 可用于:

    例如

     model = [0.1, 0.1, 0.1, 1, 0.1, 0.1, 0.1, 1, 0.1, 0.1, 0.1, 1, 0.1, 0.1, 0.1, 0,]
     view = [0.2, 0.2, 0.2, 1, 0.2, 0.2, 0.2, 1, 0.2, 0.2, 0.2, 1, 0.2, 0.2, 0.2, 0,]
     proj = [0.3, 0.3, 0.3, 1, 0.3, 0.3, 0.3, 1, 0.3, 0.3, 0.3, 1, 0.3, 0.3, 0.3, 0,]
    
    import numpy as np
    
    ubo_data = np.array([model, view, proj], dtype='f4')
    

    没有必要 reshap() 阵列。但是,如果您想访问模型矩阵的元素,当然可以这样做( ubo_data[0] ),视图矩阵( ubo_data[1] ubo_data[2] )直接:

    ubo_data = np.array([model, view, proj], dtype='f4').reshape(3, 4, 4)
    

    注意,甚至不需要使用 NumPy . 具有相同内存布局的缓冲区可以由 ctypes 数组:

    import ctypes
    
    ubo_data = (ctypes.c_float * 48)(*model, *view, *proj)
    

    使用 PyOpenGL ,上述每个数据数组都可用于装箱和初始化统一块缓冲区的缓冲区存储 glBufferData

    ubo = glGenBuffers( 1 )
    glBindBuffer(GL_UNIFORM_BUFFER, ubo)
    glBufferData(GL_UNIFORM_BUFFER, ubo_data, GL_STATIC_DRAW)
    glBindBufferBase(GL_UNIFORM_BUFFER, 0, ubo)
    glBindBuffer(GL_UNIFORM_BUFFER, 0)
    

    glBufferSubData

    glBindBuffer(GL_UNIFORM_BUFFER, ubo)
    glBufferSubData(GL_UNIFORM_BUFFER, 0, ubo_data)
    

    注意,当使用 PyGLM

    例如。:

    import glm
    
    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), 800.0/600.0, 0.1, 100)
    
    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))