cg1_tut_mdi/src/script.js

681 lines
20 KiB
JavaScript

"use strict";
let cv, gl;
let program;
let floorProgram;
let hVertices;
let hVertexBuffer;
let cubeVertices;
let cubeVertexBuffer;
let lineCubeVertices;
let lineCubeVertexBuffer;
let originVertices;
let originVertexBuffer;
let floorVertices;
let floorVertexBuffer;
let cameraVertices;
let cameraVertexBuffer;
let lastFrame = Date.now();
let interpolateProjection = 0;
let interpolateLookAt = 0;
let displayMatricesVirtually = true;
let virtualRealInterpolation = 1;
let invertZAxis = true;
let cameraPitch = 0.565;
let cameraYaw = 0.375;
let cameraDistance = 4;
let smoothCameraDistance = 4;
let mouseDragging = false;
function resizeCanvas() {
const dpr = window.devicePixelRatio;
cv.width = cv.parentElement.clientWidth * dpr;
cv.height = cv.parentElement.clientHeight * dpr;
gl.viewport(0, 0, cv.width, cv.height);
}
async function init() {
cv = document.getElementById("cv");
gl = cv.getContext("webgl");
if (!gl) {
window.alert("WebGL not supported");
}
const resizeObserver = new ResizeObserver(resizeCanvas);
resizeObserver.observe(cv.parentElement);
resizeCanvas();
// input handling
document.getElementById("interpolateProjection").addEventListener("input", (e) => {
interpolateProjection = e.target.value;
if (interpolateProjection <= 0) {
document.getElementById("interpolateLookAt").disabled = "";
} else {
document.getElementById("interpolateLookAt").disabled = "yes";
}
});
document.getElementById("invertZAxis").addEventListener("input", (e) => {
invertZAxis = e.target.checked;
});
document.getElementById("interpolateLookAt").addEventListener("input", (e) => {
interpolateLookAt = e.target.value;
if (interpolateLookAt >= 1) {
document.getElementById("interpolateProjection").disabled = "";
} else {
document.getElementById("interpolateProjection").disabled = "yes";
}
});
document.getElementById("displayMatricesVirtually").addEventListener("input", (e) => {
displayMatricesVirtually = e.target.checked;
if (!displayMatricesVirtually) {
document.getElementById("invertZAxis").checked = true;
document.getElementById("invertZAxis").disabled = true;
} else {
document.getElementById("invertZAxis").checked = invertZAxis;
document.getElementById("invertZAxis").disabled = false;
}
});
document.getElementById("backfaceCulling").addEventListener("input", (e) => {
if (e.target.checked) {
gl.enable(gl.CULL_FACE);
} else {
gl.disable(gl.CULL_FACE);
}
});
cv.addEventListener("mousedown", (e) => {
if (e.button == 0) {
mouseDragging = true;
}
});
document.addEventListener("mouseup", (e) => {
if (e.button == 0) {
mouseDragging = false;
}
});
document.addEventListener("mouseleave", (e) => {
mouseDragging = false;
});
document.addEventListener("mousemove", (e) => {
if (mouseDragging && displayMatricesVirtually) {
cameraYaw += e.movementX / 100;
cameraPitch += e.movementY / 100;
if (cameraPitch < -Math.PI / 2) cameraPitch = -Math.PI / 2;
if (cameraPitch > Math.PI / 2) cameraPitch = Math.PI / 2;
}
});
cv.addEventListener("wheel", (e) => {
cameraDistance += e.deltaY / 100;
if (cameraDistance < 1) cameraDistance = 1;
if (cameraDistance > 15) cameraDistance = 15;
e.preventDefault();
});
// end input handling
console.log("compiling shaders...");
program = await buildShaderProgram(gl, "shaders/vertex.glsl", "shaders/fragment.glsl");
floorProgram = await buildShaderProgram(gl, "shaders/floor-vertex.glsl", "shaders/floor-fragment.glsl");
console.log("creating vertex buffer");
hVertices = [
// X // Y
// left vertical bar
-0.35, 0.6, 0.0, 1.0, 0.3, 0.3,
-0.35, -0.6, 0.0, 1.0, 0.3, 0.3,
-0.2, 0.6, 0.0, 1.0, 0.3, 0.3,
-0.2, 0.6, 0.0, 1.0, 0.3, 0.3,
-0.35, -0.6, 0.0, 1.0, 0.3, 0.3,
-0.2, -0.6, 0.0, 1.0, 0.3, 0.3,
// right vertical bar
0.35, -0.6, 0.0, 1.0, 0.3, 0.3,
0.35, 0.6, 0.0, 1.0, 0.3, 0.3,
0.2, 0.6, 0.0, 1.0, 0.3, 0.3,
0.35, -0.6, 0.0, 1.0, 0.3, 0.3,
0.2, 0.6, 0.0, 1.0, 0.3, 0.3,
0.2, -0.6, 0.0, 1.0, 0.3, 0.3,
// middle bar
-0.2, 0.1, 0.0, 1.0, 0.3, 0.3,
-0.2, -0.1, 0.0, 1.0, 0.3, 0.3,
0.2, 0.1, 0.0, 1.0, 0.3, 0.3,
0.2, 0.1, 0.0, 1.0, 0.3, 0.3,
-0.2, -0.1, 0.0, 1.0, 0.3, 0.3,
0.2, -0.1, 0.0, 1.0, 0.3, 0.3,
// bottom bar
-0.35, -0.7, 0.0, 1.0, 0.3, 0.3,
-0.35, -0.9, 0.0, 1.0, 0.3, 0.3,
0.35, -0.9, 0.0, 1.0, 0.3, 0.3,
-0.35, -0.7, 0.0, 1.0, 0.3, 0.3,
0.35, -0.9, 0.0, 1.0, 0.3, 0.3,
0.35, -0.7, 0.0, 1.0, 0.3, 0.3,
];
cubeVertices = [
// Back face (red)
-1, -1, -1, 1, 0.5, 0.5,
-1, 1, -1, 1, 0.5, 0.5,
1, 1, -1, 1, 0.5, 0.5,
-1, -1, -1, 1, 0.5, 0.5,
1, 1, -1, 1, 0.5, 0.5,
1, -1, -1, 1, 0.5, 0.5,
// Front face (green)
-1, -1, 1, 0.5, 1, 0.5,
1, -1, 1, 0.5, 1, 0.5,
1, 1, 1, 0.5, 1, 0.5,
-1, -1, 1, 0.5, 1, 0.5,
1, 1, 1, 0.5, 1, 0.5,
-1, 1, 1, 0.5, 1, 0.5,
// Left face (blue)
-1, 1, -1, 0.5, 0.5, 1,
-1, -1, -1, 0.5, 0.5, 1,
-1, 1, 1, 0.5, 0.5, 1,
-1, 1, 1, 0.5, 0.5, 1,
-1, -1, -1, 0.5, 0.5, 1,
-1, -1, 1, 0.5, 0.5, 1,
// Right face (yellow)
1, -1, -1, 1, 1, 0.5,
1, 1, -1, 1, 1, 0.5,
1, 1, 1, 1, 1, 0.5,
1, -1, -1, 1, 1, 0.5,
1, 1, 1, 1, 1, 0.5,
1, -1, 1, 1, 1, 0.5,
// Top face (magenta)
-1, 1, -1, 1, 0.5, 1,
-1, 1, 1, 1, 0.5, 1,
1, 1, 1, 1, 0.5, 1,
-1, 1, -1, 1, 0.5, 1,
1, 1, 1, 1, 0.5, 1,
1, 1, -1, 1, 0.5, 1,
// Bottom face (cyan)
-1, -1, 1, 0.5, 1, 1,
-1, -1, -1, 0.5, 1, 1,
1, -1, 1, 0.5, 1, 1,
1, -1, 1, 0.5, 1, 1,
-1, -1, -1, 0.5, 1, 1,
1, -1, -1, 0.5, 1, 1
];
lineCubeVertices = [
1, 1, 1, 1, 0, 0,
1, 1, -1, 1, 0, 0,
1, 1, 1, 1, 0, 0,
1, -1, 1, 1, 0, 0,
1, 1, 1, 1, 0, 0,
-1, 1, 1, 1, 0, 0,
1, 1, -1, 1, 0, 0,
1, -1, -1, 1, 0, 0,
1, 1, -1, 1, 0, 0,
-1, 1, -1, 1, 0, 0,
1, -1, 1, 1, 0, 0,
1, -1, -1, 1, 0, 0,
1, -1, 1, 1, 0, 0,
-1, -1, 1, 1, 0, 0,
-1, 1, 1, 1, 0, 0,
-1, 1, -1, 1, 0, 0,
-1, 1, 1, 1, 0, 0,
-1, -1, 1, 1, 0, 0,
1, -1, -1, 1, 0, 0,
-1, -1, -1, 1, 0, 0,
-1, -1, 1, 1, 0, 0,
-1, -1, -1, 1, 0, 0,
-1, 1, -1, 1, 0, 0,
-1, -1, -1, 1, 0, 0,
];
originVertices = [
0, 0, 0, 1, 0, 0,
1, 0, 0, 1, 0, 0,
0, 0, 0, 0, 1, 0,
0, 1, 0, 0, 1, 0,
0, 0, 0, 0, 0, 1,
0, 0, 1, 0, 0, 1,
];
floorVertices = [
1, 0, 1, 0, 0, 0,
-1, 0, -1, 0, 0, 0,
-1, 0, 1, 0, 0, 0,
-1, 0, -1, 0, 0, 0,
1, 0, 1, 0, 0, 0,
1, 0, -1, 0, 0, 0,
];
cameraVertices = [
// Cube Body (dark gray)
// Front face
-1, -1, 1, 0.196, 0.196, 0.196,
1, -1, 1, 0.196, 0.196, 0.196,
1, 1, 1, 0.196, 0.196, 0.196,
-1, -1, 1, 0.196, 0.196, 0.196,
1, 1, 1, 0.196, 0.196, 0.196,
-1, 1, 1, 0.196, 0.196, 0.196,
// Back face
-1, -1, -1, 0.196, 0.196, 0.196,
1, 1, -1, 0.196, 0.196, 0.196,
1, -1, -1, 0.196, 0.196, 0.196,
-1, -1, -1, 0.196, 0.196, 0.196,
-1, 1, -1, 0.196, 0.196, 0.196,
1, 1, -1, 0.196, 0.196, 0.196,
// Left face
-1, -1, -1, 0.196, 0.196, 0.196,
-1, -1, 1, 0.196, 0.196, 0.196,
-1, 1, 1, 0.196, 0.196, 0.196,
-1, -1, -1, 0.196, 0.196, 0.196,
-1, 1, 1, 0.196, 0.196, 0.196,
-1, 1, -1, 0.196, 0.196, 0.196,
// Right face
1, -1, -1, 0.196, 0.196, 0.196,
1, 1, 1, 0.196, 0.196, 0.196,
1, -1, 1, 0.196, 0.196, 0.196,
1, -1, -1, 0.196, 0.196, 0.196,
1, 1, -1, 0.196, 0.196, 0.196,
1, 1, 1, 0.196, 0.196, 0.196,
// Top face
-1, 1, -1, 0.196, 0.196, 0.196,
-1, 1, 1, 0.196, 0.196, 0.196,
1, 1, 1, 0.196, 0.196, 0.196,
-1, 1, -1, 0.196, 0.196, 0.196,
1, 1, 1, 0.196, 0.196, 0.196,
1, 1, -1, 0.196, 0.196, 0.196,
// Bottom face
-1, -1, -1, 0.196, 0.196, 0.196,
1, -1, 1, 0.196, 0.196, 0.196,
-1, -1, 1, 0.196, 0.196, 0.196,
-1, -1, -1, 0.196, 0.196, 0.196,
1, -1, -1, 0.196, 0.196, 0.196,
1, -1, 1, 0.196, 0.196, 0.196,
// Lens (light gray)
// Front face
-0.5, -0.5, -1.6, 0.706, 0.706, 0.706,
0.5, 0.5, -1.6, 0.706, 0.706, 0.706,
0.5, -0.5, -1.6, 0.706, 0.706, 0.706,
-0.5, -0.5, -1.6, 0.706, 0.706, 0.706,
-0.5, 0.5, -1.6, 0.706, 0.706, 0.706,
0.5, 0.5, -1.6, 0.706, 0.706, 0.706,
// Back face
-0.5, -0.5, -1.0, 0.706, 0.706, 0.706,
0.5, -0.5, -1.0, 0.706, 0.706, 0.706,
0.5, 0.5, -1.0, 0.706, 0.706, 0.706,
-0.5, -0.5, -1.0, 0.706, 0.706, 0.706,
0.5, 0.5, -1.0, 0.706, 0.706, 0.706,
-0.5, 0.5, -1.0, 0.706, 0.706, 0.706,
// Left face
-0.5, 0.5, -1.6, 0.706, 0.706, 0.706,
-0.5, -0.5, -1.0, 0.706, 0.706, 0.706,
-0.5, 0.5, -1.0, 0.706, 0.706, 0.706,
-0.5, -0.5, -1.6, 0.706, 0.706, 0.706,
-0.5, -0.5, -1.0, 0.706, 0.706, 0.706,
-0.5, 0.5, -1.6, 0.706, 0.706, 0.706,
// Right face
0.5, 0.5, -1.0, 0.706, 0.706, 0.706,
0.5, -0.5, -1.0, 0.706, 0.706, 0.706,
0.5, 0.5, -1.6, 0.706, 0.706, 0.706,
0.5, 0.5, -1.6, 0.706, 0.706, 0.706,
0.5, -0.5, -1.0, 0.706, 0.706, 0.706,
0.5, -0.5, -1.6, 0.706, 0.706, 0.706,
// Top face
0.5, 0.5, -1.6, 0.706, 0.706, 0.706,
-0.5, 0.5, -1.0, 0.706, 0.706, 0.706,
0.5, 0.5, -1.0, 0.706, 0.706, 0.706,
-0.5, 0.5, -1.6, 0.706, 0.706, 0.706,
-0.5, 0.5, -1.0, 0.706, 0.706, 0.706,
0.5, 0.5, -1.6, 0.706, 0.706, 0.706,
// Bottom face
-0.5, -0.5, -1.0, 0.706, 0.706, 0.706,
0.5, -0.5, -1.0, 0.706, 0.706, 0.706,
0.5, -0.5, -1.6, 0.706, 0.706, 0.706,
-0.5, -0.5, -1.0, 0.706, 0.706, 0.706,
0.5, -0.5, -1.6, 0.706, 0.706, 0.706,
-0.5, -0.5, -1.6, 0.706, 0.706, 0.706
];
hVertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, hVertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(hVertices), gl.STATIC_DRAW);
cubeVertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(cubeVertices), gl.STATIC_DRAW);
lineCubeVertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, lineCubeVertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(lineCubeVertices), gl.STATIC_DRAW);
originVertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, originVertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(originVertices), gl.STATIC_DRAW);
floorVertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, floorVertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(floorVertices), gl.STATIC_DRAW);
cameraVertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, cameraVertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(cameraVertices), gl.STATIC_DRAW);
// unbind buffer
gl.bindBuffer(gl.ARRAY_BUFFER, null);
// set clear colour
gl.clearColor(...hexToRgb("181825"), 1.0);
gl.enable(gl.DEPTH_TEST);
gl.enable(gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
// start drawing
requestAnimationFrame(draw);
}
function setAttribPointers() {
let positionAttribLocation = gl.getAttribLocation(program, "vertPosition");
let colorAttribLocation = gl.getAttribLocation(program, "vertColor");
gl.vertexAttribPointer(positionAttribLocation, 3, gl.FLOAT, gl.FALSE, 6 * Float32Array.BYTES_PER_ELEMENT, 0);
gl.vertexAttribPointer(colorAttribLocation, 3, gl.FLOAT, gl.FALSE, 6 * Float32Array.BYTES_PER_ELEMENT, 3 * Float32Array.BYTES_PER_ELEMENT);
gl.enableVertexAttribArray(positionAttribLocation);
gl.enableVertexAttribArray(colorAttribLocation);
}
let frameCount = 0;
let lastStatUpdate = Date.now();
function updateStats(deltaTime) {
frameCount++;
let now = Date.now();
let timeSinceLastUpdate = (now - lastStatUpdate) / 1000;
if (timeSinceLastUpdate < 0.5) return;
lastStatUpdate = now;
let fpsDisplay = document.getElementById("fps");
fpsDisplay.innerText = Math.round(frameCount / timeSinceLastUpdate)
let msDisplay = document.getElementById("ms");
msDisplay.innerText = deltaTime * 1000 + "ms";
frameCount = 0;
}
let hue = 0;
async function draw() {
let now = Date.now();
let deltaTime = (now - lastFrame) / 1000;
hue += deltaTime / 5;
if (hue > 1) hue = 0;
if (displayMatricesVirtually) {
virtualRealInterpolation = Math.min(virtualRealInterpolation + deltaTime * 2, 1);
} else {
virtualRealInterpolation = Math.max(virtualRealInterpolation - deltaTime * 2, 0);
}
smoothCameraDistance += (cameraDistance - smoothCameraDistance) / 8;
updateStats(deltaTime);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
let identity = [];
mat4Identity(identity);
// Real Matrices
let realProjectionMatrix = [];
mat4BuildPerspective(realProjectionMatrix, 90.0 / 180.0 * Math.PI, cv.width / cv.height, 0.1, 30);
let realViewMatrix = [];
let realCameraPosition = [Math.cos(cameraYaw) * smoothCameraDistance * Math.cos(cameraPitch), Math.sin(cameraPitch) * smoothCameraDistance, Math.sin(cameraYaw) * smoothCameraDistance * Math.cos(cameraPitch)];
let realCameraLookAt = [0, 0, 0];
let realCameraUp = [0, 1, 0];
mat4BuildLookAt(realViewMatrix, realCameraPosition, realCameraLookAt, realCameraUp);
mat4Interpolate(realProjectionMatrix, identity, realProjectionMatrix, virtualRealInterpolation * virtualRealInterpolation);
mat4Interpolate(realViewMatrix, identity, realViewMatrix, virtualRealInterpolation);
gl.useProgram(program);
gl.uniformMatrix4fv(gl.getUniformLocation(program, "realProjectionMatrix"), gl.FALSE, new Float32Array(realProjectionMatrix));
gl.uniformMatrix4fv(gl.getUniformLocation(program, "realViewMatrix"), gl.FALSE, new Float32Array(realViewMatrix));
gl.useProgram(floorProgram);
gl.uniformMatrix4fv(gl.getUniformLocation(floorProgram, "realProjectionMatrix"), gl.FALSE, new Float32Array(realProjectionMatrix));
// Virtual Matrices
gl.useProgram(program);
let virtualModelViewLocation = gl.getUniformLocation(program, "virtualModelViewMatrix");
let virtualProjectionLocation = gl.getUniformLocation(program, "virtualProjectionMatrix");
let colorOverrideLocation = gl.getUniformLocation(program, "colorOverride");
let virtualProjectionMatrix = [];
mat4BuildPerspective(virtualProjectionMatrix, 90.0 / 180.0 * Math.PI, cv.width / cv.height, 0.9, 5);
if (!invertZAxis) {
let zAxisFlipMatrix = [];
mat4Identity(zAxisFlipMatrix);
zAxisFlipMatrix[10] = -1;
mat4Interpolate(zAxisFlipMatrix, identity, zAxisFlipMatrix, virtualRealInterpolation);
mat4Multiply(virtualProjectionMatrix, zAxisFlipMatrix, virtualProjectionMatrix);
}
let inverseVirtualProjectionMatrix = [];
mat4Inverse(inverseVirtualProjectionMatrix, virtualProjectionMatrix);
let virtualViewMatrix = [];
let virtualCameraPosition = [1.2, 1.2, 2];
let virtualCameraLookAt = [0, 0, -1];
let virtualCameraUp = [0, 1, 0];
mat4BuildLookAt(virtualViewMatrix, virtualCameraPosition, virtualCameraLookAt, virtualCameraUp);
let inverseVirtualViewMatrix = [];
mat4Inverse(inverseVirtualViewMatrix, virtualViewMatrix);
mat4Interpolate(virtualProjectionMatrix, identity, virtualProjectionMatrix, interpolateProjection);
mat4Interpolate(virtualViewMatrix, identity, virtualViewMatrix, interpolateLookAt);
gl.uniformMatrix4fv(virtualProjectionLocation, gl.FALSE, new Float32Array(virtualProjectionMatrix));
let modelMatrix = [];
mat4Identity(modelMatrix);
let modelViewMatrix = [];
mat4Multiply(modelViewMatrix, virtualViewMatrix, modelMatrix);
gl.uniformMatrix4fv(virtualModelViewLocation, gl.FALSE, new Float32Array(modelViewMatrix));
// draw scene
// draw H
gl.useProgram(program);
gl.bindBuffer(gl.ARRAY_BUFFER, hVertexBuffer);
setAttribPointers();
gl.drawArrays(gl.TRIANGLES, 0, hVertices.length / 6);
// draw line cube
gl.bindBuffer(gl.ARRAY_BUFFER, lineCubeVertexBuffer);
setAttribPointers();
gl.uniform3fv(colorOverrideLocation, [1, 1, 0.5]);
gl.drawArrays(gl.LINES, 0, lineCubeVertices.length / 6);
gl.uniform3fv(colorOverrideLocation, [0, 0, 0]);
// draw solid cube 1
let cube1ModelView = [];
mat4Identity(cube1ModelView);
mat4Scale(cube1ModelView, cube1ModelView, [0.3, 0.3, 0.3]);
mat4RotateY(cube1ModelView, cube1ModelView, 0.3);
mat4Translate(cube1ModelView, cube1ModelView, [-0.5, 0.3, -0.7]);
mat4Multiply(cube1ModelView, virtualViewMatrix, cube1ModelView);
gl.uniformMatrix4fv(virtualModelViewLocation, gl.FALSE, new Float32Array(cube1ModelView));
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexBuffer);
setAttribPointers();
gl.drawArrays(gl.TRIANGLES, 0, cubeVertices.length / 6);
// draw solid cube 2
let cube2ModelView = [];
mat4Identity(cube2ModelView);
mat4Scale(cube2ModelView, cube2ModelView, [0.4, 0.4, 0.4]);
mat4RotateY(cube2ModelView, cube2ModelView, 2.6);
mat4Translate(cube2ModelView, cube2ModelView, [1.6, 0.3, -1]);
mat4Multiply(cube2ModelView, virtualViewMatrix, cube2ModelView);
gl.uniformMatrix4fv(virtualModelViewLocation, gl.FALSE, new Float32Array(cube2ModelView));
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexBuffer);
setAttribPointers();
gl.drawArrays(gl.TRIANGLES, 0, cubeVertices.length / 6);
// draw virtual camera
let virtualCameraModelView = [];
mat4Identity(virtualCameraModelView);
mat4Scale(virtualCameraModelView, virtualCameraModelView, [0.1, 0.1, 0.1]);
mat4Translate(virtualCameraModelView, virtualCameraModelView, [0, 0, 0.16]);
mat4Multiply(virtualCameraModelView, inverseVirtualViewMatrix, virtualCameraModelView);
mat4Multiply(virtualCameraModelView, virtualViewMatrix, virtualCameraModelView);
gl.uniformMatrix4fv(virtualModelViewLocation, gl.FALSE, new Float32Array(virtualCameraModelView));
gl.bindBuffer(gl.ARRAY_BUFFER, cameraVertexBuffer);
setAttribPointers();
if (displayMatricesVirtually && interpolateProjection <= 0) {
gl.drawArrays(gl.TRIANGLES, 0, cameraVertices.length / 6);
}
let frustomModelMatrix = [];
mat4Multiply(frustomModelMatrix, inverseVirtualViewMatrix, inverseVirtualProjectionMatrix);
mat4Multiply(frustomModelMatrix, virtualViewMatrix, frustomModelMatrix);
// mat4Copy(inverseVirtualProjectionMatrix, frustomModelMatrix);
gl.uniformMatrix4fv(virtualModelViewLocation, gl.FALSE, new Float32Array(frustomModelMatrix));
gl.bindBuffer(gl.ARRAY_BUFFER, lineCubeVertexBuffer);
setAttribPointers();
gl.uniform3fv(colorOverrideLocation, [1, 0, 1]);
gl.drawArrays(gl.LINES, 0, lineCubeVertices.length / 6);
gl.uniform3fv(colorOverrideLocation, [0, 0, 0]);
// draw origin
gl.uniformMatrix4fv(virtualModelViewLocation, gl.FALSE, new Float32Array(identity));
gl.uniformMatrix4fv(virtualProjectionLocation, gl.FALSE, new Float32Array(identity));
gl.bindBuffer(gl.ARRAY_BUFFER, originVertexBuffer);
setAttribPointers();
gl.drawArrays(gl.LINES, 0, originVertices.length / 6);
// draw origin cube
if (interpolateProjection < 1 && interpolateLookAt > 0) {
gl.bindBuffer(gl.ARRAY_BUFFER, lineCubeVertexBuffer);
setAttribPointers();
gl.uniform3fv(colorOverrideLocation, [1, 0, 0]);
gl.drawArrays(gl.LINES, 0, lineCubeVertices.length / 6);
gl.uniform3fv(colorOverrideLocation, [0, 0, 0]);
}
// draw floor
gl.useProgram(floorProgram);
let floorModelView = [];
mat4Identity(floorModelView);
mat4Scale(floorModelView, floorModelView, [10, 0, 10]);
mat4Multiply(floorModelView, realViewMatrix, floorModelView);
gl.uniformMatrix4fv(gl.getUniformLocation(floorProgram, "realModelViewMatrix"), gl.FALSE, new Float32Array(floorModelView));
gl.bindBuffer(gl.ARRAY_BUFFER, floorVertexBuffer);
setAttribPointers();
gl.drawArrays(gl.TRIANGLES, 0, floorVertices.length / 6);
lastFrame = now;
requestAnimationFrame(draw);
}
function hexToRgb(hex) {
let r = parseInt(hex.substring(0, 2), 16) / 255;
let g = parseInt(hex.substring(2, 4), 16) / 255;
let b = parseInt(hex.substring(4, 6), 16) / 255;
return [r, g, b];
}
function hslToRgb(h, s, l) {
let r, g, b;
if (s == 0) {
r = g = b = l;
} else {
let hue2rgb = function hue2rgb(p, q, t) {
if (t < 0) t += 1;
if (t > 1) t -= 1;
if (t < 1 / 6) return p + (q - p) * 6 * t;
if (t < 1 / 2) return q;
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
return p;
}
let q = l < 0.5 ? l * (1 + s) : l + s - l * s;
let p = 2 * l - q;
r = hue2rgb(p, q, h + 1 / 3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1 / 3);
}
return [r, g, b];
}
window.addEventListener("DOMContentLoaded", init);