def get_max_texture_sizes(): """Get maximum texture sizes for 2D and 3D rendering. Returns ------- MAX_TEXTURE_SIZE_2D : int or None Max texture size allowed by the vispy canvas during 2D rendering. MAX_TEXTURE_SIZE_3D : int or None Max texture size allowed by the vispy canvas during 2D rendering. """ # A canvas must be created to access gl values c = Canvas(show=False) try: MAX_TEXTURE_SIZE_2D = gl.glGetParameter(gl.GL_MAX_TEXTURE_SIZE) finally: c.close() if MAX_TEXTURE_SIZE_2D == (): MAX_TEXTURE_SIZE_2D = None # vispy doesn't expose GL_MAX_3D_TEXTURE_SIZE so hard coding # MAX_TEXTURE_SIZE_3D = gl.glGetParameter(gl.GL_MAX_3D_TEXTURE_SIZE) # if MAX_TEXTURE_SIZE_3D == (): # MAX_TEXTURE_SIZE_3D = None MAX_TEXTURE_SIZE_3D = 2048 return MAX_TEXTURE_SIZE_2D, MAX_TEXTURE_SIZE_3D
def __init__(self, program, rview=1, zview=None, zoom_speed=0.1, move_speed=0.01, *args, **kwargs): """ Constructor """ InteractiveViewportMixin.__init__(self, rview, zview, zoom_speed, move_speed) Canvas.__init__(self, *args, **kwargs) # self._program = program self._program.set_projection_matrix(self.get_projection_matrix()) self._program.set_view_matrix(self.get_view_matrix()) # Set up framebuffer width, height = self.physical_size shape = (height, width, 3) rendertex = gloo.Texture2D(shape) self._fbo = gloo.FrameBuffer(rendertex, gloo.RenderBuffer(shape)) self._display_program = TextureDisplayShader(rendertex)
def __init__(self): Canvas.__init__(self, size=[800, 800], close_keys='ESCAPE', show=True, title='Galaxy') self.galaxy = Galaxy(35000) self.galaxy.reset(13000, 4000, 0.0004, 0.90, 0.90, 0.5, 200, 300) program = gloo.Program(vertex, fragment, count=len(self.galaxy)) view = np.eye(4, dtype=np.float32) translate(view, 0, 0, -5) program['u_view'] = view program['u_model'] = np.eye(4, dtype=np.float32) program['u_projection'] = np.eye(4, dtype=np.float32) from PIL import Image from specrend import (SMPTEsystem, spectrum_to_xyz, norm_rgb, xyz_to_rgb, bb_spectrum) image = Image.open("particle.bmp") program['u_texture'] = np.array(image)/255.0 t0 = 1000. t1 = 10000. n = 256 dt = (t1 - t0) / n colors = np.zeros((1, n, 3), dtype=np.float32) for i in range(n): cs = SMPTEsystem temperature = t0 + i*dt x, y, z = spectrum_to_xyz(bb_spectrum, temperature) r, g, b = xyz_to_rgb(cs, x, y, z) colors[0, i] = norm_rgb(r, g, b) program['u_colormap'] = gloo.Texture2D(colors) program['a_size'] = self.galaxy['size'] program['a_type'] = self.galaxy['type'] self.program = program
def test_context_sharing(): """Test context sharing""" with Canvas() as c1: vert = "attribute vec4 pos;\nvoid main (void) {gl_Position = pos;}" frag = "void main (void) {gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);}" program = Program(vert, frag) program['pos'] = [(1, 2, 3, 1), (4, 5, 6, 1)] program.draw('points') def check(): # Do something to program and see if it worked program['pos'] = [(1, 2, 3, 1), (4, 5, 6, 1)] # Do command program.draw('points') check_error() # Check while c1 is active check() # Check while c2 is active (with different context) with Canvas() as c2: # pyglet always shares if 'pyglet' not in c2.app.backend_name.lower(): assert_raises(Exception, check) # Check while c2 is active (with *same* context) with Canvas(shared=c1.context) as c2: assert c1.context.shared is c2.context.shared # same object check()
def test_capability(): """Test application capability enumeration""" non_default_vals = dict(title='foo', size=[100, 100], position=[0, 0], show=True, decorate=False, resizable=False, vsync=True) # context is tested elsewhere good_kwargs = dict() bad_kwargs = dict() with Canvas() as c: for key, val in c.app.backend_module.capability.items(): if key in non_default_vals: if val: good_kwargs[key] = non_default_vals[key] else: bad_kwargs[key] = non_default_vals[key] # ensure all settable values can be set with Canvas(**good_kwargs): # some of these are hard to test, and the ones that are easy are # tested elsewhere, so let's just make sure it runs here pass # ensure that *any* bad argument gets caught for key, val in bad_kwargs.items(): assert_raises(RuntimeError, Canvas, **{key: val})
def test_qt_designer(): """Embed Canvas via Qt Designer""" from PyQt4 import QtGui, uic if not QtGui.QApplication.instance(): QtGui.QApplication([]) # noqa fname = op.join(op.dirname(__file__), 'qt-designer.ui') WindowTemplate, TemplateBaseClass = uic.loadUiType(fname) class MainWindow(TemplateBaseClass): def __init__(self): TemplateBaseClass.__init__(self) self.ui = WindowTemplate() self.ui.setupUi(self) self.show() win = MainWindow() try: win.show() canvas = Canvas(create_native=False) canvas._set_backend(win.ui.canvas) canvas.create_native() @canvas.events.paint.connect def on_paint(ev): gl.glClearColor(0.0, 0.0, 0.0, 0.0) gl.glClear(gl.GL_COLOR_BUFFER_BIT) canvas.swap_buffers() finally: win.close()
def test_context_sharing(): """Test context sharing""" with Canvas() as c1: vert = VertexShader("uniform vec4 pos;" "void main (void) {gl_Position = pos;}") frag = FragmentShader("uniform vec4 pos;" "void main (void) {gl_FragColor = pos;}") program = Program(vert, frag) program['pos'] = [1, 2, 3, 4] program.activate() # should print def check(): program.activate() check_error() with Canvas() as c2: # pyglet always shares if 'pyglet' not in c2.app.backend_name.lower(): assert_raises(RuntimeError, check) if c1.app.backend_name.lower() in ('glut',): assert_raises(RuntimeError, Canvas, context=c1.context) else: with Canvas(context=c1.context) as c2: assert c1.context is c2.context # Same context object check()
def test_context_sharing(): """Test context sharing""" with Canvas() as c1: vert = "uniform vec4 pos;\nvoid main (void) {gl_Position = pos;}" frag = "uniform vec4 pos;\nvoid main (void) {gl_FragColor = pos;}" program = Program(vert, frag) program['pos'] = [1, 2, 3, 4] program._glir.flush() def check(): # Do something to program and see if it worked program['pos'] = [1, 2, 3, 4] # Do command program._glir.flush() # Execute that command check_error() # Check while c1 is active check() # Check while c2 is active (with different context) with Canvas() as c2: # pyglet always shares if 'pyglet' not in c2.app.backend_name.lower(): assert_raises(RuntimeError, check) # Tests unable to create canvas on glut if c1.app.backend_name.lower() in ('glut', ): assert_raises(RuntimeError, Canvas, context=c1.context) return # Check while c2 is active (with *same* context) with Canvas(context=c1.context) as c2: assert c1.context is c2.context # Same context object check()
def test_qt_designer(): """Embed Canvas via Qt Designer""" default_app.use() if 'pyqt4' not in default_app.backend_name.lower(): raise SkipTest('Not using PyQt4 backend') # wrong backend from PyQt4 import uic fname = op.join(op.dirname(__file__), 'qt-designer.ui') WindowTemplate, TemplateBaseClass = uic.loadUiType(fname) default_app.create() # make sure we have an app, or the init will fail class MainWindow(TemplateBaseClass): def __init__(self): TemplateBaseClass.__init__(self) self.ui = WindowTemplate() self.ui.setupUi(self) self.show() win = MainWindow() try: win.show() canvas = Canvas(create_native=False) canvas.app.use() # Make sure the app exists (because create_native=0) canvas._set_backend(win.ui.canvas) canvas.create_native() @canvas.events.draw.connect def on_draw(ev): gl.glClearColor(0.0, 0.0, 0.0, 0.0) gl.glClear(gl.GL_COLOR_BUFFER_BIT) canvas.swap_buffers() finally: win.close()
def test_simultaneous_backends(): """Test running multiple backends simultaneously""" # XXX knownfail Note: All the _update_process_check calls have # been crippled here because they don't work 100% of the time # depending on backend order, etc. This is not critical for # the software currently, so we let it slide for now. names = dict(qt=has_qt, pyglet=has_pyglet, glfw=has_glfw, glut=has_glut) if sys.platform == 'darwin': names.pop('glut') # XXX knownfail, fails for unknown reason... backends = [name for name, check in names.items() if check()] canvases = dict() bgcolor = dict() try: for bi, backend in enumerate(backends): canvas = Canvas(app=backend, size=_win_size, title=backend + ' simul', autoswap=False) canvas.__enter__() # invoke warmup canvases[backend] = canvas @canvas.events.paint.connect def paint(event): print(' {0:7}: {1}'.format(backend, bgcolor[backend])) gl.glViewport(0, 0, *list(_win_size)) gl.glClearColor(*bgcolor[backend]) gl.glClear(gl.GL_COLOR_BUFFER_BIT) gl.glFinish() bgcolor[backend] = [0.5, 0.5, 0.5, 1.0] _update_process_check(canvases[backend], 127) for backend in backends: print('test %s' % backend) _update_process_check(canvases[backend], 127, False, _ig_fail) bgcolor[backend] = [1., 1., 1., 1.] _update_process_check(canvases[backend], 255, True, _ig_fail) bgcolor[backend] = [0.25, 0.25, 0.25, 0.25] _update_process_check(canvases[backend], 64, True, _ig_fail) # now we do the same thing, but with sequential close() calls for backend in backends: print('test %s' % backend) _update_process_check(canvases[backend], 64, False, _ig_fail) bgcolor[backend] = [1., 1., 1., 1.] _update_process_check(canvases[backend], 255, True, _ig_fail) bgcolor[backend] = [0.25, 0.25, 0.25, 0.25] _update_process_check(canvases[backend], 64, True, _ig_fail) finally: for canvas in canvases.values(): canvas.close()
def _opengl_context(): """Assure we are running with a valid OpenGL context. Only create a Canvas is one doesn't exist. Creating and closing a Canvas causes vispy to process Qt events which can cause problems. Ideally call opengl_context() on start after creating your first Canvas. However it will work either way. """ canvas = Canvas(show=False) if get_current_canvas() is None else None try: yield finally: if canvas is not None: canvas.close()
def test_log_parser(): glir_file = tempfile.TemporaryFile(mode='r+') config.update(glir_file=glir_file) with Canvas() as c: c.context.set_clear_color('white') c.context.clear() glir_file.seek(0) lines = glir_file.read().split(',\n') assert lines[0][0] == '[' lines[0] = lines[0][1:] assert lines[-1][-1] == ']' lines[-1] = lines[-1][:-1] i = 0 assert lines[i] == json.dumps(['CURRENT', 0]) i += 1 # The 'CURRENT' command may have been called multiple times while lines[i] == lines[i - 1]: i += 1 assert lines[i] == json.dumps(['FUNC', 'clearColor', 1.0, 1.0, 1.0, 1.0]) i += 1 assert lines[i] == json.dumps(['FUNC', 'clear', 17664]) i += 1 assert lines[i] == json.dumps(['FUNC', 'finish']) i += 1 config.update(glir_file='')
def test_use_framebuffer(): """Test drawing to a framebuffer""" shape = (100, 300) # for some reason Windows wants a tall window... data = np.random.rand(*shape).astype(np.float32) use_shape = shape + (3, ) with Canvas(size=shape[::-1]) as c: orig_tex = Texture2D(data) fbo_tex = Texture2D(use_shape, format='rgb') rbo = RenderBuffer(shape, 'color') fbo = FrameBuffer(color=fbo_tex) c._glir.set_verbose(True) assert_equal(c.size, shape[::-1]) set_viewport((0, 0) + c.size) with fbo: draw_texture(orig_tex) draw_texture(fbo_tex) out_tex = _screenshot()[::-1, :, 0].astype(np.float32) assert_equal(out_tex.shape, c.size[::-1]) assert_raises(TypeError, FrameBuffer.color_buffer.fset, fbo, 1.) assert_raises(TypeError, FrameBuffer.depth_buffer.fset, fbo, 1.) assert_raises(TypeError, FrameBuffer.stencil_buffer.fset, fbo, 1.) fbo.color_buffer = rbo fbo.depth_buffer = RenderBuffer(shape) fbo.stencil_buffer = None print((fbo.color_buffer, fbo.depth_buffer, fbo.stencil_buffer)) clear(color='black') with fbo: clear(color='black') draw_texture(orig_tex) out_rbo = _screenshot()[:, :, 0].astype(np.float32) assert_allclose(data * 255., out_tex, atol=1) assert_allclose(data * 255., out_rbo, atol=1)
def test_context_properties(): """Test setting context properties""" a = use_app() if a.backend_name.lower() == 'pyglet': return # cannot set more than once on Pyglet # stereo, double buffer won't work on every sys configs = [dict(samples=4), dict(stencil_size=8), dict(samples=4, stencil_size=8)] if a.backend_name.lower() != 'glfw': # glfw *always* double-buffers configs.append(dict(double_buffer=False, samples=4)) configs.append(dict(double_buffer=False)) else: assert_raises(RuntimeError, Canvas, app=a, config=dict(double_buffer=False)) if a.backend_name.lower() == 'sdl2' and os.getenv('TRAVIS') == 'true': raise SkipTest('Travis SDL cannot set context') for config in configs: n_items = len(config) with Canvas(config=config): if 'true' in (os.getenv('TRAVIS', ''), os.getenv('APPVEYOR', '').lower()): # Travis and Appveyor cannot handle obtaining these values props = config else: props = get_gl_configuration() assert_equal(len(config), n_items) for key, val in config.items(): # XXX knownfail for windows samples, and wx (all platforms) if key == 'samples': iswx = a.backend_name.lower() == 'wx' if not (sys.platform.startswith('win') or iswx): assert_equal(val, props[key], key) assert_raises(TypeError, Canvas, config='foo') assert_raises(KeyError, Canvas, config=dict(foo=True)) assert_raises(TypeError, Canvas, config=dict(double_buffer='foo'))
def test_text(): """Test basic text support""" # test a simple cases data = ( np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 1, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 1, 1, 0, 0]]) * 255).astype(np.uint8) expd = ( np.array([ [8, 5, 4, 4, 4, 4, 4, 5, 8], [5, 2, 1, 1, 1, 1, 1, 2, 5], [4, 1, 0, 0, 0, 0, 0, 1, 4], [4, 1, 0, -1, -4, -1, 0, 1, 4], # XXX artifact [4, 1, 0, -1, -4, -1, 0, 1, 4], [4, 1, 0, -1, -4, -1, 0, 1, 4] ])) expd = 0.5 - (np.sqrt(np.abs(expd)) * np.sign(expd)) / 256. * 8 expd = np.round(256 * expd).astype(np.int) with Canvas(size=(100, 100)): tex = gloo.Texture2D(shape=data.shape + (3, ), dtype=np.ubyte, format='rgb') SDFRenderer().render_to_texture(data, tex, (0, 0), data.shape[::-1]) gloo.set_viewport(0, 0, *data.shape[::-1]) gloo.util.draw_texture(tex) result = gloo.util._screenshot()[:, :, 0].astype(np.int) print(result) print(expd) assert_allclose(result, expd, atol=1)
def _test_functionality(backend): """Create app and canvas so we have a context. Then run tests.""" # use the backend gl.use_gl(backend) with Canvas() as canvas: _clear_screen() # Prepare w, h = canvas.size gl.glViewport(0, 0, w, h) gl.glScissor(0, 0, w, h) # touch gl.glClearColor(0.0, 0.0, 0.0, 1.0) # Setup visualization, ensure to do it in a draw event objects = _prepare_vis() _clear_screen() _draw1() _clear_screen() _draw2() _clear_screen() _draw3() # Clean up for delete_func, handle in objects: delete_func(handle) gl.glFinish()
def test_capabilities(): """Test GLIR capability reporting """ with Canvas() as c: capabilities = c.context.shared.parser.capabilities assert capabilities['max_texture_size'] is not None assert capabilities['gl_version'] != 'unknown'
def test_use_uniforms(): """Test using uniform arrays""" VERT_SHADER = """ attribute vec2 a_pos; varying vec2 v_pos; void main (void) { v_pos = a_pos; gl_Position = vec4(a_pos, 0., 1.); } """ FRAG_SHADER = """ varying vec2 v_pos; uniform vec3 u_color[2]; void main() { gl_FragColor = vec4((u_color[0] + u_color[1]) / 2., 1.); } """ shape = (500, 500) with Canvas(size=shape) as c: c.set_current() c.context.glir.set_verbose(True) assert_equal(c.size, shape[::-1]) shape = (3, 3) set_viewport((0, 0) + shape) program = Program(VERT_SHADER, FRAG_SHADER) program['a_pos'] = [[-1., -1.], [1., -1.], [-1., 1.], [1., 1.]] program['u_color'] = np.ones((2, 3)) c.context.clear('k') c.set_current() program.draw('triangle_strip') out = _screenshot() assert_allclose(out[:, :, 0] / 255., np.ones(shape), atol=1. / 255.) # now set one element program['u_color[1]'] = np.zeros(3, np.float32) c.context.clear('k') program.draw('triangle_strip') out = _screenshot() assert_allclose(out[:, :, 0] / 255., 127.5 / 255. * np.ones(shape), atol=1. / 255.) # and the other assert_raises(ValueError, program.__setitem__, 'u_color', np.zeros(3, np.float32)) program['u_color'] = np.zeros((2, 3), np.float32) program['u_color[0]'] = np.ones(3, np.float32) c.context.clear((0.33, ) * 3) program.draw('triangle_strip') out = _screenshot() assert_allclose(out[:, :, 0] / 255., 127.5 / 255. * np.ones(shape), atol=1. / 255.)
def test_wrappers(): """Test gloo wrappers""" with Canvas(): gl.use_gl('desktop debug') gloo.clear('#112233') # make it so that there's something non-zero # check presets assert_raises(ValueError, gloo.set_state, preset='foo') for state in gloo.get_state_presets().keys(): gloo.set_state(state) assert_raises(ValueError, gloo.set_blend_color, (0., 0.)) # bad color assert_raises(TypeError, gloo.set_hint, 1, 2) # need strs assert_raises(TypeError, gloo.get_parameter, 1) # need str # this doesn't exist in ES 2.0 namespace assert_raises(ValueError, gloo.set_hint, 'fog_hint', 'nicest') # test bad enum assert_raises(RuntimeError, gloo.set_line_width, -1) # check read_pixels x = gloo.read_pixels() assert_true(isinstance(x, np.ndarray)) assert_true(isinstance(gloo.read_pixels((0, 0, 1, 1)), np.ndarray)) assert_raises(ValueError, gloo.read_pixels, (0, 0, 1)) # bad port y = gloo.read_pixels(alpha=False, out_type=np.ubyte) assert_equal(y.shape, x.shape[:2] + (3, )) assert_array_equal(x[..., :3], y) y = gloo.read_pixels(out_type='float') assert_allclose(x / 255., y) # now let's (indirectly) check our set_* functions viewport = (0, 0, 1, 1) blend_color = (0., 0., 0.) _funs = dict( viewport=viewport, # checked hint=('generate_mipmap_hint', 'nicest'), depth_range=(1., 2.), front_face='cw', # checked cull_face='front', line_width=1., polygon_offset=(1., 1.), blend_func=('zero', 'one'), blend_color=blend_color, blend_equation='func_add', scissor=(0, 0, 1, 1), stencil_func=('never', 1, 2, 'back'), stencil_mask=4, stencil_op=('zero', 'zero', 'zero', 'back'), depth_func='greater', depth_mask=True, color_mask=(True, True, True, True), sample_coverage=(0.5, True)) gloo.set_state(**_funs) gloo.clear((1., 1., 1., 1.), 0.5, 1) gloo.flush() gloo.finish() # check some results assert_array_equal(gloo.get_parameter('viewport'), viewport) assert_equal(gloo.get_parameter('front_face'), gl.GL_CW) assert_equal(gloo.get_parameter('blend_color'), blend_color + (1, ))
def test_fs(): """Test fullscreen support""" a = use_app() if not a.backend_module.capability['fullscreen']: return assert_raises(TypeError, Canvas, fullscreen='foo') if (a.backend_name.lower() == 'glfw' or (a.backend_name.lower() == 'sdl2' and sys.platform == 'darwin')): raise SkipTest('Backend takes over screen') with use_log_level('warning', record=True, print_msg=False) as l: with Canvas(fullscreen=False) as c: assert_equal(c.fullscreen, False) c.fullscreen = True assert_equal(c.fullscreen, True) assert_equal(len(l), 0) with use_log_level('warning', record=True, print_msg=False): # some backends print a warning b/c fullscreen can't be specified with Canvas(fullscreen=0) as c: assert_equal(c.fullscreen, True)
def test_read_pixels(): """Test read_pixels to ensure that the image is not flipped""" # Create vertices vPosition = np.array( [ [-1, 1, 0.0], [0, 1, 0.5], # For drawing a square to top left [-1, 0, 0.0], [0, 0, 0.5] ], np.float32) VERT_SHADER = """ // simple vertex shader attribute vec3 a_position; void main (void) { gl_Position = vec4(a_position, 1.0); } """ FRAG_SHADER = """ // simple fragment shader void main() { gl_FragColor = vec4(1,1,1,1); } """ with Canvas() as c: c.set_current() gloo.set_viewport(0, 0, *c.size) gloo.set_state(depth_test=True) c._program = gloo.Program(VERT_SHADER, FRAG_SHADER) c._program['a_position'] = gloo.VertexBuffer(vPosition) gloo.clear(color='black') c._program.draw('triangle_strip') # Check if the return of read_pixels is the same as our drawing img = read_pixels(alpha=False) assert_equal(img.shape[:2], c.size[::-1]) top_left = sum(img[0, 0]) assert_true(top_left > 0) # Should be > 0 (255*4) # Sum of the pixels in top right + bottom left + bottom right corners corners = sum(img[0, -1] + img[-1, 0] + img[-1, -1]) assert_true(corners == 0) # Should be all 0 gloo.flush() gloo.finish() # Check that we can read the depth buffer img = read_pixels(mode='depth') assert_equal(img.shape[:2], c.size[::-1]) assert_equal(img.shape[2], 1) unique_img = np.unique(img) # we should have quite a few different depth values assert unique_img.shape[0] > 50 assert unique_img.max() == 255 assert unique_img.min() > 0
def test_close_keys(): """Test close keys""" c = Canvas(keys='interactive') x = list() @c.events.close.connect def closer(event): x.append('done') c.events.key_press(key=keys.ESCAPE, text='', modifiers=[]) assert_equal(len(x), 1) # ensure the close event was sent c.app.process_events()
def test_run(): """Test app running""" for _ in range(2): with Canvas(size=(100, 100), show=True, title='run') as c: @c.events.draw.connect def draw(event): print(event) # test event __repr__ c.app.quit() c.update() c.app.run() c.app.quit() # make sure it doesn't break if a user quits twice
def test_sdf(): """Test basic text support - sdf""" # test a simple case data = (np.array( [[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 1, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 1, 1, 0, 0]]) * 255).astype(np.uint8) # The GPU data at one point were derived this way: # gpu = np.array( # [[8, 5, 4, 4, 4, 4, 4, 5, 8], # [5, 2, 1, 1, 1, 1, 1, 2, 5], # [4, 1, 0, 0, 0, 0, 0, 1, 4], # [4, 1, 0, -1, -4, -1, 0, 1, 4], # XXX artifact # [4, 1, 0, -1, -4, -1, 0, 1, 4], # [4, 1, 0, -1, -4, -1, 0, 1, 4]]) # gpu = 0.5 - (np.sqrt(np.abs(gpu)) * np.sign(gpu)) / 256. * 8 # gpu = np.round(256 * gpu).astype(np.int) # # But it's perhaps clearer just to give what will actually be compared: gpu = np.array( [[105, 110, 112, 112, 112, 112, 112, 110, 105], [110, 117, 120, 120, 120, 120, 120, 117, 110], [112, 120, 128, 128, 128, 128, 128, 120, 112], [112, 120, 128, 136, 144, 136, 128, 120, 112], [112, 120, 128, 136, 144, 136, 128, 120, 112], [112, 120, 128, 136, 144, 136, 128, 120, 112]]) cpu = np.array( [[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 115, 118, 118, 118, 118, 118, 115, 0], [0, 118, 137, 137, 137, 137, 137, 118, 0], [0, 118, 137, 143, 143, 143, 137, 118, 0], [0, 118, 137, 143, 149, 143, 137, 118, 0], [0, 0, 255, 255, 255, 255, 255, 0, 0]]) # XXX: The GPU and CPU solutions are quite different. # It doesn't seem to have much effect on the visualizations but would be # good to fix eventually. for Rend, expd in zip((SDFRendererGPU, SDFRendererCPU), (gpu, cpu)): with Canvas(size=(100, 100)) as c: tex = gloo.Texture2D(data.shape + (3,), format='rgb') Rend().render_to_texture(data, tex, (0, 0), data.shape[::-1]) gloo.set_viewport(0, 0, *data.shape[::-1]) gloo.util.draw_texture(tex) result = gloo.util._screenshot()[:, :, 0].astype(np.int) assert_allclose(result, expd, atol=1, err_msg=Rend.__name__) del tex, result del c # Do some garbage collection to make sure backend applications (PyQt5) actually clear things out gc.collect()
def test_use_texture3D(): """Test using a 3D texture""" vals = [0, 200, 100, 0, 255, 0, 100] d, h, w = len(vals), 3, 5 data = np.zeros((d, h, w), np.float32) VERT_SHADER = """ attribute vec2 a_pos; varying vec2 v_pos; void main (void) { v_pos = a_pos; gl_Position = vec4(a_pos, 0., 1.); } """ FRAG_SHADER = """ uniform sampler3D u_texture; varying vec2 v_pos; uniform float i; void main() { gl_FragColor = texture3D(u_texture, vec3((v_pos.y+1.)/2., (v_pos.x+1.)/2., i)); gl_FragColor.a = 1.; } """ # populate the depth "slices" with different gray colors in the bottom left for ii, val in enumerate(vals): data[ii, :2, :3] = val / 255. with Canvas(size=(100, 100)) as c: if not has_pyopengl(): t = Texture3D(data) assert_raises(ImportError, t.glir.flush, c.context.shared.parser) return program = Program(VERT_SHADER, FRAG_SHADER) program['a_pos'] = [[-1., -1.], [1., -1.], [-1., 1.], [1., 1.]] tex = Texture3D(data, interpolation='nearest') assert_equal(tex.width, w) assert_equal(tex.height, h) assert_equal(tex.depth, d) program['u_texture'] = tex for ii, val in enumerate(vals): set_viewport(0, 0, w, h) clear(color='black') iii = (ii + 0.5) / float(d) print(ii, iii) program['i'] = iii program.draw('triangle_strip') out = _screenshot()[:, :, 0].astype(int)[::-1] expected = np.zeros_like(out) expected[:2, :3] = val assert_allclose(out, expected, atol=1. / 255.)
def test_qt_designer(): """Embed Canvas via Qt Designer""" global win win = MainWindow() win.show() canvas = Canvas(native=win.ui.canvas) @canvas.events.paint.connect def on_paint(ev): gl.glClearColor(0.0, 0.0, 0.0, 0.0) gl.glClear(gl.GL_COLOR_BUFFER_BIT) canvas.swap_buffers()
def _test_basics(backend): """Create app and canvas so we have a context. Then run tests.""" # use the backend with use_log_level('error', print_msg=False): gl.use_gl(backend) # pyopengl throws warning on injection with Canvas(): _test_setting_parameters() _test_enabling_disabling() _test_setting_stuff() _test_object_creation_and_deletion() _test_fbo() gl.glFinish()
def test_run(): """Test app running""" a = use_app() if a.backend_name.lower() == 'glut': raise SkipTest('cannot test running glut') # knownfail for _ in range(2): with Canvas(size=(100, 100), show=True, title='run') as c: @c.events.draw.connect def draw(event): print(event) # test event __repr__ c.app.quit() c.update() c.app.run() c.app.quit() # make sure it doesn't break if a user quits twice
def test_canvas_render(blend_func): """Test rendering a canvas to an array. Different blending functions are used to test what various Visuals may produce without actually using different types of Visuals. """ with Canvas(size=(125, 125), show=True, title='run') as c: im1 = np.zeros((100, 100, 4)).astype(np.float32) im1[:, :, 0] = 1 im1[:, :, 3] = 1 im2 = np.zeros((50, 50, 4)).astype(np.float32) im2[:, :, 1] = 1 im2[:, :, 3] = 0.4 # Create the image image1 = ImageVisual(im1) image1.transform = STTransform(translate=(20, 20, 0)) image1.transforms.configure(canvas=c, viewport=(0, 0, 125, 125)) image2 = ImageVisual(im2) image2.transform = STTransform(translate=(0, 0, -1)) image2.transforms.configure(canvas=c, viewport=(0, 0, 125, 125)) if blend_func: image1.set_gl_state(preset='translucent', blend_func=blend_func) image2.set_gl_state(preset='translucent', blend_func=blend_func) @c.events.draw.connect def on_draw(ev): gloo.clear('black') gloo.set_viewport(0, 0, *c.physical_size) image1.draw() image2.draw() rgba_result = c.render() rgb_result = c.render(alpha=False) # the results should be the same except for alpha np.testing.assert_allclose(rgba_result[..., :3], rgb_result) # the image should have something drawn in it assert not np.allclose(rgba_result[..., :3], 0) # the alpha should not be completely transparent assert not np.allclose(rgba_result[..., 3], 0) if blend_func is None or 'one' in blend_func: # no transparency np.testing.assert_allclose(rgba_result[..., 3], 255) else: # the alpha should have some transparency assert (rgba_result[..., 3] != 255).any()
def test_basics_desktop(): """ Test desktop GL backend for basic functionality. """ _test_basics('gl2') with Canvas(): _test_setting_parameters() _test_enabling_disabling() _test_setting_stuff() _test_object_creation_and_deletion() _test_fbo() try: gl.gl2._get_gl_func('foo', None, ()) except RuntimeError as exp: exp = str(exp) assert 'version' in exp assert 'unknown' not in exp gl.glFinish()
def test_log_parser(): """Test GLIR log parsing""" glir_file = tempfile.TemporaryFile(mode='r+') config.update(glir_file=glir_file) with Canvas() as c: c.context.set_clear_color('white') c.context.clear() glir_file.seek(0) lines = glir_file.read().split(',\n') assert lines[0][0] == '[' lines[0] = lines[0][1:] assert lines[-1][-1] == ']' lines[-1] = lines[-1][:-1] i = 0 # The FBO argument may be anything based on the backend. expected = json.dumps(['CURRENT', 0, 1]) assert len(lines[i]) >= len(expected) expected = expected.split('1') assert lines[i].startswith(expected[0]) assert lines[i].endswith(expected[1]) assert int(lines[i][len(expected[0]):-len(expected[1])]) is not None # The 'CURRENT' command may have been called multiple times while lines[i].startswith('["CURRENT",'): i += 1 if lines[i] == json.dumps( ['FUNC', 'colorMask', False, False, False, True]): # Qt workaround, see #2040 i += 4 assert lines[i] == json.dumps(['FUNC', 'clearColor', 1.0, 1.0, 1.0, 1.0]) i += 1 assert lines[i] == json.dumps(['FUNC', 'clear', 17664]) i += 1 assert lines[i] == json.dumps(['FUNC', 'finish']) i += 1 config.update(glir_file='') glir_file.close()
def test_read_pixels(): """Test read_pixels to ensure that the image is not flipped""" # Create vertices vPosition = np.array( [ [-1, 1], [0, 1], # For drawing a square to top left [-1, 0], [0, 0] ], np.float32) VERT_SHADER = """ // simple vertex shader attribute vec2 a_position; void main (void) { gl_Position = vec4(a_position, 0., 1.0); } """ FRAG_SHADER = """ // simple fragment shader void main() { gl_FragColor = vec4(1,1,1,1); } """ with Canvas() as c: gloo.set_viewport(0, 0, *c.size) c._program = gloo.Program(VERT_SHADER, FRAG_SHADER) c._program['a_position'] = gloo.VertexBuffer(vPosition) gloo.clear(color='black') c._program.draw('triangle_strip') # Check if the return of read_pixels is the same as our drawing img = read_pixels(format='rgb') assert_equal(img.shape[:2], c.size[::-1]) top_left = sum(img[0, 0]) assert_true(top_left > 0) # Should be > 0 (255*4) # Sum of the pixels in top right + bottom left + bottom right corners corners = sum(img[0, -1] + img[-1, 0] + img[-1, -1]) assert_true(corners == 0) # Should be all 0 gloo.flush() gloo.finish()
def test_use_framebuffer(): """Test drawing to a framebuffer""" shape = (100, 300) # for some reason Windows wants a tall window... data = np.random.rand(*shape).astype(np.float32) use_shape = shape + (3, ) with Canvas(size=shape[::-1]) as c: c.app.process_events() c.set_current() if c.app.backend_name.lower() == 'pyqt5': # PyQt5 on OSX for some reason sets this to 1024x768... c.size = shape[::-1] c.app.process_events() orig_tex = Texture2D(data) fbo_tex = Texture2D(use_shape, format='rgb') rbo = RenderBuffer(shape, 'color') fbo = FrameBuffer(color=fbo_tex) c.context.glir.set_verbose(True) assert c.size == shape[::-1] c.set_current() set_viewport((0, 0) + c.size) with fbo: draw_texture(orig_tex) draw_texture(fbo_tex) out_tex = _screenshot()[::-1, :, 0].astype(np.float32) assert out_tex.shape == c.size[::-1] assert_raises(TypeError, FrameBuffer.color_buffer.fset, fbo, 1.) assert_raises(TypeError, FrameBuffer.depth_buffer.fset, fbo, 1.) assert_raises(TypeError, FrameBuffer.stencil_buffer.fset, fbo, 1.) fbo.color_buffer = rbo fbo.depth_buffer = RenderBuffer(shape) fbo.stencil_buffer = None print((fbo.color_buffer, fbo.depth_buffer, fbo.stencil_buffer)) clear(color='black') with fbo: clear(color='black') draw_texture(orig_tex) out_rbo = _screenshot()[:, :, 0].astype(np.float32) assert_allclose(data * 255., out_tex, atol=1) assert_allclose(data * 255., out_rbo, atol=1)