diff --git a/frontend/Dockerfile b/frontend/Dockerfile
index 2daa5de..bbddad7 100644
--- a/frontend/Dockerfile
+++ b/frontend/Dockerfile
@@ -1,12 +1,9 @@
-FROM python:3.8-alpine as build-error-pages
+FROM error-pages as build-error-pages
-WORKDIR /home/python
-COPY error-pages .
-RUN python build.py
+RUN python build.py 403 404 50x
FROM node:latest as build-webpage
-
WORKDIR /home/node
COPY src src
diff --git a/frontend/error-pages/build.py b/frontend/error-pages/build.py
deleted file mode 100644
index f9900c9..0000000
--- a/frontend/error-pages/build.py
+++ /dev/null
@@ -1,43 +0,0 @@
-from typing import NamedTuple, Dict, List, Type
-from os import makedirs, path
-
-
-template_path = 'template.html'
-result_path = 'built'
-
-class Substitutions(NamedTuple):
- title: str
- description: str
-
-error_messages: Dict[str, Substitutions] = {
- '403': Substitutions(
- title='403 - Forbidden',
- description='You are not allowed to view this resource.'
- ),
- '404': Substitutions(
- title='404 - Not found',
- description='The requested resource cannot be found.'
- ),
- '50x': Substitutions(
- title='50x - Server error',
- description='It\'s my fault.'
- ),
-}
-
-
-def substitute(source: str, substitutions: Substitutions) -> str:
- for i, property_name in enumerate(Substitutions._fields):
- source = source.replace(f'{{{property_name}}}', str(substitutions[i]))
- return source
-
-
-if __name__ == '__main__':
- with open(template_path) as f:
- template = f.read()
-
- makedirs(result_path, mode=0o440, exist_ok=True)
-
- for name, substitutions in error_messages.items():
- with open(path.join(result_path, f'{name}.html'), 'w') as f:
- html = substitute(template, substitutions)
- f.write(html)
diff --git a/frontend/error-pages/template.html b/frontend/error-pages/template.html
deleted file mode 100644
index 82a55c3..0000000
--- a/frontend/error-pages/template.html
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
- {title}
-
-
-
-
-
-
- {description}
-
-
diff --git a/frontend/nginx-config/nginx.conf b/frontend/nginx-config/nginx.conf
index beb8e6d..901dada 100644
--- a/frontend/nginx-config/nginx.conf
+++ b/frontend/nginx-config/nginx.conf
@@ -38,7 +38,7 @@ http {
root /usr/share/nginx/html;
index index.html;
- location ~* \.(jpg|jpeg|png|ico)$ {
+ location ~* \.(jpg|jpeg|png|ico)$ {
expires 30d;
}
diff --git a/frontend/package.json b/frontend/package.json
index f5e3552..3e3af8c 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -52,6 +52,7 @@
"uuid": "^8.2.0",
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11",
- "webpack-dev-server": "^3.10.3"
+ "webpack-dev-server": "^3.10.3",
+ "webpack-glsl-minify": "^1.4.0"
}
}
diff --git a/frontend/src/scripts/drawing/drawer.ts b/frontend/src/scripts/drawing/drawer.ts
index d03b3df..6fcbae0 100644
--- a/frontend/src/scripts/drawing/drawer.ts
+++ b/frontend/src/scripts/drawing/drawer.ts
@@ -4,6 +4,6 @@ export interface Drawer {
startFrame();
finishFrame();
setCameraPosition(position: Vec2);
- setInViewWidth(size: number): Vec2;
+ setInViewArea(size: number): Vec2;
drawInfoText(text: string);
}
diff --git a/frontend/src/scripts/drawing/renderer.ts b/frontend/src/scripts/drawing/renderer.ts
index dc42ef4..d2e7f2a 100644
--- a/frontend/src/scripts/drawing/renderer.ts
+++ b/frontend/src/scripts/drawing/renderer.ts
@@ -2,6 +2,7 @@ import { Drawer } from './drawer';
import { Vec2 } from '../math/vec2';
import { createProgram } from './graphics-library/create-program';
import { prepareScreenQuad } from './graphics-library/prepare-screen-quad';
+import { Mat3 } from '../math/mat3';
export class WebGl2Renderer implements Drawer {
private gl: WebGL2RenderingContext;
@@ -56,29 +57,20 @@ export class WebGl2Renderer implements Drawer {
}
finishFrame() {
- const resolutionUniformLocation = this.gl.getUniformLocation(
- this.program,
- 'resolution'
- );
- this.gl.uniform2f(
- resolutionUniformLocation,
- this.canvas.width,
- this.canvas.height
- );
+ const resolution = new Vec2(this.canvas.width, this.canvas.height);
+
+ const transform = Mat3.translateMatrix(new Vec2(0.5, 0.5))
+ .times(Mat3.scaleMatrix(this.viewBoxSize.divide(resolution)))
+ .times(Mat3.translateMatrix(this.cameraPosition));
const viewBoxSizeUniformLocation = this.gl.getUniformLocation(
this.program,
- 'viewBoxSize'
+ 'transform'
);
- this.gl.uniform2f(viewBoxSizeUniformLocation, ...this.viewBoxSize.list);
-
- const cameraPositionUniformLocation = this.gl.getUniformLocation(
- this.program,
- 'cameraPosition'
- );
- this.gl.uniform2f(
- cameraPositionUniformLocation,
- ...this.cameraPosition.list
+ this.gl.uniformMatrix3fv(
+ viewBoxSizeUniformLocation,
+ false,
+ new Float32Array(transform.transposedFlat)
);
this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4);
@@ -88,11 +80,14 @@ export class WebGl2Renderer implements Drawer {
this.cameraPosition = position;
}
- setInViewWidth(size: number): Vec2 {
+ setInViewArea(size: number): Vec2 {
const canvasAspectRatio =
- this.canvas.clientHeight / this.canvas.clientWidth;
+ this.canvas.clientWidth / this.canvas.clientHeight;
- this.viewBoxSize = new Vec2(size, size * canvasAspectRatio);
+ this.viewBoxSize = new Vec2(
+ Math.sqrt(size * canvasAspectRatio),
+ Math.sqrt(size / canvasAspectRatio)
+ );
return this.viewBoxSize;
}
diff --git a/frontend/src/scripts/game.ts b/frontend/src/scripts/game.ts
index 13cf469..05ae664 100644
--- a/frontend/src/scripts/game.ts
+++ b/frontend/src/scripts/game.ts
@@ -5,13 +5,17 @@ import { TouchListener } from './input/touch-listener';
import { CommandBroadcaster } from './commands/command-broadcaster';
import { ObjectContainer } from './objects/object-container';
import { DrawCommand } from './commands/types/draw';
-import passthroughVertexShader from '../shaders/passthrough.vert';
-import distanceFragmentShader from '../shaders/dist.frag';
+
import { StepCommand } from './commands/types/step';
import { Character } from './objects/types/character';
import { InfoText } from './objects/types/info-text';
import { timeIt } from './helper/timing';
+import { GlslShader, GlslVariable, GlslVariableMap } from 'webpack-glsl-minify';
+
+let passthroughVertexShader = require('../shaders/passthrough-vs.glsl') as GlslShader;
+let distanceFragmentShader = require('../shaders/cave-fs.glsl') as GlslShader;
+
export class Game {
private previousTime: DOMHighResTimeStamp = 0;
private objects: ObjectContainer = new ObjectContainer();
@@ -31,9 +35,11 @@ export class Game {
[this.objects]
);
+ console.log(distanceFragmentShader);
+
this.renderer = new WebGl2Renderer(canvas, overlay, [
- passthroughVertexShader,
- distanceFragmentShader,
+ passthroughVertexShader.sourceCode,
+ distanceFragmentShader.sourceCode,
]);
this.initializeScene();
diff --git a/frontend/src/scripts/math/mat3.ts b/frontend/src/scripts/math/mat3.ts
new file mode 100644
index 0000000..87af25c
--- /dev/null
+++ b/frontend/src/scripts/math/mat3.ts
@@ -0,0 +1,78 @@
+// https://github.com/Azleur/mat3/blob/master/src/index.ts
+
+import { Vec2 } from './vec2';
+
+export class Mat3 {
+ constructor(private readonly values: Array>) {}
+
+ public static get Zero() {
+ return new Mat3([
+ [0, 0, 0],
+ [0, 0, 0],
+ [0, 0, 0],
+ ]);
+ }
+
+ public static get Id() {
+ return new Mat3([
+ [1, 0, 0],
+ [0, 1, 0],
+ [0, 0, 1],
+ ]);
+ }
+
+ public static get Ones() {
+ return new Mat3([
+ [1, 1, 1],
+ [1, 1, 1],
+ [1, 1, 1],
+ ]);
+ }
+
+ public static translateMatrix(by: Vec2): Mat3 {
+ return new Mat3([
+ [1, 0, 0],
+ [0, 1, 0],
+ [by.x, by.y, 1],
+ ]);
+ }
+
+ public static scaleMatrix(by: Vec2): Mat3 {
+ return new Mat3([
+ [by.x, 0, 0],
+ [0, by.y, 0],
+ [0, 0, 1],
+ ]);
+ }
+
+ public get transposed(): Mat3 {
+ const values: number[][] = [[], [], []];
+ for (let i = 0; i < 3; i++) {
+ for (let j = 0; j < 3; j++) {
+ values[i][j] = this.values[j][i];
+ }
+ }
+ return new Mat3(values);
+ }
+
+ public times(other: Mat3): Mat3 {
+ const values: number[][] = Mat3.Zero.values;
+ for (let i = 0; i < 3; i++) {
+ for (let j = 0; j < 3; j++) {
+ for (let k = 0; k < 3; k++) {
+ values[i][j] += this.values[i][k] * other.values[k][j];
+ }
+ }
+ }
+ return new Mat3(values);
+ }
+
+ public get transposedFlat(): Array {
+ const transposed = this.transposed;
+ return [
+ ...transposed.values[0],
+ ...transposed.values[1],
+ ...transposed.values[2],
+ ];
+ }
+}
diff --git a/frontend/src/scripts/math/vec2.ts b/frontend/src/scripts/math/vec2.ts
index a71b2a0..595a26d 100644
--- a/frontend/src/scripts/math/vec2.ts
+++ b/frontend/src/scripts/math/vec2.ts
@@ -13,10 +13,6 @@ export class Vec2 extends Typed {
return new Vec2(this.x * scalar, this.y * scalar);
}
- public times(other: Vec2): Vec2 {
- return new Vec2(this.x * other.x, this.y * other.y);
- }
-
public add(other: Vec2): Vec2 {
return new Vec2(this.x + other.x, this.y + other.y);
}
@@ -25,6 +21,14 @@ export class Vec2 extends Typed {
return new Vec2(this.x - other.x, this.y - other.y);
}
+ public times(other: Vec2): Vec2 {
+ return new Vec2(this.x * other.x, this.y * other.y);
+ }
+
+ public divide(other: Vec2): Vec2 {
+ return new Vec2(this.x / other.x, this.y / other.y);
+ }
+
public get length(): number {
return Math.sqrt(this.x * this.x + this.y * this.y);
}
diff --git a/frontend/src/scripts/objects/types/camera.ts b/frontend/src/scripts/objects/types/camera.ts
index d5442a5..9908ccc 100644
--- a/frontend/src/scripts/objects/types/camera.ts
+++ b/frontend/src/scripts/objects/types/camera.ts
@@ -3,7 +3,8 @@ import { DrawCommand } from '../../commands/types/draw';
import { MoveToCommand } from '../../commands/types/move-to';
export class Camera extends GameObject {
- private inViewWidth = 1500;
+ private inViewArea = 1920 * 1080;
+
constructor() {
super();
@@ -13,7 +14,7 @@ export class Camera extends GameObject {
private draw(c: DrawCommand) {
c.drawer.setCameraPosition(this.position);
- this._boundingBoxSize = c.drawer.setInViewWidth(this.inViewWidth);
+ this._boundingBoxSize = c.drawer.setInViewArea(this.inViewArea);
}
private moveTo(c: MoveToCommand) {
diff --git a/frontend/src/shaders/dist.frag b/frontend/src/shaders/cave-fs.glsl
similarity index 81%
rename from frontend/src/shaders/dist.frag
rename to frontend/src/shaders/cave-fs.glsl
index 30d8842..187833c 100644
--- a/frontend/src/shaders/dist.frag
+++ b/frontend/src/shaders/cave-fs.glsl
@@ -4,7 +4,7 @@ precision mediump float;
const float smoothing = 10.0;
const float inf = 1000000.0;
-const float pi = atan(1.0) * 4.0;
+const float pi = 3.141592654;
float interpolate(float from, float to, float quotient) {
float steppedQ = sin(quotient * pi - pi * 0.5) * 0.5 + 0.5;
@@ -16,14 +16,14 @@ vec2 rotate90deg(in vec2 vector) {
}
struct Line {
- vec2 a;
- vec2 b;
+ vec2 from;
+ vec2 to;
vec2 normal;
bool isLineEnd;
}[16] lines;
float lineDistance(in vec2 position, in Line line, out float h) {
- vec2 pa = position - line.a, ba = line.b - line.a;
+ vec2 pa = position - line.from, ba = line.to - line.from;
h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0);
vec2 delta = pa - ba*h;
// sign can return 0, double sign prevents this
@@ -32,7 +32,7 @@ float lineDistance(in vec2 position, in Line line, out float h) {
}
Line endDummyLineFromLine(Line line) {
- return Line(line.b, line.b + rotate90deg(line.normal), line.normal, false);
+ return Line(line.to, line.to + rotate90deg(line.normal), line.normal, false);
}
float getDistance(in vec2 target) {
@@ -55,7 +55,7 @@ float getDistance(in vec2 target) {
float h;
float distanceToCurrent = lineDistance(target, current, h);
- float rightJoinAcuteness = dot(next.b - current.a, next.normal - current.normal);
+ float rightJoinAcuteness = dot(next.to - current.from, next.normal - current.normal);
distanceToCurrent -= interpolate(
sign(leftJoinAcuteness) * smoothing,
sign(rightJoinAcuteness) * smoothing, h
@@ -64,8 +64,8 @@ float getDistance(in vec2 target) {
if (
!(
- dot(target - current.a, splitterLineNormalStart * -sign(dot(current.b - current.a, splitterLineNormalStart))) > 0.0
- || dot(target - current.b, splitterLineNormalEnd * sign(dot(current.a - current.b, splitterLineNormalEnd))) <= 0.0
+ dot(target - current.from, splitterLineNormalStart * -sign(dot(current.to - current.from, splitterLineNormalStart))) > 0.0
+ || dot(target - current.to, splitterLineNormalEnd * sign(dot(current.from - current.to, splitterLineNormalEnd))) <= 0.0
) && abs(distanceToCurrent) < abs(minDistance)
) {
minDistance = distanceToCurrent;
@@ -95,24 +95,21 @@ void createWorld() {
lines[15] = Line(vec2(1150, 420.0), vec2(10200, 650.0), vec2(-1.0), true);
for (int i = 0; i < lines.length(); i++) {
- vec2 tangent = lines[i].b - lines[i].a;
+ vec2 tangent = lines[i].to - lines[i].from;
lines[i].normal = normalize(
vec2(-lines[i].normal.x * tangent.y, lines[i].normal.x * tangent.x)
);
}
}
-uniform vec2 cameraPosition;
-uniform vec2 viewBoxSize;
-uniform vec2 resolution;
-
+uniform mat3 transform;
out vec4 fragmentColor;
void main() {
createWorld();
- vec2 pixelPosition = gl_FragCoord.xy + vec2(0.5);
- vec2 position = pixelPosition / resolution * viewBoxSize + cameraPosition;
+ vec3 projectiveXY = vec3(gl_FragCoord.xy, 1.0);
+ vec2 position = (projectiveXY * transform).xy;
//fragmentColor = getDistance(position) > 0.0 ? vec4(0.0, 0.0, 0.0, 0.0) : vec4(0.0, 0.0, 0.0, 1.0);
fragmentColor = vec4(vec3(1.0) * clamp(0.0, 1.0, getDistance(position)), 1.0);
}
diff --git a/frontend/src/shaders/passthrough.vert b/frontend/src/shaders/passthrough-vs.glsl
similarity index 100%
rename from frontend/src/shaders/passthrough.vert
rename to frontend/src/shaders/passthrough-vs.glsl
diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json
index 3c93363..dd8863d 100644
--- a/frontend/tsconfig.json
+++ b/frontend/tsconfig.json
@@ -7,6 +7,7 @@
"target": "es5",
"downlevelIteration": true,
"allowJs": true,
- "experimentalDecorators": true
+ "experimentalDecorators": true,
+ "moduleResolution": "Node"
}
}
diff --git a/frontend/webpack.config.js b/frontend/webpack.config.js
index 171c4b6..097a724 100644
--- a/frontend/webpack.config.js
+++ b/frontend/webpack.config.js
@@ -5,10 +5,10 @@ const TerserJSPlugin = require('terser-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackInlineSourcePlugin = require('html-webpack-inline-source-plugin');
-const Sharp = require('responsive-loader/sharp');
const Sass = require('sass');
const isProduction = process.env.NODE_ENV === 'production';
+const isDevelopment = !isProduction;
module.exports = {
watchOptions: {
@@ -70,13 +70,18 @@ module.exports = {
module: {
rules: [
{
- test: /\.(jpe?g|png)$/i,
- loader: 'responsive-loader',
- options: {
- adapter: Sharp,
- outputPath: 'static/',
- sizes: [200, 400, 800, 1200, 2000],
- placeholder: false,
+ test: /\.(glsl)$/,
+ use: {
+ loader: 'webpack-glsl-minify',
+ options: {
+ output: 'object',
+ esModule: false,
+ stripVersion: false,
+ preserveDefines: false,
+ preserveUniforms: true,
+ preserveVariables: true,
+ disableMangle: false,
+ },
},
},
{
@@ -87,12 +92,6 @@ module.exports = {
noquotes: true,
},
},
- {
- test: /\.(frag|vert)$/i,
- use: {
- loader: 'raw-loader',
- },
- },
{
test: /\.ico$/i,
use: {
@@ -145,7 +144,7 @@ module.exports = {
],
},
resolve: {
- extensions: ['.ts', '.js'],
+ extensions: ['.ts', '.js', '.glsl'],
},
output: {
filename: '[name].[contenthash].js',