Compare commits

..

No commits in common. "main" and "u01" have entirely different histories.
main ... u01

11 changed files with 65 additions and 84742 deletions

View File

@ -4,69 +4,24 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<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 {
margin: 0;
height: 100%;
}
body {
padding: 1vw;
box-sizing: border-box;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
margin: 0;
background-color: #1e1e2e;
color: #cdd6f4;
font-family: monospace;
overflow: hidden;
}
#display {
position: relative;
overflow: hidden;
box-sizing: border-box;
border-radius: 20px;
height: 100%;
width: 100%;
border: solid 2px #11111b;
}
#cv {
position: relative;
max-width: 100%;
max-height: 100%;
width: 100%;
height: 100%;
display: block;
background-color: #181825;
}
#stats {
position: absolute;
top: var(--padding);
padding: var(--padding);
display: block;
border: solid 2px #11111b;
background-color: #313244;
border: solid 2px black;
border-radius: 20px;
}
#stats {
right: var(--padding);
}
</style>
</head>
<body>
<div id="display">
<canvas id="cv"></canvas>
<div id="stats">
FPS: <span id="fps"></span> - <span id="ms"></span>
</div>
</div>
<canvas id="cv" width="800" height="600"></canvas>
</body>
</html>

View File

@ -1,530 +0,0 @@
"use strict";
/**
* overwrites a 4x4 matrix with the identity matrix
*/
function mat4Identity(mat) {
for (let i = 0; i < 16; i++) {
mat[i] = (i % 5 == 0) ? 1 : 0;
}
}
/**
* copies a mat4 from src to dst
*/
function mat4Copy(src, dst) {
for (let i = 0; i < 16; i++) {
dst[i] = src[i];
}
}
/**
* sets all the values in a mat4 to zero
*/
function mat4Empty(mat) {
for (let i = 0; i < 16; i++) {
mat[i] = 0;
}
}
/**
* mutliplies A with B and stores the result in result
*/
function mat4Multiply(result, A, B) {
// if result is one of the arguments, modify copy instead of result directly
if (result == A || result == B) {
let tempResult = [];
mat4Multiply(tempResult, A, B);
mat4Copy(tempResult, result);
return;
}
// loops over cells of the result matrix
for (let i = 0; i < 16; i++) {
let col = (i / 4) | 0;
let row = i % 4;
// initialise current cell with 0
result[i] = 0;
// loop over the row of A and column of B
// continuously adding the multiplication of the two values to the result cell
for (let j = 0; j < 4; j++) {
result[i] += A[row + j * 4] * B[j + col * 4];
}
}
}
/**
* prints a mat4 to the screen
*/
function mat4Print(m) {
let str = "";
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 4; j++) {
str += m[j * 4 + i] + " ";
}
str += "\n";
}
console.log(str);
}
/**
* translates by the vector v
*/
function mat4Translate(out, inm, v) {
let t = [];
mat4Identity(t);
t[12] = v[0];
t[13] = v[1];
t[14] = v[2];
mat4Multiply(out, t, inm);
}
/**
* scales by the vector v
*/
function mat4Scale(out, inm, v) {
let t = [];
mat4Identity(t);
t[0] = v[0];
t[5] = v[1];
t[10] = v[2];
mat4Multiply(out, t, inm);
}
/**
* rotates around the X axis by the angle a (in radians)
*/
function mat4RotateX(out, inm, a) {
let t = [];
mat4Identity(t);
t[5] = Math.cos(a);
t[6] = Math.sin(a);
t[9] = -Math.sin(a);
t[10] = Math.cos(a);
mat4Multiply(out, t, inm);
}
/**
* rotates around the Y axis by the angle a (in radians)
*/
function mat4RotateY(out, inm, a) {
let t = [];
mat4Identity(t);
t[0] = Math.cos(a);
t[2] = -Math.sin(a);
t[8] = Math.sin(a);
t[10] = Math.cos(a);
mat4Multiply(out, t, inm);
}
/**
* rotates around the Z axis by the angle a (in radians)
*/
function mat4RotateZ(out, inm, a) {
let t = [];
mat4Identity(t);
t[0] = Math.cos(a);
t[1] = Math.sin(a);
t[4] = -Math.sin(a);
t[5] = Math.cos(a);
mat4Multiply(out, t, inm);
}
/**
* builds a look-at matrix, overwriting out
* eye is the position of the camera
* look is the position of the target to be looked at
* up is the up vector
*/
function mat4BuildLookAt(out, eye, look, up) {
let n = [];
let u = [];
let v = [];
let t = [];
vec3Subtract(n, eye, look);
vec3CrossProduct(u, up, n);
vec3CrossProduct(v, n, u);
vec3Normalise(n, n);
vec3Normalise(u, u);
vec3Normalise(v, v);
t[0] = - vec3DotProduct(u, eye);
t[1] = - vec3DotProduct(v, eye);
t[2] = - vec3DotProduct(n, eye);
out[0] = u[0]; out[4] = u[1]; out[8] = u[2]; out[12] = t[0];
out[1] = v[0]; out[5] = v[1]; out[9] = v[2]; out[13] = t[1];
out[2] = n[0]; out[6] = n[1]; out[10] = n[2]; out[14] = t[2];
out[3] = 0; out[7] = 0; out[11] = 0; out[15] = 1;
}
/**
* builds a projection matrix, overwriting out
* r, l, t, b are the right, left, top and bottom of the frustum
* n and f are the distance of the near and far planes from the camera
*/
function mat4BuildProjection(out, r, l, t, b, n, f) {
mat4Identity(out);
out[0] = 2.0 / (r - l);
out[5] = 2.0 / (t - b);
out[8] = 1.0 / n * (r + l) / (r - l);
out[9] = 1.0 / n * (t + b) / (t - b);
out[10] = -1.0 / n * (f + n) / (f - n);
out[11] = -1.0 / n;
out[14] = - 2.0 * f / (f - n);
out[15] = 0.0;
}
/**
* builds a perspective projection matrix, overwriting out
* fovy is the field of view in the y direction
* aspect is the aspect ratio
* n and f are the distance of the near and far planes from the camera
*/
function mat4BuildPerspective(out, fovy, aspect, n, f) {
let t = n * Math.tan(0.5 * fovy);
let b = -t;
let r = aspect * t;
let l = -r;
mat4BuildProjection(out, r, l, t, b, n, f);
}
/**
* linearly interpolates between a and b, storing the result in out
*/
function mat4Interpolate(out, a, b, f) {
for (let i = 0; i < 16; i++) {
out[i] = (1 - f) * a[i] + f * b[i];
}
}
function mat4From3(out, inm) {
mat4Identity(out);
out[0] = inm[0];
out[1] = inm[1];
out[2] = inm[2];
out[4] = inm[3];
out[5] = inm[4];
out[6] = inm[5];
out[8] = inm[6];
out[9] = inm[7];
out[10] = inm[8];
}
/**
* https://stackoverflow.com/questions/1148309/inverting-a-4x4-matrix
*/
function mat4Inverse(out, m) {
let inv = [];
let det;
let i;
inv[0] = m[5] * m[10] * m[15] -
m[5] * m[11] * m[14] -
m[9] * m[6] * m[15] +
m[9] * m[7] * m[14] +
m[13] * m[6] * m[11] -
m[13] * m[7] * m[10];
inv[4] = -m[4] * m[10] * m[15] +
m[4] * m[11] * m[14] +
m[8] * m[6] * m[15] -
m[8] * m[7] * m[14] -
m[12] * m[6] * m[11] +
m[12] * m[7] * m[10];
inv[8] = m[4] * m[9] * m[15] -
m[4] * m[11] * m[13] -
m[8] * m[5] * m[15] +
m[8] * m[7] * m[13] +
m[12] * m[5] * m[11] -
m[12] * m[7] * m[9];
inv[12] = -m[4] * m[9] * m[14] +
m[4] * m[10] * m[13] +
m[8] * m[5] * m[14] -
m[8] * m[6] * m[13] -
m[12] * m[5] * m[10] +
m[12] * m[6] * m[9];
inv[1] = -m[1] * m[10] * m[15] +
m[1] * m[11] * m[14] +
m[9] * m[2] * m[15] -
m[9] * m[3] * m[14] -
m[13] * m[2] * m[11] +
m[13] * m[3] * m[10];
inv[5] = m[0] * m[10] * m[15] -
m[0] * m[11] * m[14] -
m[8] * m[2] * m[15] +
m[8] * m[3] * m[14] +
m[12] * m[2] * m[11] -
m[12] * m[3] * m[10];
inv[9] = -m[0] * m[9] * m[15] +
m[0] * m[11] * m[13] +
m[8] * m[1] * m[15] -
m[8] * m[3] * m[13] -
m[12] * m[1] * m[11] +
m[12] * m[3] * m[9];
inv[13] = m[0] * m[9] * m[14] -
m[0] * m[10] * m[13] -
m[8] * m[1] * m[14] +
m[8] * m[2] * m[13] +
m[12] * m[1] * m[10] -
m[12] * m[2] * m[9];
inv[2] = m[1] * m[6] * m[15] -
m[1] * m[7] * m[14] -
m[5] * m[2] * m[15] +
m[5] * m[3] * m[14] +
m[13] * m[2] * m[7] -
m[13] * m[3] * m[6];
inv[6] = -m[0] * m[6] * m[15] +
m[0] * m[7] * m[14] +
m[4] * m[2] * m[15] -
m[4] * m[3] * m[14] -
m[12] * m[2] * m[7] +
m[12] * m[3] * m[6];
inv[10] = m[0] * m[5] * m[15] -
m[0] * m[7] * m[13] -
m[4] * m[1] * m[15] +
m[4] * m[3] * m[13] +
m[12] * m[1] * m[7] -
m[12] * m[3] * m[5];
inv[14] = -m[0] * m[5] * m[14] +
m[0] * m[6] * m[13] +
m[4] * m[1] * m[14] -
m[4] * m[2] * m[13] -
m[12] * m[1] * m[6] +
m[12] * m[2] * m[5];
inv[3] = -m[1] * m[6] * m[11] +
m[1] * m[7] * m[10] +
m[5] * m[2] * m[11] -
m[5] * m[3] * m[10] -
m[9] * m[2] * m[7] +
m[9] * m[3] * m[6];
inv[7] = m[0] * m[6] * m[11] -
m[0] * m[7] * m[10] -
m[4] * m[2] * m[11] +
m[4] * m[3] * m[10] +
m[8] * m[2] * m[7] -
m[8] * m[3] * m[6];
inv[11] = -m[0] * m[5] * m[11] +
m[0] * m[7] * m[9] +
m[4] * m[1] * m[11] -
m[4] * m[3] * m[9] -
m[8] * m[1] * m[7] +
m[8] * m[3] * m[5];
inv[15] = m[0] * m[5] * m[10] -
m[0] * m[6] * m[9] -
m[4] * m[1] * m[10] +
m[4] * m[2] * m[9] +
m[8] * m[1] * m[6] -
m[8] * m[2] * m[5];
det = m[0] * inv[0] + m[1] * inv[4] + m[2] * inv[8] + m[3] * inv[12];
if (det == 0) {
mat4Copy(m, out); // singular matrix, can't invert
return;
}
det = 1.0 / det;
for (i = 0; i < 16; i++)
out[i] = inv[i] * det;
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
*/
function vec3Subtract(out, a, b) {
out[0] = a[0] - b[0];
out[1] = a[1] - b[1];
out[2] = a[2] - b[2];
}
/**
* calculates the cross product of a and b, storing the result in out
*/
function vec3CrossProduct(out, a, b) {
let result = [];
result[0] = a[1] * b[2] - a[2] * b[1];
result[1] = a[2] * b[0] - a[0] * b[2];
result[2] = a[0] * b[1] - a[1] * b[0];
out[0] = result[0];
out[1] = result[1];
out[2] = result[2];
}
/**
* normalizes in storing the result in out
*/
function vec3Normalise(out, inv) {
let length = vec3Length(inv);
out[0] = inv[0] / length;
out[1] = inv[1] / length;
out[2] = inv[2] / length;
}
/**
* returns the length of the vector in
*/
function vec3Length(inv) {
return Math.sqrt(inv[0] * inv[0] + inv[1] * inv[1] + inv[2] * inv[2]);
}
/**
* returns the dot product of the vectors a and b
*/
function vec3DotProduct(a, b) {
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
}
/**
* sets the values of out to x, y and z
*/
function vec3Set(out, x, y, z) {
out[0] = x;
out[1] = y;
out[2] = z;
}
function mat3Copy(src, dst) {
for (let i = 0; i < 9; i++) {
dst[i] = src[i];
}
}
function mat3From4(out, inm) {
out[0] = inm[0];
out[1] = inm[1];
out[2] = inm[2];
out[3] = inm[4];
out[4] = inm[5];
out[5] = inm[6];
out[6] = inm[8];
out[7] = inm[9];
out[8] = inm[10];
}
function mat3Transpose(out, inm) {
let result = [];
for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
result[i * 3 + j] = inm[j * 3 + i];
}
}
mat3Copy(result, out);
}
function mat3Minor(out, inm) {
let result = [];
// TODO: check if this is correct
result[0] = inm[4] * inm[8] - inm[5] * inm[7];
result[1] = inm[3] * inm[8] - inm[5] * inm[6];
result[2] = inm[3] * inm[7] - inm[4] * inm[6];
result[3] = inm[1] * inm[8] - inm[2] * inm[7];
result[4] = inm[0] * inm[8] - inm[2] * inm[6];
result[5] = inm[0] * inm[7] - inm[1] * inm[6];
result[6] = inm[1] * inm[5] - inm[2] * inm[4];
result[7] = inm[0] * inm[5] - inm[2] * inm[3];
result[8] = inm[0] * inm[4] - inm[1] * inm[3];
mat3Copy(result, out);
}
function mat3Cofactor(out, inm) {
mat3Minor(out, inm);
out[1] *= -1;
out[3] *= -1;
out[5] *= -1;
out[7] *= -1;
}
function mat3Adjoint(out, inm) {
mat3Cofactor(out, inm);
mat3Transpose(out, inm);
}
function mat3MultiplyScalar(out, inm, x) {
for (let i = 0; i < 9; i++) {
out[i] = inm[i] * x;
}
}
function mat3Determinant(m) {
return + m[0] * m[4] * m[8] + m[3] * m[7] * m[2] + m[6] * m[1] * m[5] - m[2] * m[4] * m[6] - m[5] * m[7] * m[0] - m[8] * m[1] * m[3];
}
function mat3Inverse(out, inm) {
let result = [];
mat3Adjoint(result, 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

@ -4,235 +4,87 @@ let cv, gl;
let program;
class Object {
vertexBuffer;
numVertices;
}
let o = new Object();
let lastFrame = Date.now();
let cameraPitch = 0.565;
let cameraYaw = 0.375;
let cameraDistance = 4;
let smoothCameraDistance = 4;
let mouseDragging = false;
let frameTimes = [];
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);
}
let vertexBuffer;
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
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) {
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");
console.log("compiling vertex shader...");
let vertexShader = await fetchAndCompileShader(gl, gl.VERTEX_SHADER, "shaders/vertex.glsl");
console.log("compiling fragment shader...");
let fragmentShader = await fetchAndCompileShader(gl, gl.FRAGMENT_SHADER, "shaders/fragment.glsl");
console.log("linking shader program...");
program = linkShaderProgram(gl, vertexShader, fragmentShader);
let triangleVertices = [
// X // Y // R // G // B
0.0, 0.5, 0.0, 1.0, 1.0,
-0.5, -0.5, 1.0, 0.0, 1.0,
0.5, -0.5, 1.0, 1.0, 0.0
];
console.log("creating vertex buffer");
vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(triangleVertices), gl.STATIC_DRAW);
let f = await readObjFile("obj/smooth_monkey.obj");
o = new Object();
// get location of vertPosition attribute
let positionAttribLocation = gl.getAttribLocation(program, "vertPosition");
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);
gl.vertexAttribPointer(
positionAttribLocation, // which attribute is read
2, // number of values to read
gl.FLOAT, // type of values
gl.FALSE, // whether to normalize
5 * Float32Array.BYTES_PER_ELEMENT, // size of individual vertex / distance between values to read
0 // offset where to start reading
);
// enable attribute
gl.enableVertexAttribArray(positionAttribLocation);
let colorAttribLocation = gl.getAttribLocation(program, "vertColor");
gl.vertexAttribPointer(
colorAttribLocation,
3,
gl.FLOAT,
gl.FALSE,
5 * Float32Array.BYTES_PER_ELEMENT,
2 * Float32Array.BYTES_PER_ELEMENT
);
gl.enableVertexAttribArray(colorAttribLocation);
// 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.clearColor(0.1, 0.1, 0.1, 1.0);
// start drawing
requestAnimationFrame(draw);
}
function setAttribPointers() {
let positionAttribLocation = gl.getAttribLocation(program, "vertPosition");
let normalAttribLocation = gl.getAttribLocation(program, "vertNormal");
let textureAttribLocation = gl.getAttribLocation(program, "vertTexture");
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.enableVertexAttribArray(positionAttribLocation);
gl.enableVertexAttribArray(textureAttribLocation);
gl.enableVertexAttribArray(normalAttribLocation);
}
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");
if (frameTimes.length > 0) {
msDisplay.innerText = (Math.round(frameTimes.reduce((prev, curr) => prev + curr) / frameTimes.length * 100) / 100) + "ms";
}
frameTimes = [];
frameCount = 0;
}
let hue = 0;
async function draw() {
let now = Date.now();
let deltaTime = (now - lastFrame) / 1000;
let frameStart = performance.now();
hue += deltaTime / 5;
if (hue > 1) hue = 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 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 normalMatrix = [];
mat3MakeNormal(normalMatrix, viewMatrix);
gl.clear(gl.COLOR_BUFFER_BIT);
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));
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.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.uniform3f(gl.getUniformLocation(program, "Light.position"), ...lightPosition.slice(0, 3));
gl.uniform3f(gl.getUniformLocation(program, "Light.color"), 1, 1, 1);
gl.drawArrays(gl.TRIANGLES, 0, 3);
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);
setAttribPointers();
gl.drawArrays(gl.TRIANGLES, 0, o.numVertices);
frameTimes.push(performance.now() - frameStart);
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);

View File

@ -46,9 +46,3 @@ function linkShaderProgram(gl, vertexShader, fragmentShader) {
return program;
}
async function buildShaderProgram(gl, vertexPath, fragmentPath) {
let vertexShader = await fetchAndCompileShader(gl, gl.VERTEX_SHADER, vertexPath);
let fragmentShader = await fetchAndCompileShader(gl, gl.FRAGMENT_SHADER, fragmentPath);
return linkShaderProgram(gl, vertexShader, fragmentShader);
}

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,10 @@
precision mediump float;
attribute vec3 vertPosition;
attribute vec3 vertNormal;
attribute vec2 vertTexture;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
uniform mat3 normalMatrix;
varying vec3 vNormal;
varying vec2 vTexture;
varying vec3 vPosition;
attribute vec2 vertPosition;
attribute vec3 vertColor;
varying vec3 fragColor;
void main() {
vNormal = normalize(normalMatrix * vertNormal);
vTexture = vertTexture;
vPosition = (modelViewMatrix * vec4(vertPosition, 1.0)).xyz;
gl_Position = projectionMatrix * modelViewMatrix * vec4(vertPosition, 1.0);
fragColor = vertColor;
gl_Position = vec4(vertPosition, 0.0, 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;
}