diff --git a/algebra.mjs b/algebra.mjs new file mode 100644 index 0000000..4a565b6 --- /dev/null +++ b/algebra.mjs @@ -0,0 +1,36 @@ +export function calcRotationMatrix(vec, rad) { + // Equation used from: + // https://people.eecs.berkeley.edu/~ug/slide/pipeline/assignments/as5/rotation.html + let A = glMatrix.mat3.fromValues( + 0, + -vec[2], + vec[1], + vec[2], + 0, + -vec[0], + -vec[1], + vec[0], + 0, + ); + + let I = glMatrix.mat3.create(); + + // Matrix Exponential + let Mpow = glMatrix.mat3.create(); + glMatrix.mat3.mul(Mpow, A, A); + + let M1 = glMatrix.mat3.create(); + let M2 = glMatrix.mat3.create(); + + // Scalar Multiplications + glMatrix.mat3.multiplyScalar(M1, A, Math.sin(rad)); + glMatrix.mat3.multiplyScalar(M2, Mpow, 1 - Math.cos(rad)); + + // Matrix Addition + let M3 = glMatrix.mat3.create(); + let Q = glMatrix.mat3.create(); + glMatrix.mat3.add(M3, I, M1); + glMatrix.mat3.add(Q, M3, M2); + + return Q; +} diff --git a/index.html b/index.html index 290c63e..b9da3b0 100644 --- a/index.html +++ b/index.html @@ -4,7 +4,7 @@ Shaders are Fun - + diff --git a/main.mjs b/main.mjs new file mode 100644 index 0000000..3177ed0 --- /dev/null +++ b/main.mjs @@ -0,0 +1,85 @@ +import "https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/3.4.2/gl-matrix-min.js"; +import { initShader } from "./shader.mjs"; +import { calcRotationMatrix } from "./algebra.mjs"; + +const CANVAS_WIDTH = 700; +const CANVAS_HEIGHT = 700; +let TIME = 0; +let camera_pos = [0, 0, 0]; +let mouse_pos = [0, 0]; + +// Update the Camera position +function updateCamera(gl, program) { + if (keymap.get("w")) { + camera_pos[2] += 0.1; + } + if (keymap.get("a")) { + camera_pos[0] += -0.1; + } + if (keymap.get("s")) { + camera_pos[2] += -0.1; + } + if (keymap.get("d")) { + camera_pos[0] += 0.1; + } + if (keymap.get("e")) { + camera_pos[1] += 0.1; + } + if (keymap.get("q")) { + camera_pos[1] += -0.1; + } + + // Position + const pos = gl.getUniformLocation(program, "camera_pos"); + gl.uniform3fv(pos, camera_pos); + + // Rotation + const rot = gl.getUniformLocation(program, "camera_rot"); + + let M1 = calcRotationMatrix([0, -1, 0], mouse_pos[0]); + let M2 = calcRotationMatrix([-1, 0, 0], mouse_pos[1]); + let rot_mat = glMatrix.mat3.create(); + + glMatrix.mat3.mul(rot_mat, M1, M2); + gl.uniform3fv(rot, rot_mat); +} + +// update the canvas +function draw(gl, program) { + // Create uniform + const loc = gl.getUniformLocation(program, "time"); + TIME += 1 / 60; + gl.uniform1f(loc, TIME); + + updateCamera(gl, program); + + // Draw the frame recursively on next frame + gl.drawArrays(gl.TRIANGLES, 0, 6); + requestAnimationFrame(() => draw(gl, program)); +} + +// Initialize the shader +const [gl, program, canvas] = await initShader(CANVAS_WIDTH, CANVAS_HEIGHT); + +// Key Presses +let keymap = new Map(); +document.addEventListener("keydown", function (event) { + keymap.set(event.key, true); +}); +document.addEventListener("keyup", function (event) { + keymap.set(event.key, false); +}); +// Mouse movement +document.addEventListener("mousemove", function (event) { + mouse_pos[0] += event.movementX / 800; + mouse_pos[1] += event.movementY / 800; +}); + +// Request pointer Lock +canvas.addEventListener("click", async () => { + await canvas.requestPointerLock(); +}); + +// Update loop +updateCamera(gl, program); +draw(gl, program); diff --git a/shader.mjs b/shader.mjs index 919e5f2..c522800 100644 --- a/shader.mjs +++ b/shader.mjs @@ -1,22 +1,14 @@ -import "https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/3.4.2/gl-matrix-min.js"; - -const CANVAS_WIDTH = 700; -const CANVAS_HEIGHT = 700; -let TIME = 0; -let camera_pos = [0, 0, 0]; -let mouse_pos = [0, 0]; - // ** Initialization stuffs ** // -async function initShader() { +export async function initShader(c_width, c_height) { // Get GL contexts and stuffs const canvas = document.getElementById("shader"); const gl = canvas.getContext("webgl2"); - canvas.width = CANVAS_WIDTH; - canvas.height = CANVAS_HEIGHT; + canvas.width = c_width; + canvas.height = c_height; - gl.viewport(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT); + gl.viewport(0, 0, c_width, c_height); // Create Vertex Array const vao = gl.createVertexArray(); @@ -97,93 +89,7 @@ async function fetch_local(src) { return await res.text(); } -// Update the Camera position -function updateCamera(gl, program) { - if (keymap.get("w")) { - camera_pos[2] += 0.1; - } - if (keymap.get("a")) { - camera_pos[0] += -0.1; - } - if (keymap.get("s")) { - camera_pos[2] += -0.1; - } - if (keymap.get("d")) { - camera_pos[0] += 0.1; - } - if (keymap.get("e")) { - camera_pos[1] += 0.1; - } - if (keymap.get("q")) { - camera_pos[1] += -0.1; - } - - // Position - const pos = gl.getUniformLocation(program, "camera_pos"); - gl.uniform3fv(pos, camera_pos); - - // Rotation - const rot = gl.getUniformLocation(program, "camera_rot"); - - let M1 = calcRotationMatrix([0, -1, 0], mouse_pos[0]); - let M2 = calcRotationMatrix([-1, 0, 0], mouse_pos[1]); - let rot_mat = glMatrix.mat3.create(); - - glMatrix.mat3.mul(rot_mat, M1, M2); - gl.uniform3fv(rot, rot_mat); -} - -// update the canvas -function draw(gl, program) { - // Create uniform - const loc = gl.getUniformLocation(program, "time"); - TIME += 1 / 60; - gl.uniform1f(loc, TIME); - - updateCamera(gl, program); - - // Draw the frame recursively on next frame - gl.drawArrays(gl.TRIANGLES, 0, 6); - requestAnimationFrame(() => draw(gl, program)); -} - -function calcRotationMatrix(vec, rad) { - // Equation used from: - // https://people.eecs.berkeley.edu/~ug/slide/pipeline/assignments/as5/rotation.html - let A = glMatrix.mat3.fromValues( - 0, - -vec[2], - vec[1], - vec[2], - 0, - -vec[0], - -vec[1], - vec[0], - 0, - ); - - let I = glMatrix.mat3.create(); - - // Matrix Exponential - let Mpow = glMatrix.mat3.create(); - glMatrix.mat3.mul(Mpow, A, A); - - let M1 = glMatrix.mat3.create(); - let M2 = glMatrix.mat3.create(); - - // Scalar Multiplications - glMatrix.mat3.multiplyScalar(M1, A, Math.sin(rad)); - glMatrix.mat3.multiplyScalar(M2, Mpow, 1 - Math.cos(rad)); - - // Matrix Addition - let M3 = glMatrix.mat3.create(); - let Q = glMatrix.mat3.create(); - glMatrix.mat3.add(M3, I, M1); - glMatrix.mat3.add(Q, M3, M2); - - return Q; -} - +// Loads a single Texture to the Shader function loadTexture(gl, url, gl_tex) { // Create texture const texture = gl.createTexture(); @@ -211,28 +117,3 @@ function loadTexture(gl, url, gl_tex) { return texture; } - -// Initialize the shader -const [gl, program, canvas] = await initShader(); - -// Key Presses -let keymap = new Map(); -document.addEventListener("keydown", function (event) { - keymap.set(event.key, true); -}); -document.addEventListener("keyup", function (event) { - keymap.set(event.key, false); -}); -// Mouse movement -document.addEventListener("mousemove", function (event) { - mouse_pos[0] += event.movementX / 800; - mouse_pos[1] += event.movementY / 800; -}); - -// Request pointer Lock -canvas.addEventListener("click", async () => { - await canvas.requestPointerLock(); -}); - -// Update loop -draw(gl, program);