From 8e73aee9bab49aabc651f3e54aea7d8a07ac337b Mon Sep 17 00:00:00 2001 From: schmelczerandras Date: Fri, 18 Sep 2020 15:27:21 +0200 Subject: [PATCH] Various improvements --- src/drawables/lights/circle-light.ts | 4 +- src/drawables/shapes/inverted-tunnel.ts | 89 +++++++++++++++++++ src/drawables/shapes/tunnel.ts | 56 ++++++------ .../frame-buffer/frame-buffer.ts | 4 + .../frame-buffer/intermediate-frame-buffer.ts | 4 + .../graphics-library/parallel-compiler.ts | 1 + .../program/fragment-shader-only-program.ts | 8 +- .../graphics-library/program/i-program.ts | 5 +- .../graphics-library/program/program.ts | 13 ++- .../uniform-array-autoscaling-program.ts | 29 +++--- src/graphics/rendering/insights.ts | 39 +++++--- src/graphics/rendering/rendering-pass.ts | 36 ++++++-- .../rendering/shaders/shading-fs.glsl | 4 +- src/graphics/rendering/startup-settings.ts | 1 - src/graphics/rendering/webgl2-renderer.ts | 57 +++++++----- src/graphics/settings.ts | 2 +- src/helper/ms-to-string.ts | 1 + src/main.ts | 21 +++-- 18 files changed, 259 insertions(+), 115 deletions(-) create mode 100644 src/drawables/shapes/inverted-tunnel.ts create mode 100644 src/helper/ms-to-string.ts diff --git a/src/drawables/lights/circle-light.ts b/src/drawables/lights/circle-light.ts index b8d0ad7..b74cad9 100644 --- a/src/drawables/lights/circle-light.ts +++ b/src/drawables/lights/circle-light.ts @@ -16,8 +16,8 @@ export class CircleLight extends Drawable { super(); } - public distance(_: vec2): number { - return 0; + public distance(target: vec2): number { + return vec2.dist(this.center, target); } protected getObjectToSerialize(transform2d: mat2d, transform1d: number): any { diff --git a/src/drawables/shapes/inverted-tunnel.ts b/src/drawables/shapes/inverted-tunnel.ts new file mode 100644 index 0000000..09599c8 --- /dev/null +++ b/src/drawables/shapes/inverted-tunnel.ts @@ -0,0 +1,89 @@ +import { mat2d, vec2 } from 'gl-matrix'; +import { clamp01 } from '../../helper/clamp'; +import { mix } from '../../helper/mix'; +import { Drawable } from '../drawable'; +import { DrawableDescriptor } from '../drawable-descriptor'; + +export class InvertedTunnel extends Drawable { + public static get descriptor(): DrawableDescriptor { + return { + sdf: { + shader: ` + uniform struct InvertedTunnel { + vec2 from; + vec2 toFromDelta; + float fromRadius; + float toRadius; + }[INVERTED_TUNNEL_COUNT] invertedTunnels; + + void invertedTunnelMinDistance(inout float minDistance, inout float color) { + float myMinDistance = -minDistance; + for (int i = 0; i < INVERTED_TUNNEL_COUNT; i++) { + InvertedTunnel tunnel = invertedTunnels[i]; + vec2 targetFromDelta = position - tunnel.from; + + float h = clamp( + dot(targetFromDelta, tunnel.toFromDelta) + / dot(tunnel.toFromDelta, tunnel.toFromDelta), + 0.0, 1.0 + ); + + float currentDistance = -mix( + tunnel.fromRadius, tunnel.toRadius, h + ) + distance( + targetFromDelta, tunnel.toFromDelta * h + ); + + myMinDistance = min(myMinDistance, currentDistance); + } + + color = mix(0.0, color, step( + distanceNdcPixelSize + SURFACE_OFFSET, + -myMinDistance + )); + minDistance = -myMinDistance; + } + `, + distanceFunctionName: 'invertedTunnelMinDistance', + }, + uniformName: 'invertedTunnels', + uniformCountMacroName: 'INVERTED_TUNNEL_COUNT', + shaderCombinationSteps: [0, 1, 4, 16, 32], + empty: new InvertedTunnel(vec2.fromValues(0, 0), vec2.fromValues(0, 0), 0, 0), + }; + } + + constructor( + public readonly from: vec2, + public readonly to: vec2, + public readonly fromRadius: number, + public readonly toRadius: number + ) { + super(); + } + + public distance(target: vec2): number { + const toFromDelta = vec2.subtract(vec2.create(), this.to, this.from); + const targetFromDelta = vec2.subtract(vec2.create(), target, this.from); + + const h = clamp01( + vec2.dot(targetFromDelta, toFromDelta) / vec2.dot(toFromDelta, toFromDelta) + ); + + return ( + vec2.distance(targetFromDelta, vec2.scale(vec2.create(), toFromDelta, h)) - + mix(this.fromRadius, this.toRadius, h) + ); + } + + protected getObjectToSerialize(transform2d: mat2d, transform1d: number): any { + const toFromDelta = vec2.subtract(vec2.create(), this.to, this.from); + + return { + from: vec2.transformMat2d(vec2.create(), this.from, transform2d), + toFromDelta: vec2.scale(vec2.create(), toFromDelta, transform1d), + fromRadius: this.fromRadius * transform1d, + toRadius: this.toRadius * transform1d, + }; + } +} diff --git a/src/drawables/shapes/tunnel.ts b/src/drawables/shapes/tunnel.ts index 7beef1b..fb185d2 100644 --- a/src/drawables/shapes/tunnel.ts +++ b/src/drawables/shapes/tunnel.ts @@ -10,38 +10,38 @@ export class Tunnel extends Drawable { sdf: { shader: ` uniform struct Tunnel { - vec2 from; - vec2 toFromDelta; - float fromRadius; - float toRadius; + vec2 from; + vec2 toFromDelta; + float fromRadius; + float toRadius; }[TUNNEL_COUNT] tunnels; void tunnelMinDistance(inout float minDistance, inout float color) { - float myMinDistance = maxMinDistance; - for (int i = 0; i < TUNNEL_COUNT; i++) { - Tunnel tunnel = tunnels[i]; - vec2 targetFromDelta = position - tunnel.from; - - float h = clamp( - dot(targetFromDelta, tunnel.toFromDelta) - / dot(tunnel.toFromDelta, tunnel.toFromDelta), - 0.0, 1.0 - ); + float myMinDistance = minDistance; + for (int i = 0; i < TUNNEL_COUNT; i++) { + Tunnel tunnel = tunnels[i]; + vec2 targetFromDelta = position - tunnel.from; + + float h = clamp( + dot(targetFromDelta, tunnel.toFromDelta) + / dot(tunnel.toFromDelta, tunnel.toFromDelta), + 0.0, 1.0 + ); + + float currentDistance = -mix( + tunnel.fromRadius, tunnel.toRadius, h + ) + distance( + targetFromDelta, tunnel.toFromDelta * h + ); + + myMinDistance = min(myMinDistance, currentDistance); + } - float currentDistance = -mix( - tunnel.fromRadius, tunnel.toRadius, h - ) + distance( - targetFromDelta, tunnel.toFromDelta * h - ); - - myMinDistance = min(myMinDistance, currentDistance); - } - - color = mix(2.0, color, step( - distanceNdcPixelSize + SURFACE_OFFSET, - myMinDistance - )); - minDistance = min(minDistance, myMinDistance); + color = mix(2.0, color, step( + distanceNdcPixelSize + SURFACE_OFFSET, + myMinDistance + )); + minDistance = min(minDistance, myMinDistance); } `, distanceFunctionName: 'tunnelMinDistance', diff --git a/src/graphics/graphics-library/frame-buffer/frame-buffer.ts b/src/graphics/graphics-library/frame-buffer/frame-buffer.ts index 1ad4e78..f5af835 100644 --- a/src/graphics/graphics-library/frame-buffer/frame-buffer.ts +++ b/src/graphics/graphics-library/frame-buffer/frame-buffer.ts @@ -23,6 +23,10 @@ export abstract class FrameBuffer { this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT); } + public destroy(): void { + this.gl.deleteFramebuffer(this.frameBuffer); + } + public setSize(): boolean { const realToCssPixels = (this.enableHighDpiRendering ? window.devicePixelRatio : 1) * this.renderScale; diff --git a/src/graphics/graphics-library/frame-buffer/intermediate-frame-buffer.ts b/src/graphics/graphics-library/frame-buffer/intermediate-frame-buffer.ts index ff99787..3f67a51 100644 --- a/src/graphics/graphics-library/frame-buffer/intermediate-frame-buffer.ts +++ b/src/graphics/graphics-library/frame-buffer/intermediate-frame-buffer.ts @@ -28,6 +28,10 @@ export class IntermediateFrameBuffer extends FrameBuffer { this.setSize(); } + public destroy(): void { + this.gl.deleteTexture(this.frameTexture); + } + public get colorTexture(): WebGLTexture { return this.frameTexture; } diff --git a/src/graphics/graphics-library/parallel-compiler.ts b/src/graphics/graphics-library/parallel-compiler.ts index bbdd59e..4ad5eea 100644 --- a/src/graphics/graphics-library/parallel-compiler.ts +++ b/src/graphics/graphics-library/parallel-compiler.ts @@ -50,6 +50,7 @@ export abstract class ParallelCompiler { return promise; } + @Insights.measure('compile programs') public static async compilePrograms(): Promise { ParallelCompiler.programs.forEach((p) => ParallelCompiler.gl.linkProgram(p.program)); 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 6b78fc4..8ac38fa 100644 --- a/src/graphics/graphics-library/program/fragment-shader-only-program.ts +++ b/src/graphics/graphics-library/program/fragment-shader-only-program.ts @@ -20,10 +20,16 @@ export class FragmentShaderOnlyProgram extends Program { this.gl.bindVertexArray(this.vao!); } - public draw() { + public draw(uniforms: { [name: string]: any }) { + super.draw(uniforms); this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4); } + public destroy(): void { + this.gl.deleteVertexArray(this.vao!); + super.destroy(); + } + private prepareScreenQuad(attributeName: string) { const positionAttributeLocation = this.gl.getAttribLocation( this.program!, diff --git a/src/graphics/graphics-library/program/i-program.ts b/src/graphics/graphics-library/program/i-program.ts index 633ea3c..069ea86 100644 --- a/src/graphics/graphics-library/program/i-program.ts +++ b/src/graphics/graphics-library/program/i-program.ts @@ -2,7 +2,6 @@ import { vec2 } from 'gl-matrix'; export interface IProgram { setDrawingRectangleUV(bottomLeft: vec2, size: vec2): void; - bindAndSetUniforms(values: { [name: string]: any }): void; - draw(): void; - delete(): void; + draw(values: { [name: string]: any }): void; + destroy(): void; } diff --git a/src/graphics/graphics-library/program/program.ts b/src/graphics/graphics-library/program/program.ts index 6b5c09a..b6c6108 100644 --- a/src/graphics/graphics-library/program/program.ts +++ b/src/graphics/graphics-library/program/program.ts @@ -31,11 +31,6 @@ export default abstract class Program implements IProgram { this.queryUniforms(); } - public bindAndSetUniforms(values: { [name: string]: any }) { - this.bind(); - this.setUniforms({ modelTransform: this.modelTransform, ...values }); - } - public setDrawingRectangleUV(bottomLeft: vec2, size: vec2) { mat2d.invert(this.modelTransform, this.ndcToUv); mat2d.translate(this.modelTransform, this.modelTransform, bottomLeft); @@ -56,12 +51,14 @@ export default abstract class Program implements IProgram { }); } - public delete() { - this.gl.getAttachedShaders(this.program!)?.forEach((s) => this.gl.deleteShader(s)); + public destroy() { this.gl.deleteProgram(this.program!); } - public abstract draw(): void; + public draw(values: { [name: string]: any }): void { + this.bind(); + this.setUniforms({ modelTransform: this.modelTransform, ...values }); + } protected bind() { this.gl.useProgram(this.program!); 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 ebd6a5f..9568022 100644 --- a/src/graphics/graphics-library/program/uniform-array-autoscaling-program.ts +++ b/src/graphics/graphics-library/program/uniform-array-autoscaling-program.ts @@ -38,7 +38,12 @@ export class UniformArrayAutoScalingProgram implements IProgram { await Promise.all(promises); } - public bindAndSetUniforms(uniforms: { [name: string]: any }): void { + public setDrawingRectangleUV(bottomLeft: vec2, size: vec2) { + this.drawingRectangleBottomLeft = bottomLeft; + this.drawingRectangleSize = size; + } + + public draw(uniforms: { [name: string]: any }): void { const values = this.descriptors!.map((d) => uniforms[d.uniformName] ? uniforms[d.uniformName].length : 0 ); @@ -56,28 +61,16 @@ export class UniformArrayAutoScalingProgram implements IProgram { }); } - this.current?.setDrawingRectangleUV( + this.current!.setDrawingRectangleUV( this.drawingRectangleBottomLeft, this.drawingRectangleSize ); - this.current?.bindAndSetUniforms(uniforms); + + this.current!.draw(uniforms); } - public setDrawingRectangleUV(bottomLeft: vec2, size: vec2) { - this.drawingRectangleBottomLeft = bottomLeft; - this.drawingRectangleSize = size; - } - - public draw(): void { - if (!this.current) { - throw new Error('Method bindAndSetUniforms have not been called yet'); - } - - this.current.draw(); - } - - public delete(): void { - this.programs.forEach((p) => p.program.delete()); + public destroy(): void { + this.programs.forEach((p) => p.program.destroy()); } private async createProgram( diff --git a/src/graphics/rendering/insights.ts b/src/graphics/rendering/insights.ts index fef0814..94c0a3b 100644 --- a/src/graphics/rendering/insights.ts +++ b/src/graphics/rendering/insights.ts @@ -1,39 +1,54 @@ +import { last } from '../../helper/last'; +import { msToString } from '../../helper/ms-to-string'; + export class Insights { private static insights: any = {}; public static setValue(key: string | Array, value: any): void { if (Array.isArray(key)) { - key.reduce((previousValue, currentKey, i, a) => { + if (key.length == 0) { + throw new Error('Key length must be greater than 0'); + } + + const lastObject = key.slice(0, -1).reduce((previousValue, currentKey) => { if (!Object.prototype.hasOwnProperty.call(previousValue, currentKey)) { - previousValue[currentKey] = i == a.length - 1 ? value : {}; + previousValue[currentKey] = {}; } return previousValue[currentKey]; }, Insights.insights); + + lastObject[last(key)!] = value; } else { Insights.insights[key] = value; } } - public static measure(name: string) { + public static measure(key: string | Array) { return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) { const targetFunction = descriptor.value; descriptor.value = function (...values: Array) { - const start = performance.now(); - - const result = targetFunction.bind(this)(...values); - - const end = performance.now(); - Insights.setValue(['measurements', name], `${(end - start).toFixed(3)} ms`); - - return result; + return Insights.measureFunction(key, () => targetFunction(...values)); }; - return descriptor; }; } + public static measureFunction( + key: string | Array, + targetFunction: () => any + ): any { + const start = performance.now(); + const result = targetFunction(); + const end = performance.now(); + + const newKey = Array.isArray(key) ? ['measurements', ...key] : ['measurements', key]; + Insights.setValue(newKey, msToString(end - start)); + + return result; + } + public static get values(): any { return Insights.insights; } diff --git a/src/graphics/rendering/rendering-pass.ts b/src/graphics/rendering/rendering-pass.ts index 5f24d3d..8866825 100644 --- a/src/graphics/rendering/rendering-pass.ts +++ b/src/graphics/rendering/rendering-pass.ts @@ -3,6 +3,8 @@ import { Drawable } from '../../drawables/drawable'; import { DrawableDescriptor } from '../../drawables/drawable-descriptor'; import { FrameBuffer } from '../graphics-library/frame-buffer/frame-buffer'; import { UniformArrayAutoScalingProgram } from '../graphics-library/program/uniform-array-autoscaling-program'; +import { Insights } from './insights'; +import { RenderingPassName } from './rendering-pass-name'; export class RenderingPass { public tileMultiplier = 8; @@ -11,7 +13,11 @@ export class RenderingPass { private drawables: Array = []; private program: UniformArrayAutoScalingProgram; - constructor(gl: WebGL2RenderingContext, private frame: FrameBuffer) { + constructor( + gl: WebGL2RenderingContext, + private frame: FrameBuffer, + private name: RenderingPassName + ) { this.program = new UniformArrayAutoScalingProgram(gl); } @@ -40,6 +46,7 @@ export class RenderingPass { const stepsInNDC = 2 * stepsInUV; + let drawnDrawablesCount = 0; for (let x = -1; x < 1; x += stepsInNDC) { for (let y = -1; y < 1; y += stepsInNDC) { const uniforms = { @@ -47,10 +54,10 @@ export class RenderingPass { maxMinDistance: radiusInNDC * (this.isWorldInverted ? -1 : 1), }; - const ndcBottomLeft = vec2.fromValues(x, y); + const uvBottomLeft = vec2.fromValues(x / 2 + 0.5, y / 2 + 0.5); this.program.setDrawingRectangleUV( - [(ndcBottomLeft.x + 1) / 2, (ndcBottomLeft.y + 1) / 2], + uvBottomLeft, vec2.fromValues(stepsInUV, stepsInUV) ); @@ -58,17 +65,19 @@ export class RenderingPass { vec2.create(), vec2.add( vec2.create(), - [(ndcBottomLeft.x + 1) / 2, (ndcBottomLeft.y + 1) / 2], + uvBottomLeft, vec2.fromValues(stepsInUV / 2, stepsInUV / 2) ), uniforms.uvToWorld ); - const primitivesNearTile = this.drawables.filter( + const drawablesNearTile = this.drawables.filter( (d) => d.distance(tileCenterWorldCoordinates) < 2 * worldR ); - primitivesNearTile.forEach((p) => + drawnDrawablesCount += drawablesNearTile.length; + + drawablesNearTile.forEach((p) => p.serializeToUniforms( uniforms, uniforms.transformWorldToNDC, @@ -76,11 +85,22 @@ export class RenderingPass { ) ); - this.program.bindAndSetUniforms(uniforms); - this.program.draw(); + this.program.draw(uniforms); } } + Insights.setValue(['render pass', this.name, 'all drawables'], this.drawables.length); + Insights.setValue(['render pass', this.name, 'tile count'], this.tileMultiplier ** 2); + Insights.setValue( + ['render pass', this.name, 'rendered drawables'], + drawnDrawablesCount / this.tileMultiplier ** 2 + ); + this.drawables = []; } + + public destroy(): void { + this.frame.destroy(); + this.program.destroy(); + } } diff --git a/src/graphics/rendering/shaders/shading-fs.glsl b/src/graphics/rendering/shaders/shading-fs.glsl index e4123dd..7bc0728 100644 --- a/src/graphics/rendering/shaders/shading-fs.glsl +++ b/src/graphics/rendering/shaders/shading-fs.glsl @@ -42,7 +42,7 @@ float softShadowTransparency(float startingDistance, float lightCenterDistance, float minDistance = getDistance(uvCoordinates + direction * rayLength); q = min(q, minDistance / rayLength); - rayLength += minDistance / 2.5; + rayLength += minDistance; if (rayLength >= lightCenterDistance) { return q * SHADOW_HARDNESS; @@ -59,7 +59,7 @@ float hardShadowTransparency(float startingDistance, float lightCenterDistance, rayLength += getDistance(uvCoordinates + direction * rayLength); } - return step(lightCenterDistance, rayLength); + return min(1.0, step(lightCenterDistance, rayLength) + rayLength / (150.0 * shadingNdcPixelSize)); } float shadowTransparency(float startingDistance, float lightCenterDistance, vec2 direction) { diff --git a/src/graphics/rendering/startup-settings.ts b/src/graphics/rendering/startup-settings.ts index 2eb3be4..4fbbba8 100644 --- a/src/graphics/rendering/startup-settings.ts +++ b/src/graphics/rendering/startup-settings.ts @@ -1,5 +1,4 @@ export interface StartupSettings { - enableStopwatch: boolean; softShadowTraceCount: string; hardShadowTraceCount: string; } diff --git a/src/graphics/rendering/webgl2-renderer.ts b/src/graphics/rendering/webgl2-renderer.ts index 18e92c1..ea758be 100644 --- a/src/graphics/rendering/webgl2-renderer.ts +++ b/src/graphics/rendering/webgl2-renderer.ts @@ -1,6 +1,7 @@ import { vec2, vec3 } from 'gl-matrix'; import { Drawable } from '../../drawables/drawable'; import { DrawableDescriptor } from '../../drawables/drawable-descriptor'; +import { msToString } from '../../helper/ms-to-string'; 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'; @@ -39,7 +40,7 @@ export class WebGl2Renderer implements Renderer { }, tileMultiplier: (v) => { this.passes[RenderingPassName.distance].tileMultiplier = v; - this.passes[RenderingPassName.pixel].tileMultiplier = v; + this.passes[RenderingPassName.pixel].tileMultiplier = 1; }, isWorldInverted: (v) => { this.passes[RenderingPassName.distance].isWorldInverted = v; @@ -51,13 +52,12 @@ export class WebGl2Renderer implements Renderer { }; private static defaultStartupSettings: StartupSettings = { - enableStopwatch: true, softShadowTraceCount: '128', hardShadowTraceCount: '32', }; setRuntimeSettings(overrides: Partial): void { - Object.entries(overrides).forEach((k, v) => { + Object.entries(overrides).forEach(([k, v]) => { this.applyRuntimeSettings[(k as unknown) as string](v); }); } @@ -75,6 +75,8 @@ export class WebGl2Renderer implements Renderer { this.passes = this.createPasses(); + this.passes.pixel.tileMultiplier = 1; + this.uniformsProvider = new UniformsProvider(this.gl); this.autoscaler = new FpsAutoscaler({ @@ -86,18 +88,21 @@ export class WebGl2Renderer implements Renderer { }); } - @Insights.measure('create render passes') private createPasses(): Passes { return { [RenderingPassName.distance]: new RenderingPass( this.gl, - this.distanceFieldFrameBuffer + this.distanceFieldFrameBuffer, + RenderingPassName.distance + ), + [RenderingPassName.pixel]: new RenderingPass( + this.gl, + this.lightingFrameBuffer, + RenderingPassName.pixel ), - [RenderingPassName.pixel]: new RenderingPass(this.gl, this.lightingFrameBuffer), }; } - @Insights.measure('initialize render passes') public async initialize( palette: Array, settingsOverrides: Partial @@ -129,12 +134,10 @@ export class WebGl2Renderer implements Renderer { await Promise.all(promises); - if (settings.enableStopwatch) { - try { - this.stopwatch = new WebGlStopwatch(this.gl); - } catch { - // no problem - } + try { + this.stopwatch = new WebGlStopwatch(this.gl); + } catch { + // no problem } } @@ -142,13 +145,6 @@ export class WebGl2Renderer implements Renderer { return Insights.values; } - public destroy(): void { - // todo - /*const extension = enableExtension(this.gl, 'WEBGL_lose_context'); - extension.loseContext(); - extension.restoreContext();*/ - } - private static hasSdf(descriptor: DrawableDescriptor) { return Object.prototype.hasOwnProperty.call(descriptor, 'sdf'); } @@ -178,7 +174,17 @@ export class WebGl2Renderer implements Renderer { } public renderDrawables() { - this.stopwatch?.start(); + if (this.stopwatch) { + if (this.stopwatch.isReady) { + this.stopwatch.start(); + } else { + this.stopwatch.tryGetResults(); + Insights.setValue( + 'GPU render time', + msToString(this.stopwatch.resultsInMilliSeconds) + ); + } + } this.distanceFieldFrameBuffer.setSize(); this.lightingFrameBuffer.setSize(); @@ -196,7 +202,9 @@ export class WebGl2Renderer implements Renderer { this.distanceFieldFrameBuffer.colorTexture ); - this.stopwatch?.stop(); + if (this.stopwatch?.isRunning) { + this.stopwatch?.stop(); + } } public setViewArea(topLeft: vec2, size: vec2) { @@ -210,4 +218,9 @@ export class WebGl2Renderer implements Renderer { public get canvasSize(): vec2 { return vec2.fromValues(this.canvas.clientWidth, this.canvas.clientHeight); } + + public destroy(): void { + this.passes.distance.destroy(); + this.passes.pixel.destroy(); + } } diff --git a/src/graphics/settings.ts b/src/graphics/settings.ts index e9369d4..23abdc6 100644 --- a/src/graphics/settings.ts +++ b/src/graphics/settings.ts @@ -23,7 +23,7 @@ export const settings = { { distanceRenderScale: 0.3, finalRenderScale: 1.0, - softShadowsEnabled: true, + softShadowsEnabled: false, }, /*{ distanceRenderScale: 1.0, diff --git a/src/helper/ms-to-string.ts b/src/helper/ms-to-string.ts new file mode 100644 index 0000000..83ae4cd --- /dev/null +++ b/src/helper/ms-to-string.ts @@ -0,0 +1 @@ +export const msToString = (value: number) => `${value.toFixed(3)} ms`; diff --git a/src/main.ts b/src/main.ts index 9c463d8..a1e1955 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,15 +1,16 @@ import { vec3 } from 'gl-matrix'; import { DrawableDescriptor } from './drawables/drawable-descriptor'; +import { Insights } from './graphics/rendering/insights'; import { Renderer } from './graphics/rendering/renderer'; import { StartupSettings } from './graphics/rendering/startup-settings'; import { WebGl2Renderer } from './graphics/rendering/webgl2-renderer'; import { applyArrayPlugins } from './helper/array'; - export { Drawable } from './drawables/drawable'; export { DrawableDescriptor } from './drawables/drawable-descriptor'; export { CircleLight } from './drawables/lights/circle-light'; export { Flashlight } from './drawables/lights/flashlight'; export { Circle } from './drawables/shapes/circle'; +export { InvertedTunnel } from './drawables/shapes/inverted-tunnel'; export { Tunnel } from './drawables/shapes/tunnel'; export { Renderer } from './graphics/rendering/renderer'; export { RenderingPassName } from './graphics/rendering/rendering-pass-name'; @@ -26,15 +27,17 @@ declare global { } } -export const compile = async ( +applyArrayPlugins(); + +export async function compile( canvas: HTMLCanvasElement, descriptors: Array, palette: Array, settings: Partial = {} -): Promise => { - applyArrayPlugins(); - - const renderer = new WebGl2Renderer(canvas, descriptors); - await renderer.initialize(palette, settings); - return renderer; -}; +): Promise { + return Insights.measureFunction('startup', async () => { + const renderer = new WebGl2Renderer(canvas, descriptors); + await renderer.initialize(palette, settings); + return renderer; + }); +}