Skip to content

Instantly share code, notes, and snippets.

@nikki93
Created October 5, 2016 01:54
Show Gist options
  • Save nikki93/cc7b71c811d7516641d4a9a966ee0943 to your computer and use it in GitHub Desktop.
Save nikki93/cc7b71c811d7516641d4a9a966ee0943 to your computer and use it in GitHub Desktop.
/*
<p>This example shows how you can apply multiple light sources to a model</p>
*/
const regl = require('regl')()
const normals = require('angle-normals')
const mat4 = require('gl-mat4')
const bunny = require('bunny')
const teapot = require('teapot')
const DIST = 400;
const NUM_MODELS = 170;
const REGION_SIZE = 80;
const symRand = () => 2 * Math.random() - 1;
const bunnyOffsets = Array(NUM_MODELS).fill().map(() => ({
offset: [
REGION_SIZE * symRand(),
REGION_SIZE * Math.random(),
REGION_SIZE * symRand(),
],
}));
const teapotOffsets = Array(NUM_MODELS).fill().map(() => ({
offset: [
REGION_SIZE * symRand(),
-REGION_SIZE * Math.random(),
REGION_SIZE * symRand(),
],
}));
const _makeModelCommand = (model) => regl({
vert: `
precision highp float;
attribute vec3 position, normal;
uniform mat4 model, view, projection;
varying vec3 fragNormal, fragPosition;
uniform vec3 offset;
void main() {
fragNormal = normal;
fragPosition = position + offset;
gl_Position = projection * view * model * vec4(position + offset, 1);
}`,
frag: `
precision mediump float;
struct Light {
vec3 color;
vec3 position;
};
uniform Light lights[4];
varying vec3 fragNormal, fragPosition;
void main() {
vec3 normal = normalize(fragNormal);
vec3 light = vec3(0, 0, 0);
for (int i = 0; i < 4; ++i) {
vec3 lightDir = normalize(lights[i].position - fragPosition);
float diffuse = max(0.0, dot(lightDir, normal));
light += diffuse * lights[i].color;
}
gl_FragColor = vec4(light, 1);
}`,
attributes: {
position: model.positions,
normal: normals(model.cells, model.positions)
},
elements: model.cells,
uniforms: {
offset: regl.prop('offset'),
model: mat4.identity([]),
view: ({time: t}) => {
return mat4.lookAt([],
[DIST * Math.cos(t), 2.5, DIST * Math.sin(t)],
[0, 2.5, 0],
[0, 1, 0])
},
projection: ({viewportWidth, viewportHeight}) =>
mat4.perspective([],
Math.PI / 4,
viewportWidth / viewportHeight,
0.01,
1000),
'lights[0].color': [1, 0, 0],
'lights[1].color': [0, 1, 0],
'lights[2].color': [0, 0, 1],
'lights[3].color': [1, 1, 0],
'lights[0].position': ({time: t}) => {
return [
10 * Math.cos(0.09 * (t)),
10 * Math.sin(0.09 * (2 * t)),
10 * Math.cos(0.09 * (3 * t))
]
},
'lights[1].position': ({time: t}) => {
return [
10 * Math.cos(0.05 * (5 * t + 1)),
10 * Math.sin(0.05 * (4 * t)),
10 * Math.cos(0.05 * (0.1 * t))
]
},
'lights[2].position': ({time: t}) => {
return [
10 * Math.cos(0.05 * (9 * t)),
10 * Math.sin(0.05 * (0.25 * t)),
10 * Math.cos(0.05 * (4 * t))
]
},
'lights[3].position': ({time: t}) => {
return [
10 * Math.cos(0.1 * (0.3 * t)),
10 * Math.sin(0.1 * (2.1 * t)),
10 * Math.cos(0.1 * (1.3 * t))
]
}
}
})
const drawBunny = _makeModelCommand(bunny);
const drawTeapot = _makeModelCommand(teapot);
const frame = () => {
regl.poll();
regl.clear({
color: [0, 0, 0, 1],
depth: 1,
});
drawBunny(bunnyOffsets);
drawTeapot(teapotOffsets);
regl._gl.flush();
setTimeout(frame, 33);
};
frame();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment