From 36c64554f597457222e441f313398b39970d8cf3 Mon Sep 17 00:00:00 2001 From: schmelczerandras Date: Thu, 17 Sep 2020 16:04:09 +0200 Subject: [PATCH] Add parallel compiler --- .../compiling/check-program.ts | 13 -- .../compiling/check-shader.ts | 7 - .../compiling/create-program.ts | 47 ------- .../compiling/create-shader.ts | 19 --- .../graphics-library/parallel-compiler.ts | 131 ++++++++++++++++++ .../program/fragment-shader-only-program.ts | 11 +- .../graphics-library/program/program.ts | 12 +- .../uniform-array-autoscaling-program.ts | 48 ++++--- src/graphics/rendering/rendering-pass.ts | 18 +-- .../rendering/shaders/shading-fs.glsl | 12 ++ .../rendering/shaders/shading-vs.glsl | 8 ++ src/graphics/rendering/webgl2-renderer.ts | 73 +++++----- src/helper/random.ts | 18 --- src/main.ts | 24 +++- 14 files changed, 260 insertions(+), 181 deletions(-) delete mode 100644 src/graphics/graphics-library/compiling/check-program.ts delete mode 100644 src/graphics/graphics-library/compiling/check-shader.ts delete mode 100644 src/graphics/graphics-library/compiling/create-program.ts delete mode 100644 src/graphics/graphics-library/compiling/create-shader.ts create mode 100644 src/graphics/graphics-library/parallel-compiler.ts delete mode 100644 src/helper/random.ts diff --git a/src/graphics/graphics-library/compiling/check-program.ts b/src/graphics/graphics-library/compiling/check-program.ts deleted file mode 100644 index b963139..0000000 --- a/src/graphics/graphics-library/compiling/check-program.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { checkShader } from './check-shader'; - -export const checkProgram = (gl: WebGL2RenderingContext, program: WebGLProgram) => { - const success = gl.getProgramParameter(program, gl.LINK_STATUS); - - if (!success && !gl.isContextLost()) { - gl.getAttachedShaders(program)?.forEach((s) => { - checkShader(gl, s); - }); - - throw new Error(gl.getProgramInfoLog(program)!); - } -}; diff --git a/src/graphics/graphics-library/compiling/check-shader.ts b/src/graphics/graphics-library/compiling/check-shader.ts deleted file mode 100644 index 670915b..0000000 --- a/src/graphics/graphics-library/compiling/check-shader.ts +++ /dev/null @@ -1,7 +0,0 @@ -export const checkShader = (gl: WebGL2RenderingContext, shader: WebGLShader) => { - const success = gl.getShaderParameter(shader, gl.COMPILE_STATUS); - - if (!success && !gl.isContextLost()) { - throw new Error(gl.getShaderInfoLog(shader)!); - } -}; diff --git a/src/graphics/graphics-library/compiling/create-program.ts b/src/graphics/graphics-library/compiling/create-program.ts deleted file mode 100644 index 80a08cc..0000000 --- a/src/graphics/graphics-library/compiling/create-program.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { checkProgram } from './check-program'; -import { createShader } from './create-shader'; - -export const createProgram = ( - gl: WebGL2RenderingContext, - vertexShaderSource: string, - fragmentShaderSource: string, - substitutions: { [name: string]: string } -): WebGLProgram => { - // can only return null on lost context - const program = gl.createProgram()!; - - // const extension = tryEnableExtension(gl, 'KHR_parallel_shader_compile'); - - const vertexShader = createShader( - gl, - gl.VERTEX_SHADER, - vertexShaderSource, - substitutions - ); - gl.attachShader(program, vertexShader); - - const fragmentShader = createShader( - gl, - gl.FRAGMENT_SHADER, - fragmentShaderSource, - substitutions - ); - - gl.attachShader(program, fragmentShader); - - gl.linkProgram(program); - - /*if (extension) { - const checkCompileStatus = () => - gl.getProgramParameter(program, extension.COMPLETION_STATUS_KHR); - - await waitWhileFalse(checkCompileStatus); - }*/ - - checkProgram(gl, program); - - gl.deleteShader(vertexShader); - gl.deleteShader(fragmentShader); - - return program; -}; diff --git a/src/graphics/graphics-library/compiling/create-shader.ts b/src/graphics/graphics-library/compiling/create-shader.ts deleted file mode 100644 index 18dd20b..0000000 --- a/src/graphics/graphics-library/compiling/create-shader.ts +++ /dev/null @@ -1,19 +0,0 @@ -export const createShader = ( - gl: WebGL2RenderingContext, - type: GLenum, - source: string, - substitutions: { [name: string]: string } -): WebGLShader => { - source = source.replace(/{(.+)}/gm, (_, name: string): string => { - const value = substitutions[name]; - return Number.isInteger(value) ? `${value}.0` : value; - }); - - // can only return null on lost context - const shader = gl.createShader(type)!; - - gl.shaderSource(shader, source); - gl.compileShader(shader); - - return shader; -}; diff --git a/src/graphics/graphics-library/parallel-compiler.ts b/src/graphics/graphics-library/parallel-compiler.ts new file mode 100644 index 0000000..bbdd59e --- /dev/null +++ b/src/graphics/graphics-library/parallel-compiler.ts @@ -0,0 +1,131 @@ +import { wait } from '../../helper/wait'; +import { Insights } from '../rendering/insights'; +import { tryEnableExtension } from './helper/enable-extension'; + +type CompilingProgram = { + program: WebGLProgram; + resolvePromise: ((program: WebGLProgram) => void) | null; +}; + +export abstract class ParallelCompiler { + private static extension?: any; + private static gl: WebGL2RenderingContext; + private static programs: Array = []; + + public static initialize(gl: WebGL2RenderingContext) { + ParallelCompiler.gl = gl; + ParallelCompiler.extension = tryEnableExtension(gl, 'KHR_parallel_shader_compile'); + } + + public static createProgram( + vertexShaderSource: string, + fragmentShaderSource: string, + substitutions: { [name: string]: string } + ): Promise { + let resolvePromise: ((program: WebGLProgram) => void) | null = null; + const promise = new Promise((r) => (resolvePromise = r)); + + // can only return null on lost context + const program = ParallelCompiler.gl.createProgram()!; + + ParallelCompiler.compileShader( + vertexShaderSource, + ParallelCompiler.gl.VERTEX_SHADER, + program, + substitutions + ); + + ParallelCompiler.compileShader( + fragmentShaderSource, + ParallelCompiler.gl.FRAGMENT_SHADER, + program, + substitutions + ); + + ParallelCompiler.programs.push({ + program, + resolvePromise, + }); + + return promise; + } + + public static async compilePrograms(): Promise { + ParallelCompiler.programs.forEach((p) => ParallelCompiler.gl.linkProgram(p.program)); + + Insights.setValue('program count', ParallelCompiler.programs.length); + + while (ParallelCompiler.programs.length > 0) { + ParallelCompiler.resolveFinishedPrograms(); + await wait(0); + } + } + + private static compileShader( + source: string, + type: GLenum, + program: WebGLProgram, + substitutions: { [name: string]: string } + ) { + const processedSource = source.replace(/{(.+)}/gm, (_, name: string): string => { + const value = substitutions[name]; + return Number.isInteger(value) ? `${value}.0` : value; + }); + + // can only return null on lost context + const shader = ParallelCompiler.gl.createShader(type)!; + + this.gl.shaderSource(shader, processedSource); + this.gl.compileShader(shader); + this.gl.attachShader(program, shader); + this.gl.deleteShader(shader); + } + + private static resolveFinishedPrograms() { + const done: Array = []; + + ParallelCompiler.programs.forEach((p) => { + if ( + !ParallelCompiler.extension || + ParallelCompiler.gl.getProgramParameter( + p.program, + ParallelCompiler.extension.COMPLETION_STATUS_KHR + ) + ) { + ParallelCompiler.checkProgram(p.program); + done.push(p); + p.resolvePromise!(p.program); + } + }); + + ParallelCompiler.programs = ParallelCompiler.programs.filter( + (p1) => done.findIndex((p2) => p2 === p1) == -1 + ); + } + + private static checkProgram(program: WebGLProgram) { + const success = ParallelCompiler.gl.getProgramParameter( + program, + ParallelCompiler.gl.LINK_STATUS + ); + + if (!success && !ParallelCompiler.gl.isContextLost()) { + ParallelCompiler.gl.getAttachedShaders(program)?.forEach((s) => { + ParallelCompiler.checkShader(s); + }); + + throw new Error(ParallelCompiler.gl.getProgramInfoLog(program)!); + } + } + + private static checkShader(shader: WebGLShader) { + const success = ParallelCompiler.gl.getShaderParameter( + shader, + ParallelCompiler.gl.COMPILE_STATUS + ); + + if (!success && !ParallelCompiler.gl.isContextLost()) { + throw new Error(ParallelCompiler.gl.getShaderInfoLog(shader)!); + } + } +} diff --git a/src/graphics/graphics-library/program/fragment-shader-only-program.ts b/src/graphics/graphics-library/program/fragment-shader-only-program.ts index d6ad3ab..6b78fc4 100644 --- a/src/graphics/graphics-library/program/fragment-shader-only-program.ts +++ b/src/graphics/graphics-library/program/fragment-shader-only-program.ts @@ -3,12 +3,15 @@ import Program from './program'; export class FragmentShaderOnlyProgram extends Program { private vao?: WebGLVertexArrayObject; - constructor( - gl: WebGL2RenderingContext, + constructor(gl: WebGL2RenderingContext) { + super(gl); + } + + public async initialize( sources: [string, string], substitutions: { [name: string]: string } - ) { - super(gl, sources, substitutions); + ): Promise { + await super.initialize(sources, substitutions); this.prepareScreenQuad('vertexPosition'); } diff --git a/src/graphics/graphics-library/program/program.ts b/src/graphics/graphics-library/program/program.ts index 081dbb3..6b5c09a 100644 --- a/src/graphics/graphics-library/program/program.ts +++ b/src/graphics/graphics-library/program/program.ts @@ -1,6 +1,6 @@ import { mat2d, vec2 } from 'gl-matrix'; -import { createProgram } from '../compiling/create-program'; import { loadUniform } from '../helper/load-uniform'; +import { ParallelCompiler } from '../parallel-compiler'; import { IProgram } from './i-program'; export default abstract class Program implements IProgram { @@ -14,15 +14,15 @@ export default abstract class Program implements IProgram { type: GLenum; }> = []; - constructor( - protected gl: WebGL2RenderingContext, + constructor(protected gl: WebGL2RenderingContext) {} + + public async initialize( [vertexShaderSource, fragmentShaderSource]: [string, string], substitutions: { [name: string]: string } - ) { + ): Promise { substitutions = { ...substitutions }; - this.program = createProgram( - this.gl, + this.program = await ParallelCompiler.createProgram( vertexShaderSource, fragmentShaderSource, substitutions diff --git a/src/graphics/graphics-library/program/uniform-array-autoscaling-program.ts b/src/graphics/graphics-library/program/uniform-array-autoscaling-program.ts index 1b44690..ebd6a5f 100644 --- a/src/graphics/graphics-library/program/uniform-array-autoscaling-program.ts +++ b/src/graphics/graphics-library/program/uniform-array-autoscaling-program.ts @@ -12,24 +12,34 @@ export class UniformArrayAutoScalingProgram implements IProgram { }> = []; private current?: FragmentShaderOnlyProgram; + private descriptors?: Array; private drawingRectangleBottomLeft = vec2.fromValues(0, 0); private drawingRectangleSize = vec2.fromValues(1, 1); - constructor( - private gl: WebGL2RenderingContext, + constructor(private gl: WebGL2RenderingContext) {} + + public async initialize( shaderSources: [string, string], - private descriptors: Array, - private substitutions: { [name: string]: any } - ) { + descriptors: Array, + substitutions: { [name: string]: any } + ): Promise { + this.descriptors = descriptors; + + const promises: Array> = []; + for (const combination of getCombinations( descriptors.map((o) => o.shaderCombinationSteps) )) { - this.createProgram(descriptors, combination, shaderSources); + promises.push( + this.createProgram(descriptors, substitutions, combination, shaderSources) + ); } + + await Promise.all(promises); } public bindAndSetUniforms(uniforms: { [name: string]: any }): void { - const values = this.descriptors.map((d) => + const values = this.descriptors!.map((d) => uniforms[d.uniformName] ? uniforms[d.uniformName].length : 0 ); @@ -38,7 +48,7 @@ export class UniformArrayAutoScalingProgram implements IProgram { this.current = closest ? closest.program : last(this.programs)?.program; if (closest) { - this.descriptors.map((d, i) => { + this.descriptors!.map((d, i) => { const difference = closest.values[i] - values[i]; for (let i = 0; i < difference; i++) { d.empty.serializeToUniforms(uniforms, mat2d.create(), 0); @@ -70,26 +80,26 @@ export class UniformArrayAutoScalingProgram implements IProgram { this.programs.forEach((p) => p.program.delete()); } - private createProgram( + private async createProgram( descriptors: Array, + substitutions: { [name: string]: any }, combination: Array, shaderSources: [string, string] - ): FragmentShaderOnlyProgram { - const substitutions = { - ...this.substitutions, + ): Promise { + const processedSubstitutions = { + ...substitutions, macroDefinitions: this.getMacroDefinitions(combination, descriptors), declarations: this.getDeclarations(combination, descriptors), functionCalls: this.getFunctionCalls(combination, descriptors), }; - const program = new FragmentShaderOnlyProgram(this.gl, shaderSources, substitutions); + const program = new FragmentShaderOnlyProgram(this.gl); + await program.initialize(shaderSources, processedSubstitutions); this.programs.push({ program, values: combination, }); - - return program; } private getMacroDefinitions( @@ -97,13 +107,7 @@ export class UniformArrayAutoScalingProgram implements IProgram { descriptors: Array ): string { return combination - .map( - (v, i) => ` - #ifndef ${descriptors[i].uniformCountMacroName} - #define ${descriptors[i].uniformCountMacroName} ${v} - #endif - ` - ) + .map((v, i) => `#define ${descriptors[i].uniformCountMacroName} ${v}`) .join('\n'); } diff --git a/src/graphics/rendering/rendering-pass.ts b/src/graphics/rendering/rendering-pass.ts index 70fb2cf..a757024 100644 --- a/src/graphics/rendering/rendering-pass.ts +++ b/src/graphics/rendering/rendering-pass.ts @@ -10,18 +10,18 @@ export class RenderingPass { constructor( gl: WebGL2RenderingContext, - shaderSources: [string, string], - drawableDescriptors: Array, private frame: FrameBuffer, - substitutions: { [name: string]: any }, private tileMultiplier: number ) { - this.program = new UniformArrayAutoScalingProgram( - gl, - shaderSources, - drawableDescriptors, - substitutions - ); + this.program = new UniformArrayAutoScalingProgram(gl); + } + + public async initialize( + shaderSources: [string, string], + descriptors: Array, + substitutions: { [name: string]: any } + ): Promise { + await this.program.initialize(shaderSources, descriptors, substitutions); } public addDrawable(drawable: Drawable) { diff --git a/src/graphics/rendering/shaders/shading-fs.glsl b/src/graphics/rendering/shaders/shading-fs.glsl index a3dfd42..cd1addc 100644 --- a/src/graphics/rendering/shaders/shading-fs.glsl +++ b/src/graphics/rendering/shaders/shading-fs.glsl @@ -68,6 +68,7 @@ float shadowTransparency(float startingDistance, float lightCenterDistance, vec2 } +#ifdef CIRCLE_LIGHT_COUNT #if CIRCLE_LIGHT_COUNT > 0 uniform struct CircleLight { vec2 center; @@ -91,7 +92,9 @@ float shadowTransparency(float startingDistance, float lightCenterDistance, vec2 ); } #endif +#endif +#ifdef FLASHLIGHT_COUNT #if FLASHLIGHT_COUNT > 0 uniform struct Flashlight { vec2 center; @@ -120,6 +123,7 @@ float shadowTransparency(float startingDistance, float lightCenterDistance, vec2 ); } #endif +#endif out vec4 fragmentColor; void main() { @@ -129,20 +133,25 @@ void main() { float startingDistance = getDistance(uvCoordinates, colorAtPosition); if (startingDistance < 0.0) { + #ifdef CIRCLE_LIGHT_COUNT #if CIRCLE_LIGHT_COUNT > 0 for (int i = 0; i < CIRCLE_LIGHT_COUNT; i++) { lighting += colorInPositionInside(circleLights[i]); } #endif + #endif + #ifdef FLASHLIGHT_COUNT #if FLASHLIGHT_COUNT > 0 for (int i = 0; i < FLASHLIGHT_COUNT; i++) { lighting += colorInPositionInside(flashlights[i], normalize(flashlightDirections[i])); } #endif + #endif } else { colorAtPosition = vec3(1.0); + #ifdef CIRCLE_LIGHT_COUNT #if CIRCLE_LIGHT_COUNT > 0 for (int i = 0; i < CIRCLE_LIGHT_COUNT; i++) { vec2 direction = normalize(circleLightDirections[i]) / squareToAspectRatioTimes2; @@ -153,7 +162,9 @@ void main() { lighting += lightColorAtPosition * shadowTransparency(startingDistance, lightCenterDistance, direction); } #endif + #endif + #ifdef FLASHLIGHT_COUNT #if FLASHLIGHT_COUNT > 0 for (int i = 0; i < FLASHLIGHT_COUNT; i++) { vec2 originalDirection = normalize(flashlightDirections[i]); @@ -169,6 +180,7 @@ void main() { lighting += lightColorAtPosition * shadowTransparency(startingDistance, lightCenterDistance, direction); } #endif + #endif } fragmentColor = vec4(colorAtPosition * lighting, 1.0); diff --git a/src/graphics/rendering/shaders/shading-vs.glsl b/src/graphics/rendering/shaders/shading-vs.glsl index 179d9d9..860fe47 100644 --- a/src/graphics/rendering/shaders/shading-vs.glsl +++ b/src/graphics/rendering/shaders/shading-vs.glsl @@ -12,6 +12,7 @@ out vec2 uvCoordinates; uniform vec2 squareToAspectRatio; +#ifdef CIRCLE_LIGHT_COUNT #if CIRCLE_LIGHT_COUNT > 0 uniform struct CircleLight { vec2 center; @@ -21,7 +22,9 @@ uniform vec2 squareToAspectRatio; out vec2[CIRCLE_LIGHT_COUNT] circleLightDirections; #endif +#endif +#ifdef FLASHLIGHT_COUNT #if FLASHLIGHT_COUNT > 0 uniform struct Flashlight { vec2 center; @@ -32,6 +35,7 @@ uniform vec2 squareToAspectRatio; out vec2[FLASHLIGHT_COUNT] flashlightDirections; #endif +#endif void main() { vec3 vertexPosition2D = vec3(vertexPosition.xy, 1.0) * modelTransform; @@ -44,15 +48,19 @@ void main() { 0.0, 0.0, 1.0 )).xy; + #ifdef CIRCLE_LIGHT_COUNT #if CIRCLE_LIGHT_COUNT > 0 for (int i = 0; i < CIRCLE_LIGHT_COUNT; i++) { circleLightDirections[i] = circleLights[i].center - position; } #endif + #endif + #ifdef FLASHLIGHT_COUNT #if FLASHLIGHT_COUNT > 0 for (int i = 0; i < FLASHLIGHT_COUNT; i++) { flashlightDirections[i] = flashlights[i].center - position; } #endif + #endif } diff --git a/src/graphics/rendering/webgl2-renderer.ts b/src/graphics/rendering/webgl2-renderer.ts index f7fdb70..08040b3 100644 --- a/src/graphics/rendering/webgl2-renderer.ts +++ b/src/graphics/rendering/webgl2-renderer.ts @@ -1,12 +1,11 @@ import { vec2, vec3 } from 'gl-matrix'; import { Drawable } from '../../drawables/drawable'; import { DrawableDescriptor } from '../../drawables/drawable-descriptor'; -import { CircleLight } from '../../drawables/lights/circle-light'; -import { Flashlight } from '../../drawables/lights/flashlight'; import { DefaultFrameBuffer } from '../graphics-library/frame-buffer/default-frame-buffer'; import { IntermediateFrameBuffer } from '../graphics-library/frame-buffer/intermediate-frame-buffer'; import { getWebGl2Context } from '../graphics-library/helper/get-webgl2-context'; import { WebGlStopwatch } from '../graphics-library/helper/stopwatch'; +import { ParallelCompiler } from '../graphics-library/parallel-compiler'; import { FpsAutoscaler } from './fps-autoscaler'; import { Insights } from './insights'; import { Renderer } from './renderer'; @@ -29,6 +28,7 @@ export class WebGl2Renderer implements Renderer { private lightingFrameBuffer: DefaultFrameBuffer; private passes: Passes; private autoscaler: FpsAutoscaler; + private settings: WebGl2RendererSettings; private static defaultSettings: WebGl2RendererSettings = { enableHighDpiRendering: true, @@ -42,24 +42,26 @@ export class WebGl2Renderer implements Renderer { constructor( private canvas: HTMLCanvasElement, - descriptors: Array, - palette: Array, + private descriptors: Array, + private palette: Array, settingsOverrides: Partial ) { - const settings = { ...WebGl2Renderer.defaultSettings, ...settingsOverrides }; + this.settings = { ...WebGl2Renderer.defaultSettings, ...settingsOverrides }; this.gl = getWebGl2Context(canvas); + ParallelCompiler.initialize(this.gl); + this.distanceFieldFrameBuffer = new IntermediateFrameBuffer( this.gl, - settings.enableHighDpiRendering + this.settings.enableHighDpiRendering ); this.lightingFrameBuffer = new DefaultFrameBuffer( this.gl, - settings.enableHighDpiRendering + this.settings.enableHighDpiRendering ); - this.passes = this.createPasses(descriptors, palette, settings); + this.passes = this.createPasses(); this.uniformsProvider = new UniformsProvider(this.gl); @@ -71,7 +73,7 @@ export class WebGl2Renderer implements Renderer { (this.uniformsProvider.softShadowsEnabled = v as boolean), }); - if (settings.enableStopwatch) { + if (this.settings.enableStopwatch) { try { this.stopwatch = new WebGlStopwatch(this.gl); } catch { @@ -81,40 +83,49 @@ export class WebGl2Renderer implements Renderer { } @Insights.measure('create render passes') - private createPasses( - descriptors: Array, - palette: Array, - settings: WebGl2RendererSettings - ): Passes { - const allDescriptors = [ - ...descriptors, - CircleLight.descriptor, - Flashlight.descriptor, - ]; - + private createPasses(): Passes { return { [RenderingPassName.distance]: new RenderingPass( this.gl, - [distanceVertexShader, distanceFragmentShader], - allDescriptors.filter(WebGl2Renderer.hasSdf), this.distanceFieldFrameBuffer, - settings.shaderMacros, - settings.tileMultiplier + this.settings.tileMultiplier ), [RenderingPassName.pixel]: new RenderingPass( this.gl, - [lightsVertexShader, lightsFragmentShader], - allDescriptors.filter((d) => !WebGl2Renderer.hasSdf(d)), this.lightingFrameBuffer, - { - palette: this.generatePaletteCode(palette), - ...settings.shaderMacros, - }, - settings.tileMultiplier + this.settings.tileMultiplier ), }; } + @Insights.measure('initialize render passes') + public async initialize(): Promise { + const promises: Array> = []; + + promises.push( + this.passes[RenderingPassName.distance].initialize( + [distanceVertexShader, distanceFragmentShader], + this.descriptors.filter(WebGl2Renderer.hasSdf), + this.settings.shaderMacros + ) + ); + + promises.push( + this.passes[RenderingPassName.pixel].initialize( + [lightsVertexShader, lightsFragmentShader], + this.descriptors.filter((d) => !WebGl2Renderer.hasSdf(d)), + { + palette: this.generatePaletteCode(this.palette), + ...this.settings.shaderMacros, + } + ) + ); + + ParallelCompiler.compilePrograms(); + + await Promise.all(promises); + } + public get insights(): any { return Insights.values; } diff --git a/src/helper/random.ts b/src/helper/random.ts deleted file mode 100644 index 10e93bb..0000000 --- a/src/helper/random.ts +++ /dev/null @@ -1,18 +0,0 @@ -// src -// https://stackoverflow.com/questions/521295/seeding-the-random-number-generator-in-javascript -// Mulberry32 - -export abstract class Random { - private static _seed = Math.random(); - - public static set seed(value: number) { - Random._seed = value; - } - - public static getRandom(): number { - let t = (Random._seed += 0x6d2b79f5); - t = Math.imul(t ^ (t >>> 15), t | 1); - t ^= t + Math.imul(t ^ (t >>> 7), t | 61); - return ((t ^ (t >>> 14)) >>> 0) / 4294967296; - } -} diff --git a/src/main.ts b/src/main.ts index 54785a2..2b7b471 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,4 +1,4 @@ -import { glMatrix, vec3 } from 'gl-matrix'; +import { vec3 } from 'gl-matrix'; import { DrawableDescriptor } from './drawables/drawable-descriptor'; import { Renderer } from './graphics/rendering/renderer'; import { WebGl2Renderer } from './graphics/rendering/webgl2-renderer'; @@ -14,13 +14,27 @@ export { Tunnel } from './drawables/shapes/tunnel'; export { Renderer } from './graphics/rendering/renderer'; export { RenderingPassName } from './graphics/rendering/rendering-pass-name'; -export const compile = ( +declare global { + interface Array { + x: number; + y: number; + } + + interface Float32Array { + x: number; + y: number; + } +} + +export const compile = async ( canvas: HTMLCanvasElement, descriptors: Array, palette: Array, settings: Partial = {} -): Renderer => { - glMatrix.setMatrixArrayType(Array); +): Promise => { applyArrayPlugins(); - return new WebGl2Renderer(canvas, descriptors, palette, settings); + + const renderer = new WebGl2Renderer(canvas, descriptors, palette, settings); + await renderer.initialize(); + return renderer; };