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)