Compare commits
No commits in common. "main" and "u02" have entirely different histories.
|
@ -4,69 +4,42 @@
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>CG1 MDI</title>
|
<title>CG1 MDI</title>
|
||||||
<script src="matrix-math.js"></script>
|
|
||||||
<script src="shader.js"></script>
|
<script src="shader.js"></script>
|
||||||
<script src="wavefront.js"></script>
|
|
||||||
<script src="script.js"></script>
|
<script src="script.js"></script>
|
||||||
<style>
|
<style>
|
||||||
:root {
|
|
||||||
font-size: 20px;
|
|
||||||
--padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
html, body {
|
|
||||||
margin: 0;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
body {
|
||||||
padding: 1vw;
|
display: flex;
|
||||||
box-sizing: border-box;
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
min-height: 100vh;
|
||||||
|
margin: 0;
|
||||||
background-color: #1e1e2e;
|
background-color: #1e1e2e;
|
||||||
color: #cdd6f4;
|
color: #cdd6f4;
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
overflow: hidden;
|
font-size: 20px;
|
||||||
}
|
gap: 20px;
|
||||||
#display {
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
box-sizing: border-box;
|
|
||||||
border-radius: 20px;
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
border: solid 2px #11111b;
|
|
||||||
}
|
}
|
||||||
#cv {
|
#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;
|
border: solid 2px #11111b;
|
||||||
background-color: #313244;
|
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#stats {
|
#stats {
|
||||||
right: var(--padding);
|
width: 100%;
|
||||||
|
max-width: 800px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 20px;
|
||||||
|
border: solid 2px #11111b;
|
||||||
|
border-radius: 20px;
|
||||||
|
background-color: #181825;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="display">
|
<canvas id="cv" width="800" height="600"></canvas>
|
||||||
<canvas id="cv"></canvas>
|
<div id="stats">
|
||||||
<div id="stats">
|
<div>FPS: <span id="fps"></span></div>
|
||||||
FPS: <span id="fps"></span> - <span id="ms"></span>
|
<div>Frame time: <span id="ms"></span></div>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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
|
|
33819
src/obj/monkey.obj
33819
src/obj/monkey.obj
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
16109
src/obj/teapot.obj
16109
src/obj/teapot.obj
File diff suppressed because it is too large
Load Diff
232
src/script.js
232
src/script.js
|
@ -4,120 +4,122 @@ let cv, gl;
|
||||||
|
|
||||||
let program;
|
let program;
|
||||||
|
|
||||||
class Object {
|
let vertices;
|
||||||
vertexBuffer;
|
let vertexBuffer;
|
||||||
numVertices;
|
|
||||||
}
|
|
||||||
|
|
||||||
let o = new Object();
|
|
||||||
|
|
||||||
let lastFrame = Date.now();
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function init() {
|
async function init() {
|
||||||
cv = document.getElementById("cv");
|
cv = document.getElementById("cv");
|
||||||
|
|
||||||
gl = cv.getContext("webgl");
|
gl = cv.getContext("webgl");
|
||||||
|
|
||||||
if (!gl) {
|
if (!gl) {
|
||||||
window.alert("WebGL not supported");
|
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...");
|
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);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* -0.35 0.35
|
||||||
|
* | -0.2 0.2 |
|
||||||
|
* | | | |
|
||||||
|
*
|
||||||
|
* +----+ +----+ --- 0.6
|
||||||
|
* | | | |
|
||||||
|
* | | | |
|
||||||
|
* | +--------+ | --- 0.1
|
||||||
|
* | |
|
||||||
|
* | +--------+ | --- -0.1
|
||||||
|
* | | | |
|
||||||
|
* | | | |
|
||||||
|
* +----+ +----+ --- -0.6
|
||||||
|
*
|
||||||
|
* +------------------+ --- -0.7
|
||||||
|
* | |
|
||||||
|
* +------------------+ --- -0.9
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
vertices = [
|
||||||
|
// X // Y
|
||||||
|
|
||||||
|
// left vertical bar
|
||||||
|
-0.35, -0.6,
|
||||||
|
-0.35, 0.6,
|
||||||
|
-0.2, 0.6,
|
||||||
|
|
||||||
|
-0.35, -0.6,
|
||||||
|
-0.2, 0.6,
|
||||||
|
-0.2, -0.6,
|
||||||
|
|
||||||
|
// right vertical bar
|
||||||
|
0.35, -0.6,
|
||||||
|
0.35, 0.6,
|
||||||
|
0.2, 0.6,
|
||||||
|
|
||||||
|
0.35, -0.6,
|
||||||
|
0.2, 0.6,
|
||||||
|
0.2, -0.6,
|
||||||
|
|
||||||
|
// middle bar
|
||||||
|
-0.2, -0.1,
|
||||||
|
-0.2, 0.1,
|
||||||
|
0.2, 0.1,
|
||||||
|
|
||||||
|
-0.2, -0.1,
|
||||||
|
0.2, 0.1,
|
||||||
|
0.2, -0.1,
|
||||||
|
|
||||||
|
// bottom bar
|
||||||
|
-0.35, -0.7,
|
||||||
|
-0.35, -0.9,
|
||||||
|
0.35, -0.9,
|
||||||
|
|
||||||
|
-0.35, -0.7,
|
||||||
|
0.35, -0.9,
|
||||||
|
0.35, -0.7
|
||||||
|
];
|
||||||
|
|
||||||
console.log("creating vertex buffer");
|
console.log("creating vertex buffer");
|
||||||
|
|
||||||
|
vertexBuffer = gl.createBuffer();
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
|
||||||
|
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
|
||||||
|
|
||||||
let f = await readObjFile("obj/smooth_monkey.obj");
|
// get location of vertPosition attribute
|
||||||
o = new Object();
|
let positionAttribLocation = gl.getAttribLocation(program, "vertPosition");
|
||||||
|
|
||||||
o.vertexBuffer = gl.createBuffer();
|
gl.vertexAttribPointer(
|
||||||
o.numVertices = f.length / 8;
|
positionAttribLocation, // which attribute is read
|
||||||
gl.bindBuffer(gl.ARRAY_BUFFER, o.vertexBuffer);
|
2, // number of values to read
|
||||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(f), gl.STATIC_DRAW);
|
gl.FLOAT, // type of values
|
||||||
|
gl.FALSE, // whether to normalize
|
||||||
|
2 * Float32Array.BYTES_PER_ELEMENT, // size of individual vertex / distance between values to read
|
||||||
|
0 // offset where to start reading
|
||||||
|
);
|
||||||
|
|
||||||
|
// enable attribute
|
||||||
|
gl.enableVertexAttribArray(positionAttribLocation);
|
||||||
|
|
||||||
|
// unbind buffer
|
||||||
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
||||||
|
|
||||||
|
|
||||||
// set clear colour
|
// set clear colour
|
||||||
gl.clearColor(...hexToRgb("181825"), 1.0);
|
gl.clearColor(0.1, 0.1, 0.1, 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);
|
|
||||||
|
|
||||||
// start drawing
|
// start drawing
|
||||||
requestAnimationFrame(draw);
|
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 frameCount = 0;
|
||||||
let lastStatUpdate = Date.now();
|
let lastStatUpdate = Date.now();
|
||||||
|
|
||||||
|
@ -135,11 +137,8 @@ function updateStats(deltaTime) {
|
||||||
fpsDisplay.innerText = Math.round(frameCount / timeSinceLastUpdate)
|
fpsDisplay.innerText = Math.round(frameCount / timeSinceLastUpdate)
|
||||||
|
|
||||||
let msDisplay = document.getElementById("ms");
|
let msDisplay = document.getElementById("ms");
|
||||||
if (frameTimes.length > 0) {
|
msDisplay.innerText = deltaTime * 1000 + "ms";
|
||||||
msDisplay.innerText = (Math.round(frameTimes.reduce((prev, curr) => prev + curr) / frameTimes.length * 100) / 100) + "ms";
|
|
||||||
}
|
|
||||||
|
|
||||||
frameTimes = [];
|
|
||||||
frameCount = 0;
|
frameCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,60 +147,31 @@ let hue = 0;
|
||||||
async function draw() {
|
async function draw() {
|
||||||
let now = Date.now();
|
let now = Date.now();
|
||||||
let deltaTime = (now - lastFrame) / 1000;
|
let deltaTime = (now - lastFrame) / 1000;
|
||||||
let frameStart = performance.now();
|
|
||||||
|
|
||||||
hue += deltaTime / 5;
|
hue += deltaTime / 5;
|
||||||
if (hue > 1) hue = 0;
|
if (hue > 1) hue -= 1;
|
||||||
|
|
||||||
smoothCameraDistance += (cameraDistance - smoothCameraDistance) / 8;
|
|
||||||
|
|
||||||
updateStats(deltaTime);
|
updateStats(deltaTime);
|
||||||
|
|
||||||
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
gl.clear(gl.COLOR_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.useProgram(program);
|
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];
|
let colorLocation = gl.getUniformLocation(program, "color");
|
||||||
mat4vec4Multiply(lightPosition, viewMatrix, lightPosition);
|
gl.uniform3f(colorLocation, ...hslToRgb(hue, 1, 0.5));
|
||||||
|
|
||||||
gl.uniform3f(gl.getUniformLocation(program, "Light.position"), ...lightPosition.slice(0, 3));
|
let positionLocation = gl.getUniformLocation(program, "position");
|
||||||
gl.uniform3f(gl.getUniformLocation(program, "Light.color"), 1, 1, 1);
|
gl.uniform2f(positionLocation, Math.cos(hue * 2 * Math.PI) * 0.2, Math.sin(hue * 2 * Math.PI) * 0.2);
|
||||||
|
|
||||||
gl.uniform3f(gl.getUniformLocation(program, "Material.ambientColor"), 0.1, 0.1, 0.1);
|
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
|
||||||
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);
|
gl.drawArrays(gl.TRIANGLES, 0, vertices.length / 2);
|
||||||
setAttribPointers();
|
|
||||||
gl.drawArrays(gl.TRIANGLES, 0, o.numVertices);
|
|
||||||
|
|
||||||
frameTimes.push(performance.now() - frameStart);
|
|
||||||
lastFrame = now;
|
lastFrame = now;
|
||||||
requestAnimationFrame(draw);
|
requestAnimationFrame(draw);
|
||||||
}
|
}
|
||||||
|
|
||||||
function hexToRgb(hex) {
|
function hexColorToFloatArray(hex) {
|
||||||
let r = parseInt(hex.substring(0, 2), 16) / 255;
|
let r = parseInt(hex.substring(0, 2), 16) / 255;
|
||||||
let g = parseInt(hex.substring(2, 4), 16) / 255;
|
let g = parseInt(hex.substring(2, 4), 16) / 255;
|
||||||
let b = parseInt(hex.substring(4, 6), 16) / 255;
|
let b = parseInt(hex.substring(4, 6), 16) / 255;
|
||||||
|
|
|
@ -45,10 +45,4 @@ function linkShaderProgram(gl, vertexShader, fragmentShader) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return program;
|
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);
|
|
||||||
}
|
}
|
|
@ -1,33 +1,6 @@
|
||||||
precision mediump float;
|
precision mediump float;
|
||||||
|
varying vec3 fragColor;
|
||||||
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;
|
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec3 pleaseDontDeleteMe = vec3(vTexture, 0.0);
|
gl_FragColor = vec4(fragColor, 1.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);
|
|
||||||
}
|
}
|
|
@ -1,21 +1,11 @@
|
||||||
precision mediump float;
|
precision mediump float;
|
||||||
|
|
||||||
attribute vec3 vertPosition;
|
attribute vec2 vertPosition;
|
||||||
attribute vec3 vertNormal;
|
uniform vec3 color;
|
||||||
attribute vec2 vertTexture;
|
uniform vec2 position;
|
||||||
|
varying vec3 fragColor;
|
||||||
uniform mat4 modelViewMatrix;
|
|
||||||
uniform mat4 projectionMatrix;
|
|
||||||
uniform mat3 normalMatrix;
|
|
||||||
|
|
||||||
varying vec3 vNormal;
|
|
||||||
varying vec2 vTexture;
|
|
||||||
varying vec3 vPosition;
|
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vNormal = normalize(normalMatrix * vertNormal);
|
fragColor = color;
|
||||||
vTexture = vertTexture;
|
gl_Position = vec4(position + vertPosition, 0.0, 1.0);
|
||||||
vPosition = (modelViewMatrix * vec4(vertPosition, 1.0)).xyz;
|
|
||||||
|
|
||||||
gl_Position = projectionMatrix * modelViewMatrix * vec4(vertPosition, 1.0);
|
|
||||||
}
|
}
|
|
@ -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;
|
|
||||||
}
|
|
Loading…
Reference in New Issue