mirror of
https://github.com/visgl/luma.gl.git
synced 2026-01-25 14:08:58 +00:00
184 lines
4.1 KiB
JavaScript
184 lines
4.1 KiB
JavaScript
import {
|
|
GL, AnimationLoop, Framebuffer, Cube, setParameters, clear, Matrix4, radians
|
|
} from 'luma.gl';
|
|
|
|
const SCENE_FRAGMENT = `\
|
|
#ifdef GL_ES
|
|
precision highp float;
|
|
#endif
|
|
|
|
uniform sampler2D uShadowMap;
|
|
uniform float uShadow;
|
|
|
|
varying vec4 shadowCoord;
|
|
varying vec3 normal;
|
|
|
|
void main(void) {
|
|
float d = clamp(dot(normalize(normal), vec3(0,1,0)), 0.25, 1.0);
|
|
float s = 1.0;
|
|
if (texture2D(uShadowMap, shadowCoord.xy).z < shadowCoord.z - 0.005) {
|
|
s -= 0.5 * uShadow;
|
|
}
|
|
float c = d * s;
|
|
gl_FragColor = vec4(c,c,c,1);
|
|
}
|
|
`;
|
|
|
|
const SCENE_VERTEX = `\
|
|
#define SHADER_NAME scene.vs
|
|
|
|
attribute vec3 positions;
|
|
attribute vec3 normals;
|
|
|
|
uniform mat4 uModel;
|
|
uniform mat4 uView;
|
|
uniform mat4 uProjection;
|
|
uniform mat4 uShadowView;
|
|
uniform mat4 uShadowProj;
|
|
|
|
varying vec4 shadowCoord;
|
|
varying vec3 normal;
|
|
|
|
void main(void) {
|
|
gl_Position = uProjection * uView * uModel * vec4(positions, 1.0);
|
|
normal = vec3(uModel * vec4(normals, 0.0));
|
|
mat4 bias = mat4(
|
|
0.5, 0.0, 0.0, 0.0,
|
|
0.0, 0.5, 0.0, 0.0,
|
|
0.0, 0.0, 0.5, 0.0,
|
|
0.5, 0.5, 0.5, 1.0
|
|
);
|
|
shadowCoord = bias * uShadowProj * uShadowView * uModel * vec4(positions, 1.0);
|
|
}
|
|
`;
|
|
|
|
const SHADOWMAP_VERTEX = `\
|
|
#define SHADER_NAME shadowmap.vs
|
|
|
|
attribute vec3 positions;
|
|
|
|
uniform mat4 uModel;
|
|
uniform mat4 uView;
|
|
uniform mat4 uProjection;
|
|
|
|
void main(void) {
|
|
gl_Position = uProjection * uView * uModel * vec4(positions, 1.0);
|
|
}
|
|
`;
|
|
|
|
const SHADOWMAP_FRAGMENT = `\
|
|
#ifdef GL_ES
|
|
precision highp float;
|
|
#endif
|
|
|
|
void main(void) {
|
|
gl_FragColor = vec4(0,0,gl_FragCoord.z,1);
|
|
}
|
|
`;
|
|
|
|
// const q = 1;
|
|
// const y = -3;
|
|
// const plane = [
|
|
// -q, y, q, q, y, q, q, y, -q,
|
|
// -q, y, q, q, y, -q, -q, y, -q
|
|
// ];
|
|
|
|
// const planeBuffers = {
|
|
// positions: new Buffer(gl).setData({
|
|
// data: new Float32Array(plane),
|
|
// size: 3
|
|
// })
|
|
// };
|
|
|
|
const animationLoop = new AnimationLoop({
|
|
// gl: createGLContext()})
|
|
onInitialize: ({gl}) => {
|
|
|
|
setParameters(gl, {
|
|
depthTest: true,
|
|
depthFunc: GL.LEQUAL
|
|
});
|
|
|
|
return {
|
|
fbShadow: new Framebuffer(gl, {id: 'shadowmap', width: 1024, height: 1024}),
|
|
cube: new Cube(gl, {vs: SCENE_VERTEX, fs: SCENE_FRAGMENT}),
|
|
shadow: new Cube(gl, {vs: SHADOWMAP_VERTEX, fs: SHADOWMAP_FRAGMENT})
|
|
};
|
|
},
|
|
|
|
onRender: ({gl, tick, width, height, aspect, cube, shadow, fbShadow}) => {
|
|
const model = new Matrix4()
|
|
.translate([0, 6, 0])
|
|
.rotateXYZ([tick * 0.01, 0, 0])
|
|
.rotateXYZ([0, tick * 0.013, 0]);
|
|
|
|
const model2 = new Matrix4()
|
|
.scale([2, -2, 2])
|
|
.translate([0, 0, 0])
|
|
.rotateXYZ([0, 0, tick * 0.007]);
|
|
|
|
// Render the shadow buffer
|
|
gl.viewport(0, 0, 1024, 1024);
|
|
clear(gl, {framebuffer: fbShadow, color: [1, 1, 1, 1], depth: true});
|
|
|
|
const lightPos = [0, 8, 0];
|
|
const shadowView = new Matrix4().lookAt({eye: lightPos, center: [0, 0, 0], up: [0, 0, -1]});
|
|
const shadowProj =
|
|
new Matrix4().ortho({left: -4, right: 4, bottom: -4, top: 4, near: 0, far: 64});
|
|
|
|
shadow.setUniforms({
|
|
uModel: model,
|
|
uView: shadowView,
|
|
uProjection: shadowProj,
|
|
uLightPosition: lightPos
|
|
})
|
|
.draw({
|
|
framebuffer: fbShadow
|
|
});
|
|
|
|
// Render the screen
|
|
gl.viewport(0, 0, width, height);
|
|
clear(gl, {color: [0, 0.2, 0, 1], depth: true});
|
|
|
|
const camView = new Matrix4().lookAt({eye: [0, 8, 8], center: [0, 3, 0], up: [0, 1, 0]});
|
|
const camProj = new Matrix4().perspective({fov: radians(75), aspect, near: 0.1, far: 100});
|
|
|
|
cube.setUniforms({
|
|
uModel: model,
|
|
uView: camView,
|
|
uProjection: camProj,
|
|
uShadowView: shadowView,
|
|
uShadowProj: shadowProj,
|
|
uShadowMap: fbShadow
|
|
});
|
|
|
|
cube.render({
|
|
uShadow: 0.0
|
|
});
|
|
|
|
cube.render({
|
|
uModel: model2,
|
|
uShadow: 1.0
|
|
});
|
|
}
|
|
});
|
|
|
|
animationLoop.getInfo = () => {
|
|
return `
|
|
<p>
|
|
Simple <b>shadow mapping</b>.
|
|
<p>
|
|
A luma.gl <code>Cube</code>, rendering into a shadowmap framebuffer
|
|
and then rendering onto the screen.
|
|
`;
|
|
};
|
|
|
|
export default animationLoop;
|
|
|
|
/* expose on Window for standalone example */
|
|
/* global window */
|
|
if (typeof window !== 'undefined') {
|
|
window.animationLoop = animationLoop;
|
|
}
|
|
|