Summary Files Commits Branches @commit @diff @stats
diff options
context:
space:
mode:
Commit53c352887fdb3e0345e97c2760d8f7985a1bfc48 (patch)
Author
 Syndamia <kamen@syndamia.com>
2023-08-28 13:01:49 +0300
Committer
 Syndamia <kamen@syndamia.com>
2023-08-28 13:01:49 +0300
Files4ca4700916a35a216a96ac7c347a5ad1b33a4ef2
uni-projects-53c352887fdb3e0345e97c2760d8f7985a1bfc48.tar
uni-projects-53c352887fdb3e0345e97c2760d8f7985a1bfc48.tar.gz
uni-projects-53c352887fdb3e0345e97c2760d8f7985a1bfc48.zip
Parent8861a3e72f28f1757954c7f20ebeb469980f573a (diff)
[WGL/P] Added a lot of comments and reworked formatting of certain code
diff --git a/Year 2/Computer Graphics with WebGL/Project/Project.html b/Year 2/Computer Graphics with WebGL/Project/Project.html
index a74b065..e43f213 100644
--- a/Year 2/Computer Graphics with WebGL/Project/Project.html
+++ b/Year 2/Computer Graphics with WebGL/Project/Project.html
@@ -77,10 +77,8 @@ body > div, #noscript {
}
</style>
- <script src="spaceship.js"></script>
+ <script src="camera-movement.js"></script>
<script src="skybox.js"></script>
- <script src="star.js"></script>
- <script src="blackhole.js"></script>
<script src="level.js"></script>
<script>
/*
@@ -102,16 +100,19 @@ body > div, #noscript {
function init()
{
+ /* Get WebGL stuff */
gl = getContext('picasso');
glprog = getProgram(vShader,fShader);
getVariables();
+ /* WebGL settings */
gl.enable(gl.DEPTH_TEST);
gl.clearColor(1,1,1,1);
// For proper transparency
gl.enable(gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
+ /* Matricies (for color in shaders) */
identity();
gl.uniform1i(uUseNormalMatrix,false);
@@ -119,12 +120,17 @@ body > div, #noscript {
gl.uniform3f(uDiffuseColor,1,1,1);
gl.uniform3f(uLightDir,0,0,-1);
+ /* Fragment shader settings */
+ gl.uniform3fv(uStarColor, STAR_COLOR);
gl.uniform4f(uBlack, 0,0,0,1);
gl.uniform4f(uBHBlack, 0,0,0,1);
gl.uniform1i(uDisableRayMarching, false);
+ /* Create physical objects */
skybox = new Skybox(10000, [0,0,0], undefined);
createLevels();
+
+ /* Since we have the gl context, run stuff that depend on it */
initMenu();
resizeglcanvas();
@@ -146,11 +152,13 @@ body > div, #noscript {
var frames = 0;
function drawFrame()
{
+ /* Update time t */
if (startT == -1) { startT = Date.now(); t = 0; }
var candidat = Math.floor(Date.now() - startT) / 100; // tenths of a second
if (pauseAnimations) startT += (candidat - t)*100;
else t = candidat;
+ /* Update fps counter */
var now = Math.floor(Date.now() / 1000);
if (now - lastTime >= 1) {
fpsElem.innerText = Math.floor(frames / (now - lastTime));
@@ -161,8 +169,8 @@ body > div, #noscript {
gl.clear(gl.COLOR_BUFFER_BIT+gl.DEPTH_BUFFER_BIT);
updateCamera();
- gl.uniform3fv(uEye, pos);
+ /* Draw scene objects */
if (!pauseAnimations || t == 0) animations.forEach((a) => a(t));
skybox.draw();
stars.forEach((s) => s.draw());
diff --git a/Year 2/Computer Graphics with WebGL/Project/blackhole.js b/Year 2/Computer Graphics with WebGL/Project/blackhole.js
deleted file mode 100644
index 0bd0ff5..0000000
--- a/Year 2/Computer Graphics with WebGL/Project/blackhole.js
+++ /dev/null
@@ -1,17 +0,0 @@
-BlackHole = function(center, size, blackHolesBuf) {
- if (blackHolesBuf.length == BLACKHOLE_MAX_COUNT)
- throw 'Error: cannot add more black holes, limit of ' + BLACKHOLE_MAX_COUNT + ' reached!'
-
- this.rs = size / 3;
- this.index = blackHolesBuf.push([]) - 1;
- this.center = center;
-
- blackHolesBuf[this.index] = center.concat(this.rs);
-}
-BlackHole.prototype.moveTo = function(newCenter, blackHolesBuf) {
- blackHolesBuf[this.index] = newCenter.concat(this.rs);
- gl.uniform4fv(gl.getUniformLocation(glprog, 'uBH[' + this.index + ']'), blackHolesBuf[this.index]);
-}
-BlackHole.prototype.draw = function() {
- // Black holes are not "drawn"
-}
diff --git a/Year 2/Computer Graphics with WebGL/Project/spaceship.js b/Year 2/Computer Graphics with WebGL/Project/camera-movement.js
index a50f2fc..f06db00 100644
--- a/Year 2/Computer Graphics with WebGL/Project/spaceship.js
+++ b/Year 2/Computer Graphics with WebGL/Project/camera-movement.js
@@ -1,9 +1,13 @@
-// This file contains navigation and "pause" menu configuration
+/* Logic for moving around with mouse and keyboard */
-/*
- * Helpers
- */
+/* Helpers */
+// Since with the mouse cursor we change the looking direction vertically or horizontally
+// it's significantly simpler to just use spherical coordinates and change the angles upon
+// mouse movement.
+// Since these are looking directions, the sphere radius is one (meaning the spherical coordinates
+// will always be converted into a cartesian unit vector).
+// The downside is that we have additional calculations to make, but it's worth it.
SphericalCoord = function(theta, phi) {
this.fulltheta = this.theta = theta;
this.phi = phi;
@@ -55,9 +59,7 @@ function vecSub(a, b) {
return [a[0]-b[0], a[1]-b[1], a[2]-b[2]];
}
-/*
- * Variables
- */
+/* Variables */
const MOVE_SPEED = 1.5;
const ROTATION_SPEED = 3;
@@ -71,10 +73,10 @@ var left = new SphericalCoord(Math.PI / 2, Math.PI / 2);
var isPaused = true;
-/*
- * Navigation keys
- */
+/* Navigation keys */
+// Since I'm lazy, there is a different function, changing pos, for every key
+// so when a key is pressed, we'll execute the action on the same index
var pressedKeys = [ false, false, false, false, false, false ];
var keyAction = [
() => { pos = vecSum(pos, up.toCartesian()); }, // ' '
@@ -109,15 +111,14 @@ document.addEventListener('keyup', (event) => {
}
});
-/*
- * Mouse movement
- */
+/* Mouse movement */
var onlyHorizontal = false;
var onlyVertical = false;
function updateLookingDirection(e) {
if (isPaused) return;
+ // Get mouse movement
var vertical = (1-onlyHorizontal) * (e.movementY / canvas.offsetHeight) * ROTATION_SPEED;
var horizontal = (1-onlyVertical) * (-e.movementX / canvas.offsetWidth) * ROTATION_SPEED;
@@ -132,6 +133,7 @@ document.addEventListener('pointerlockchange', () => {
});
function mouseInit() {
+ // Capture mouse pointer when appropriate
paused = document.getElementById('paused');
canvas.addEventListener('click', async () => {
@@ -147,16 +149,16 @@ function mouseInit() {
});
}
-/*
- * On every draw
- */
+/* On every drawFrame */
coordsElem = undefined;
function updateCamera() {
+ // Move camera position
for (var i = 0; i < pressedKeys.length; i++)
if (pressedKeys[i]) keyAction[i]();
lookAt(pos, vecSum(pos, forward.toCartesian()), up.toCartesian());
- if (coordsElem) {
- coordsElem.innerText = 'X: '+pos[0]+' Y: '+pos[1]+' Z: '+pos[2];
- }
+
+ // Update "external" variables
+ if (coordsElem) coordsElem.innerText = 'X: '+pos[0]+' Y: '+pos[1]+' Z: '+pos[2];
+ gl.uniform3fv(uEye, pos);
}
diff --git a/Year 2/Computer Graphics with WebGL/Project/level.js b/Year 2/Computer Graphics with WebGL/Project/level.js
index 5a5a22a..2a525d2 100644
--- a/Year 2/Computer Graphics with WebGL/Project/level.js
+++ b/Year 2/Computer Graphics with WebGL/Project/level.js
@@ -1,3 +1,7 @@
+/* Logic for levels, where each level contains all the objects that a scene needs */
+
+/* Global variables */
+
stars = [];
blackHoles = [];
animations = [];
@@ -7,6 +11,52 @@ blackHolesBuf = [];
levels = [];
var startT = -1;
+/* Star "class" */
+
+Star = function(center, size, starsBuf) {
+ if (starsBuf.length == STAR_MAX_COUNT)
+ throw 'Error: cannot add more stars, limit of ' + STAR_MAX_COUNT + ' reached!'
+
+ this.sphere = new Sphere(center, size);
+ this.sphere.color = STAR_COLOR;
+ this.index = starsBuf.push([]) - 1;
+ this.center = center;
+
+ this.sphere.center = center;
+ starsBuf[this.index] = center.concat(this.sphere.size);
+}
+Star.prototype.moveTo = function(newCenter, starsBuf) {
+ this.sphere.center = newCenter;
+ starsBuf[this.index] = newCenter.concat(this.sphere.size);
+ gl.uniform4fv(gl.getUniformLocation(glprog, 'uStars[' + this.index + ']'), starsBuf[this.index]);
+}
+Star.prototype.draw = function() {
+ this.sphere.draw();
+}
+
+/* BlackHole "class" */
+
+BlackHole = function(center, size, blackHolesBuf) {
+ if (blackHolesBuf.length == BLACKHOLE_MAX_COUNT)
+ throw 'Error: cannot add more black holes, limit of ' + BLACKHOLE_MAX_COUNT + ' reached!'
+
+ this.rs = size / 3;
+ this.index = blackHolesBuf.push([]) - 1;
+ this.center = center;
+
+ blackHolesBuf[this.index] = center.concat(this.rs);
+}
+BlackHole.prototype.moveTo = function(newCenter, blackHolesBuf) {
+ blackHolesBuf[this.index] = newCenter.concat(this.rs);
+ gl.uniform4fv(gl.getUniformLocation(glprog, 'uBH[' + this.index + ']'), blackHolesBuf[this.index]);
+}
+BlackHole.prototype.draw = function() {
+ // Black holes are not "drawn"
+ // But I'm keeping that function in case I put blackHole.draw() by accident
+}
+
+/* Level "class" */
+
Level = function(name, description, cameraCoords) {
this.name = name;
this.description = description;
@@ -47,6 +97,8 @@ Level.prototype.load = function() {
startT = -1;
}
+/* Our levels, this is ran in init() */
+
function createLevels() {
var l1 = new Level(
"Star passing behind black hole",
diff --git a/Year 2/Computer Graphics with WebGL/Project/menu.js b/Year 2/Computer Graphics with WebGL/Project/menu.js
index 10cac05..6a86f1e 100644
--- a/Year 2/Computer Graphics with WebGL/Project/menu.js
+++ b/Year 2/Computer Graphics with WebGL/Project/menu.js
@@ -1,3 +1,6 @@
+/* Logic for all controls in the sidebar */
+
+// Since we have gl context, initialise whatever needs it
function initMenu() {
initLevels();
debugChange.call(debugModeCB);
@@ -8,7 +11,7 @@ function initMenu() {
const levelSelect = document.getElementById('level-select');
const levelDesc = document.getElementById('level-description');
-
+// Add levels to dropdown box
function initLevels() {
for (var i = 0; i < levels.length; i++) {
var elem = document.createElement('option');
@@ -18,7 +21,6 @@ function initLevels() {
}
levelChange.call(levelSelect);
}
-
function levelChange() {
levelDesc.innerText = levels[this.value].description;
levels[this.value].load();
diff --git a/Year 2/Computer Graphics with WebGL/Project/shaders.js b/Year 2/Computer Graphics with WebGL/Project/shaders.js
index a77e9b3..bd98880 100644
--- a/Year 2/Computer Graphics with WebGL/Project/shaders.js
+++ b/Year 2/Computer Graphics with WebGL/Project/shaders.js
@@ -1,5 +1,6 @@
const STAR_MAX_COUNT = 5;
const BLACKHOLE_MAX_COUNT = 5;
+const STAR_COLOR = [0.956,0.5,0.215];
var vShader =`
uniform mat4 uProjectionMatrix;
@@ -36,22 +37,28 @@ var vShader =`
`;
var fShader = `
- precision highp float;
+ precision highp float; // Needed, since we'll get uniforms which were in vertex shader
+ // Distance a ray should travel inside a black hole,
+ // changing it can alter weirdly the amount of rays that don't escape the black hole
#define MAGIC_STEP 0.01
- #define STAR_COLOR vec3(0.95,0.5,0.215)
varying vec3 vColor;
varying vec3 vXYZ;
+ // This is dumb, but we can't just pass the color from vertex shader, because
+ // we could need it when the fragment shader is ran on the skybox (or just not on a star)
+ // And in those cases, we recalculate the star color, based on where our ray landed
+ uniform vec3 uStarColor;
+
// Settings
uniform bool uDisableRayMarching;
uniform vec4 uBlack;
uniform vec4 uBHBlack;
// For ray marching
- uniform vec4 uStars[` + STAR_MAX_COUNT + `];
- uniform vec4 uBH[` + BLACKHOLE_MAX_COUNT + `];
+ uniform vec4 uStars[`+STAR_MAX_COUNT+`];
+ uniform vec4 uBH[`+BLACKHOLE_MAX_COUNT+`];
uniform vec3 uEye;
// For light recalculation
@@ -66,7 +73,8 @@ var fShader = `
uniform vec3 uLightDir;
- // Thanks https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line#Vector_formulation
+ // Direction implementation of the math from
+ // https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line#Vector_formulation
float linePointDistance(vec3 linePoint, vec3 lineDir, vec3 point) {
vec3 projectionDir = dot(point - linePoint, lineDir) * lineDir; // aka projectionVector - linePoint
float dist = length((point - linePoint) - projectionDir); // aka length of perpendicular vector
@@ -76,7 +84,8 @@ var fShader = `
return dist;
}
- // Thanks https://en.wikipedia.org/wiki/Line%E2%80%93sphere_intersection#Calculation_using_vectors_in_3D
+ // Direct implementation of the math from
+ // https://en.wikipedia.org/wiki/Line%E2%80%93sphere_intersection#Calculation_using_vectors_in_3D
vec3 spherePoint(vec3 lineOrigin, vec3 lineDir, vec4 sphere) {
lineDir = normalize(lineDir);
float b = dot(lineDir, lineOrigin - sphere.xyz);
@@ -84,7 +93,8 @@ var fShader = `
return lineOrigin + min(-b + sqrt(Delta), -b - sqrt(Delta)) * lineDir;
}
- // Thanks https://en.wikipedia.org/wiki/Dot_product#Geometric_definition
+ // Direct implementation of the math from
+ // https://en.wikipedia.org/wiki/Dot_product#Geometric_definition
float angleBetweenVectors(vec3 v1, vec3 v2) {
return acos(radians(dot(v1, v2) / (length(v1) * length(v2))));
}
@@ -98,17 +108,19 @@ var fShader = `
for (int i = 0; i < 100; i++) {
float dist = distance(ray, BH.xyz);
- if (dist <= BH.a) { // if inside event horizon
+ // if inside event horizon
+ if (dist <= BH.a) {
return 1;
}
- if (dist > BH.a * 3.0 + 1.0) { // if outside ISCO
+ // if outside ISCO
+ if (dist > BH.a * 3.0 + 1.0) { // adding 1 fixes some rays wrongfully passing directly through
return 0;
}
// Gravity bends light (actually spacetime, which in turn changes it's path for outside observers).
// This is a more or less correct (as far as I can tell) implementation of Riccardo Antonelli's formula
// http://rantonels.github.io/starless/#MathJax-Element-29-Frame
- // Though I found it difficult to understand, so I referred to some of the code from
+ // Though I found it difficult to understand, so I referred to some of it's implementations from
// https://github.com/rantonels/starless/blob/7a0c3c4efdc0666f53dcfa48d310fb2164be2d1a/tracer.py
// and
// https://github.com/dbrant/BlackHoleRaytracer/blob/master/Equation/SchwarzschildBlackHoleEquation.cs
@@ -130,10 +142,10 @@ var fShader = `
mat4 mvMatrix = uViewMatrix * uModelMatrix;
mat4 nMatrix = uUseNormalMatrix?uNormalMatrix:mvMatrix;
- vec3 color = uAmbientColor*STAR_COLOR;
+ vec3 color = uAmbientColor*uStarColor;
vec3 light = normalize(-uLightDir);
vec3 normal = vec3(normalize(nMatrix*vec4(anormal,0)));
- color += STAR_COLOR*uDiffuseColor*max(dot(normal,light),0.0);
+ color += uStarColor*uDiffuseColor*max(dot(normal,light),0.0);
return vec4(color, 1);
}
@@ -143,7 +155,7 @@ var fShader = `
vec4 rayMarch(vec3 ray, vec3 step) {
// Does the ray pass through any blackholes
int bhStatus = 2;
- for (int i = 0; i < 5; i++) {
+ for (int i = 0; i < `+BLACKHOLE_MAX_COUNT+`; i++) {
float dist = linePointDistance(ray, step, uBH[i].xyz);
if (dist >= 0.0 && dist < uBH[i].a * 3.0) {
bhStatus = rayMarchInBH(uBH[i], ray, step);
@@ -154,8 +166,8 @@ var fShader = `
return uBHBlack;
}
- // Does the ray hit a star
- for (int i = 0; i < 5; i++) {
+ // Does the ray hit a star (even when it has escaped a black hole)
+ for (int i = 0; i < `+STAR_MAX_COUNT+`; i++) {
float dist = linePointDistance(ray, step, uStars[i].xyz);
if (dist >= 0.0 && dist < uStars[i].a) {
return calculateColor(bhStatus == 2, uStars[i], ray, step);
diff --git a/Year 2/Computer Graphics with WebGL/Project/star.js b/Year 2/Computer Graphics with WebGL/Project/star.js
deleted file mode 100644
index 8aad803..0000000
--- a/Year 2/Computer Graphics with WebGL/Project/star.js
+++ /dev/null
@@ -1,20 +0,0 @@
-Star = function(center, size, starsBuf) {
- if (starsBuf.length == STAR_MAX_COUNT)
- throw 'Error: cannot add more stars, limit of ' + STAR_MAX_COUNT + ' reached!'
-
- this.sphere = new Sphere(center, size);
- this.sphere.color = [0.956,0.5,0.215];
- this.index = starsBuf.push([]) - 1;
- this.center = center;
-
- this.sphere.center = center;
- starsBuf[this.index] = center.concat(this.sphere.size);
-}
-Star.prototype.moveTo = function(newCenter, starsBuf) {
- this.sphere.center = newCenter;
- starsBuf[this.index] = newCenter.concat(this.sphere.size);
- gl.uniform4fv(gl.getUniformLocation(glprog, 'uStars[' + this.index + ']'), starsBuf[this.index]);
-}
-Star.prototype.draw = function() {
- this.sphere.draw();
-}