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
|
# -*- coding: utf-8 -*-
# -----------------------------------------------------------------------------
# Copyright (c) Vispy Development Team. All Rights Reserved.
# Distributed under the (new) BSD License. See LICENSE.txt for more info.
# -----------------------------------------------------------------------------
# Author: Nicolas P .Rougier
# Date: 06/03/2014
# Abstract: Water ripple effect following mouse
# Keywords: antialias, water, mouse
# -----------------------------------------------------------------------------
import numpy as np
from vispy import gloo, app
from vispy.gloo import Program, VertexBuffer
from vispy.util.transforms import ortho
vertex = """
#version 120
uniform mat4 u_model;
uniform mat4 u_view;
uniform mat4 u_projection;
uniform float u_linewidth;
uniform float u_antialias;
attribute vec3 a_position;
attribute vec4 a_fg_color;
attribute float a_size;
varying vec4 v_fg_color;
varying float v_size;
void main (void)
{
v_size = a_size;
v_fg_color = a_fg_color;
if( a_fg_color.a > 0.0)
{
gl_Position = u_projection * u_view * u_model * vec4(a_position,1.0);
gl_PointSize = v_size + u_linewidth + 2.*1.5*u_antialias;
}
else
{
gl_Position = u_projection * u_view * u_model * vec4(-1.,-1.,0.,1.);
gl_PointSize = 0.0;
}
}
"""
fragment = """
#version 120
uniform float u_linewidth;
uniform float u_antialias;
varying vec4 v_fg_color;
varying vec4 v_bg_color;
varying float v_size;
float disc(vec2 P, float size)
{
return length((P.xy - vec2(0.5,0.5))*size);
}
void main()
{
if( v_fg_color.a <= 0.0)
discard;
float actual_size = v_size + u_linewidth + 2*1.5*u_antialias;
float t = u_linewidth/2.0 - u_antialias;
float r = disc(gl_PointCoord, actual_size);
float d = abs(r - v_size/2.0) - t;
if( d < 0.0 )
{
gl_FragColor = v_fg_color;
}
else if( abs(d) > 2.5*u_antialias )
{
discard;
}
else
{
d /= u_antialias;
gl_FragColor = vec4(v_fg_color.rgb, exp(-d*d)*v_fg_color.a);
}
}
"""
class Canvas(app.Canvas):
def __init__(self):
app.Canvas.__init__(self, title='Rain [Move mouse]',
size=(512, 512), keys='interactive')
# Build data
# --------------------------------------
n = 500
self.data = np.zeros(n, [('a_position', np.float32, 2),
('a_fg_color', np.float32, 4),
('a_size', np.float32)])
self.index = 0
self.program = Program(vertex, fragment)
self.vdata = VertexBuffer(self.data)
self.program.bind(self.vdata)
self.program['u_antialias'] = 1.00
self.program['u_linewidth'] = 1.00
self.program['u_model'] = np.eye(4, dtype=np.float32)
self.program['u_view'] = np.eye(4, dtype=np.float32)
self.activate_zoom()
gloo.set_clear_color('white')
gloo.set_state(blend=True,
blend_func=('src_alpha', 'one_minus_src_alpha'))
self.timer = app.Timer('auto', self.on_timer, start=True)
self.show()
def on_draw(self, event):
gloo.clear()
self.program.draw('points')
def on_resize(self, event):
self.activate_zoom()
def activate_zoom(self):
gloo.set_viewport(0, 0, *self.physical_size)
projection = ortho(0, self.size[0], 0,
self.size[1], -1, +1)
self.program['u_projection'] = projection
def on_timer(self, event):
self.data['a_fg_color'][..., 3] -= 0.01
self.data['a_size'] += 1.0
self.vdata.set_data(self.data)
self.update()
def on_mouse_move(self, event):
x, y = event.pos
h = self.size[1]
self.data['a_position'][self.index] = x, h - y
self.data['a_size'][self.index] = 5
self.data['a_fg_color'][self.index] = 0, 0, 0, 1
self.index = (self.index + 1) % 500
if __name__ == '__main__':
canvas = Canvas()
app.run()
|