-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy path21.lighting.spot.basic.js
107 lines (83 loc) · 3.21 KB
/
21.lighting.spot.basic.js
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
104
105
106
107
/*
This demonstrates a basic example of a spotlight WebGL program. It
simply uses a user-facing rectangle without any transformations and a
static spotlight with static cutoff values pointed straight at the
rectangle.
In the JavaScript, experiment by changing the light position, light
direction and cuttoff angles.
This example does not include any model-view-matrix transformations, but
feel free to add them. Remember to apply the View transformation to your
light position and light direction as well as the vertex positions as
your light source and object geometry should exist in the same coordinate
space.
*/
const vertexShaderSource = `#version 300 es
#pragma vscode_glsllint_stage: vert
layout(location=0) in vec4 aPosition;
layout(location=1) in vec3 aNormal;
out vec3 vNormal;
out vec3 vPosition;
void main()
{
vNormal = aNormal;
gl_Position = aPosition;
vPosition = aPosition.xyz;
}`;
const fragmentShaderSource = `#version 300 es
#pragma vscode_glsllint_stage: frag
precision mediump float;
uniform vec3 uLightPosition;
uniform vec3 uLightDirection;
uniform float uLightInnerCutoff;
uniform float uLightOuterCutoff;
in vec3 vNormal;
in vec3 vPosition;
out vec4 fragColor;
void main()
{
vec3 offset = uLightPosition - vPosition;
vec3 surfaceToLight = normalize(offset);
float diffuse = max(0.0, dot(surfaceToLight, normalize(vNormal)));
float angleToSurface = dot(uLightDirection, -surfaceToLight);
float spot = smoothstep(uLightOuterCutoff, uLightInnerCutoff, angleToSurface);
float brightness = diffuse * spot;
fragColor.rgb = vec3(1.0, 0.0, 0.0) * brightness;
fragColor.a = 1.0;
}`;
const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl2');
const program = gl.createProgram();
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexShaderSource);
gl.compileShader(vertexShader);
gl.attachShader(program, vertexShader);
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentShaderSource);
gl.compileShader(fragmentShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
console.log(gl.getShaderInfoLog(vertexShader));
console.log(gl.getShaderInfoLog(fragmentShader));
}
gl.useProgram(program);
const verts = new Float32Array([
-.75,-.75,0, 0,0,-1,
.75,-.75,0, 0,0,-1,
.75, .75,0, 0,0,-1,
-.75,-.75,0, 0,0,-1,
.75, .75,0, 0,0,-1,
-.75, .75,0, 0,0,-1,
]);
const buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, verts, gl.STATIC_DRAW);
gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 24, 0);
gl.vertexAttribPointer(1, 3, gl.FLOAT, false, 24, 12);
gl.enableVertexAttribArray(0);
gl.enableVertexAttribArray(1);
gl.uniform3f(gl.getUniformLocation(program, 'uLightPosition'), 0.0, 0.0, -.5);
gl.uniform3f(gl.getUniformLocation(program, 'uLightDirection'), 0.0, 0.0, 1.0);
gl.uniform1f(gl.getUniformLocation(program, 'uLightInnerCutoff'), Math.cos(Math.PI / 12));
gl.uniform1f(gl.getUniformLocation(program, 'uLightOuterCutoff'), Math.cos(Math.PI / 6));
gl.drawArrays(gl.TRIANGLES, 0, 6);