emeraldengine 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/README.md +968 -0
  2. package/dist/types/imports/BitmapText.d.ts +79 -0
  3. package/dist/types/imports/Color.d.ts +17 -0
  4. package/dist/types/imports/Drawable.d.ts +157 -0
  5. package/dist/types/imports/Emerald.d.ts +73 -0
  6. package/dist/types/imports/FPSCounter.d.ts +19 -0
  7. package/dist/types/imports/GLUtils.d.ts +6 -0
  8. package/dist/types/imports/Instance.d.ts +87 -0
  9. package/dist/types/imports/InstancedTexture.d.ts +230 -0
  10. package/dist/types/imports/Physics.d.ts +139 -0
  11. package/dist/types/imports/Scene.d.ts +39 -0
  12. package/dist/types/imports/Shaders.d.ts +4 -0
  13. package/dist/types/imports/Shapes.d.ts +25 -0
  14. package/dist/types/imports/Storage.d.ts +46 -0
  15. package/dist/types/imports/Texture.d.ts +19 -0
  16. package/dist/types/imports/Time.d.ts +22 -0
  17. package/dist/types/imports/Transform.d.ts +41 -0
  18. package/dist/types/imports/components/BoxCollider.d.ts +41 -0
  19. package/dist/types/imports/components/BoxColliderDebug.d.ts +19 -0
  20. package/dist/types/imports/components/CircleCollider.d.ts +39 -0
  21. package/dist/types/imports/components/CircleColliderDebug.d.ts +19 -0
  22. package/dist/types/imports/components/Collider.d.ts +53 -0
  23. package/dist/types/imports/components/GameObject.d.ts +72 -0
  24. package/dist/types/imports/components/RigidBody.d.ts +104 -0
  25. package/dist/types/imports/lights/DirectionalLight.d.ts +26 -0
  26. package/dist/types/imports/lights/PointLight.d.ts +18 -0
  27. package/dist/types/imports/managers/AudioManager.d.ts +60 -0
  28. package/dist/types/imports/managers/CameraManager.d.ts +35 -0
  29. package/dist/types/imports/managers/EventManager.d.ts +187 -0
  30. package/dist/types/imports/managers/GLManager.d.ts +47 -0
  31. package/dist/types/imports/managers/IDManager.d.ts +21 -0
  32. package/dist/types/imports/managers/SceneManager.d.ts +22 -0
  33. package/dist/types/imports/particlesystem/Particle.d.ts +42 -0
  34. package/dist/types/imports/particlesystem/ParticleSettings.d.ts +49 -0
  35. package/dist/types/imports/particlesystem/Particles.d.ts +71 -0
  36. package/dist/types/index.d.ts +32 -0
  37. package/imports/BitmapText.js +245 -0
  38. package/imports/Color.js +18 -0
  39. package/imports/Drawable.js +550 -0
  40. package/imports/Emerald.js +459 -0
  41. package/imports/FPSCounter.js +43 -0
  42. package/imports/GLUtils.js +67 -0
  43. package/imports/Instance.js +187 -0
  44. package/imports/InstancedTexture.js +856 -0
  45. package/imports/Physics.js +242 -0
  46. package/imports/Scene.js +79 -0
  47. package/imports/Shaders.js +165 -0
  48. package/imports/Shapes.js +129 -0
  49. package/imports/Storage.js +63 -0
  50. package/imports/Texture.js +67 -0
  51. package/imports/Time.js +28 -0
  52. package/imports/Transform.js +59 -0
  53. package/imports/components/BoxCollider.js +67 -0
  54. package/imports/components/BoxColliderDebug.js +38 -0
  55. package/imports/components/CircleCollider.js +67 -0
  56. package/imports/components/CircleColliderDebug.js +36 -0
  57. package/imports/components/Collider.js +51 -0
  58. package/imports/components/GameObject.js +160 -0
  59. package/imports/components/RigidBody.js +169 -0
  60. package/imports/lights/DirectionalLight.js +68 -0
  61. package/imports/lights/PointLight.js +17 -0
  62. package/imports/managers/AudioManager.js +146 -0
  63. package/imports/managers/CameraManager.js +60 -0
  64. package/imports/managers/EventManager.js +479 -0
  65. package/imports/managers/GLManager.js +65 -0
  66. package/imports/managers/IDManager.js +32 -0
  67. package/imports/managers/SceneManager.js +27 -0
  68. package/imports/managers/ShaderManager.js +133 -0
  69. package/imports/particlesystem/Particle.js +75 -0
  70. package/imports/particlesystem/ParticleSettings.js +49 -0
  71. package/imports/particlesystem/Particles.js +226 -0
  72. package/index.js +67 -0
  73. package/package.json +38 -0
@@ -0,0 +1,459 @@
1
+ import { STANDARD_FRAGMENT_SHADER, STANDARD_VERTEX_SHADER } from "./Shaders.js";
2
+ import { initShaderProgram } from "./GLUtils.js";
3
+ import { mat4 } from "gl-matrix";
4
+ import Color from "./Color.js";
5
+ import Transform from "./Transform.js";
6
+ import { Vector2, Vector3 } from "./Physics.js";
7
+ import Time from "./Time.js";
8
+ import GLManager from "./managers/GLManager.js";
9
+ import CameraManager from "./managers/CameraManager.js";
10
+ import PointLight from "./lights/PointLight.js";
11
+ import DirectionalLight from "./lights/DirectionalLight.js";
12
+
13
+ /**
14
+ * @class Emerald
15
+ * @description A class that represents the Emerald engine
16
+ * @param {HTMLCanvasElement} canvas - The canvas element
17
+ */
18
+ class Emerald {
19
+ constructor(canvas) {
20
+ const gl = canvas.getContext("webgl2", {
21
+ antialias: true,
22
+ powerPreference: "high-performance",
23
+ desynchronized: false,
24
+ });
25
+ if (!gl) {
26
+ console.error("[Emerald.js] > No WebGL context found");
27
+ return undefined;
28
+ }
29
+
30
+ const shaderProgram = initShaderProgram(
31
+ gl,
32
+ STANDARD_VERTEX_SHADER,
33
+ STANDARD_FRAGMENT_SHADER
34
+ );
35
+ this.shaderProgram = shaderProgram;
36
+ this.gl = gl;
37
+ this.programInfo = {
38
+ program: shaderProgram,
39
+ attribLocations: {
40
+ vertexPosition: gl.getAttribLocation(shaderProgram, "aVertexPosition"),
41
+ aTexCoord: gl.getAttribLocation(shaderProgram, "aTextureCoord"),
42
+ instanceMatrix: gl.getAttribLocation(shaderProgram, "aInstanceMatrix0"),
43
+ instanceTexCoord0: gl.getAttribLocation(
44
+ shaderProgram,
45
+ "aInstanceTexCoord0"
46
+ ),
47
+ instanceTexCoord1: gl.getAttribLocation(
48
+ shaderProgram,
49
+ "aInstanceTexCoord1"
50
+ ),
51
+ instanceTexCoord2: gl.getAttribLocation(
52
+ shaderProgram,
53
+ "aInstanceTexCoord2"
54
+ ),
55
+ instanceTexCoord3: gl.getAttribLocation(
56
+ shaderProgram,
57
+ "aInstanceTexCoord3"
58
+ ),
59
+ },
60
+ uniformLocations: {
61
+ projectionMatrix: gl.getUniformLocation(
62
+ shaderProgram,
63
+ "uProjectionMatrix"
64
+ ),
65
+ globalViewMatrix: gl.getUniformLocation(
66
+ shaderProgram,
67
+ "uModelViewMatrix"
68
+ ),
69
+ instancedModelViewMatrix: gl.getUniformLocation(
70
+ shaderProgram,
71
+ "uInstancedModelViewMatrix"
72
+ ),
73
+ uModelMatrix: gl.getUniformLocation(shaderProgram, "uModelMatrix"),
74
+ uInstancedModelMatrix: gl.getUniformLocation(
75
+ shaderProgram,
76
+ "uInstancedModelMatrix"
77
+ ),
78
+ uAmbientLightValues: gl.getUniformLocation(
79
+ shaderProgram,
80
+ "uAmbientLightValues"
81
+ ),
82
+ uSampler: gl.getUniformLocation(shaderProgram, "uSampler"),
83
+ color: gl.getUniformLocation(shaderProgram, "uColor"),
84
+ useTexture: gl.getUniformLocation(shaderProgram, "useTexture"),
85
+ useInstances: gl.getUniformLocation(shaderProgram, "useInstances"),
86
+ useText: gl.getUniformLocation(shaderProgram, "useText"),
87
+ useLighting: gl.getUniformLocation(shaderProgram, "uUseLighting"),
88
+ uOpacity: gl.getUniformLocation(shaderProgram, "uOpacity"),
89
+ // Point light uniforms
90
+ uLightPosition: gl.getUniformLocation(shaderProgram, "uLightPosition"),
91
+ uLightColor: gl.getUniformLocation(shaderProgram, "uLightColor"),
92
+ uLightIntensity: gl.getUniformLocation(
93
+ shaderProgram,
94
+ "uLightIntensity"
95
+ ),
96
+ uLightRadius: gl.getUniformLocation(shaderProgram, "uLightRadius"),
97
+ uActiveLights: gl.getUniformLocation(shaderProgram, "uActiveLights"),
98
+ // Directional light uniforms
99
+ uDirLightPosition: gl.getUniformLocation(
100
+ shaderProgram,
101
+ "uDirLightPosition"
102
+ ),
103
+ uDirLightDirection: gl.getUniformLocation(
104
+ shaderProgram,
105
+ "uDirLightDirection"
106
+ ),
107
+ uDirLightColor: gl.getUniformLocation(shaderProgram, "uDirLightColor"),
108
+ uDirLightIntensity: gl.getUniformLocation(
109
+ shaderProgram,
110
+ "uDirLightIntensity"
111
+ ),
112
+ uDirLightWidth: gl.getUniformLocation(shaderProgram, "uDirLightWidth"),
113
+ uActiveDirLights: gl.getUniformLocation(
114
+ shaderProgram,
115
+ "uActiveDirLights"
116
+ ),
117
+ },
118
+ };
119
+ GLManager.setGL(gl);
120
+ GLManager.setProgramInfo(this.programInfo);
121
+ this.camera = {
122
+ transform: new Transform(new Vector3(0, 0, 0), 0, new Vector2(1, 1)),
123
+ setPosition(x, y, z) {
124
+ this.transform.position.x = -x;
125
+ this.transform.position.y = -y;
126
+ this.transform.position.z = -z;
127
+ },
128
+ };
129
+
130
+ CameraManager.setCamera(this.camera);
131
+
132
+ this.ambientLight = new Vector3(1.0, 1.0, 1.0);
133
+ this.pointLights = [];
134
+ this.directionalLights = [];
135
+ this.debugLogged = false; // Flag to prevent spam in console
136
+ this.backgroundColor = {
137
+ r: 0.0,
138
+ g: 0.0,
139
+ b: 0.0,
140
+ a: 1.0,
141
+ };
142
+ }
143
+
144
+ /**
145
+ * @method setAmbientLight
146
+ * @description Sets the ambient light for the scene
147
+ * @param {Vector3} vector3 - The ambient light color as a Vector3 instance
148
+ */
149
+ setAmbientLight(vector3) {
150
+ if (vector3.x && vector3.y && vector3.z) {
151
+ this.ambientLight = vector3;
152
+ } else {
153
+ console.error(
154
+ "[Emerald.js] > vector3 is not an instance of Vector3 class."
155
+ );
156
+ }
157
+ }
158
+
159
+ /**
160
+ * @method resize
161
+ * @description Resizes the canvas
162
+ * @param {number} width - The width of the canvas
163
+ * @param {number} height - The height of the canvas
164
+ */
165
+ resize(width, height) {
166
+ // Update canvas dimensions
167
+ this.gl.canvas.width = width;
168
+ this.gl.canvas.height = height;
169
+
170
+ // Update WebGL viewport
171
+ this.gl.viewport(0, 0, width, height);
172
+ }
173
+
174
+ /**
175
+ * @method addPointLight
176
+ * @description Adds a point light to the scene
177
+ * @param {PointLight} pointLight - The point light to add
178
+ */
179
+ addPointLight(pointLight) {
180
+ if (!(pointLight instanceof PointLight)) {
181
+ console.error(
182
+ "[Emerald.js] > Passed argument is not an instance of PointLight class."
183
+ );
184
+ return;
185
+ }
186
+ if (this.pointLights.length < 4) {
187
+ // Maximum 4 lights as defined in shader
188
+ this.pointLights.push(pointLight);
189
+ } else {
190
+ console.warn("Maximum number of point lights reached (4)");
191
+ }
192
+ }
193
+
194
+ /**
195
+ * @method addDirectionalLight
196
+ * @description Adds a directional light to the scene
197
+ * @param {DirectionalLight} directionalLight - The directional light to add
198
+ */
199
+ addDirectionalLight(directionalLight) {
200
+ if (!(directionalLight instanceof DirectionalLight)) {
201
+ console.error(
202
+ "[Emerald.js] > Passed argument is not an instance of DirectionalLight class."
203
+ );
204
+ return;
205
+ }
206
+ if (this.directionalLights.length < 4) {
207
+ // Maximum 4 directional lights as defined in shader
208
+ this.directionalLights.push(directionalLight);
209
+ } else {
210
+ console.warn("Maximum number of directional lights reached (4)");
211
+ }
212
+ }
213
+
214
+ /**
215
+ * @method removeDirectionalLight
216
+ * @description Removes a directional light from the scene
217
+ * @param {DirectionalLight} directionalLight - The directional light to remove
218
+ */
219
+ removeDirectionalLight(directionalLight) {
220
+ const index = this.directionalLights.indexOf(directionalLight);
221
+ if (index > -1) {
222
+ this.directionalLights.splice(index, 1);
223
+ }
224
+ }
225
+
226
+ /**
227
+ * @method setBackgroundColor
228
+ * @description Sets the background color of the scene
229
+ * @param {Color} color - The background color
230
+ */
231
+ setBackgroundColor(color) {
232
+ if (color instanceof Color) {
233
+ this.backgroundColor = {
234
+ r: color.r / 255,
235
+ g: color.g / 255,
236
+ b: color.b / 255,
237
+ a: color.a / 255,
238
+ };
239
+ } else {
240
+ console.error("[Emerald.js] > color is not an instance of Color class.");
241
+ }
242
+ }
243
+ // Buggy (events don't work correctly when zoom changes from 1)
244
+ // setZoom(float) {
245
+ // vec3.set(this.camera.scale, float, float, float);
246
+ // }
247
+
248
+ // getZoom() {
249
+ // return this.camera.scale[0];
250
+ // }
251
+
252
+ /**
253
+ * @method drawScene
254
+ * @description Draws the scene
255
+ * @param {Scene} scene - The scene to draw
256
+ * @param {number} deltaTime - The delta time
257
+ */
258
+ drawScene(scene, deltaTime) {
259
+ Time.setDeltaTime(deltaTime);
260
+ if (this.backgroundColor) {
261
+ this.gl.clearColor(
262
+ this.backgroundColor.r,
263
+ this.backgroundColor.g,
264
+ this.backgroundColor.b,
265
+ this.backgroundColor.a
266
+ );
267
+ } else {
268
+ this.gl.clearColor(0.0, 0.0, 0.0, 1.0); // Default to black if no background color is set
269
+ }
270
+ // 2D rendering: disable depth testing to allow proper alpha blending with back-to-front draw order
271
+ this.gl.clearDepth(1.0);
272
+ this.gl.disable(this.gl.DEPTH_TEST);
273
+
274
+ this.gl.enable(this.gl.BLEND);
275
+ // Keep framebuffer alpha at 1.0 to avoid page compositing artifacts while blending RGB correctly
276
+ // newRGB = srcRGB * srcA + dstRGB * (1 - srcA)
277
+ // newA = 1 * srcA + (1 - srcA) * 1 = 1
278
+ this.gl.blendFuncSeparate(
279
+ this.gl.SRC_ALPHA,
280
+ this.gl.ONE_MINUS_SRC_ALPHA,
281
+ this.gl.ONE,
282
+ this.gl.ONE_MINUS_SRC_ALPHA
283
+ );
284
+ this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);
285
+
286
+ const projectionMatrix = mat4.create();
287
+ const left = -this.gl.canvas.clientWidth / 2;
288
+ const right = this.gl.canvas.clientWidth / 2;
289
+ const bottom = -this.gl.canvas.clientHeight / 2;
290
+ const top = this.gl.canvas.clientHeight / 2;
291
+ const near = -100;
292
+ const far = 100;
293
+ mat4.ortho(projectionMatrix, left, right, bottom, top, near, far);
294
+
295
+ const globalViewMatrix = mat4.create();
296
+ mat4.translate(globalViewMatrix, globalViewMatrix, [
297
+ this.camera.transform.position.x,
298
+ this.camera.transform.position.y,
299
+ this.camera.transform.position.z,
300
+ ]); // Translation
301
+ mat4.rotate(globalViewMatrix, globalViewMatrix, 0, [1, 0, 0]); // X-axis rotation
302
+ mat4.rotate(globalViewMatrix, globalViewMatrix, 0, [0, 1, 0]); // Y-axis rotation
303
+ mat4.rotate(
304
+ globalViewMatrix,
305
+ globalViewMatrix,
306
+ this.camera.transform.rotation,
307
+ [0, 0, 1]
308
+ ); // Z-axis rotation
309
+ mat4.scale(globalViewMatrix, globalViewMatrix, [
310
+ this.camera.transform.scale.x,
311
+ this.camera.transform.scale.y,
312
+ 1,
313
+ ]); // Scale
314
+
315
+ this.gl.useProgram(this.programInfo.program);
316
+
317
+ this.gl.uniform3fv(
318
+ this.programInfo.uniformLocations.uAmbientLightValues,
319
+ new Float32Array([
320
+ this.ambientLight.x,
321
+ this.ambientLight.y,
322
+ this.ambientLight.z,
323
+ ])
324
+ );
325
+ this.gl.uniformMatrix4fv(
326
+ this.programInfo.uniformLocations.projectionMatrix,
327
+ false,
328
+ projectionMatrix
329
+ );
330
+ this.gl.uniformMatrix4fv(
331
+ this.programInfo.uniformLocations.globalViewMatrix,
332
+ false,
333
+ globalViewMatrix
334
+ );
335
+
336
+ this.gl.uniformMatrix4fv(
337
+ this.programInfo.uniformLocations.instancedModelViewMatrix,
338
+ false,
339
+ globalViewMatrix
340
+ );
341
+
342
+ const lightPositions = [];
343
+ const lightColors = [];
344
+ const lightIntensities = [];
345
+ const lightRadii = [];
346
+
347
+ this.pointLights.forEach((light) => {
348
+ // Get original world position
349
+ const worldPos = new Vector2(light.position.x, light.position.y);
350
+
351
+ // This transforms the world position to account for camera movement
352
+ const adjustedPos = new Vector2(
353
+ worldPos.x + this.camera.transform.position.x,
354
+ worldPos.y + this.camera.transform.position.y
355
+ );
356
+
357
+ // Push the adjusted position to the array
358
+ lightPositions.push(adjustedPos.x, adjustedPos.y);
359
+ lightColors.push(
360
+ light.color.r / 255,
361
+ light.color.g / 255,
362
+ light.color.b / 255
363
+ );
364
+ lightIntensities.push(light.intensity);
365
+ lightRadii.push(light.radius);
366
+ });
367
+
368
+ // Get uniform locations
369
+ const uLightPositionLoc = this.programInfo.uniformLocations.uLightPosition;
370
+ const uLightColorLoc = this.programInfo.uniformLocations.uLightColor;
371
+ const uLightIntensityLoc =
372
+ this.programInfo.uniformLocations.uLightIntensity;
373
+ const uLightRadiusLoc = this.programInfo.uniformLocations.uLightRadius;
374
+ const uActiveLightsLoc = this.programInfo.uniformLocations.uActiveLights;
375
+
376
+ // Set uniform values
377
+ if (lightPositions.length > 0) {
378
+ this.gl.uniform2fv(uLightPositionLoc, new Float32Array(lightPositions));
379
+ this.gl.uniform3fv(uLightColorLoc, new Float32Array(lightColors));
380
+ this.gl.uniform1fv(
381
+ uLightIntensityLoc,
382
+ new Float32Array(lightIntensities)
383
+ );
384
+ this.gl.uniform1fv(uLightRadiusLoc, new Float32Array(lightRadii));
385
+ }
386
+ this.gl.uniform1i(uActiveLightsLoc, this.pointLights.length);
387
+
388
+ // Prepare directional light data
389
+ const dirLightPositions = [];
390
+ const dirLightDirections = [];
391
+ const dirLightColors = [];
392
+ const dirLightIntensities = [];
393
+ const dirLightWidths = [];
394
+
395
+ this.directionalLights.forEach((light) => {
396
+ // Apply camera transformation to directional light position
397
+ const worldPos = new Vector2(light.position.x, light.position.y);
398
+ const adjustedPos = new Vector2(
399
+ worldPos.x + this.camera.transform.position.x,
400
+ worldPos.y + this.camera.transform.position.y
401
+ );
402
+
403
+ dirLightPositions.push(adjustedPos.x, adjustedPos.y);
404
+ dirLightDirections.push(light.direction.x, light.direction.y);
405
+ dirLightColors.push(
406
+ light.color.r / 255,
407
+ light.color.g / 255,
408
+ light.color.b / 255
409
+ );
410
+ dirLightIntensities.push(light.intensity);
411
+ dirLightWidths.push(light.width);
412
+ });
413
+
414
+ // Get directional light uniform locations
415
+ const uDirLightPositionLoc =
416
+ this.programInfo.uniformLocations.uDirLightPosition;
417
+ const uDirLightDirectionLoc =
418
+ this.programInfo.uniformLocations.uDirLightDirection;
419
+ const uDirLightColorLoc = this.programInfo.uniformLocations.uDirLightColor;
420
+ const uDirLightIntensityLoc =
421
+ this.programInfo.uniformLocations.uDirLightIntensity;
422
+ const uDirLightWidthLoc = this.programInfo.uniformLocations.uDirLightWidth;
423
+ const uActiveDirLightsLoc =
424
+ this.programInfo.uniformLocations.uActiveDirLights;
425
+
426
+ // Set directional light uniform values
427
+ if (dirLightPositions.length > 0) {
428
+ this.gl.uniform2fv(
429
+ uDirLightPositionLoc,
430
+ new Float32Array(dirLightPositions)
431
+ );
432
+ this.gl.uniform2fv(
433
+ uDirLightDirectionLoc,
434
+ new Float32Array(dirLightDirections)
435
+ );
436
+ this.gl.uniform3fv(uDirLightColorLoc, new Float32Array(dirLightColors));
437
+ this.gl.uniform1fv(
438
+ uDirLightIntensityLoc,
439
+ new Float32Array(dirLightIntensities)
440
+ );
441
+ this.gl.uniform1fv(uDirLightWidthLoc, new Float32Array(dirLightWidths));
442
+ }
443
+ this.gl.uniform1i(uActiveDirLightsLoc, this.directionalLights.length);
444
+
445
+ // Draw objects back-to-front based on their z to ensure correct transparency blending
446
+ const sortedObjects = [...scene.objects].sort(
447
+ (a, b) => a.transform.position.z - b.transform.position.z
448
+ );
449
+ for (const object of sortedObjects) {
450
+ object.draw(
451
+ globalViewMatrix,
452
+ this.programInfo.uniformLocations.globalViewMatrix,
453
+ performance.now()
454
+ );
455
+ }
456
+ }
457
+ }
458
+
459
+ export default Emerald;
@@ -0,0 +1,43 @@
1
+ /**
2
+ * @class FPSCounter
3
+ * @description Represents a FPS counter
4
+ */
5
+ class FPSCounter {
6
+ constructor() {
7
+ this.lastFrameTime = performance.now();
8
+ this.frameCount = 0;
9
+ this.fps = 0;
10
+ this.fpsElement = document.createElement("div");
11
+ this.fpsElement.style.position = "absolute";
12
+ this.fpsElement.style.top = "10px";
13
+ this.fpsElement.style.left = "10px";
14
+ this.fpsElement.style.color = "white";
15
+ this.fpsElement.style.backgroundColor = "rgba(0, 0, 0, 0.5)";
16
+ this.fpsElement.style.padding = "5px";
17
+ this.fpsElement.style.fontFamily = "Arial";
18
+ this.fpsElement.style.fontSize = "14px";
19
+ document.body.appendChild(this.fpsElement);
20
+ this.accumulatedTime = 0;
21
+ }
22
+
23
+ /**
24
+ * @method update
25
+ * @description Updates the FPS counter
26
+ */
27
+ update() {
28
+ const now = performance.now();
29
+ const delta = now - this.lastFrameTime;
30
+ this.lastFrameTime = now;
31
+ this.accumulatedTime += delta;
32
+ this.frameCount++;
33
+
34
+ if (this.accumulatedTime >= 1000) {
35
+ this.fps = this.frameCount;
36
+ this.frameCount = 0;
37
+ this.accumulatedTime = 0;
38
+ this.fpsElement.textContent = `FPS: ${this.fps}`;
39
+ }
40
+ }
41
+ }
42
+
43
+ export default FPSCounter;
@@ -0,0 +1,67 @@
1
+ // Initializing a shader program
2
+
3
+ function initShaderProgram(gl, vShader, fShader) {
4
+ const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vShader);
5
+ const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fShader);
6
+
7
+ // Create the shader program
8
+ const shaderProgram = gl.createProgram();
9
+ gl.attachShader(shaderProgram, vertexShader);
10
+ gl.attachShader(shaderProgram, fragmentShader);
11
+ gl.linkProgram(shaderProgram);
12
+
13
+ // Error handling
14
+ if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
15
+ alert(
16
+ `[GLUtils.js] > Unable to initialize the shader program: ${gl.getProgramInfoLog(
17
+ shaderProgram
18
+ )}`
19
+ );
20
+ return null;
21
+ }
22
+ return shaderProgram;
23
+ }
24
+
25
+ // Loading a shader
26
+
27
+ function loadShader(gl, type, source) {
28
+ const shader = gl.createShader(type);
29
+
30
+ // Send the source to the shader object
31
+ gl.shaderSource(shader, source);
32
+
33
+ // Compile the shader program
34
+ gl.compileShader(shader);
35
+
36
+ if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
37
+ alert(
38
+ `[GLUtils.js] An error occurred compiling the shaders: ${gl.getShaderInfoLog(
39
+ shader
40
+ )}`
41
+ );
42
+ gl.deleteShader(shader);
43
+ return null;
44
+ }
45
+
46
+ return shader;
47
+ }
48
+
49
+ const initVertexBuffer = (gl, vertices) => {
50
+ const floatArray = new Float32Array(vertices);
51
+ const buffer = gl.createBuffer();
52
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
53
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
54
+ buffer._bufferSize = floatArray.byteLength;
55
+ return buffer;
56
+ };
57
+
58
+ function initInstancedBuffer(gl, data, itemSize) {
59
+ const buffer = gl.createBuffer();
60
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
61
+ gl.bufferData(gl.ARRAY_BUFFER, data, gl.DYNAMIC_DRAW);
62
+ buffer.itemSize = itemSize;
63
+ buffer.numItems = data.length / itemSize;
64
+ return buffer;
65
+ }
66
+
67
+ export { initShaderProgram, loadShader, initVertexBuffer, initInstancedBuffer };