1
+ const vertexShaderSource = `#version 300 es
2
+ #pragma vscode_glsllint_stage: vert
3
+
4
+ layout(location=0) in vec4 aPosition;
5
+ layout(location=1) in vec3 aNormal;
6
+
7
+ out vec3 vPosition;
8
+ out vec3 vNormal;
9
+
10
+ void main()
11
+ {
12
+ gl_Position = aPosition;
13
+ vPosition = gl_Position.xyz;
14
+ vNormal = aNormal;
15
+ }` ;
16
+
17
+ const fragmentShaderSource = `#version 300 es
18
+ #pragma vscode_glsllint_stage: frag
19
+
20
+ precision mediump float;
21
+
22
+ uniform sampler2D sampler;
23
+
24
+ in vec3 vNormal;
25
+ in vec3 vPosition;
26
+
27
+ out vec4 fragColor;
28
+
29
+ struct Spotlight
30
+ {
31
+ vec4 location;
32
+ vec4 direction;
33
+ vec4 angles; // x = innerConeAngle, y = outerConeAngle
34
+ vec4 texCoord; // xy = texCoord UV
35
+ };
36
+
37
+ layout(std140) uniform Lighting
38
+ {
39
+ Spotlight spotlight[10];
40
+ };
41
+
42
+ void main()
43
+ {
44
+ for (int x = 0; x < 10; x++)
45
+ {
46
+ vec3 offset = spotlight[x].location.xyz - vPosition;
47
+ vec3 surfaceToLight = normalize(offset);
48
+ float distance = length(surfaceToLight);
49
+ float angleToSurface = dot(spotlight[x].direction.xyz, -surfaceToLight);
50
+
51
+ float diffuse = max(0.0, dot(surfaceToLight, normalize(vNormal)));
52
+ float attenuation = 1.0 / (distance * distance);
53
+ float spot = smoothstep(spotlight[x].angles.x, spotlight[x].angles.y, angleToSurface);
54
+
55
+ float brightness = spot * attenuation * diffuse;
56
+
57
+ vec4 color = texture(sampler, spotlight[x].texCoord.xy) * brightness;
58
+ fragColor += color;
59
+ }
60
+
61
+ fragColor.a = 1.0;
62
+ }` ;
63
+
64
+ const canvas = document . querySelector ( 'canvas' ) ;
65
+ const gl = canvas . getContext ( 'webgl2' ) ;
66
+
67
+ const program = gl . createProgram ( ) ;
68
+
69
+ const vertexShader = gl . createShader ( gl . VERTEX_SHADER ) ;
70
+ gl . shaderSource ( vertexShader , vertexShaderSource ) ;
71
+ gl . compileShader ( vertexShader ) ;
72
+ gl . attachShader ( program , vertexShader ) ;
73
+
74
+ const fragmentShader = gl . createShader ( gl . FRAGMENT_SHADER ) ;
75
+ gl . shaderSource ( fragmentShader , fragmentShaderSource ) ;
76
+ gl . compileShader ( fragmentShader ) ;
77
+ gl . attachShader ( program , fragmentShader ) ;
78
+
79
+ gl . linkProgram ( program ) ;
80
+
81
+ if ( ! gl . getProgramParameter ( program , gl . LINK_STATUS ) ) {
82
+ console . log ( gl . getShaderInfoLog ( vertexShader ) ) ;
83
+ console . log ( gl . getShaderInfoLog ( fragmentShader ) ) ;
84
+ }
85
+
86
+ gl . useProgram ( program ) ;
87
+
88
+ // Geometry (just one quad)
89
+ const quad = new Float32Array ( [
90
+ // position normal
91
+ - .75 , - .75 , 0 , 0 , 0 , - 1 ,
92
+ 0.75 , - .75 , 0 , 0 , 0 , - 1 ,
93
+ 0.75 , 0.75 , 0 , 0 , 0 , - 1 ,
94
+ 0.75 , 0.75 , 0 , 0 , 0 , - 1 ,
95
+ - .75 , 0.75 , 0 , 0 , 0 , - 1 ,
96
+ - .75 , - .75 , 0 , 0 , 0 , - 1 ,
97
+ ] ) ;
98
+
99
+ const quadBuffer = gl . createBuffer ( ) ;
100
+ gl . bindBuffer ( gl . ARRAY_BUFFER , quadBuffer ) ;
101
+ gl . bufferData ( gl . ARRAY_BUFFER , quad , gl . STATIC_DRAW ) ;
102
+ gl . vertexAttribPointer ( 0 , 3 , gl . FLOAT , false , 24 , 0 ) ;
103
+ gl . vertexAttribPointer ( 1 , 3 , gl . FLOAT , false , 24 , 12 ) ;
104
+ gl . enableVertexAttribArray ( 0 ) ;
105
+ gl . enableVertexAttribArray ( 1 ) ;
106
+
107
+ // Light colours
108
+ const tex = gl . createTexture ( ) ;
109
+ gl . bindTexture ( gl . TEXTURE_2D , tex ) ;
110
+ gl . texImage2D ( gl . TEXTURE_2D , 0 , gl . RGBA , 2 , 2 , 0 , gl . RGBA , gl . UNSIGNED_BYTE , new Uint8Array ( [
111
+ 255 , 0 , 0 , 255 , 0 , 255 , 0 , 255 , // red green
112
+ 0 , 0 , 255 , 255 , 255 , 255 , 255 , 255 , // blue white
113
+ ] ) ) ;
114
+ gl . texParameteri ( gl . TEXTURE_2D , gl . TEXTURE_MIN_FILTER , gl . NEAREST ) ;
115
+
116
+ const _ = 0 ;
117
+ const lightData = new Float32Array ( [
118
+ // Chunk 1 Chunk 2 Chunk 3
119
+ // position direction innerCone outerCone texCoord
120
+ 0.500 , 0.000 , - .200 , _ , - .500 , 0.000 , .125 , _ , 0.278 , 0.362 , _ , _ , .25 , .25 , _ , _ ,
121
+ 0.405 , 0.294 , - .200 , _ , - .405 , - .294 , .125 , _ , 0.322 , 0.418 , _ , _ , .25 , .75 , _ , _ ,
122
+ 0.155 , 0.476 , - .200 , _ , - .155 , - .476 , .125 , _ , 0.386 , 0.501 , _ , _ , .75 , .75 , _ , _ ,
123
+ - .155 , 0.476 , - .200 , _ , 0.155 , - .476 , .125 , _ , 0.273 , 0.355 , _ , _ , .75 , .25 , _ , _ ,
124
+ - .405 , 0.294 , - .200 , _ , 0.405 , - .294 , .125 , _ , 0.276 , 0.359 , _ , _ , .25 , .25 , _ , _ ,
125
+ - .500 , 0.000 , - .200 , _ , 0.500 , - .000 , .125 , _ , 0.345 , 0.448 , _ , _ , .25 , .75 , _ , _ ,
126
+ - .405 , - .294 , - .200 , _ , 0.405 , 0.294 , .125 , _ , 0.295 , 0.383 , _ , _ , .75 , .75 , _ , _ ,
127
+ - .155 , - .476 , - .200 , _ , 0.155 , 0.476 , .125 , _ , 0.300 , 0.390 , _ , _ , .75 , .25 , _ , _ ,
128
+ 0.155 , - .476 , - .200 , _ , - .155 , 0.476 , .125 , _ , 0.242 , 0.315 , _ , _ , .25 , .25 , _ , _ ,
129
+ 0.405 , - .294 , - .200 , _ , - .405 , 0.294 , .125 , _ , 0.365 , 0.475 , _ , _ , .25 , .75 , _ , _ ,
130
+ ] ) ;
131
+
132
+ const buffer = gl . createBuffer ( ) ;
133
+ gl . bindBufferBase ( gl . UNIFORM_BUFFER , 0 , buffer ) ;
134
+ gl . bufferData ( gl . UNIFORM_BUFFER , lightData , gl . STATIC_DRAW ) ;
135
+ gl . uniformBlockBinding ( program , gl . getUniformBlockIndex ( program , 'Lighting' ) , 0 ) ;
136
+
137
+ gl . drawArrays ( gl . TRIANGLES , 0 , 6 ) ;
0 commit comments