From e88b4589d26bd9c0045a1ed1aa149f85621296e3 Mon Sep 17 00:00:00 2001 From: schmelczerandras Date: Wed, 22 Jul 2020 20:00:57 +0200 Subject: [PATCH] Add glMatrix --- README.md | 1 + frontend/package.json | 2 + frontend/src/index.ts | 5 + .../src/scripts/commands/types/move-to.ts | 4 +- .../scripts/commands/types/primary-action.ts | 4 +- .../commands/types/secondary-action.ts | 4 +- frontend/src/scripts/commands/types/swipe.ts | 4 +- frontend/src/scripts/drawing/drawer.ts | 10 +- .../drawing/graphics-library/frame-buffer.ts | 8 +- .../drawing/graphics-library/load-uniform.ts | 21 +-- .../src/scripts/drawing/webgl2-renderer.ts | 49 ++++--- frontend/src/scripts/helper/array.ts | 49 +++++++ frontend/src/scripts/helper/clamp.ts | 4 + frontend/src/scripts/input/mouse-listener.ts | 19 +-- frontend/src/scripts/input/touch-listener.ts | 19 +-- frontend/src/scripts/math/mat3.ts | 78 ---------- frontend/src/scripts/math/rectangle.ts | 10 +- frontend/src/scripts/math/vec2.ts | 50 ------- frontend/src/scripts/objects/game-object.ts | 10 +- frontend/src/scripts/objects/types/camera.ts | 12 ++ .../src/scripts/objects/types/character.ts | 22 ++- frontend/src/scripts/objects/types/dungeon.ts | 29 ++-- frontend/src/shaders/cave-distance-fs.glsl | 17 ++- frontend/src/shaders/dist copy.frag | 135 ------------------ frontend/src/shaders/rainbow-shading-fs.glsl | 3 +- .../shaders/{dist copy 2.frag => random.frag} | 0 26 files changed, 211 insertions(+), 358 deletions(-) create mode 100644 frontend/src/scripts/helper/array.ts create mode 100644 frontend/src/scripts/helper/clamp.ts delete mode 100644 frontend/src/scripts/math/mat3.ts delete mode 100644 frontend/src/scripts/math/vec2.ts delete mode 100644 frontend/src/shaders/dist copy.frag rename frontend/src/shaders/{dist copy 2.frag => random.frag} (100%) diff --git a/README.md b/README.md index 9bfd1c9..c1fab6d 100644 --- a/README.md +++ b/README.md @@ -22,3 +22,4 @@ A good-looking 2D adventure. - monitoring - traefik - digital ocean docker contianer registry +- dynamic shader generation diff --git a/frontend/package.json b/frontend/package.json index f5e3552..57126ae 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -26,11 +26,13 @@ "usedExports": true }, "devDependencies": { + "@types/gl-matrix": "^2.4.5", "@types/uuid": "^8.0.0", "autoprefixer": "^9.8.5", "clean-webpack-plugin": "^3.0.0", "css-loader": "^3.5.2", "cssnano": "^4.1.10", + "gl-matrix": "^3.3.0", "html-webpack-inline-source-plugin": "0.0.10", "html-webpack-plugin": "^3.2.0", "image-webpack-loader": "^6.0.0", diff --git a/frontend/src/index.ts b/frontend/src/index.ts index 5687ef5..93255b2 100644 --- a/frontend/src/index.ts +++ b/frontend/src/index.ts @@ -1,4 +1,9 @@ import './styles/main.scss'; import { Game } from './scripts/game'; +import { applyArrayPlugins } from './scripts/helper/array'; +import { glMatrix } from 'gl-matrix'; + +glMatrix.setMatrixArrayType(Array); +applyArrayPlugins(); new Game(); diff --git a/frontend/src/scripts/commands/types/move-to.ts b/frontend/src/scripts/commands/types/move-to.ts index eebf714..8b2f29e 100644 --- a/frontend/src/scripts/commands/types/move-to.ts +++ b/frontend/src/scripts/commands/types/move-to.ts @@ -1,8 +1,8 @@ import { Command } from '../command'; -import { Vec2 } from '../../math/vec2'; +import { vec2 } from 'gl-matrix'; export class MoveToCommand extends Command { - public constructor(public readonly position?: Vec2) { + public constructor(public readonly position?: vec2) { super(); } } diff --git a/frontend/src/scripts/commands/types/primary-action.ts b/frontend/src/scripts/commands/types/primary-action.ts index 8797939..59bab02 100644 --- a/frontend/src/scripts/commands/types/primary-action.ts +++ b/frontend/src/scripts/commands/types/primary-action.ts @@ -1,8 +1,8 @@ import { Command } from '../command'; -import { Vec2 } from '../../math/vec2'; +import { vec2 } from 'gl-matrix'; export class PrimaryActionCommand extends Command { - public constructor(public readonly position?: Vec2) { + public constructor(public readonly position?: vec2) { super(); } } diff --git a/frontend/src/scripts/commands/types/secondary-action.ts b/frontend/src/scripts/commands/types/secondary-action.ts index e3e946e..6ab7b4b 100644 --- a/frontend/src/scripts/commands/types/secondary-action.ts +++ b/frontend/src/scripts/commands/types/secondary-action.ts @@ -1,8 +1,8 @@ import { Command } from '../command'; -import { Vec2 } from '../../math/vec2'; +import { vec2 } from 'gl-matrix'; export class SecondaryActionCommand extends Command { - public constructor(public readonly position?: Vec2) { + public constructor(public readonly position?: vec2) { super(); } } diff --git a/frontend/src/scripts/commands/types/swipe.ts b/frontend/src/scripts/commands/types/swipe.ts index f74e391..5e15460 100644 --- a/frontend/src/scripts/commands/types/swipe.ts +++ b/frontend/src/scripts/commands/types/swipe.ts @@ -1,8 +1,8 @@ import { Command } from '../command'; -import { Vec2 } from '../../math/vec2'; +import { vec2 } from 'gl-matrix'; export class SwipeCommand extends Command { - public constructor(public readonly delta?: Vec2) { + public constructor(public readonly delta?: vec2) { super(); } } diff --git a/frontend/src/scripts/drawing/drawer.ts b/frontend/src/scripts/drawing/drawer.ts index bd3da83..95f4e31 100644 --- a/frontend/src/scripts/drawing/drawer.ts +++ b/frontend/src/scripts/drawing/drawer.ts @@ -1,12 +1,12 @@ -import { Vec2 } from '../math/vec2'; -import { Rectangle } from '../math/rectangle'; +import { vec2 } from 'gl-matrix'; export interface Drawer { startFrame(): void; finishFrame(): void; giveUniforms(uniforms: any): void; - setCameraPosition(position: Vec2): void; - setInViewArea(size: number): Vec2; + setCameraPosition(position: vec2): void; + setCursorPosition(position: vec2): void; + setInViewArea(size: number): vec2; drawInfoText(text: string): void; - isOnScreen(position: Vec2): boolean; + isOnScreen(position: vec2): boolean; } diff --git a/frontend/src/scripts/drawing/graphics-library/frame-buffer.ts b/frontend/src/scripts/drawing/graphics-library/frame-buffer.ts index f1a8aad..a57f6fd 100644 --- a/frontend/src/scripts/drawing/graphics-library/frame-buffer.ts +++ b/frontend/src/scripts/drawing/graphics-library/frame-buffer.ts @@ -1,11 +1,11 @@ -import { Vec2 } from '../../math/vec2'; import { FragmentShaderOnlyProgram } from './fragment-shader-only-program'; +import { vec2 } from 'gl-matrix'; export abstract class FrameBuffer { public renderScale = 1; public enableHighDpiRendering = false; - protected size: Vec2; + protected size: vec2; protected frameBuffer: WebGLFramebuffer; constructor( @@ -39,10 +39,10 @@ export abstract class FrameBuffer { const displayWidth = Math.floor(canvasWidth * realToCssPixels); const displayHeight = Math.floor(canvasHeight * realToCssPixels); - this.size = new Vec2(displayWidth, displayHeight); + this.size = vec2.fromValues(displayWidth, displayHeight); } - public getSize(): Vec2 { + public getSize(): vec2 { return this.size; } } diff --git a/frontend/src/scripts/drawing/graphics-library/load-uniform.ts b/frontend/src/scripts/drawing/graphics-library/load-uniform.ts index d9bf6a9..e03167c 100644 --- a/frontend/src/scripts/drawing/graphics-library/load-uniform.ts +++ b/frontend/src/scripts/drawing/graphics-library/load-uniform.ts @@ -1,5 +1,6 @@ -import { Vec2 } from '../../math/vec2'; -import { Mat3 } from '../../math/mat3'; +import { mat3, vec2 } from 'gl-matrix'; + +const loaderMat3 = mat3.create(); export const loadUniform = ( gl: WebGL2RenderingContext, @@ -22,23 +23,23 @@ export const loadUniform = ( converters.set( WebGL2RenderingContext.FLOAT_VEC2, - (gl, v: Vec2 | Array, l) => { - if (v instanceof Array) { + (gl, v: vec2 | Array, l) => { + if (v[0] instanceof Array) { const result = new Float32Array(v.length * 2); for (let i = 0; i < v.length; i++) { - result[2 * i] = v[i].x; - result[2 * i + 1] = v[i].y; + result[2 * i] = (v[i] as Array).x; + result[2 * i + 1] = (v[i] as Array).y; } gl.uniform2fv(l, new Float32Array(result)); } else { - gl.uniform2fv(l, new Float32Array(v.list)); + gl.uniform2fv(l, v as vec2); } } ); - converters.set(WebGL2RenderingContext.FLOAT_MAT3, (gl, v: Mat3, l) => - gl.uniformMatrix3fv(l, false, new Float32Array(v.transposedFlat)) - ); + converters.set(WebGL2RenderingContext.FLOAT_MAT3, (gl, v, l) => { + gl.uniformMatrix3fv(l, true, mat3.fromMat2d(loaderMat3, v)); + }); converters.set(WebGL2RenderingContext.BOOL, (gl, v, l) => gl.uniform1i(l, v) diff --git a/frontend/src/scripts/drawing/webgl2-renderer.ts b/frontend/src/scripts/drawing/webgl2-renderer.ts index 7099bde..f8cfb47 100644 --- a/frontend/src/scripts/drawing/webgl2-renderer.ts +++ b/frontend/src/scripts/drawing/webgl2-renderer.ts @@ -1,6 +1,5 @@ import { Drawer } from './drawer'; -import { Vec2 } from '../math/vec2'; -import { Mat3 } from '../math/mat3'; +import { mat2d, vec2, mat2, mat3 } from 'gl-matrix'; import { FragmentShaderOnlyProgram } from './graphics-library/fragment-shader-only-program'; import { WebGlStopwatch } from './graphics-library/stopwatch'; import { Rectangle } from '../math/rectangle'; @@ -14,6 +13,7 @@ export class WebGl2Renderer implements Drawer { private viewBox: Rectangle = new Rectangle(); private nextFrameUniforms: any; + private cursorPosition = vec2.create(); private frameBuffers: Array = []; constructor( @@ -38,7 +38,7 @@ export class WebGl2Renderer implements Drawer { ]) ); - this.frameBuffers[0].renderScale = 0.2; + this.frameBuffers[0].renderScale = 1; this.frameBuffers[1].renderScale = 1; try { @@ -53,19 +53,30 @@ export class WebGl2Renderer implements Drawer { } public finishFrame() { - const resolution = new Vec2(this.canvas.width, this.canvas.height); + const resolution = vec2.fromValues(this.canvas.width, this.canvas.height); - this.nextFrameUniforms.transform = Mat3.translateMatrix(new Vec2(0.5, 0.5)) - .times( - Mat3.scaleMatrix( - this.viewBox.size.divide(this.frameBuffers[0].getSize()) - ) + const transform = mat2d.fromTranslation( + mat2d.create(), + this.viewBox.topLeft + ); + mat2d.scale( + transform, + transform, + vec2.divide( + vec2.create(), + this.viewBox.size, + this.frameBuffers[0].getSize() ) - .times(Mat3.translateMatrix(this.viewBox.topLeft)); + ); + mat2d.translate(transform, transform, vec2.fromValues(0.5, 0.5)); + this.nextFrameUniforms.transform = transform; - this.nextFrameUniforms.transformUV = Mat3.translateMatrix( - new Vec2(0.5, 0.5) - ).times(Mat3.scaleMatrix(new Vec2(1).divide(resolution))); + const transformUV = mat2d.fromScaling( + mat2d.create(), + vec2.divide(vec2.create(), vec2.fromValues(1, 1), resolution) + ); + mat2d.translate(transformUV, transformUV, vec2.fromValues(0.5, 0.5)); + this.nextFrameUniforms.transformUV = transformUV; this.frameBuffers[0].render(this.nextFrameUniforms); this.frameBuffers[1].render( @@ -76,19 +87,23 @@ export class WebGl2Renderer implements Drawer { this.stopwatch?.stop(); } - public setCameraPosition(position: Vec2) { + public setCameraPosition(position: vec2) { this.viewBox.topLeft = position; } + public setCursorPosition(position: vec2): void { + this.cursorPosition = position; + } + public giveUniforms(uniforms: any): void { this.nextFrameUniforms = { ...this.nextFrameUniforms, ...uniforms }; } - public setInViewArea(size: number): Vec2 { + public setInViewArea(size: number): vec2 { const canvasAspectRatio = this.canvas.clientWidth / this.canvas.clientHeight; - this.viewBox.size = new Vec2( + this.viewBox.size = vec2.fromValues( Math.sqrt(size * canvasAspectRatio), Math.sqrt(size / canvasAspectRatio) ); @@ -101,7 +116,7 @@ export class WebGl2Renderer implements Drawer { } } - isOnScreen(position: Vec2): boolean { + isOnScreen(position: vec2): boolean { return this.viewBox.isInside(position); } } diff --git a/frontend/src/scripts/helper/array.ts b/frontend/src/scripts/helper/array.ts new file mode 100644 index 0000000..7523b4f --- /dev/null +++ b/frontend/src/scripts/helper/array.ts @@ -0,0 +1,49 @@ +declare global { + interface Array { + x: number; + y: number; + } + + interface Float32Array { + x: number; + y: number; + } +} + +export const applyArrayPlugins = () => { + Object.defineProperty(Array.prototype, 'x', { + get: function () { + return this[0]; + }, + set: function (value) { + this[0] = value; + }, + }); + + Object.defineProperty(Array.prototype, 'y', { + get: function () { + return this[1]; + }, + set: function (value) { + this[1] = value; + }, + }); + + Object.defineProperty(Float32Array.prototype, 'x', { + get: function () { + return this[0]; + }, + set: function (value) { + this[0] = value; + }, + }); + + Object.defineProperty(Float32Array.prototype, 'y', { + get: function () { + return this[1]; + }, + set: function (value) { + this[1] = value; + }, + }); +}; diff --git a/frontend/src/scripts/helper/clamp.ts b/frontend/src/scripts/helper/clamp.ts new file mode 100644 index 0000000..33aa210 --- /dev/null +++ b/frontend/src/scripts/helper/clamp.ts @@ -0,0 +1,4 @@ +export const clamp = (value: number, min: number, max: number): number => + Math.min(max, Math.max(min, value)); + +export const clamp01 = (value: number): number => clamp(value, 0, 1); diff --git a/frontend/src/scripts/input/mouse-listener.ts b/frontend/src/scripts/input/mouse-listener.ts index c57ad49..9b2e05e 100644 --- a/frontend/src/scripts/input/mouse-listener.ts +++ b/frontend/src/scripts/input/mouse-listener.ts @@ -1,12 +1,13 @@ import { CommandGenerator } from '../commands/command-generator'; import { PrimaryActionCommand } from '../commands/types/primary-action'; import { SecondaryActionCommand } from '../commands/types/secondary-action'; -import { Vec2 } from '../math/vec2'; import { SwipeCommand } from '../commands/types/swipe'; import { ZoomCommand } from '../commands/types/zoom'; +import { vec2 } from 'gl-matrix'; +import { clamp01 } from '../helper/clamp'; export class MouseListener extends CommandGenerator { - private previousPosition: Vec2 = null; + private previousPosition = vec2.create(); private isMouseDown = false; constructor(private target: Element) { @@ -27,7 +28,9 @@ export class MouseListener extends CommandGenerator { if (this.isMouseDown) { const position = this.positionFromEvent(event); this.sendCommand( - new SwipeCommand(this.previousPosition.subtract(position)) + new SwipeCommand( + vec2.subtract(vec2.create(), this.previousPosition, position) + ) ); this.previousPosition = position; } @@ -52,12 +55,12 @@ export class MouseListener extends CommandGenerator { }); } - private positionFromEvent(event: MouseEvent): Vec2 { + private positionFromEvent(event: MouseEvent): vec2 { const bb = this.target.getBoundingClientRect(); - return new Vec2( - (event.clientX - bb.x) / bb.width, - 1 - (event.clientY - bb.y) / bb.height - ).clamped_0_1; + return vec2.fromValues( + clamp01((event.clientX - bb.x) / bb.width), + clamp01(1 - (event.clientY - bb.y) / bb.height) + ); } } diff --git a/frontend/src/scripts/input/touch-listener.ts b/frontend/src/scripts/input/touch-listener.ts index 83e7564..fe9e23c 100644 --- a/frontend/src/scripts/input/touch-listener.ts +++ b/frontend/src/scripts/input/touch-listener.ts @@ -1,11 +1,12 @@ import { CommandGenerator } from '../commands/command-generator'; import { PrimaryActionCommand } from '../commands/types/primary-action'; import { SecondaryActionCommand } from '../commands/types/secondary-action'; -import { Vec2 } from '../math/vec2'; import { SwipeCommand } from '../commands/types/swipe'; +import { vec2 } from 'gl-matrix'; +import { clamp01 } from '../helper/clamp'; export class TouchListener extends CommandGenerator { - private previousPosition: Vec2 = null; + private previousPosition = vec2.create(); constructor(private target: HTMLElement) { super(); @@ -30,19 +31,21 @@ export class TouchListener extends CommandGenerator { const position = this.positionFromEvent(event); this.sendCommand( - new SwipeCommand(position.subtract(this.previousPosition)) + new SwipeCommand( + vec2.subtract(vec2.create(), position, this.previousPosition) + ) ); this.previousPosition = position; }); } - private positionFromEvent(event: TouchEvent): Vec2 { + private positionFromEvent(event: TouchEvent): vec2 { const bb = this.target.getBoundingClientRect(); - return new Vec2( - 1 - (event.touches[0].clientX - bb.x) / bb.width, - (event.touches[0].clientY - bb.y) / bb.height - ).clamped_0_1; + return vec2.fromValues( + clamp01(1 - (event.touches[0].clientX - bb.x) / bb.width), + clamp01((event.touches[0].clientY - bb.y) / bb.height) + ); } } diff --git a/frontend/src/scripts/math/mat3.ts b/frontend/src/scripts/math/mat3.ts deleted file mode 100644 index 87af25c..0000000 --- a/frontend/src/scripts/math/mat3.ts +++ /dev/null @@ -1,78 +0,0 @@ -// 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/rectangle.ts b/frontend/src/scripts/math/rectangle.ts index 0d68b62..ddefb76 100644 --- a/frontend/src/scripts/math/rectangle.ts +++ b/frontend/src/scripts/math/rectangle.ts @@ -1,16 +1,16 @@ import { Typed } from '../transport/serializable'; -import { Vec2 } from './vec2'; +import { vec2 } from 'gl-matrix'; export class Rectangle extends Typed { public constructor( - public topLeft: Vec2 = new Vec2(), - public size: Vec2 = new Vec2() + public topLeft: vec2 = vec2.create(), + public size: vec2 = vec2.create() ) { super(); } - public isInside(position: Vec2): boolean { - const translated = position.subtract(this.topLeft); + public isInside(position: vec2): boolean { + const translated = vec2.subtract(vec2.create(), position, this.topLeft); return ( 0 <= translated.x && translated.x < this.size.x && diff --git a/frontend/src/scripts/math/vec2.ts b/frontend/src/scripts/math/vec2.ts deleted file mode 100644 index 595a26d..0000000 --- a/frontend/src/scripts/math/vec2.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { Typed } from '../transport/serializable'; - -export class Vec2 extends Typed { - public constructor(public x: number = 0.0, public y: number = null) { - super(); - - if (this.y === null) { - this.y = this.x; - } - } - - public scale(scalar: number): Vec2 { - return new Vec2(this.x * scalar, this.y * scalar); - } - - public add(other: Vec2): Vec2 { - return new Vec2(this.x + other.x, this.y + other.y); - } - - public subtract(other: Vec2): Vec2 { - 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); - } - - public get normalized(): Vec2 { - return this.scale(1 / this.length); - } - - public get clamped_0_1(): Vec2 { - return new Vec2( - Math.min(1, Math.max(0, this.x)), - Math.min(1, Math.max(0, this.y)) - ); - } - - public get list(): [number, number] { - return [this.x, this.y]; - } -} diff --git a/frontend/src/scripts/objects/game-object.ts b/frontend/src/scripts/objects/game-object.ts index 7628bec..a5a822b 100644 --- a/frontend/src/scripts/objects/game-object.ts +++ b/frontend/src/scripts/objects/game-object.ts @@ -1,19 +1,19 @@ import { Typed } from '../transport/serializable'; -import { Vec2 } from '../math/vec2'; import { IdentityManager } from '../identity/identity-manager'; import { Command } from '../commands/command'; import { CommandReceiver } from '../commands/command-receiver'; +import { vec2 } from 'gl-matrix'; export abstract class GameObject extends Typed implements CommandReceiver { public readonly id = IdentityManager.generateId(); - protected _position = new Vec2(); - public get position(): Vec2 { + protected _position = vec2.create(); + public get position(): vec2 { return this._position; } - protected _boundingBoxSize = new Vec2(); - public get boundingBoxSize(): Vec2 { + protected _boundingBoxSize = vec2.create(); + public get boundingBoxSize(): vec2 { return this._boundingBoxSize; } diff --git a/frontend/src/scripts/objects/types/camera.ts b/frontend/src/scripts/objects/types/camera.ts index 87ad7da..87b0724 100644 --- a/frontend/src/scripts/objects/types/camera.ts +++ b/frontend/src/scripts/objects/types/camera.ts @@ -2,9 +2,12 @@ import { GameObject } from '../game-object'; import { MoveToCommand } from '../../commands/types/move-to'; import { ZoomCommand } from '../../commands/types/zoom'; import { BeforeDrawCommand } from '../../commands/types/before-draw'; +import { PrimaryActionCommand } from '../../commands/types/primary-action'; +import { vec2 } from 'gl-matrix'; export class Camera extends GameObject { private inViewArea = 1920 * 1080; + private cursorPosition = vec2.create(); constructor() { super(); @@ -12,10 +15,15 @@ export class Camera extends GameObject { this.addCommandExecutor(BeforeDrawCommand, this.draw.bind(this)); this.addCommandExecutor(MoveToCommand, this.moveTo.bind(this)); this.addCommandExecutor(ZoomCommand, this.zoom.bind(this)); + this.addCommandExecutor( + PrimaryActionCommand, + this.setCursorPosition.bind(this) + ); } private draw(c: BeforeDrawCommand) { c.drawer.setCameraPosition(this.position); + c.drawer.setCursorPosition(this.cursorPosition); this._boundingBoxSize = c.drawer.setInViewArea(this.inViewArea); } @@ -26,4 +34,8 @@ export class Camera extends GameObject { private zoom(c: ZoomCommand) { this.inViewArea *= c.factor; } + + private setCursorPosition(c: PrimaryActionCommand) { + this.cursorPosition = c.position; + } } diff --git a/frontend/src/scripts/objects/types/character.ts b/frontend/src/scripts/objects/types/character.ts index b850f10..5edb416 100644 --- a/frontend/src/scripts/objects/types/character.ts +++ b/frontend/src/scripts/objects/types/character.ts @@ -1,5 +1,4 @@ import { GameObject } from '../game-object'; -import { Vec2 } from '../../math/vec2'; import { ObjectContainer } from '../object-container'; import { Camera } from './camera'; import { MoveToCommand } from '../../commands/types/move-to'; @@ -7,6 +6,7 @@ import { StepCommand } from '../../commands/types/step'; import { KeyDownCommand } from '../../commands/types/key-down'; import { KeyUpCommand } from '../../commands/types/key-up'; import { SwipeCommand } from '../../commands/types/swipe'; +import { vec2 } from 'gl-matrix'; export class Character extends GameObject { private keysDown: Set = new Set(); @@ -23,12 +23,16 @@ export class Character extends GameObject { this.addCommandExecutor(KeyUpCommand, (c) => this.keysDown.delete(c.key)); this.addCommandExecutor(SwipeCommand, (c) => this.setPosition( - this.position.add(c.delta.times(this.camera.boundingBoxSize)) + vec2.add( + vec2.create(), + this.position, + vec2.multiply(vec2.create(), c.delta, this.camera.boundingBoxSize) + ) ) ); } - private setPosition(value: Vec2) { + private setPosition(value: vec2) { this._position = value; this.camera.sendCommand(new MoveToCommand(this.position)); } @@ -41,11 +45,17 @@ export class Character extends GameObject { const left = ~~this.keysDown.has('a'); const right = ~~this.keysDown.has('d'); - const movementVector = new Vec2(right - left, up - down); + const movementVector = vec2.fromValues(right - left, up - down); if (movementVector.length > 0) { this.setPosition( - this.position.add( - movementVector.normalized.scale(Character.speed * deltaTime) + vec2.add( + vec2.create(), + this.position, + vec2.scale( + vec2.create(), + vec2.normalize(movementVector, movementVector), + Character.speed * deltaTime + ) ) ); } diff --git a/frontend/src/scripts/objects/types/dungeon.ts b/frontend/src/scripts/objects/types/dungeon.ts index 0cf32f7..e2dbbc5 100644 --- a/frontend/src/scripts/objects/types/dungeon.ts +++ b/frontend/src/scripts/objects/types/dungeon.ts @@ -1,12 +1,12 @@ import { GameObject } from '../game-object'; import { DrawCommand } from '../../commands/types/draw'; -import { Vec2 } from '../../math/vec2'; -import { last } from '../../helper/last'; +import { vec2 } from 'gl-matrix'; export interface Line { - start: Vec2; - end: Vec2; - radius: number; + start: vec2; + end: vec2; + radiusFrom: number; + radiusTo: number; } export class Dungeon extends GameObject { @@ -17,33 +17,36 @@ export class Dungeon extends GameObject { this.addCommandExecutor(DrawCommand, this.draw.bind(this)); - let previousHeight = 0; - let previousEnd = new Vec2(); + let previousRadius = 0; + let previousEnd = vec2.create(); for (let i = 0; i < 5000; i += 50) { - const height = previousHeight + (Math.random() - 0.5) * 200; - previousHeight = height; - const currentEnd = new Vec2(i, height); + const height = previousEnd.y + (Math.random() - 0.5) * 200; + const currentEnd = vec2.fromValues(i, height); + const currentToRadius = Math.random() * 10 + 30; this.lines.push({ start: previousEnd, end: currentEnd, - radius: Math.random() * 15 + 15, + radiusFrom: previousRadius, + radiusTo: currentToRadius, }); previousEnd = currentEnd; + previousRadius = currentToRadius; } } private draw(c: DrawCommand) { - const lines: Array = []; + const lines: Array = []; const radii: Array = []; for (let line of this.lines) { if (c.drawer.isOnScreen(line.start) || c.drawer.isOnScreen(line.end)) { lines.push(line.start); lines.push(line.end); - radii.push(line.radius); + radii.push(line.radiusFrom); + radii.push(line.radiusTo); } } diff --git a/frontend/src/shaders/cave-distance-fs.glsl b/frontend/src/shaders/cave-distance-fs.glsl index ef94e29..685bb26 100644 --- a/frontend/src/shaders/cave-distance-fs.glsl +++ b/frontend/src/shaders/cave-distance-fs.glsl @@ -8,12 +8,18 @@ precision mediump float; uniform vec2[LINE_COUNT * 2] lines; -uniform float[LINE_COUNT] radii; +uniform float[LINE_COUNT * 2] radii; -float lineDistance(in vec2 target, in vec2 start, in vec2 end, in float radius) { +float lineDistance( + in vec2 target, + in vec2 start, + in vec2 end, + in float radiusFrom, + in float radiusTo +) { vec2 pa = target - start, ba = end - start; float h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0); - return distance(pa, ba * h) - radius; + return distance(pa, ba * h) - mix(radiusFrom, radiusTo, smoothstep(0.0, 1.0, h)); } float getDistance(in vec2 target) { @@ -22,8 +28,9 @@ float getDistance(in vec2 target) { for (int i = 0; i < LINE_COUNT; i++) { vec2 start = lines[2 * i]; vec2 end = lines[2 * i + 1]; - float r = radii[i]; - minDistance = min(minDistance, lineDistance(target, start, end, r)); + float rFrom = radii[2 * i]; + float rTo = radii[2 * i + 1]; + minDistance = min(minDistance, lineDistance(target, start, end, rFrom, rTo)); } return -minDistance; diff --git a/frontend/src/shaders/dist copy.frag b/frontend/src/shaders/dist copy.frag deleted file mode 100644 index 173be51..0000000 --- a/frontend/src/shaders/dist copy.frag +++ /dev/null @@ -1,135 +0,0 @@ -#version 300 es - -precision mediump float; - - -#define INFINITY 1.0 / 0.0 -#define WORLD_SIZE 4 -#define N (20) - -#define CIRCLE 1 -#define LINE 2 -#define TRIANGLE 3 - -out vec4 fragmentColor; -uniform vec2 resolution; -uniform float time; - - -struct Material { - vec3 color; -}; - -struct Primitive { - uint type; - uint index; -}; - -struct Object { - Material material; - Primitive[10] primitives; -}; - -struct Circle { - uint parent; - vec2 center; - float radius; -}; - -struct Line { - uint parent; - vec2 a; - vec2 b; -}; - -struct Triangle { - uint parent; - vec2 a; - vec2 b; - vec2 c; -}; - -// uniform Object[100] objects; - -Circle[3] circles; -Line[1] lines; -Triangle[1] triangles; - -float triangleDistance(in vec2 position, in Triangle triangle) -{ - vec2 e0 = triangle.b - triangle.a, e1 = triangle.c - triangle.b, e2 = triangle.a - triangle.c; - vec2 v0 = position - triangle.a, v1 = position - triangle.b, v2 = position - triangle.c; - vec2 pq0 = v0 - e0 * clamp(dot(v0, e0) / dot(e0, e0), 0.0, 1.0); - vec2 pq1 = v1 - e1 * clamp(dot(v1, e1) / dot(e1, e1), 0.0, 1.0); - vec2 pq2 = v2 - e2 * clamp(dot(v2, e2) / dot(e2, e2), 0.0, 1.0); - float s = sign(e0.x*e2.y - e0.y*e2.x); - vec2 d = min(min(vec2(dot(pq0,pq0), s*(v0.x*e0.y-v0.y*e0.x)), - vec2(dot(pq1,pq1), s*(v1.x*e1.y-v1.y*e1.x))), - vec2(dot(pq2,pq2), s*(v2.x*e2.y-v2.y*e2.x))); - return -sqrt(d.x)*sign(d.y); -} - -float lineDistance(in vec2 position, in Line line) -{ - vec2 pa = position - line.a, ba = line.b - line.a; - float h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0); - return length(pa - ba*h); -} - -float circleDistance(in vec2 position, in Circle circle) -{ - return length(position - circle.center) - circle.radius; -} - -float getDistance(in vec2 target, out uint nearestParentIndex) { - float distance = INFINITY; - - for (int i = 0; i < circles.length(); i++) { - float distanceToCurrent = circleDistance(target, circles[i]); - if (distanceToCurrent < distance) { - distance = distanceToCurrent; - nearestParentIndex = circles[i].parent; - } - } - - for (int i = 0; i < lines.length(); i++) { - float distanceToCurrent = lineDistance(target, lines[i]); - if (distanceToCurrent < distance) { - distance = distanceToCurrent; - nearestParentIndex = lines[i].parent; - } - } - - for (int i = 0; i < triangles.length(); i++) { - float distanceToCurrent = triangleDistance(target, triangles[i]); - if (distanceToCurrent < distance) { - distance = distanceToCurrent; - nearestParentIndex = triangles[i].parent; - } - } - - return distance; -} - -void createWorld() { - circles[0] = Circle(0u, vec2(250.0, 100.0), 12.5); - circles[1] = Circle(0u, vec2(150.0, 50.0), 32.5); - circles[2] = Circle(0u, vec2(300.0, 350.0), 52.5); - - lines[0] = Line(0u, vec2(100.0, 300.0), vec2(550.0, 140.0)); - - triangles[0] = Triangle(0u, vec2(400.0, 100.0), vec2(200.0, 240.0), vec2(600.0, 340.0)); -} - -float linearstep(float a, float b, float q) { - return a + clamp((b - a) * q, 0.0, 1.0); -} - -void main() { - createWorld(); - - vec2 position = gl_FragCoord.xy + vec2(0.5); - uint index; - vec3 color = vec3(1.0) * linearstep(0.0, 1.0, getDistance(position, index)); - fragmentColor = vec4(color, 1.0); -} diff --git a/frontend/src/shaders/rainbow-shading-fs.glsl b/frontend/src/shaders/rainbow-shading-fs.glsl index 3bfd8ad..aade889 100644 --- a/frontend/src/shaders/rainbow-shading-fs.glsl +++ b/frontend/src/shaders/rainbow-shading-fs.glsl @@ -28,5 +28,6 @@ out vec4 fragmentColor; void main() { vec2 position = (vec3(gl_FragCoord.xy, 1.0) * transformUV).xy; vec4 previous = texture(distanceTexture, position); - fragmentColor = smoothRainbow(previous.a); + //fragmentColor = smoothRainbow(previous.a); + fragmentColor = previous.a > 0.5 ? vec4(1.0, 1.0, 1.0, 1.0) : vec4(0.0, 0.0, 0.0, 1.0); } diff --git a/frontend/src/shaders/dist copy 2.frag b/frontend/src/shaders/random.frag similarity index 100% rename from frontend/src/shaders/dist copy 2.frag rename to frontend/src/shaders/random.frag