Compare commits

..

7 Commits
main ... prod

13 changed files with 576 additions and 84029 deletions

View File

@ -3,5 +3,9 @@ services:
image: nginx:alpine
volumes:
- ./src:/usr/share/nginx/html:ro
ports:
- "8080:80"
networks:
- public
restart: unless-stopped
networks:
public:
external: true

View File

@ -6,12 +6,10 @@
<title>CG1 MDI</title>
<script src="matrix-math.js"></script>
<script src="shader.js"></script>
<script src="wavefront.js"></script>
<script src="script.js"></script>
<style>
:root {
font-size: 20px;
--padding: 10px;
}
html, body {
@ -46,10 +44,10 @@
display: block;
background-color: #181825;
}
#stats {
#stats, #controls {
position: absolute;
top: var(--padding);
padding: var(--padding);
top: 20px;
padding: 20px;
display: block;
border: solid 2px #11111b;
background-color: #313244;
@ -57,7 +55,11 @@
}
#stats {
right: var(--padding);
right: 20px;
}
#controls {
left: 20px;
}
</style>
</head>
@ -67,6 +69,28 @@
<div id="stats">
FPS: <span id="fps"></span> - <span id="ms"></span>
</div>
<div id="controls">
<div>
Click & Drag to move camera
</div>
<div>
Scroll to zoom
</div>
<div>
LookAt Matrix: <input type="range" min=0 max=1 step=0.01 value=0 id="interpolateLookAt" autocomplete="off">
</div>
<div>
Projection Matrix: <input type="range" min=0 max=1 step=0.01 value=0 id="interpolateProjection" autocomplete="off" disabled="yes">
<div style="margin-left: 20px;">Invert Z-Axis: <input type="checkbox" id="invertZAxis" checked autocomplete="off"></div>
</div>
<div>
Use virtual camera: <input type="checkbox" id="displayMatricesVirtually" checked autocomplete="off">
</div>
<div>
Backface Culling: <input type="checkbox" id="backfaceCulling" autocomplete="off">
</div>
</div>
</div>
</body>
</html>

View File

@ -369,18 +369,6 @@ function mat4Inverse(out, m) {
return;
}
function mat4vec4Multiply(out, inMat, inVec) {
let result = [0, 0, 0, 0];
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 4; j++) {
result[i] += inMat[i + j * 4] * inVec[j];
}
}
out[0] = result[0];
out[1] = result[1];
out[2] = result[2];
out[3] = result[3];
}
/**
* subtracts b from a, storing the result in out
@ -520,11 +508,3 @@ function mat3Inverse(out, inm) {
mat3MultiplyScalar(result, result, 1 / mat3Determinant(inm));
mat3Copy(result, out);
}
function mat3MakeNormal(out, inm) {
let result = [];
mat3From4(result, inm);
mat3Inverse(result, result);
mat3Transpose(result, result);
mat3Copy(result, out);
}

View File

@ -1,34 +0,0 @@
# Blender 4.4.3
# www.blender.org
o Cube
v 1.000000 1.000000 -1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 1.000000 -1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 1.000000
vn -0.0000 1.0000 -0.0000
vn -0.0000 -0.0000 1.0000
vn -1.0000 -0.0000 -0.0000
vn -0.0000 -1.0000 -0.0000
vn 1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 -1.0000
vt 1.000000 0.000000
vt 0.000000 1.000000
vt 0.000000 0.000000
vt 1.000000 1.000000
s 0
f 5/1/1 3/2/1 1/3/1
f 3/1/2 8/2/2 4/3/2
f 7/1/3 6/2/3 8/3/3
f 2/1/4 8/2/4 6/3/4
f 1/1/5 4/2/5 2/3/5
f 5/1/6 2/2/6 6/3/6
f 5/1/1 7/4/1 3/2/1
f 3/1/2 7/4/2 8/2/2
f 7/1/3 5/4/3 6/2/3
f 2/1/4 4/4/4 8/2/4
f 1/1/5 3/4/5 4/2/5
f 5/1/6 1/4/6 2/2/6

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -3,16 +3,36 @@
let cv, gl;
let program;
let floorProgram;
class Object {
vertexBuffer;
numVertices;
}
let hVertices;
let hVertexBuffer;
let o = new Object();
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;
@ -44,6 +64,43 @@ async function init() {
// 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;
@ -59,7 +116,7 @@ async function init() {
});
document.addEventListener("mousemove", (e) => {
if (mouseDragging) {
if (mouseDragging && displayMatricesVirtually) {
cameraYaw += e.movementX / 100;
cameraPitch += e.movementY / 100;
@ -73,49 +130,303 @@ async function init() {
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
let f = await readObjFile("obj/smooth_monkey.obj");
o = new Object();
// 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,
o.vertexBuffer = gl.createBuffer();
o.numVertices = f.length / 8;
gl.bindBuffer(gl.ARRAY_BUFFER, o.vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(f), gl.STATIC_DRAW);
-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.enable(gl.CULL_FACE);
gl.frontFace(gl.CCW);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
gl.enable( gl.LINE_SMOOTH );
gl.enable( gl.POLYGON_SMOOTH );
gl.hint( gl.LINE_SMOOTH_HINT, gl.NICEST );
gl.hint( gl.POLYGON_SMOOTH_HINT, gl.NICEST )
// start drawing
requestAnimationFrame(draw);
}
function setAttribPointers() {
let positionAttribLocation = gl.getAttribLocation(program, "vertPosition");
let normalAttribLocation = gl.getAttribLocation(program, "vertNormal");
let textureAttribLocation = gl.getAttribLocation(program, "vertTexture");
let colorAttribLocation = gl.getAttribLocation(program, "vertColor");
gl.vertexAttribPointer(positionAttribLocation, 3, gl.FLOAT, gl.FALSE, 8 * Float32Array.BYTES_PER_ELEMENT, 0);
gl.vertexAttribPointer(textureAttribLocation, 2, gl.FLOAT, gl.FALSE, 8 * Float32Array.BYTES_PER_ELEMENT, 3 * Float32Array.BYTES_PER_ELEMENT);
gl.vertexAttribPointer(normalAttribLocation, 3, gl.FLOAT, gl.FALSE, 8 * Float32Array.BYTES_PER_ELEMENT, 5 * Float32Array.BYTES_PER_ELEMENT);
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(textureAttribLocation);
gl.enableVertexAttribArray(normalAttribLocation);
gl.enableVertexAttribArray(colorAttribLocation);
}
let frameCount = 0;
@ -153,48 +464,193 @@ async function draw() {
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 projectionMatrix = [];
mat4BuildPerspective(projectionMatrix, 90.0 / 180.0 * Math.PI, cv.width / cv.height, 0.1, 30);
let realProjectionMatrix = [];
mat4BuildPerspective(realProjectionMatrix, 90.0 / 180.0 * Math.PI, cv.width / cv.height, 0.1, 30);
let viewMatrix = [];
let cameraPosition = [Math.cos(cameraYaw) * smoothCameraDistance * Math.cos(cameraPitch), Math.sin(cameraPitch) * smoothCameraDistance, Math.sin(cameraYaw) * smoothCameraDistance * Math.cos(cameraPitch)];
let cameraLookAt = [0, 0, 0];
let cameraUp = [0, 1, 0];
mat4BuildLookAt(viewMatrix, cameraPosition, cameraLookAt, cameraUp);
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);
let normalMatrix = [];
mat3MakeNormal(normalMatrix, viewMatrix);
mat4Interpolate(realProjectionMatrix, identity, realProjectionMatrix, virtualRealInterpolation * virtualRealInterpolation);
mat4Interpolate(realViewMatrix, identity, realViewMatrix, virtualRealInterpolation);
gl.useProgram(program);
gl.uniformMatrix4fv(gl.getUniformLocation(program, "projectionMatrix"), gl.FALSE, new Float32Array(projectionMatrix));
gl.uniformMatrix4fv(gl.getUniformLocation(program, "modelViewMatrix"), gl.FALSE, new Float32Array(viewMatrix));
gl.uniformMatrix3fv(gl.getUniformLocation(program, "normalMatrix"), gl.FALSE, new Float32Array(normalMatrix));
gl.uniformMatrix4fv(gl.getUniformLocation(program, "realProjectionMatrix"), gl.FALSE, new Float32Array(realProjectionMatrix));
gl.uniformMatrix4fv(gl.getUniformLocation(program, "realViewMatrix"), gl.FALSE, new Float32Array(realViewMatrix));
let lightPosition = [Math.cos(hue * Math.PI * 2) * 3, 2.0, Math.sin(hue * Math.PI * 2) * 3, 1.0];
mat4vec4Multiply(lightPosition, viewMatrix, lightPosition);
gl.useProgram(floorProgram);
gl.uniformMatrix4fv(gl.getUniformLocation(floorProgram, "realProjectionMatrix"), gl.FALSE, new Float32Array(realProjectionMatrix));
gl.uniform3f(gl.getUniformLocation(program, "Light.position"), ...lightPosition.slice(0, 3));
gl.uniform3f(gl.getUniformLocation(program, "Light.color"), 1, 1, 1);
// Virtual Matrices
gl.useProgram(program);
let virtualModelViewLocation = gl.getUniformLocation(program, "virtualModelViewMatrix");
let virtualProjectionLocation = gl.getUniformLocation(program, "virtualProjectionMatrix");
let colorOverrideLocation = gl.getUniformLocation(program, "colorOverride");
gl.uniform3f(gl.getUniformLocation(program, "Material.ambientColor"), 0.1, 0.1, 0.1);
gl.uniform3f(gl.getUniformLocation(program, "Material.emitColor"), 0.05, 0.05, 0.0);
gl.uniform3f(gl.getUniformLocation(program, "Material.diffColor"), 0.7, 0.8, 0.1);
gl.uniform3f(gl.getUniformLocation(program, "Material.specColor"), 1, 1, 0.8);
gl.uniform1f(gl.getUniformLocation(program, "Material.shininess"), 10);
gl.bindBuffer(gl.ARRAY_BUFFER, o.vertexBuffer);
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, o.numVertices);
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);
frameTimes.push(performance.now() - frameStart);
lastFrame = now;

View File

@ -0,0 +1,6 @@
precision mediump float;
varying vec3 vPosition;
void main() {
gl_FragColor = mix(vec4(1,1,1,0.5), vec4(0.8,0.8,0.8,0.5), step(0.0, sin(vPosition.x * 3.14159 * 20.0) * sin(vPosition.z * 3.14159 * 20.0)));
}

View File

@ -0,0 +1,14 @@
precision mediump float;
attribute vec3 vertPosition;
attribute vec3 vertColor;
uniform mat4 realModelViewMatrix;
uniform mat4 realProjectionMatrix;
varying vec3 vPosition;
void main() {
vPosition = vertPosition;
gl_Position = realProjectionMatrix * realModelViewMatrix * vec4(vertPosition, 1.0);
}

View File

@ -1,33 +1,6 @@
precision mediump float;
uniform struct {
vec3 position;
vec3 color;
} Light;
uniform struct {
vec3 ambientColor;
vec3 emitColor;
vec3 diffColor;
vec3 specColor;
float shininess;
} Material;
varying vec3 vNormal;
varying vec2 vTexture;
varying vec3 vPosition;
varying vec3 fragColor;
void main() {
vec3 pleaseDontDeleteMe = vec3(vTexture, 0.0);
vec3 eyeDir = normalize(-vPosition);
vec3 lightDir = normalize(Light.position - vPosition);
vec3 r = reflect(-lightDir, vNormal);
vec3 ambient = Material.ambientColor;
vec3 emit = Material.emitColor;
vec3 diff = max(dot(lightDir, vNormal), 0.0) * Material.diffColor * Light.color;
vec3 spec = pow(max(dot(r, eyeDir), 0.0), Material.shininess) * Material.specColor * Light.color;
gl_FragColor = vec4(ambient + emit + diff + spec, 1);
gl_FragColor = vec4(fragColor, 1.0);
}

View File

@ -1,21 +1,21 @@
precision mediump float;
attribute vec3 vertPosition;
attribute vec3 vertNormal;
attribute vec2 vertTexture;
attribute vec3 vertColor;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
uniform mat3 normalMatrix;
uniform mat4 virtualModelViewMatrix;
uniform mat4 virtualProjectionMatrix;
varying vec3 vNormal;
varying vec2 vTexture;
varying vec3 vPosition;
uniform mat4 realViewMatrix;
uniform mat4 realProjectionMatrix;
uniform vec3 colorOverride;
varying vec3 fragColor;
void main() {
vNormal = normalize(normalMatrix * vertNormal);
vTexture = vertTexture;
vPosition = (modelViewMatrix * vec4(vertPosition, 1.0)).xyz;
float colorOverrideActive = step(0.001, length(colorOverride));
fragColor = colorOverride * colorOverrideActive + vertColor * (1.0 - colorOverrideActive);
gl_Position = projectionMatrix * modelViewMatrix * vec4(vertPosition, 1.0);
gl_Position = realProjectionMatrix * realViewMatrix * virtualProjectionMatrix * virtualModelViewMatrix * vec4(vertPosition, 1.0);
}

View File

@ -1,43 +0,0 @@
async function readObjFile(path) {
const res = await fetch(path);
const text = await res.text();
let vertices = [];
let textures = [];
let normals = [];
let result = [];
const lines = text.replace("\r","").split("\n");
for (let line of lines) {
const parts = line.split(/\s+/);
switch (parts[0]) {
case "v":
vertices.push(parts.slice(1, 4).map(parseFloat));
break;
case "vt":
textures.push(parts.slice(1, 3).map(parseFloat));
break;
case "vn":
normals.push(parts.slice(1, 4).map(parseFloat));
break;
case "f":
for (const part of parts.slice(1, 4)) {
const [v, vt, vn] = part.split("/").map((i) => parseInt(i) - 1);
result.push(...vertices[v], ...textures[vt], ...normals[vn]);
}
// support for quads:
if (parts.length > 4) {
for (let i of [1, 3, 4]) {
const part = parts[i];
const [v, vt, vn] = part.split("/").map((i) => parseInt(i) - 1);
result.push(...vertices[v], ...textures[vt], ...normals[vn]);
}
}
}
}
return result;
}