def _prepare_vis(): objects = [] # --- program and shaders # Create program and shaders hprog = gl.glCreateProgram() hvert = gl.glCreateShader(gl.GL_VERTEX_SHADER) hfrag = gl.glCreateShader(gl.GL_FRAGMENT_SHADER) objects.append((gl.glDeleteProgram, hprog)) objects.append((gl.glDeleteShader, hvert)) objects.append((gl.glDeleteShader, hfrag)) # Compile source code gl.glShaderSource_compat(hvert, VERT) gl.glShaderSource_compat(hfrag, FRAG) gl.glCompileShader(hvert) gl.glCompileShader(hfrag) # Check assert_equal(gl.glGetShaderInfoLog(hvert), '') assert_equal(gl.glGetShaderInfoLog(hfrag), '') assert_equal(gl.glGetShaderParameter(hvert, gl.GL_COMPILE_STATUS), 1) assert_equal(gl.glGetShaderParameter(hfrag, gl.GL_COMPILE_STATUS), 1) # Attach and link gl.glAttachShader(hprog, hvert) gl.glAttachShader(hprog, hfrag) # touch glDetachShader gl.glDetachShader(hprog, hvert) gl.glAttachShader(hprog, hvert) gl.glLinkProgram(hprog) # Test that indeed these shaders are attached attached_shaders = gl.glGetAttachedShaders(hprog) assert_equal(set(attached_shaders), set([hvert, hfrag])) # Check assert_equal(gl.glGetProgramInfoLog(hprog), '') assert_equal(gl.glGetProgramParameter(hprog, gl.GL_LINK_STATUS), 1) gl.glValidateProgram(hprog) assert_equal(gl.glGetProgramParameter(hprog, gl.GL_VALIDATE_STATUS), 1) # Use it! gl.glUseProgram(hprog) # Bind one attribute gl.glBindAttribLocation(hprog, 1, 'a_2') # Check if all is ok assert_equal(gl.glGetError(), 0) # Check source vert_source = gl.glGetShaderSource(hvert) assert_true('attribute vec2 a_2;' in vert_source) # --- get information on attributes and uniforms # Count attribbutes and uniforms natt = gl.glGetProgramParameter(hprog, gl.GL_ACTIVE_ATTRIBUTES) nuni = gl.glGetProgramParameter(hprog, gl.GL_ACTIVE_UNIFORMS) assert_equal(natt, 4) assert_equal(nuni, 4+4+3+1) # Get names names = {} for i in range(natt): name, count, type = gl.glGetActiveAttrib(hprog, i) names[name] = type assert_equal(count, 1) for i in range(nuni): name, count, type = gl.glGetActiveUniform(hprog, i) names[name] = type assert_equal(count, 1) # Check assert_equal(names['a_1'], gl.GL_FLOAT) assert_equal(names['a_2'], gl.GL_FLOAT_VEC2) assert_equal(names['a_3'], gl.GL_FLOAT_VEC3) assert_equal(names['a_4'], gl.GL_FLOAT_VEC4) assert_equal(names['s_1'], gl.GL_SAMPLER_2D) # for i, type in enumerate([gl.GL_FLOAT, gl.GL_FLOAT_VEC2, gl.GL_FLOAT_VEC3, gl.GL_FLOAT_VEC4]): assert_equal(names['u_f%i' % (i+1)], type) for i, type in enumerate([gl.GL_INT, gl.GL_INT_VEC2, gl.GL_INT_VEC3, gl.GL_INT_VEC4]): assert_equal(names['u_i%i' % (i+1)], type) for i, type in enumerate([gl.GL_FLOAT_MAT2, gl.GL_FLOAT_MAT3, gl.GL_FLOAT_MAT4]): assert_equal(names['u_m%i' % (i+2)], type) # Check if all is ok assert_equal(gl.glGetError(), 0) # --- texture # Create, bind, activate htex = gl.glCreateTexture() objects.append((gl.glDeleteTexture, htex)) gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 1) gl.glBindTexture(gl.GL_TEXTURE_2D, htex) # Allocate data and upload # This data is luminance and not C-contiguous gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_LUMINANCE, gl.GL_LUMINANCE, gl.GL_UNSIGNED_BYTE, im2) # touch gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_LUMINANCE, gl.GL_LUMINANCE, gl.GL_UNSIGNED_BYTE, im2.shape[:2]) gl.glTexSubImage2D(gl.GL_TEXTURE_2D, 0, 0, 0, gl.GL_LUMINANCE, gl.GL_UNSIGNED_BYTE, im2) # Set texture parameters (use f and i to touch both) T = gl.GL_TEXTURE_2D gl.glTexParameterf(T, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR) gl.glTexParameteri(T, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR) # Re-allocate data and upload gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGB, gl.GL_RGB, gl.GL_UNSIGNED_BYTE, im1.shape[:2]) gl.glTexSubImage2D(gl.GL_TEXTURE_2D, 0, 0, 0, gl.GL_RGB, gl.GL_UNSIGNED_BYTE, im1) # Attach! loc = gl.glGetUniformLocation(hprog, 's_1') unit = 0 gl.glActiveTexture(gl.GL_TEXTURE0+unit) gl.glUniform1i(loc, unit) # Mipmaps (just to touch this function) gl.glGenerateMipmap(gl.GL_TEXTURE_2D) # Check min filter (touch getTextParameter) minfilt = gl.glGetTexParameter(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER) assert_equal(minfilt, gl.GL_LINEAR) # Check if all is ok assert_equal(gl.glGetError(), 0) # --- buffer vec2 (contiguous VBO) # Create buffer hbuf2 = gl.glCreateBuffer() objects.append((gl.glDeleteBuffer, hbuf2)) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, hbuf2) # Allocate and set data gl.glBufferData(gl.GL_ARRAY_BUFFER, buf2.nbytes, gl.GL_DYNAMIC_DRAW) gl.glBufferSubData(gl.GL_ARRAY_BUFFER, 0, buf2) # Attach! loc = gl.glGetAttribLocation(hprog, 'a_2') gl.glDisableVertexAttribArray(loc) # touch gl.glEnableVertexAttribArray(loc) gl.glVertexAttribPointer(loc, 2, gl.GL_FLOAT, False, 2*4, 0) # Check (touch glGetBufferParameter, glGetVertexAttrib and # glGetVertexAttribOffset) size = gl.glGetBufferParameter(gl.GL_ARRAY_BUFFER, gl.GL_BUFFER_SIZE) assert_equal(size, buf2.nbytes) stride = gl.glGetVertexAttrib(loc, gl.GL_VERTEX_ATTRIB_ARRAY_STRIDE) assert_equal(stride, 2*4) offset = gl.glGetVertexAttribOffset(loc, gl.GL_VERTEX_ATTRIB_ARRAY_POINTER) assert_equal(offset, 0) # Check if all is ok assert_equal(gl.glGetError(), 0) # --- buffer vec3 (non-contiguous VBO) # Create buffer hbuf3 = gl.glCreateBuffer() objects.append((gl.glDeleteBuffer, hbuf3)) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, hbuf3) # Allocate and set data gl.glBufferData(gl.GL_ARRAY_BUFFER, buf3.nbytes, gl.GL_DYNAMIC_DRAW) gl.glBufferSubData(gl.GL_ARRAY_BUFFER, 0, buf3) # Attach! loc = gl.glGetAttribLocation(hprog, 'a_3') gl.glEnableVertexAttribArray(loc) gl.glVertexAttribPointer(loc, 3, gl.GL_FLOAT, False, 3*4, 0) # Check if all is ok assert_equal(gl.glGetError(), 0) # --- buffer vec4 (client vertex data) # Select no FBO gl.glBindBuffer(gl.GL_ARRAY_BUFFER, 0) # Attach! loc = gl.glGetAttribLocation(hprog, 'a_4') gl.glEnableVertexAttribArray(loc) gl.glVertexAttribPointer(loc, 4, gl.GL_FLOAT, False, 4*4, buf4) # Check if all is ok assert_equal(gl.glGetError(), 0) # --- element buffer # Create buffer global helements helements = gl.glCreateBuffer() objects.append((gl.glDeleteBuffer, helements)) gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, helements) # Allocate and set data gl.glBufferData(gl.GL_ELEMENT_ARRAY_BUFFER, elements, gl.GL_DYNAMIC_DRAW) gl.glBufferSubData(gl.GL_ELEMENT_ARRAY_BUFFER, 0, elements) # Turn off gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, 0) # Check if all is ok assert_equal(gl.glGetError(), 0) # --- uniforms # Set integer uniforms to 0 # We set them twice just to touch both i and iv functions for i, fun1, fun2 in [(1, gl.glUniform1i, gl.glUniform1iv), (2, gl.glUniform2i, gl.glUniform2iv), (3, gl.glUniform3i, gl.glUniform3iv), (4, gl.glUniform4i, gl.glUniform4iv)]: name = 'u_i%i' % i value = [0] * i loc = gl.glGetUniformLocation(hprog, name) fun1(loc, *value) # e.g. glUniform4i fun2(loc, 1, value) # e.g. glUniform4iv # Set float uniforms to 1.0 # We set them twice just to touch both i and iv functions for i, fun1, fun2 in [(1, gl.glUniform1f, gl.glUniform1fv), (2, gl.glUniform2f, gl.glUniform2fv), (3, gl.glUniform3f, gl.glUniform3fv), (4, gl.glUniform4f, gl.glUniform4fv)]: name = 'u_f%i' % i value = [1.0] * i loc = gl.glGetUniformLocation(hprog, name) fun1(loc, *value) # e.g. glUniform4f fun2(loc, 1, value) # e.g. glUniform4fv # Set matrix uniforms m = np.eye(5, dtype='float32') loc = gl.glGetUniformLocation(hprog, 'u_m2') gl.glUniformMatrix2fv(loc, 1, False, m[:2, :2]) # loc = gl.glGetUniformLocation(hprog, 'u_m3') m = np.eye(3, dtype='float32') gl.glUniformMatrix3fv(loc, 1, False, m[:3, :3]) # loc = gl.glGetUniformLocation(hprog, 'u_m4') m = np.eye(4, dtype='float32') gl.glUniformMatrix4fv(loc, 1, False, m[:4, :4]) # Check some uniforms loc = gl.glGetUniformLocation(hprog, 'u_i1') assert_equal(gl.glGetUniform(hprog, loc), 0) loc = gl.glGetUniformLocation(hprog, 'u_i2') assert_equal(gl.glGetUniform(hprog, loc), (0, 0)) loc = gl.glGetUniformLocation(hprog, 'u_f2') assert_equal(gl.glGetUniform(hprog, loc), (1.0, 1.0)) # Check if all is ok assert_equal(gl.glGetError(), 0) # --- attributes # Constant values for attributes. We do not even use this ... loc = gl.glGetAttribLocation(hprog, 'a_1') gl.glVertexAttrib1f(loc, 1.0) loc = gl.glGetAttribLocation(hprog, 'a_2') gl.glVertexAttrib2f(loc, 1.0, 1.0) loc = gl.glGetAttribLocation(hprog, 'a_3') gl.glVertexAttrib3f(loc, 1.0, 1.0, 1.0) loc = gl.glGetAttribLocation(hprog, 'a_4') gl.glVertexAttrib4f(loc, 1.0, 1.0, 1.0, 1.0) # --- flush and finish # Not really necessary, but we want to touch the functions gl.glFlush() gl.glFinish() #print([i[1] for i in objects]) return objects
def render_with_gloo(draw_data): """draw ImGui's drawlists with vispy's gloo interface Parameters ---------- draw_data: ImDrawData """ global device_objects # adapted from imgui_impl_ios.cpp in imgui, to target the minimal GLES API d = pymgui.ImDrawData(draw_data) io = pymgui.get_io() fb_scale = io.display_framebuffer_scale fb_width, fb_height = io.display_size if fb_width == 0 or fb_height == 0: return conf = gloo.get_gl_configuration() # backup GL state last_program = gl.glGetParameter(gl.GL_CURRENT_PROGRAM) last_texture = gl.glGetParameter(gl.GL_TEXTURE_BINDING_2D) last_array_buffer = gl.glGetParameter(gl.GL_ARRAY_BUFFER_BINDING) last_element_array_buffer = gl.glGetParameter(gl.GL_ELEMENT_ARRAY_BUFFER_BINDING) last_viewport = gl.glGetParameter(gl.GL_VIEWPORT) last_enable_blend = gl.glIsEnabled(gl.GL_BLEND), last_blend_equation = gl.glGetParameter(gl.GL_BLEND_EQUATION_RGB), last_blend_func = dict( last_blend_equation_alpha=gl.glGetParameter(gl.GL_BLEND_EQUATION_ALPHA), ) last_gl_states = dict( cull_face = gl.glIsEnabled(gl.GL_CULL_FACE), depth_test = gl.glIsEnabled(gl.GL_DEPTH_TEST), scissor_test = gl.glIsEnabled(gl.GL_SCISSOR_TEST)) gloo.set_state(blend=True) gloo.set_blend_equation('func_add') gloo.set_blend_func(salpha='src_alpha', dalpha='one_minus_src_alpha') gloo.set_state(cull_face=False, depth_test=False, scissor_test=True) gl.glActiveTexture(gl.GL_TEXTURE0) # Setup viewport, orthographic projection matrix gloo.set_viewport(0, 0, int(fb_width), int(fb_height)) p = device_objects['program'] # type: gloo.Program ortho_projection = np.array([ [2./fb_width, 0, 0, 0], [0., 2./-fb_height, 0, 0], [0., 0., -1., 0], [-1., 1., 0, 0] ]) vtype = [('a_position', np.float32, 2), ('a_uv', np.float32, 2), # ('a_color', np.uint8, 4)] ('a_color', np.uint32, 1)] # pos_dtype = [('a_position', np.float32, 2)] # uv_dtype = [('a_uv', np.float32, 2)] # color_dtype = [('a_color', np.uint8, 4)] itype = np.uint16 display_scale = 1.0 p['u_mvp'] = ortho_projection # print("draw {} cmd_list".format(len(d.cmd_lists))) for cmd_list in d.cmd_lists: vertex_count =C.ImDrawList_GetVertexBufferSize(cmd_list) index_count = C.ImDrawList_GetIndexBufferSize(cmd_list) vertex_buffer_ptr = C.ImDrawList_GetVertexPtr(cmd_list, 0) index_buffer_ptr = C.ImDrawList_GetIndexPtr(cmd_list, 0) def to_nparray(ptr, item_count, dtype): byte_count = item_count * dtype.itemsize as_bytes = ffi.buffer(ptr, byte_count) return np.frombuffer(as_bytes, dtype=dtype) ig_vertices = to_nparray(vertex_buffer_ptr, vertex_count, np.dtype(vtype)) ig_indices = to_nparray(index_buffer_ptr, index_count, np.dtype(itype)) # print("{} vertices to draw".format(len(ig_vertices))) # p['a_position'] = ig_vertices[:] # p['a_uv'] = ig_vertices['a_uv'] # p['a_color'] = ig_vertices['a_color'] # device_objects['geometry'] = ig_vertices # # gl.glBufferData(gl.GL_ARRAY_BUFFER, ig_vertices, gl.GL_STREAM_DRAW) # gl.glBufferData(gl.GL_ELEMENT_ARRAY_BUFFER, indices, gl.GL_STREAM_DRAW) # # index_buffer_offset = 0 # cmd_size = C.ImDrawList_GetCmdSize(cmd_list) # for cmd_index in range(cmd_size): # draw_cmd_ptr = C.ImDrawList_GetCmdPtr(cmd_list, cmd_index) # draw_cmd = pymgui.ImDrawCmd(draw_cmd_ptr) # # if draw_cmd.texture_id: # gl.glBindTexture(gl.GL_TEXTURE_2D, draw_cmd.texture_id) # x1, y1, x2, y2 = draw_cmd.clip_rect # # gl.glScissor( # x=int(x1 * display_scale), # y=int(y1 * display_scale), # width=int((x2 - x1) * display_scale), # height=int((y2 - y1) * display_scale) # ) # # start, stop = index_buffer_offset, draw_cmd.elem_count # # gl.glDrawElements(gl.GL_TRIANGLES, draw_cmd.elem_count, gl.GL_UNSIGNED_SHORT, indices[index_buffer_offset:]) # p.draw('triangles', gloo.IndexBuffer(ig_indices[start:stop])) # index_buffer_offset += draw_cmd.elem_count # # # Restore modified state gloo.set_state(**last_gl_states) gloo.set_state(blend=last_enable_blend) # gloo.set_blend_equation(last_blend_equation) # # gl.glBindVertexArray(0) # gl.glBindBuffer(gl.GL_ARRAY_BUFFER, 0) gl.glUseProgram(last_program)
def _prepare_vis(): objects = [] # --- program and shaders # Create program and shaders hprog = gl.glCreateProgram() hvert = gl.glCreateShader(gl.GL_VERTEX_SHADER) hfrag = gl.glCreateShader(gl.GL_FRAGMENT_SHADER) objects.append((gl.glDeleteProgram, hprog)) objects.append((gl.glDeleteShader, hvert)) objects.append((gl.glDeleteShader, hfrag)) # Compile source code gl.glShaderSource(hvert, VERT) gl.glShaderSource(hfrag, FRAG) gl.glCompileShader(hvert) gl.glCompileShader(hfrag) # Check assert gl.glGetShaderInfoLog(hvert) == '' assert gl.glGetShaderInfoLog(hfrag) == '' assert gl.glGetShaderParameter(hvert, gl.GL_COMPILE_STATUS) == 1 assert gl.glGetShaderParameter(hfrag, gl.GL_COMPILE_STATUS) == 1 # Attach and link gl.glAttachShader(hprog, hvert) gl.glAttachShader(hprog, hfrag) # touch glDetachShader gl.glDetachShader(hprog, hvert) gl.glAttachShader(hprog, hvert) # Bind all attributes - we could let this occur automatically, but some # implementations bind an attribute to index 0, which has the unfortunate # property of being unable to be modified. gl.glBindAttribLocation(hprog, 1, 'a_1') gl.glBindAttribLocation(hprog, 2, 'a_2') gl.glBindAttribLocation(hprog, 3, 'a_3') gl.glBindAttribLocation(hprog, 4, 'a_4') gl.glLinkProgram(hprog) # Test that indeed these shaders are attached attached_shaders = gl.glGetAttachedShaders(hprog) assert_equal(set(attached_shaders), set([hvert, hfrag])) # Check assert_equal(gl.glGetProgramInfoLog(hprog), '') assert_equal(gl.glGetProgramParameter(hprog, gl.GL_LINK_STATUS), 1) gl.glValidateProgram(hprog) assert_equal(gl.glGetProgramParameter(hprog, gl.GL_VALIDATE_STATUS), 1) # Use it! gl.glUseProgram(hprog) # Check if all is ok assert_equal(gl.glGetError(), 0) # Check source vert_source = gl.glGetShaderSource(hvert) assert_true('attribute vec2 a_2;' in vert_source) # --- get information on attributes and uniforms # Count attributes and uniforms natt = gl.glGetProgramParameter(hprog, gl.GL_ACTIVE_ATTRIBUTES) nuni = gl.glGetProgramParameter(hprog, gl.GL_ACTIVE_UNIFORMS) assert_equal(natt, 4) assert_equal(nuni, 4+4+3+1) # Get names names = {} for i in range(natt): name, count, type = gl.glGetActiveAttrib(hprog, i) names[name] = type assert_equal(count, 1) for i in range(nuni): name, count, type = gl.glGetActiveUniform(hprog, i) names[name] = type assert_equal(count, 1) # Check assert_equal(names['a_1'], gl.GL_FLOAT) assert_equal(names['a_2'], gl.GL_FLOAT_VEC2) assert_equal(names['a_3'], gl.GL_FLOAT_VEC3) assert_equal(names['a_4'], gl.GL_FLOAT_VEC4) assert_equal(names['s_1'], gl.GL_SAMPLER_2D) # for i, type in enumerate([gl.GL_FLOAT, gl.GL_FLOAT_VEC2, gl.GL_FLOAT_VEC3, gl.GL_FLOAT_VEC4]): assert_equal(names['u_f%i' % (i+1)], type) for i, type in enumerate([gl.GL_INT, gl.GL_INT_VEC2, gl.GL_INT_VEC3, gl.GL_INT_VEC4]): assert_equal(names['u_i%i' % (i+1)], type) for i, type in enumerate([gl.GL_FLOAT_MAT2, gl.GL_FLOAT_MAT3, gl.GL_FLOAT_MAT4]): assert_equal(names['u_m%i' % (i+2)], type) # Check if all is ok assert_equal(gl.glGetError(), 0) # --- texture # Create, bind, activate htex = gl.glCreateTexture() objects.append((gl.glDeleteTexture, htex)) gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 1) gl.glBindTexture(gl.GL_TEXTURE_2D, htex) # Allocate data and upload # This data is luminance and not C-contiguous gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_LUMINANCE, gl.GL_LUMINANCE, gl.GL_UNSIGNED_BYTE, im2) # touch gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_LUMINANCE, gl.GL_LUMINANCE, gl.GL_UNSIGNED_BYTE, im2.shape[:2]) gl.glTexSubImage2D(gl.GL_TEXTURE_2D, 0, 0, 0, gl.GL_LUMINANCE, gl.GL_UNSIGNED_BYTE, im2) # Set texture parameters (use f and i to touch both) T = gl.GL_TEXTURE_2D gl.glTexParameterf(T, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR) gl.glTexParameteri(T, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR) # Re-allocate data and upload gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGB, gl.GL_RGB, gl.GL_UNSIGNED_BYTE, im1.shape[:2]) gl.glTexSubImage2D(gl.GL_TEXTURE_2D, 0, 0, 0, gl.GL_RGB, gl.GL_UNSIGNED_BYTE, im1) # Attach! loc = gl.glGetUniformLocation(hprog, 's_1') unit = 0 gl.glActiveTexture(gl.GL_TEXTURE0+unit) gl.glUniform1i(loc, unit) # Mipmaps (just to touch this function) gl.glGenerateMipmap(gl.GL_TEXTURE_2D) # Check min filter (touch getTextParameter) minfilt = gl.glGetTexParameter(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER) assert_equal(minfilt, gl.GL_LINEAR) # Check if all is ok assert_equal(gl.glGetError(), 0) # --- buffer vec2 (contiguous VBO) # Create buffer hbuf2 = gl.glCreateBuffer() objects.append((gl.glDeleteBuffer, hbuf2)) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, hbuf2) # Allocate and set data gl.glBufferData(gl.GL_ARRAY_BUFFER, buf2.nbytes, gl.GL_DYNAMIC_DRAW) gl.glBufferSubData(gl.GL_ARRAY_BUFFER, 0, buf2) # Attach! loc = gl.glGetAttribLocation(hprog, 'a_2') gl.glDisableVertexAttribArray(loc) # touch gl.glEnableVertexAttribArray(loc) gl.glVertexAttribPointer(loc, 2, gl.GL_FLOAT, False, 2*4, 0) # Check (touch glGetBufferParameter, glGetVertexAttrib and # glGetVertexAttribOffset) size = gl.glGetBufferParameter(gl.GL_ARRAY_BUFFER, gl.GL_BUFFER_SIZE) assert_equal(size, buf2.nbytes) stride = gl.glGetVertexAttrib(loc, gl.GL_VERTEX_ATTRIB_ARRAY_STRIDE) assert_equal(stride, 2*4) offset = gl.glGetVertexAttribOffset(loc, gl.GL_VERTEX_ATTRIB_ARRAY_POINTER) assert_equal(offset, 0) # Check if all is ok assert_equal(gl.glGetError(), 0) # --- buffer vec3 (non-contiguous VBO) # Create buffer hbuf3 = gl.glCreateBuffer() objects.append((gl.glDeleteBuffer, hbuf3)) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, hbuf3) # Allocate and set data gl.glBufferData(gl.GL_ARRAY_BUFFER, buf3.nbytes, gl.GL_DYNAMIC_DRAW) gl.glBufferSubData(gl.GL_ARRAY_BUFFER, 0, buf3) # Attach! loc = gl.glGetAttribLocation(hprog, 'a_3') gl.glEnableVertexAttribArray(loc) gl.glVertexAttribPointer(loc, 3, gl.GL_FLOAT, False, 3*4, 0) # Check if all is ok assert_equal(gl.glGetError(), 0) # --- buffer vec4 (client vertex data) # Select no FBO gl.glBindBuffer(gl.GL_ARRAY_BUFFER, 0) # Attach! loc = gl.glGetAttribLocation(hprog, 'a_4') gl.glEnableVertexAttribArray(loc) gl.glVertexAttribPointer(loc, 4, gl.GL_FLOAT, False, 4*4, buf4) # Check if all is ok assert_equal(gl.glGetError(), 0) # --- element buffer # Create buffer global helements helements = gl.glCreateBuffer() objects.append((gl.glDeleteBuffer, helements)) gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, helements) # Allocate and set data gl.glBufferData(gl.GL_ELEMENT_ARRAY_BUFFER, elements, gl.GL_DYNAMIC_DRAW) gl.glBufferSubData(gl.GL_ELEMENT_ARRAY_BUFFER, 0, elements) # Turn off gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, 0) # Check if all is ok assert_equal(gl.glGetError(), 0) # --- uniforms # Set integer uniforms to 0 # We set them twice just to touch both i and iv functions for i, fun1, fun2 in [(1, gl.glUniform1i, gl.glUniform1iv), (2, gl.glUniform2i, gl.glUniform2iv), (3, gl.glUniform3i, gl.glUniform3iv), (4, gl.glUniform4i, gl.glUniform4iv)]: name = 'u_i%i' % i value = [0] * i loc = gl.glGetUniformLocation(hprog, name) fun1(loc, *value) # e.g. glUniform4i fun2(loc, 1, value) # e.g. glUniform4iv # Set float uniforms to 1.0 # We set them twice just to touch both i and iv functions for i, fun1, fun2 in [(1, gl.glUniform1f, gl.glUniform1fv), (2, gl.glUniform2f, gl.glUniform2fv), (3, gl.glUniform3f, gl.glUniform3fv), (4, gl.glUniform4f, gl.glUniform4fv)]: name = 'u_f%i' % i value = [1.0] * i loc = gl.glGetUniformLocation(hprog, name) fun1(loc, *value) # e.g. glUniform4f fun2(loc, 1, value) # e.g. glUniform4fv # Set matrix uniforms m = np.eye(5, dtype='float32') loc = gl.glGetUniformLocation(hprog, 'u_m2') gl.glUniformMatrix2fv(loc, 1, False, m[:2, :2]) # loc = gl.glGetUniformLocation(hprog, 'u_m3') m = np.eye(3, dtype='float32') gl.glUniformMatrix3fv(loc, 1, False, m[:3, :3]) # loc = gl.glGetUniformLocation(hprog, 'u_m4') m = np.eye(4, dtype='float32') gl.glUniformMatrix4fv(loc, 1, False, m[:4, :4]) # Check some uniforms loc = gl.glGetUniformLocation(hprog, 'u_i1') assert_equal(gl.glGetUniform(hprog, loc), 0) loc = gl.glGetUniformLocation(hprog, 'u_i2') assert_equal(gl.glGetUniform(hprog, loc), (0, 0)) loc = gl.glGetUniformLocation(hprog, 'u_f2') assert_equal(gl.glGetUniform(hprog, loc), (1.0, 1.0)) # Check if all is ok assert_equal(gl.glGetError(), 0) # --- attributes # Constant values for attributes. We do not even use this ... loc = gl.glGetAttribLocation(hprog, 'a_1') gl.glVertexAttrib1f(loc, 1.0) loc = gl.glGetAttribLocation(hprog, 'a_2') gl.glVertexAttrib2f(loc, 1.0, 1.0) loc = gl.glGetAttribLocation(hprog, 'a_3') gl.glVertexAttrib3f(loc, 1.0, 1.0, 1.0) loc = gl.glGetAttribLocation(hprog, 'a_4') gl.glVertexAttrib4f(loc, 1.0, 1.0, 1.0, 1.0) # --- flush and finish # Not really necessary, but we want to touch the functions gl.glFlush() gl.glFinish() # print([i[1] for i in objects]) return objects
def render_with_gloo(draw_data): """draw ImGui's drawlists with vispy's gloo interface Parameters ---------- draw_data: ImDrawData """ global device_objects # adapted from imgui_impl_ios.cpp in imgui, to target the minimal GLES API d = pymgui.ImDrawData(draw_data) io = pymgui.get_io() fb_scale = io.display_framebuffer_scale fb_width, fb_height = io.display_size if fb_width == 0 or fb_height == 0: return conf = gloo.get_gl_configuration() # backup GL state last_program = gl.glGetParameter(gl.GL_CURRENT_PROGRAM) last_texture = gl.glGetParameter(gl.GL_TEXTURE_BINDING_2D) last_array_buffer = gl.glGetParameter(gl.GL_ARRAY_BUFFER_BINDING) last_element_array_buffer = gl.glGetParameter( gl.GL_ELEMENT_ARRAY_BUFFER_BINDING) last_viewport = gl.glGetParameter(gl.GL_VIEWPORT) last_enable_blend = gl.glIsEnabled(gl.GL_BLEND), last_blend_equation = gl.glGetParameter(gl.GL_BLEND_EQUATION_RGB), last_blend_func = dict(last_blend_equation_alpha=gl.glGetParameter( gl.GL_BLEND_EQUATION_ALPHA), ) last_gl_states = dict(cull_face=gl.glIsEnabled(gl.GL_CULL_FACE), depth_test=gl.glIsEnabled(gl.GL_DEPTH_TEST), scissor_test=gl.glIsEnabled(gl.GL_SCISSOR_TEST)) gloo.set_state(blend=True) gloo.set_blend_equation('func_add') gloo.set_blend_func(salpha='src_alpha', dalpha='one_minus_src_alpha') gloo.set_state(cull_face=False, depth_test=False, scissor_test=True) gl.glActiveTexture(gl.GL_TEXTURE0) # Setup viewport, orthographic projection matrix gloo.set_viewport(0, 0, int(fb_width), int(fb_height)) p = device_objects['program'] # type: gloo.Program ortho_projection = np.array([[2. / fb_width, 0, 0, 0], [0., 2. / -fb_height, 0, 0], [0., 0., -1., 0], [-1., 1., 0, 0]]) vtype = [ ('a_position', np.float32, 2), ('a_uv', np.float32, 2), # ('a_color', np.uint8, 4)] ('a_color', np.uint32, 1) ] # pos_dtype = [('a_position', np.float32, 2)] # uv_dtype = [('a_uv', np.float32, 2)] # color_dtype = [('a_color', np.uint8, 4)] itype = np.uint16 display_scale = 1.0 p['u_mvp'] = ortho_projection # print("draw {} cmd_list".format(len(d.cmd_lists))) for cmd_list in d.cmd_lists: vertex_count = C.ImDrawList_GetVertexBufferSize(cmd_list) index_count = C.ImDrawList_GetIndexBufferSize(cmd_list) vertex_buffer_ptr = C.ImDrawList_GetVertexPtr(cmd_list, 0) index_buffer_ptr = C.ImDrawList_GetIndexPtr(cmd_list, 0) def to_nparray(ptr, item_count, dtype): byte_count = item_count * dtype.itemsize as_bytes = ffi.buffer(ptr, byte_count) return np.frombuffer(as_bytes, dtype=dtype) ig_vertices = to_nparray(vertex_buffer_ptr, vertex_count, np.dtype(vtype)) ig_indices = to_nparray(index_buffer_ptr, index_count, np.dtype(itype)) # print("{} vertices to draw".format(len(ig_vertices))) # p['a_position'] = ig_vertices[:] # p['a_uv'] = ig_vertices['a_uv'] # p['a_color'] = ig_vertices['a_color'] # device_objects['geometry'] = ig_vertices # # gl.glBufferData(gl.GL_ARRAY_BUFFER, ig_vertices, gl.GL_STREAM_DRAW) # gl.glBufferData(gl.GL_ELEMENT_ARRAY_BUFFER, indices, gl.GL_STREAM_DRAW) # # index_buffer_offset = 0 # cmd_size = C.ImDrawList_GetCmdSize(cmd_list) # for cmd_index in range(cmd_size): # draw_cmd_ptr = C.ImDrawList_GetCmdPtr(cmd_list, cmd_index) # draw_cmd = pymgui.ImDrawCmd(draw_cmd_ptr) # # if draw_cmd.texture_id: # gl.glBindTexture(gl.GL_TEXTURE_2D, draw_cmd.texture_id) # x1, y1, x2, y2 = draw_cmd.clip_rect # # gl.glScissor( # x=int(x1 * display_scale), # y=int(y1 * display_scale), # width=int((x2 - x1) * display_scale), # height=int((y2 - y1) * display_scale) # ) # # start, stop = index_buffer_offset, draw_cmd.elem_count # # gl.glDrawElements(gl.GL_TRIANGLES, draw_cmd.elem_count, gl.GL_UNSIGNED_SHORT, indices[index_buffer_offset:]) # p.draw('triangles', gloo.IndexBuffer(ig_indices[start:stop])) # index_buffer_offset += draw_cmd.elem_count # # # Restore modified state gloo.set_state(**last_gl_states) gloo.set_state(blend=last_enable_blend) # gloo.set_blend_equation(last_blend_equation) # # gl.glBindVertexArray(0) # gl.glBindBuffer(gl.GL_ARRAY_BUFFER, 0) gl.glUseProgram(last_program)