Source code for plato.draw.vispy.Spheres

import itertools

import numpy as np

from ... import mesh
from .internal import GLPrimitive, GLShapeDecorator
from ... import draw
from ..internal import ShapeAttribute
from ..Scene import DEFAULT_DIRECTIONAL_LIGHTS

[docs]@GLShapeDecorator class Spheres(draw.Spheres, GLPrimitive): __doc__ = draw.Spheres.__doc__ shaders = {} shaders['vertex'] = """ uniform mat4 camera; uniform vec4 rotation; uniform vec3 translation; uniform int transparency_mode; attribute vec4 color; attribute vec3 position; attribute vec2 image; attribute float radius; attribute vec4 shape_id; varying vec4 v_color; varying vec3 v_position; varying vec2 v_image; varying float v_radius; varying float v_depth; varying vec4 v_shape_id; vec3 rotate(vec3 point, vec4 quat) { vec3 result = (quat.x*quat.x - dot(quat.yzw, quat.yzw))*point; result += 2.0*quat.x*cross(quat.yzw, point); result += 2.0*dot(quat.yzw, point)*quat.yzw; return result; } void main() { vec3 vertexPos = position; vec2 localPos = image*radius; vertexPos = rotate(vertexPos, rotation) + vec3(localPos, 0.0) + translation; vec4 screenPosition = camera * vec4(vertexPos, 1.0); int should_discard = 0; should_discard += int(transparency_mode < 0 && color.a < 1.0); should_discard += int(transparency_mode > 0 && color.a >= 1.0); if(should_discard > 0) screenPosition = vec4(2.0, 2.0, 2.0, 2.0); // transform to screen coordinates gl_Position = screenPosition; v_color = color; v_image = localPos; v_radius = radius; v_position = vertexPos; v_depth = vertexPos.z; v_shape_id = shape_id; } """ shaders['fragment'] = """ #ifdef GL_ES precision highp float; #endif // base light level uniform float ambientLight; // (x, y, z) direction*intensity uniform vec3 diffuseLight[NUM_DIFFUSELIGHT]; uniform int transparency_mode; uniform mat4 camera; uniform float light_levels; uniform float outline; varying vec4 v_color; varying vec2 v_image; varying float v_radius; varying float v_depth; void main() { float rsq = dot(v_image, v_image); float Rsq = v_radius*v_radius; float r = sqrt(rsq); float lambda1 = 1.0; if(outline > 1e-6) { lambda1 = (v_radius - r)/outline; lambda1 *= lambda1; lambda1 *= lambda1; lambda1 *= lambda1; lambda1 *= lambda1; lambda1 = min(lambda1, 1.0); } if(r > v_radius) discard; vec3 r_local = vec3(v_image.xy, sqrt(Rsq - rsq)); vec3 normal = normalize(r_local); float light = ambientLight; for(int i = 0; i < NUM_DIFFUSELIGHT; ++i) light += max(0.0, -dot(normal, diffuseLight[i])); if(light_levels > 0.0) { light *= light_levels; light = floor(light); light /= light_levels; } vec4 color = vec4(v_color.xyz*lambda1*light, v_color.w); #ifndef WEBGL float depth = v_depth + r_local.z; gl_FragDepth = 0.5*(camera[2][2]*depth + camera[3][2] + camera[2][3]*depth + camera[3][3])/(camera[2][3]*depth + camera[3][3]); #endif float z = abs(v_depth); float alpha = color.a; float weight = alpha*max(3e3*pow( (1.0 - gl_FragCoord.z), 3.0), 1e-2); if(transparency_mode < 1) gl_FragColor = color; else if(transparency_mode == 1) gl_FragColor = vec4(color.rgb*alpha, alpha)*weight; else gl_FragColor = vec4(alpha); } """ shaders['fragment_plane'] = """ // base light level uniform mat4 camera; uniform float render_positions = 0.0; varying vec3 v_position; varying vec2 v_image; varying float v_radius; varying float v_depth; void main() { float rsq = dot(v_image, v_image); float Rsq = v_radius*v_radius; if(rsq > Rsq) discard; vec3 r_local = vec3(v_image.xy, sqrt(Rsq - rsq)); vec3 normal = normalize(r_local); #ifndef WEBGL float depth = v_depth + r_local.z; gl_FragDepth = 0.5*(camera[2][2]*depth + camera[3][2] + camera[2][3]*depth + camera[3][3])/(camera[2][3]*depth + camera[3][3]); #endif if(render_positions > 0.5) gl_FragColor = vec4(gl_FragCoord.xyz, 1.0); else if(render_positions < -0.5) gl_FragColor = 0.5 + 0.5*vec4(normal.xyz, 1.0); else // Store the plane equation as a color gl_FragColor = vec4(normal, dot(normal, v_position.xyz)); } """ shaders['fragment_pick'] = """ uniform mat4 camera; uniform vec4 pick_prim_index; varying vec3 v_position; varying vec2 v_image; varying float v_radius; varying float v_depth; varying vec4 v_shape_id; void main() { float rsq = dot(v_image, v_image); float Rsq = v_radius*v_radius; if(rsq > Rsq) discard; vec3 r_local = vec3(v_image.xy, sqrt(Rsq - rsq)); vec3 normal = normalize(r_local); #ifndef WEBGL float depth = v_depth + r_local.z; gl_FragDepth = 0.5*(camera[2][2]*depth + camera[3][2] + camera[2][3]*depth + camera[3][3])/(camera[2][3]*depth + camera[3][3]); #endif gl_FragColor = pick_prim_index + v_shape_id; } """ _vertex_attribute_names = ['shape_id', 'position', 'color', 'radius', 'image'] _GL_UNIFORMS = list(itertools.starmap(ShapeAttribute, [ ('camera', np.float32, np.eye(4), 2, False, 'Internal: 4x4 Camera matrix for world projection'), ('ambientLight', np.float32, .25, 0, False, 'Internal: Ambient (minimum) light level for all surfaces'), ('diffuseLight[]', np.float32, DEFAULT_DIRECTIONAL_LIGHTS, 2, False, 'Internal: Diffuse light direction*magnitude'), ('rotation', np.float32, (1, 0, 0, 0), 1, False, 'Internal: Rotation to be applied to each scene as a quaternion'), ('translation', np.float32, (0, 0, 0), 1, False, 'Internal: Translation to be applied to the scene'), ('transparency_mode', np.int32, 0, 0, False, 'Internal: Transparency stage (<0: opaque, 0: all, 1: ' 'translucency stage 1, 2: translucency stage 2)'), ('light_levels', np.float32, 0, 0, False, 'Number of light levels to quantize to (0: disable)'), ('outline', np.float32, 0, 0, False, 'Outline for all particles') ])) def __init__(self, *args, **kwargs): GLPrimitive.__init__(self) draw.Spheres.__init__(self, *args, **kwargs) def update_arrays(self): try: for name in self._dirty_attributes: self._gl_vertex_arrays[name][:] = self._attributes[name] self._dirty_vertex_attribs.add(name) except (ValueError, KeyError): # vertices for an equilateral triangle triangle = np.array([[2, 0], [-1, np.sqrt(3)], [-1, -np.sqrt(3)]], dtype=np.float32)*1.01 shape_ids = np.arange(len(self), dtype=np.uint32).view(np.uint8).reshape((-1, 4)) shape_ids = shape_ids.astype(np.float32)/255 vertex_arrays = mesh.unfoldProperties( [shape_ids, self.positions, self.colors, self.radii.reshape((-1, 1))], [triangle]) unfolded_shape = vertex_arrays[0].shape[:-1] indices = (np.arange(unfolded_shape[0])[:, np.newaxis, np.newaxis]*unfolded_shape[1] + np.array([[0, 1, 2]], dtype=np.uint32)) indices = indices.reshape((-1, 3)) self._finalize_array_updates(indices, vertex_arrays) self._dirty_attributes.clear()