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
|
# -*- coding: utf-8 -*-
# Copyright (c) Vispy Development Team. All Rights Reserved.
# Distributed under the (new) BSD License. See LICENSE.txt for more info.
"""
Material components are modular shader components used for modifying fragment
colors to change the visual's appearance.
These generally create a function in the fragment shader that accepts a vec4
color as its only argument and returns a modified vec4 color.
"""
from __future__ import division
from .component import VisualComponent
from ..shaders import Varying
class GridContourComponent(VisualComponent):
"""
Draw grid lines across a surface.
"""
SHADERS = dict(
frag_color="""
vec4 grid_contour(vec4 color) {
if ( mod($pos.x, $spacing.x) < 0.005 ||
mod($pos.y, $spacing.y) < 0.005 ||
mod($pos.z, $spacing.z) < 0.005 ) {
return color + 0.7 * (vec4(1,1,1,1) - color);
}
else {
return color;
}
}
""",
vert_post_hook="""
void grid_contour_support() {
$output_pos = local_position();
}
""")
def __init__(self, spacing):
super(GridContourComponent, self).__init__()
self.spacing = spacing
# Create Varying to connect vertex / fragment shaders
var = Varying('pos', dtype='vec4')
self._funcs['frag_color']['pos'] = var
self._funcs['vert_post_hook']['output_pos'] = var
@property
def color(self):
return self._color
@color.setter
def color(self, c):
self._color = c
def activate(self, program, mode):
ff = self._funcs['frag_color']
ff['spacing'] = self.spacing # uniform vec3
class ShadingComponent(VisualComponent):
"""
Phong reflection and shading material.
"""
SHADERS = dict(
frag_color="""
vec4 shading(vec4 color) {
vec3 norm = normalize($normal().xyz);
vec3 light = normalize($light_direction.xyz);
float p = dot(light, norm);
p = (p < 0. ? 0. : p);
vec4 diffuse = $light_color * p;
diffuse.a = 1.0;
p = dot(reflect(light, norm), vec3(0,0,1));
if (p < 0.0) {
p = 0.0;
}
vec4 specular = $light_color * 5.0 * pow(p, 100.);
return color * ($ambient + diffuse) + specular;
}
""")
def __init__(self, normal_comp, lights, ambient=0.2):
super(ShadingComponent, self).__init__()
self.normal_comp = normal_comp
self._deps = [normal_comp]
self.lights = lights
self.ambient = ambient
def activate(self, program, mode):
# Normals are generated by output of another component
ff = self._funcs['frag_color']
ff['normal'] = self.normal_comp.normal_shader()
# TODO: add support for multiple lights
ff['light_direction'] = tuple(self.lights[0][0][:3]) + (1,) # u vec4
ff['light_color'] = tuple(self.lights[0][1][:3]) + (1,) # u vec4
ff['ambient'] = self.ambient # u float
|