1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
|
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# author: Irwin Zaid
# vispy: gallery 2:40:4
"""
Animate an Image
================
Use a timer to trigger updating an image.
This example demonstrates a 3D Texture. The volume contains noise that
is smoothed in the z-direction. Shown is one slice through that volume
to give the effect of "morphing" noise.
"""
import numpy as np
from vispy.util.transforms import ortho
from vispy import gloo
from vispy import app
from vispy.visuals.shaders import ModularProgram
# Shape of image to be displayed
D, H, W = 30, 60, 90
# Modulated image
img_array = np.random.uniform(0, 0.1, (D, H, W, 3)).astype(np.float32)
# Depth slices are dark->light
img_array[...] += np.linspace(0, 0.9, D)[:, np.newaxis, np.newaxis, np.newaxis]
# Make vertical direction more green moving upward
img_array[..., 1] *= np.linspace(0, 1, H)[np.newaxis, :, np.newaxis]
# Make horizontal direction more red moving rightward
img_array[..., 0] *= np.linspace(0, 1, W)[np.newaxis, np.newaxis, :]
# A simple texture quad
data = np.zeros(4, dtype=[('a_position', np.float32, 2),
('a_texcoord', np.float32, 2)])
data['a_position'] = np.array([[0, 0], [W, 0], [0, H], [W, H]])
data['a_texcoord'] = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
VERT_SHADER = """
// Uniforms
uniform mat4 u_model;
uniform mat4 u_view;
uniform mat4 u_projection;
// Attributes
attribute vec2 a_position;
attribute vec2 a_texcoord;
// Varyings
varying vec2 v_texcoord;
// Main
void main (void)
{
v_texcoord = a_texcoord;
gl_Position = u_projection * u_view * u_model * vec4(a_position,0.0,1.0);
}
"""
FRAG_SHADER = """
uniform $sampler_type u_texture;
uniform float i;
varying vec2 v_texcoord;
void main()
{
// step through gradient with i, note that slice (depth) comes last here!
gl_FragColor = $sample(u_texture, vec3(v_texcoord, i));
gl_FragColor.a = 1.0;
}
"""
class Canvas(app.Canvas):
def __init__(self, emulate3d=True):
app.Canvas.__init__(self, keys='interactive', size=((W*5), (H*5)))
if emulate3d:
tex_cls = gloo.TextureEmulated3D
else:
tex_cls = gloo.Texture3D
self.texture = tex_cls(img_array, interpolation='nearest',
wrapping='clamp_to_edge')
self.program = ModularProgram(VERT_SHADER, FRAG_SHADER)
self.program.frag['sampler_type'] = self.texture.glsl_sampler_type
self.program.frag['sample'] = self.texture.glsl_sample
self.program['u_texture'] = self.texture
self.program['i'] = 0.0
self.program.bind(gloo.VertexBuffer(data))
self.view = np.eye(4, dtype=np.float32)
self.model = np.eye(4, dtype=np.float32)
self.projection = np.eye(4, dtype=np.float32)
self.program['u_model'] = self.model
self.program['u_view'] = self.view
self.projection = ortho(0, W, 0, H, -1, 1)
self.program['u_projection'] = self.projection
self.i = 0
gloo.set_clear_color('white')
self._timer = app.Timer('auto', connect=self.on_timer, start=True)
self.show()
def on_resize(self, event):
width, height = event.physical_size
gloo.set_viewport(0, 0, width, height)
self.projection = ortho(0, width, 0, height, -100, 100)
self.program['u_projection'] = self.projection
# Compute the new size of the quad
r = width / float(height)
R = W / float(H)
if r < R:
w, h = width, width / R
x, y = 0, int((height - h) / 2)
else:
w, h = height * R, height
x, y = int((width - w) / 2), 0
data['a_position'] = np.array(
[[x, y], [x + w, y], [x, y + h], [x + w, y + h]])
self.program.bind(gloo.VertexBuffer(data))
def on_timer(self, event):
# cycle every 2 sec
self.i = (self.i + 1./120.) % 1.0
self.update()
def on_draw(self, event):
gloo.clear(color=True, depth=True)
self.program['i'] = 1.9 * np.abs(0.5 - self.i)
self.program.draw('triangle_strip')
if __name__ == '__main__':
# Use emulated3d to switch from an emulated 3D texture to an actual one
canvas = Canvas(emulate3d=True)
app.run()
|