我怎么会在 glMultiDrawArraysIndirect 函数中出错?

How am I going wrong in glMultiDrawArraysIndirect function?

我正在使用 Python 和现代 OpenGL 进行编程,我尝试在我的代码中实现 glMultiDrawArraysIndirect 函数来绘制一个简单的形状,我想稍后将它应用到更多复杂的东西,但这只是一个简单的测试,我不知道错误在哪里。

import glfw, time, ctypes, math, pyrr
import numpy as np
from OpenGL.GL import *
from OpenGL.GL.shaders import *

glfw.init()

glfw.window_hint(glfw.SAMPLES, 4)

w = glfw.create_window(640, 480, "Galeria das Sombras", None, None)

glfw.make_context_current(w)

v = """
#version 430
in layout(location=0) vec3 posicao;
in layout(location=1) vec2 textura;
uniform mat4 view;
uniform vec3 def;
uniform vec3 pos;
uniform vec3 scale;
uniform float giro;
uniform float giro2;
out vec2 texcords;
void main(){
    texcords = textura;
    vec3 p = vec3(posicao.x*scale.x,posicao.y*scale.y,posicao.z*scale.z);
    p = p+def;
    p = vec3(-sin(giro)*p.z+cos(giro)*p.x,p.y,sin(giro)*p.x+cos(giro)*p.z);
    p = vec3(p.x,-sin(giro2)*p.z+cos(giro2)*p.y,sin(giro2)*p.y+cos(giro2)*p.z);
    p = p+pos+vec3(gl_InstanceID,0,0);
    gl_Position = view*vec4(p,1);
}
"""

f = """
#version 430
in vec2 texcords;
uniform vec3 cor;
uniform sampler2D texinfo;
void main(){
    gl_FragColor = vec4(cor,1)*texture(texinfo,texcords);
}
"""

shader = compileProgram(compileShader(v,GL_VERTEX_SHADER),compileShader(f,GL_FRAGMENT_SHADER))

tudo = [-1,-1,0,0,1,
        1,-1,0,1,1,
        1,1,0,1,0,
        -1,1,0,0,0]

tudo = np.array(tudo, np.float32)

VBO = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, VBO)
glBufferData(GL_ARRAY_BUFFER, len(tudo)*4, tudo, GL_STATIC_DRAW)

'''
tudo = [[1,1,0,3],[2,2,1,3]]

tudo = np.array(tudo, np.uint8)

VBI = glGenBuffers(1)
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, VBI)
glBufferData(GL_DRAW_INDIRECT_BUFFER, len(tudo)*4, tudo, GL_STATIC_DRAW)
'''

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 20, ctypes.c_void_p(0))
glEnableVertexAttribArray(0)

glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 20, ctypes.c_void_p(12))
glEnableVertexAttribArray(1)

glUseProgram(shader)

view = pyrr.matrix44.create_perspective_projection_matrix(60, 640/480, .1, 1000)
p = glGetUniformLocation(shader, "view")
glUniformMatrix4fv(p, 1, GL_FALSE, view)

glEnable(GL_DEPTH_TEST)
glEnable(GL_MULTISAMPLE)
glEnable(GL_TEXTURE_2D)

from PIL import Image

t = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, t)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
buffer = Image.open("p.jpg")
data = buffer.tobytes()
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, buffer.size[0], buffer.size[1], 0, GL_RGB, GL_UNSIGNED_BYTE, data)

girar = 0
tempo = glfw.get_time()
tfps = glfw.get_time()
fps = 0
action = 0

while not glfw.window_should_close(w):
    glfw.swap_buffers(w)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    view = pyrr.matrix44.create_perspective_projection_matrix(60, glfw.get_window_size(w)[0]/glfw.get_window_size(w)[1], .1, 1000)
    p = glGetUniformLocation(shader, "view")
    glUniformMatrix4fv(p, 1, GL_FALSE, view)
    glViewport(0,0,glfw.get_window_size(w)[0],glfw.get_window_size(w)[1])
    p = glGetUniformLocation(shader, "cor")
    glUniform3f(p, 1, 0, 0)
    p = glGetUniformLocation(shader, "def")
    glUniform3f(p, 0, 0, 0)
    p = glGetUniformLocation(shader, "scale")
    glUniform3f(p, 1, 1, 1)
    p = glGetUniformLocation(shader, "giro")
    glUniform1f(p, girar*math.pi/180)
    if glfw.get_time() - tempo > 1/60:
        girar+=1
        tempo = glfw.get_time()
        if action > 0:
            action-=.05
        if action < 0:
            action = 0
    p = glGetUniformLocation(shader, "giro2")
    if glfw.get_key(w, glfw.KEY_W) and action == 0:
        action = 2
    if action > 1:
        glUniform1f(p, (1-(action-1))*-90*(math.pi/180))
    else:
        glUniform1f(p, action*-90*(math.pi/180))
    p = glGetUniformLocation(shader, "pos")
    glUniform3f(p, 0, 0, -10)
    glMultiDrawArraysIndirect(GL_TRIANGLES, np.array([[0,3,1,0],[1,3,1,1]]), 2, 1)
    fps+=1
    if glfw.get_time() - tfps > 1:
        print("FPS:",fps)
        fps = 0
        tfps = glfw.get_time()
    glfw.poll_events()
    if fps > 400:
        time.sleep(.01)

glfw.destroy_window(w)
glfw.terminate()

在 VBO 中有一个正方形,但我打算只使用前 3 个点绘制 2 个三角形,然后使用彼此相邻的最后 3 个点绘制三角形,我没有找到很多此类代码的示例互联网,只有 glMultiDrawArraysIndirect 文档,但我无法在我的代码中做到 运行,至少在没有提供良好锁定的情况下,当我为 1 个轮子更改 drawcount 但没有出现时在屏幕上。

还有 drawcount 我从网站上获取的:http://docs.gl/gl4/glMultiDrawArraysIndirect

我尝试为不同类型的 numpy 数组更改 indirect 值,具有不同的 uint dtypes 但大多数错误或 运行 没有任何显示屏幕上有人知道哪里出了问题吗?

指定NumPy数组时需要指定类型uint32。最后一个参数 (stride) 指定绘图参数数组元素之间的基本机器单位距离(16 字节):
(参见 glMultiDrawArraysIndirect

indirect = np.array([[3, 10, 0, 0], [3, 5, 1, 0]], dtype=np.uint32)
glMultiDrawArraysIndirect(GL_TRIANGLES, indirect, 2, 16)

glMultiDrawArraysIndirect(GL_TRIANGLES, indirect, 
    indirect.shape[0], indirect.dtype.itemsize * indirect.shape[1])

以上代码作用与:
(参见 glDrawArraysIndirect

indirect1 = np.array([3, 10, 0, 0], dtype=np.uint32)
glDrawArraysIndirect(GL_TRIANGLES, indirect1)
indirect2 = np.array([3, 5, 1, 0], dtype=np.uint32)
glDrawArraysIndirect(GL_TRIANGLES, indirect2)

分别为:
(参见 glDrawArraysInstancedBaseInstance

glDrawArraysInstancedBaseInstance(GL_TRIANGLES, 0, 3, 10, 0)
glDrawArraysInstancedBaseInstance(GL_TRIANGLES, 1, 3, 5, 0)

当你使用glDrawArraysIndirectglMultiDrawArraysIndirect时,你需要创建如下数据结构: (参见 GLAPI/glMultiDrawArraysIndirect

typedef  struct {
    uint  count;
    uint  instanceCount;
    uint  first;
    uint  baseInstance;
} DrawArraysIndirectCommand;

这可以使用数据类型为 uint32:

的 NumPy 数组来实现
np.array([count, instanceCount, first, baseInstance], dtype=np.uint32)