Skip to content

Instantly share code, notes, and snippets.

@GuillaumeFavelier
Last active June 10, 2020 22:11
Show Gist options
  • Save GuillaumeFavelier/d12b3f9406b68b11bcae09bddfdbaf3e to your computer and use it in GitHub Desktop.
Save GuillaumeFavelier/d12b3f9406b68b11bcae09bddfdbaf3e to your computer and use it in GitHub Desktop.
This file is here to name the Gist.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
This example is a prototype demonstrating normal mapping
by using a subsample version of a plane with textures.
"""
import numpy as np
from vispy import app, gloo
from vispy .io import imread
from vispy.geometry import create_plane
from vispy.util.transforms import perspective, translate
vert = """
uniform mat4 u_model;
uniform mat4 u_view;
uniform mat4 u_projection;
uniform vec3 u_light;
attribute vec3 a_position;
attribute vec2 a_texcoord;
varying vec2 v_texcoord;
varying vec3 v_light_vec;
varying vec3 v_eye_vec;
varying vec4 v_ambientk;
varying vec4 v_light_color;
void main()
{
v_texcoord = a_texcoord;
v_ambientk = vec4(0.3, 0.3, 0.3, 1.0);
v_light_color = vec4(1.0, 1.0, 1.0, 1.0);
vec3 position = a_position;
v_light_vec = normalize(u_light);
v_eye_vec = normalize(vec3(0, 0, 5));
gl_Position = u_projection * u_view * u_model * vec4(position,1.0);
}
"""
frag = """
uniform sampler2D a_texture;
uniform sampler2D a_normal;
varying vec2 v_texcoord;
varying vec3 v_light_vec;
varying vec3 v_eye_vec;
varying vec4 v_ambientk;
varying vec4 v_light_color;
void main() {
vec4 v_base_color = texture2D(a_texture, v_texcoord);
vec3 v_normal_vec = texture2D(a_normal, v_texcoord).xyz * 2.0 - 1.0;
// disabled because of artifact
float shininess = 0.0;
//float shininess = 1. / 200.;
//DIFFUSE
float diffusek = dot(v_light_vec, v_normal_vec);
// clamp, because 0 < theta < pi/2
diffusek = clamp(diffusek, 0.0, 1.0);
vec4 diffuse_color = v_light_color * diffusek;
//SPECULAR
//reflect light wrt normal for the reflected ray, then
//find the angle made with the eye
float speculark = 0.0;
if (shininess > 0.) {
speculark = dot(reflect(v_light_vec, v_normal_vec), v_eye_vec);
speculark = clamp(speculark, 0.0, 1.0);
//raise to the material's shininess, multiply with a
//small factor for spread
speculark = 20.0 * pow(speculark, 1.0 / shininess);
}
vec4 specular_color = v_light_color * speculark;
gl_FragColor = v_base_color * (v_ambientk + diffuse_color) + specular_color;
}
""" # noqa
def mesh(n_segments=5, length=3):
v, indices, _ = create_plane(width=length,
height=length,
width_segments=n_segments,
height_segments=n_segments)
return v['position'], v['texcoord'], indices
# -----------------------------------------------------------------------------
class Canvas(app.Canvas):
def __init__(self):
app.Canvas.__init__(self, keys='interactive', size=(800, 600))
self.theta = 0.0
self.light_distance = 10.0
self.filled_buf = gloo.IndexBuffer(filled)
self.program = gloo.Program(vert, frag)
self.buffer = np.array(list(zip(vertices, texcoord)),
dtype=[('a_position', np.float32, 3),
('a_texcoord', np.float32, 2)])
self.program.bind(gloo.VertexBuffer(self.buffer))
self.view = translate((0, 0, -5))
self.model = np.eye(4, dtype=np.float32)
gloo.set_viewport(0, 0, self.physical_size[0], self.physical_size[1])
self.projection = perspective(45.0, self.size[0] /
float(self.size[1]), 2.0, 10.0)
self.program['a_texture'] = gloo.Texture2D(texture,
interpolation='linear')
self.program['a_normal'] = gloo.Texture2D(normals,
interpolation='linear')
self.program['u_projection'] = self.projection
self.program['u_model'] = self.model
self.program['u_view'] = self.view
self.program['u_light'] = [self.light_distance*np.cos(self.theta),
self.light_distance*np.sin(self.theta),
self.light_distance]
gloo.set_clear_color('black')
self._timer = app.Timer('auto', connect=self.on_timer, start=True)
self.show()
# ---------------------------------
def on_timer(self, event):
self.theta += .05
self.program['u_light'] = [self.light_distance*np.cos(self.theta),
self.light_distance*np.sin(self.theta),
5.0]
self.update()
# ---------------------------------
def on_resize(self, event):
gloo.set_viewport(0, 0, event.physical_size[0], event.physical_size[1])
self.projection = perspective(45.0, event.size[0] /
float(event.size[1]), 2.0, 10.0)
self.program['u_projection'] = self.projection
# ---------------------------------
def on_draw(self, event):
gloo.clear()
self.program.draw('triangles', self.filled_buf)
if __name__ == '__main__':
# parameters for mesh generation
length = 2.5
n_segments = 32
# create the reference mesh
vertices, texcoord, filled = mesh(n_segments=n_segments,
length=length)
texture = imread("brickwall.jpg")
normals = imread("brickwall_normal.jpg")
c = Canvas()
app.run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment