Skip to content

Commit

Permalink
refactor: full TypeScript support + partial external vendor definitions
Browse files Browse the repository at this point in the history
  • Loading branch information
timkurvers committed Feb 5, 2024
1 parent ec4cf86 commit 24c8edb
Show file tree
Hide file tree
Showing 83 changed files with 1,565 additions and 766 deletions.
8 changes: 5 additions & 3 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ module.exports = {
root: true,
env: { browser: true, node: true },
rules: {
'camelcase': 'off',
'no-console': 'off',
'no-unused-vars': ['error', {
'@typescript-eslint/no-this-alias': 'off',
'@typescript-eslint/no-unused-vars': ['error', {
'argsIgnorePattern': '^_',
'varsIgnorePattern': '^_'
}],
'camelcase': 'off',
'no-cond-assign': 'off',
'no-console': 'off',
'quotes': ['error', 'single', {
'avoidEscape': true
}],
Expand Down
19 changes: 16 additions & 3 deletions src/Client.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,26 @@
import Device from './gfx/Device';
import WebGL2Device from './gfx/apis/webgl2/WebGL2Device';
import WebGPUDevice from './gfx/apis/webgpu/WebGPUDevice';
import Screen from './gfx/Screen';
import TextureRegistry from './gfx/TextureRegistry';
import UIContext from './ui/UIContext';
import { fetch } from './utils';

type ClientOptions = {
api: 'webgl2' | 'webgpu' | string
}

class Client {
constructor(canvas, { api }) {
this.constructor.instance = this;
static instance: Client;

fetch: typeof fetch;
device: Device;
screen: Screen;
textures: TextureRegistry;
ui: UIContext;

constructor(canvas: HTMLCanvasElement, { api }: ClientOptions) {
Client.instance = this;

this.fetch = fetch;

Expand All @@ -17,7 +30,7 @@ class Client {
this.device = new WebGL2Device(canvas);
break;
case 'webgpu':
this.device = new WebGPUDevice(canvas);
this.device = new WebGPUDevice();
break;
}

Expand Down
2 changes: 2 additions & 0 deletions src/gfx/Color.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
class Color {
value: number;

constructor(value = 0x00000000) {
this.value = value;
}
Expand Down
10 changes: 5 additions & 5 deletions src/gfx/Device.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import ShaderRegistry from './ShaderRegistry';
import { ShaderType } from './Shader';

abstract class Device {
static instance: Device;

class Device {
constructor() {
Device.instance = this;

this.shaders = new ShaderRegistry();
}

createShader() {
createShader(_type: ShaderType, _source: string): WebGLShader {
throw new Error(`${this.constructor.name} must implement 'createShader'`);
}

Expand Down
48 changes: 30 additions & 18 deletions src/gfx/Screen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,20 @@ import Device from './Device';
import { LinkedList, LinkStrategy } from '../utils';

import ScreenLayer from './ScreenLayer';
import WebGL2Device from './apis/webgl2/WebGL2Device';

class Screen {
constructor(canvas) {
this.constructor.instance = this;
static instance: Screen;

canvas: HTMLCanvasElement;
layers: LinkedList<ScreenLayer>;
debugProgram?: WebGLProgram;

constructor(canvas: HTMLCanvasElement) {
Screen.instance = this;

this.canvas = canvas;
this.layers = LinkedList.of(ScreenLayer, 'zorderLink');
this.layers = LinkedList.using('zorderLink');

this.render = this.render.bind(this);

Expand All @@ -23,12 +30,13 @@ class Screen {
return this;
}

setViewport(..._viewport) {
setViewport(_minX: number, _maxX: number, _minY: number, _maxY: number, _minZ: number, _maxZ: number) {
// TODO: Set viewport
}

render() {
const { gl } = Device.instance;
// TODO: Generic device interface
const { gl } = Device.instance as WebGL2Device;

console.group('render');

Expand Down Expand Up @@ -57,8 +65,8 @@ class Screen {
// TODO: Combinatory magic with base rect
}

const _viewport = this.viewport;
// TODO: Save viewport
// TODO: Viewport
// const _viewport = this.viewport;

gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
gl.clearColor(0, 0, 0, 1);
Expand All @@ -76,7 +84,10 @@ class Screen {
if (layer.flags & 0x4) {
this.setViewport(0, 1, 0, 1, 0, 1);
} else {
this.setViewport(...visibleRect.args, 0, 1);
this.setViewport(
visibleRect.left, visibleRect.right,
visibleRect.bottom, visibleRect.top,
0, 1);
}

if (layer.flags & 0x2) {
Expand All @@ -97,31 +108,32 @@ class Screen {

this.debugLines();

console.groupEnd('render');
console.groupEnd();

// TODO: Render again
// requestAnimationFrame(this.render);
}

createLayer(...args) {
createLayer(...args: ConstructorParameters<typeof ScreenLayer>) {
const layer = new ScreenLayer(...args);
this.addLayer(layer);
return layer;
}

addLayer(layer) {
addLayer(layer: ScreenLayer) {
const { zorder } = layer;

let target = this.layers.head;
while (target && zorder < target.zorder) {
target = target.zorderLink.next.entity;
target = target.zorderLink.next?.entity;
}

this.layers.link(layer, LinkStrategy.BEFORE, target);
}

debugLines() {
const device = Device.instance;
// TODO: Generic device interface
const device = Device.instance as WebGL2Device;
const { gl } = device;

if (!this.debugProgram) {
Expand All @@ -131,9 +143,9 @@ class Screen {
return;
}

this.debugProgram = gl.createProgram();
gl.attachShader(this.debugProgram, vertexShader.apiShader);
gl.attachShader(this.debugProgram, pixelShader.apiShader);
this.debugProgram = gl.createProgram()!;
gl.attachShader(this.debugProgram, vertexShader.apiShader!);
gl.attachShader(this.debugProgram, pixelShader.apiShader!);
gl.linkProgram(this.debugProgram);

const success = gl.getProgramParameter(this.debugProgram, gl.LINK_STATUS);
Expand All @@ -148,8 +160,8 @@ class Screen {

const positionPtr = gl.getAttribLocation(this.debugProgram, 'position');

const vertical = (x) => [x, -1, x, 1];
const horizontal = (y) => [-1, y, 1, y];
const vertical = (x: number) => [x, -1, x, 1];
const horizontal = (y: number) => [-1, y, 1, y];

const dataBuffer = gl.createBuffer();
const data = new Float32Array([
Expand Down
12 changes: 11 additions & 1 deletion src/gfx/ScreenLayer.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
import { LinkedListLink } from '../utils';
import { EdgeRect } from '../math';

type ScreenRenderFn = (_param: null, _rect: EdgeRect, _visible: EdgeRect, _elapsedSecs: number) => void;

class ScreenLayer {
constructor(rect, zorder, flags, param, render) {
rect: EdgeRect;
zorder: number;
flags: number;
param: null;
render: ScreenRenderFn;
zorderLink: LinkedListLink<ScreenLayer>;
visibleRect: EdgeRect;

constructor(rect: EdgeRect | null, zorder: number, flags: number, param: null, render: ScreenRenderFn) {
this.rect = rect || new EdgeRect({ right: 1, top: 1 });
this.zorder = zorder || 0.0;
this.flags = flags || 0;
Expand Down
15 changes: 12 additions & 3 deletions src/gfx/Shader.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
import Client from '../Client';
import Device from './Device';

type ShaderType = 'vertex' | 'pixel'

class Shader {
constructor(type, path) {
type: ShaderType;
path: string;
isLoaded: boolean;

source?: string;
apiShader?: WebGLShader;

constructor(type: ShaderType, path: string) {
this.type = type;
this.path = path;
this.data = null;
this.isLoaded = false;

this.onSourceLoaded = this.onSourceLoaded.bind(this);
Expand All @@ -17,7 +25,7 @@ class Shader {
return this.isLoaded;
}

onSourceLoaded(source) {
onSourceLoaded(source: string) {
this.source = source;

const device = Device.instance;
Expand All @@ -28,3 +36,4 @@ class Shader {
}

export default Shader;
export type { ShaderType };
16 changes: 10 additions & 6 deletions src/gfx/ShaderRegistry.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
import { HashMap, HashStrategy } from '../utils';

import Shader from './Shader';
import Shader, { ShaderType } from './Shader';

class ShaderRegistry extends HashMap {
constructor(pathFor) {
type ShaderPathFn = (_type: ShaderType, _name: string) => string;

class ShaderRegistry extends HashMap<string, Shader> {
pathFor: ShaderPathFn;

constructor(pathFor: ShaderPathFn) {
super(HashStrategy.UPPERCASE);

this.pathFor = pathFor;
}

shaderFor(type, name) {
shaderFor(type: ShaderType, name: string) {
const path = this.pathFor(type, name);
let shader = this.get(path);
if (!shader) {
Expand All @@ -19,11 +23,11 @@ class ShaderRegistry extends HashMap {
return shader;
}

pixelShaderFor(name) {
pixelShaderFor(name: string) {
return this.shaderFor('pixel', name);
}

vertexShaderFor(name) {
vertexShaderFor(name: string) {
return this.shaderFor('vertex', name);
}
}
Expand Down
6 changes: 5 additions & 1 deletion src/gfx/Texture.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
class Texture {
constructor(path) {
path: string;
isLoaded: boolean;
image: HTMLImageElement;

constructor(path: string) {
this.path = path;
this.isLoaded = false;

Expand Down
19 changes: 15 additions & 4 deletions src/gfx/TextureFlags.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
import { TextureFilter } from './types';

class TextureFlags {
constructor({
filter, wrapU, wrapV,
forceMipTracking, generateMipMaps,
} = {}) {
filter: number;
wrapU: boolean;
wrapV: boolean;
forceMipTracking: boolean;
generateMipMaps: boolean;

constructor(
filter = TextureFilter.Linear,
wrapU = false,
wrapV = false,
forceMipTracking = false,
generateMipMaps = false
) {
this.filter = filter;
this.wrapU = wrapU;
this.wrapV = wrapV;
Expand Down
4 changes: 2 additions & 2 deletions src/gfx/TextureRegistry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import { HashMap, HashStrategy } from '../utils';

import Texture from './Texture';

class TextureRegistry extends HashMap {
class TextureRegistry extends HashMap<string, Texture> {
constructor() {
super(HashStrategy.UPPERCASE);
}

lookup(path) {
lookup(path: string) {
// TODO: BLP/TGA support instead of PNG
path = `${path.replace(/\.blp|\.tga/i, '')}.png`;
let texture = this.get(path);
Expand Down
21 changes: 14 additions & 7 deletions src/gfx/apis/webgl2/WebGL2Device.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,32 @@
import Device from '../../Device';
import ShaderRegistry from '../../ShaderRegistry';
import constantsFor from './constants';
import { ShaderType } from '../../Shader';

// import constantsFor from './constants';


class WebGL2Device extends Device {
constructor(canvas) {
super(canvas);
gl: WebGL2RenderingContext;
shaders: ShaderRegistry;

constructor(canvas: HTMLCanvasElement) {
super();

// TODO: Handle context loss
this.gl = canvas.getContext('webgl2');
this.constants = constantsFor(this.gl);
this.gl = canvas.getContext('webgl2')!;
// TODO: Constants
// this.constants = constantsFor(this.gl);

this.shaders = new ShaderRegistry((type, name) => {
const ext = type === 'pixel' ? 'frag' : 'vert';
return `Shaders\\${type}\\glsles300\\${name}.${ext}`;
});
}

createShader(type, source) {
createShader(type: ShaderType, source: string): WebGLShader {
const { gl } = this;
const shaderType = type === 'pixel' ? gl.FRAGMENT_SHADER : gl.VERTEX_SHADER;
const shader = this.gl.createShader(shaderType);
const shader = this.gl.createShader(shaderType)!;
this.gl.shaderSource(shader, source);
this.gl.compileShader(shader);

Expand Down
Loading

0 comments on commit 24c8edb

Please sign in to comment.