diff --git a/raymarcher.glsl b/raymarcher.glsl index 137b6a9..1b5953b 100644 --- a/raymarcher.glsl +++ b/raymarcher.glsl @@ -7,6 +7,7 @@ uniform float time; uniform sampler2D uSampler1; uniform sampler2D uSampler2; uniform vec3 camera_pos; +uniform vec3 camera_rot[3]; // Output out vec4 color; @@ -32,10 +33,15 @@ float remap11(float val) { return ((val - .5) * 2.); } +vec3 mat3_vec_mul(vec3 m[3], vec3 v) { + return v.x * m[0] + v.y * m[1] + v.z * m[2]; +} + void main() { // Set up camera and sphere object vec3 ray_dir = normalize(vec3(remap11(texture_coordinates.x), remap11(texture_coordinates.y), 1.)); + ray_dir = mat3_vec_mul(camera_rot, ray_dir); vec3 ray_pos = camera_pos; const vec3 sphere_pos = vec3(0., 0., 3.); const float rad = 1.; diff --git a/shader.mjs b/shader.mjs index 8fd4d86..be42fe4 100644 --- a/shader.mjs +++ b/shader.mjs @@ -1,8 +1,10 @@ +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 camera_rot = [0, 0, 0]; +let mouse_pos = [0, 0]; // ** Initialization stuffs ** // @@ -115,8 +117,22 @@ function updateCamera(gl, program) { 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 @@ -131,6 +147,43 @@ function draw(gl, program) { 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; +} + function loadTexture(gl, url, gl_tex) { // Create texture const texture = gl.createTexture(); @@ -170,6 +223,12 @@ document.addEventListener("keydown", function (event) { 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();