I'm trying to shy away from the slow and high-overhead latebind frontend of PyOpenGL and specifically use the raw backend implementation...
The problem I'm having is I can't seem to figure out how the frontend turns the backend function glGenBuffers( n, buffers )
into buffers = glGenBuffers( n )
.
All I want to know is what do I pass to the buffers
argument of the backend function??
Here are some examples of creating one or multiple buffers using glGenBuffers
. If you must use function calls like glGenBuffers(n, buffers)
, you can either use ctypes directly or use PyOpenGL's GLint
, which wraps up a ctypes data type.
import ctypes
import numpy as np
from OpenGL.GL import *
import pygame
pygame.init()
screen = pygame.display.set_mode((800,600), pygame.OPENGL | pygame.DOUBLEBUF) #initialize OpenGL
py_id = glGenBuffers(1) #typical way to generate a single index
c_id = ctypes.c_int() #using ctypes to generate a second index
glGenBuffers(1, c_id)
gl_id = GLint() #using GL wrapper to generate a third index
glGenBuffers(1, gl_id)
print py_id, c_id.value, gl_id.value #should print 1 2 3
n = 10
py_list = glGenBuffers(n) #typical way to generate multiple indices
c_list = (ctypes.c_int * n)() #using ctypes to generate multiple indices
glGenBuffers(n, c_list)
gl_list = (GLint * n)() #using GL wrapper to generate multiple indices
glGenBuffers(n, gl_list)
print py_list, list(py_list) #note the default is a numpy array!
print np.array(c_list), list(c_list)
print np.array(gl_list), list(gl_list)
As a side note, I am not sure what the benefit of doing this is. I doubt that the convenient wrapper around glGenBuffers
is really so slow that the typical approach like buffers = glGenBuffers(n)
should be avoided. I am really curious to know if this is a performance bottleneck for you. Hope this helps!
Update:
After your comment about the overhead of __call__
, I figured I would test it out in timeit. Here is my code, with the results in seconds included next to each timed block:
import ctypes
import numpy as np
from OpenGL.GL import *
import pygame
import timeit
pygame.init()
screen = pygame.display.set_mode((800,600), pygame.OPENGL | pygame.DOUBLEBUF) #initialize OpenGL
def test(func, repeats):
start_time = timeit.default_timer()
for i in range(repeats):
func()
elapsed = timeit.default_timer() - start_time
print elapsed
def func1():
py_id = glGenBuffers(1)
def func2():
c_id = ctypes.c_int()
glGenBuffers(1, c_id)
def func3():
gl_id = GLint()
glGenBuffers(1, gl_id)
def func4():
n = 1
py_list = glGenBuffers(n)
def func5():
n = 1
c_list = (ctypes.c_int * n)()
glGenBuffers(n, c_list)
def func6():
n = 1
gl_list = (GLint * n)()
glGenBuffers(n, gl_list)
def func7():
n = 100
py_list = glGenBuffers(n)
def func8():
n = 100
c_list = (ctypes.c_int * n)()
glGenBuffers(n, c_list)
def func9():
n = 100
gl_list = (GLint * n)()
glGenBuffers(n, gl_list)
test(func1, 1000000)#4.12597930903
test(func2, 1000000)#5.2951610055
test(func3, 1000000)#5.17853478658
test(func4, 1000000)#4.06362866711
test(func5, 1000000)#3.45259988251
test(func6, 1000000)#3.43240155354
test(func7, 1000000)#4.128162421
test(func8, 1000000)#3.57384911559
test(func9, 1000000)#3.52125689729
From these results, it looks like the number of buffers you are generating does not make too much of an impact, so it should always be treated as a list, even when n=1. Not really sure why that is the case, perhaps some sort of conversion is going on behind the scenes in that case. Oddly enough, it looks like GLint() performs better than using ctypes directly which also makes no sense to me. Either way, the pure python version does perform the slowest, and I imagine that for other more complex OpenGL functions, the difference can be even greater!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With