Skip to content
Advertisement

How am I going wrong in glMultiDrawArraysIndirect function?

I’m programming using Python and Modern OpenGL, and I tried to implement the glMultiDrawArraysIndirect function in my code to draw a simple shape, I want to apply it later on to a more complex thing, but this is just a simple test that I don’t know exactly where the error is.

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()

In the VBO there is a square, but I was going to draw only 2 triangles using the first 3 points and then the last 3 next to each other, I didn’t find many examples of this type of code on the internet, only glMultiDrawArraysIndirect documentation but I couldn’t do it run in my code, at least not without giving a good lock, when I change the drawcount for 1 wheel but nothing appears on the screen.

There is and the drawcount I took from the site: http://docs.gl/gl4/glMultiDrawArraysIndirect

I tried to change the indirect value for different types of numpy arrays, with different uint dtypes but most of them either error or run without anything appearing on the screen does anyone know what’s wrong?

Advertisement

Answer

When you specify the NumPy array you need to specify the type uint32. The last argument (stride) is specifies the distance in basic machine units between elements of the draw parameter array (16 bytes):
(see glMultiDrawArraysIndirect)

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

or

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

The above code does the same as:
(see 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)

Respectively the same as:
(see glDrawArraysInstancedBaseInstance)

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

When you use glDrawArraysIndirect or glMultiDrawArraysIndirect, you need to create the following data structure: (see GLAPI/glMultiDrawArraysIndirect)

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

This can be achieved using a NumPy array with the data type uint32:

np.array([count, instanceCount, first, baseInstance], dtype=np.uint32)
User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement