diff options
| Commit | 53c352887fdb3e0345e97c2760d8f7985a1bfc48 (patch) | |
|---|---|---|
| Author | 2023-08-28 13:01:49 +0300 | |
| Committer | 2023-08-28 13:01:49 +0300 | |
| Files | 4ca4700916a35a216a96ac7c347a5ad1b33a4ef2 | |
| uni-projects-53c352887fdb3e0345e97c2760d8f7985a1bfc48.tar uni-projects-53c352887fdb3e0345e97c2760d8f7985a1bfc48.tar.gz uni-projects-53c352887fdb3e0345e97c2760d8f7985a1bfc48.zip | ||
| Parent | 8861a3e72f28f1757954c7f20ebeb469980f573a (diff) | |
[WGL/P] Added a lot of comments and reworked formatting of certain code
7 files changed, 116 insertions, 77 deletions
| -rw-r--r-- | Year 2/Computer Graphics with WebGL/Project/Project.html | 16 | ||||
| -rw-r--r-- | Year 2/Computer Graphics with WebGL/Project/blackhole.js | 17 | ||||
| -rw-r--r-- | Year 2/Computer Graphics with WebGL/Project/camera-movement.js (renamed from Year 2/Computer Graphics with WebGL/Project/spaceship.js) | 40 | ||||
| -rw-r--r-- | Year 2/Computer Graphics with WebGL/Project/level.js | 52 | ||||
| -rw-r--r-- | Year 2/Computer Graphics with WebGL/Project/menu.js | 6 | ||||
| -rw-r--r-- | Year 2/Computer Graphics with WebGL/Project/shaders.js | 42 | ||||
| -rw-r--r-- | Year 2/Computer Graphics with WebGL/Project/star.js | 20 |
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(); -} |
