diff --git a/src/graphics/graphics-library/texture/distance-texture.ts b/src/graphics/graphics-library/texture/distance-texture.ts index 81fa51e..c68d527 100644 --- a/src/graphics/graphics-library/texture/distance-texture.ts +++ b/src/graphics/graphics-library/texture/distance-texture.ts @@ -18,8 +18,8 @@ export class DistanceTexture extends Texture { const bufferFloatExtension = tryEnableExtension(gl, 'EXT_color_buffer_float'); const floatLinearExtension = tryEnableExtension(gl, 'OES_texture_float_linear'); - this.floatLinearEnabled = !!bufferFloatExtension && !!floatLinearExtension; + this.floatLinearEnabled = !!bufferFloatExtension && !!floatLinearExtension; gl.insights.floatInterpolationEnabled = this.floatLinearEnabled; } diff --git a/src/graphics/graphics-library/universal-rendering-context.ts b/src/graphics/graphics-library/universal-rendering-context.ts index 6726652..ad9916c 100644 --- a/src/graphics/graphics-library/universal-rendering-context.ts +++ b/src/graphics/graphics-library/universal-rendering-context.ts @@ -11,9 +11,18 @@ export const getUniversalRenderingContext = ( canvas: HTMLCanvasElement, ignoreWebGL2 = false ): UniversalRenderingContext => { + const contextAttributes: WebGLContextAttributes = { + alpha: true, + antialias: false, + depth: false, + desynchronized: true, + preserveDrawingBuffer: true, + powerPreference: 'high-performance', + }; + const context: WebGL2RenderingContext | WebGLRenderingContext | null = ignoreWebGL2 ? null - : canvas.getContext('webgl2'); + : canvas.getContext('webgl2', contextAttributes); let result = context as UniversalRenderingContext; @@ -23,10 +32,13 @@ export const getUniversalRenderingContext = ( } } else { result = (canvas.getContext('webgl') || - canvas.getContext('experimental-webgl')) as UniversalRenderingContext; + canvas.getContext('experimental-webgl', { + ...contextAttributes, + alpha: false, + })) as UniversalRenderingContext; if (!result) { - throw new Error('Neither WebGL or WebGL2 is supported'); + throw new Error('Neither WebGL nor WebGL2 is supported'); } result.isWebGL2 = false; diff --git a/src/graphics/rendering/renderer/renderer-implementation.ts b/src/graphics/rendering/renderer/renderer-implementation.ts index 580b6b8..db662a1 100644 --- a/src/graphics/rendering/renderer/renderer-implementation.ts +++ b/src/graphics/rendering/renderer/renderer-implementation.ts @@ -47,7 +47,8 @@ export class RendererImplementation implements Renderer { private stopwatch?: WebGlStopwatch; private textures: Array = []; private palette!: PaletteTexture; - private _canvasSize = vec2.fromValues(1, 1); + private _canvasSize: vec2; + private blendFactor!: number; private canvasResizeObserver!: ResizeObserver; private applyRuntimeSettings: { @@ -63,6 +64,7 @@ export class RendererImplementation implements Renderer { this.distanceFieldFrameBuffer.renderScale = v; this.gl.insights.renderPasses.distance.renderScale = v; }, + motionBlur: (v) => (this.blendFactor = 1 - v), lightsRenderScale: (v) => { this.lightingFrameBuffer.renderScale = v; this.gl.insights.renderPasses.lights.renderScale = v; @@ -89,7 +91,10 @@ export class RendererImplementation implements Renderer { ignoreWebGL2 !== undefined ? ignoreWebGL2 : defaultStartupSettings.ignoreWebGL2 ); - this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE); + this.gl.blendFunc(this.gl.CONSTANT_COLOR, this.gl.ONE_MINUS_CONSTANT_COLOR); + + const { width, height } = canvas.getBoundingClientRect(); + this._canvasSize = vec2.fromValues(width, height); this.applyCanvasResizeObserver(); @@ -144,6 +149,7 @@ export class RendererImplementation implements Renderer { compiler, { paletteSize: settings.paletteSize, + floatLinearEnabled: this.gl.insights.floatInterpolationEnabled ? '1' : '0', backgroundColor: colorToString(settings.backgroundColor), } ) @@ -158,6 +164,7 @@ export class RendererImplementation implements Renderer { { shadowTraceCount: settings.shadowTraceCount.toString(), intensityInsideRatio: settings.lightPenetrationRatio, + floatLinearEnabled: this.gl.insights.floatInterpolationEnabled ? '1' : '0', backgroundColor: colorToString(settings.backgroundColor), } ) @@ -225,7 +232,7 @@ export class RendererImplementation implements Renderer { } this.distanceFieldFrameBuffer.setSize(this.canvasSize); - this.lightingFrameBuffer.setSize(this.canvasSize); + const sizeChanged = this.lightingFrameBuffer.setSize(this.canvasSize); const common = { // texture units @@ -243,6 +250,8 @@ export class RendererImplementation implements Renderer { ]); this.gl.enable(this.gl.BLEND); + const q = sizeChanged ? 1 : this.blendFactor; + this.gl.blendColor(q, q, q, 1); this.lightsPass.render( this.uniformsProvider.getUniforms(common), this.distanceFieldFrameBuffer.textures diff --git a/src/graphics/rendering/settings/default-runtime-settings.ts b/src/graphics/rendering/settings/default-runtime-settings.ts index 025ed71..73f486f 100644 --- a/src/graphics/rendering/settings/default-runtime-settings.ts +++ b/src/graphics/rendering/settings/default-runtime-settings.ts @@ -12,6 +12,7 @@ export const defaultRuntimeSettings: RuntimeSettings = { distanceRenderScale: 0.5, lightsRenderScale: 1, colorPalette: [], + motionBlur: 0.3, ambientLight: vec3.fromValues(0.25, 0.15, 0.25), textures: {}, }; diff --git a/src/graphics/rendering/settings/runtime-settings.ts b/src/graphics/rendering/settings/runtime-settings.ts index 8dc3eb2..14212fd 100644 --- a/src/graphics/rendering/settings/runtime-settings.ts +++ b/src/graphics/rendering/settings/runtime-settings.ts @@ -65,6 +65,14 @@ export interface RuntimeSettings { */ lightsRenderScale: number; + /** + * Set the extent of the motion blur. + * + * The values must be between 0 and 1. Where 0 means no motion blur, + * and values just below 1 mean an extreme amount of motion blur. + */ + motionBlur: number; + /** * It is possible to use your own textures in your SDF definitions. * diff --git a/src/graphics/rendering/shaders/distance-fs.glsl b/src/graphics/rendering/shaders/distance-fs.glsl index 1b0ad90..5f56e11 100644 --- a/src/graphics/rendering/shaders/distance-fs.glsl +++ b/src/graphics/rendering/shaders/distance-fs.glsl @@ -2,6 +2,8 @@ precision lowp float; +#define FLOAT_LINEAR_ENABLED {floatLinearEnabled} + uniform float maxMinDistance; uniform float distanceNdcPixelSize; in vec2 position; @@ -28,6 +30,11 @@ void main() { {functionCalls} - distanceValue = minDistance; + #if FLOAT_LINEAR_ENABLED + distanceValue = minDistance; + #else + distanceValue = minDistance * 8.0; + #endif + fragmentColor = color; } diff --git a/src/graphics/rendering/shaders/shading-fs.glsl b/src/graphics/rendering/shaders/shading-fs.glsl index 27d5439..71077ee 100644 --- a/src/graphics/rendering/shaders/shading-fs.glsl +++ b/src/graphics/rendering/shaders/shading-fs.glsl @@ -4,6 +4,7 @@ precision lowp float; #define INTENSITY_INSIDE_RATIO {intensityInsideRatio} #define SHADOW_TRACE_COUNT {shadowTraceCount} +#define FLOAT_LINEAR_ENABLED {floatLinearEnabled} {macroDefinitions} @@ -23,7 +24,11 @@ vec4 getColor(vec2 target) { } float getDistance(vec2 target) { + #if FLOAT_LINEAR_ENABLED return texture(distanceTexture, target)[0]; + #else + return texture(distanceTexture, target)[0] / 8.0; + #endif } float shadowTransparency(float startingDistance, float lightCenterDistance, vec2 direction) {