Add motion blur and better interpolation when OES_texture_float_linear is not available

This commit is contained in:
schmelczerandras 2020-10-31 11:15:45 +01:00
parent 2889fd54db
commit 7803bbeaee
7 changed files with 50 additions and 8 deletions

View file

@ -18,8 +18,8 @@ export class DistanceTexture extends Texture {
const bufferFloatExtension = tryEnableExtension(gl, 'EXT_color_buffer_float'); const bufferFloatExtension = tryEnableExtension(gl, 'EXT_color_buffer_float');
const floatLinearExtension = tryEnableExtension(gl, 'OES_texture_float_linear'); const floatLinearExtension = tryEnableExtension(gl, 'OES_texture_float_linear');
this.floatLinearEnabled = !!bufferFloatExtension && !!floatLinearExtension;
this.floatLinearEnabled = !!bufferFloatExtension && !!floatLinearExtension;
gl.insights.floatInterpolationEnabled = this.floatLinearEnabled; gl.insights.floatInterpolationEnabled = this.floatLinearEnabled;
} }

View file

@ -11,9 +11,18 @@ export const getUniversalRenderingContext = (
canvas: HTMLCanvasElement, canvas: HTMLCanvasElement,
ignoreWebGL2 = false ignoreWebGL2 = false
): UniversalRenderingContext => { ): UniversalRenderingContext => {
const contextAttributes: WebGLContextAttributes = {
alpha: true,
antialias: false,
depth: false,
desynchronized: true,
preserveDrawingBuffer: true,
powerPreference: 'high-performance',
};
const context: WebGL2RenderingContext | WebGLRenderingContext | null = ignoreWebGL2 const context: WebGL2RenderingContext | WebGLRenderingContext | null = ignoreWebGL2
? null ? null
: canvas.getContext('webgl2'); : canvas.getContext('webgl2', contextAttributes);
let result = context as UniversalRenderingContext; let result = context as UniversalRenderingContext;
@ -23,10 +32,13 @@ export const getUniversalRenderingContext = (
} }
} else { } else {
result = (canvas.getContext('webgl') || result = (canvas.getContext('webgl') ||
canvas.getContext('experimental-webgl')) as UniversalRenderingContext; canvas.getContext('experimental-webgl', {
...contextAttributes,
alpha: false,
})) as UniversalRenderingContext;
if (!result) { if (!result) {
throw new Error('Neither WebGL or WebGL2 is supported'); throw new Error('Neither WebGL nor WebGL2 is supported');
} }
result.isWebGL2 = false; result.isWebGL2 = false;

View file

@ -47,7 +47,8 @@ export class RendererImplementation implements Renderer {
private stopwatch?: WebGlStopwatch; private stopwatch?: WebGlStopwatch;
private textures: Array<Texture> = []; private textures: Array<Texture> = [];
private palette!: PaletteTexture; private palette!: PaletteTexture;
private _canvasSize = vec2.fromValues(1, 1); private _canvasSize: vec2;
private blendFactor!: number;
private canvasResizeObserver!: ResizeObserver; private canvasResizeObserver!: ResizeObserver;
private applyRuntimeSettings: { private applyRuntimeSettings: {
@ -63,6 +64,7 @@ export class RendererImplementation implements Renderer {
this.distanceFieldFrameBuffer.renderScale = v; this.distanceFieldFrameBuffer.renderScale = v;
this.gl.insights.renderPasses.distance.renderScale = v; this.gl.insights.renderPasses.distance.renderScale = v;
}, },
motionBlur: (v) => (this.blendFactor = 1 - v),
lightsRenderScale: (v) => { lightsRenderScale: (v) => {
this.lightingFrameBuffer.renderScale = v; this.lightingFrameBuffer.renderScale = v;
this.gl.insights.renderPasses.lights.renderScale = v; this.gl.insights.renderPasses.lights.renderScale = v;
@ -89,7 +91,10 @@ export class RendererImplementation implements Renderer {
ignoreWebGL2 !== undefined ? ignoreWebGL2 : defaultStartupSettings.ignoreWebGL2 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(); this.applyCanvasResizeObserver();
@ -144,6 +149,7 @@ export class RendererImplementation implements Renderer {
compiler, compiler,
{ {
paletteSize: settings.paletteSize, paletteSize: settings.paletteSize,
floatLinearEnabled: this.gl.insights.floatInterpolationEnabled ? '1' : '0',
backgroundColor: colorToString(settings.backgroundColor), backgroundColor: colorToString(settings.backgroundColor),
} }
) )
@ -158,6 +164,7 @@ export class RendererImplementation implements Renderer {
{ {
shadowTraceCount: settings.shadowTraceCount.toString(), shadowTraceCount: settings.shadowTraceCount.toString(),
intensityInsideRatio: settings.lightPenetrationRatio, intensityInsideRatio: settings.lightPenetrationRatio,
floatLinearEnabled: this.gl.insights.floatInterpolationEnabled ? '1' : '0',
backgroundColor: colorToString(settings.backgroundColor), backgroundColor: colorToString(settings.backgroundColor),
} }
) )
@ -225,7 +232,7 @@ export class RendererImplementation implements Renderer {
} }
this.distanceFieldFrameBuffer.setSize(this.canvasSize); this.distanceFieldFrameBuffer.setSize(this.canvasSize);
this.lightingFrameBuffer.setSize(this.canvasSize); const sizeChanged = this.lightingFrameBuffer.setSize(this.canvasSize);
const common = { const common = {
// texture units // texture units
@ -243,6 +250,8 @@ export class RendererImplementation implements Renderer {
]); ]);
this.gl.enable(this.gl.BLEND); this.gl.enable(this.gl.BLEND);
const q = sizeChanged ? 1 : this.blendFactor;
this.gl.blendColor(q, q, q, 1);
this.lightsPass.render( this.lightsPass.render(
this.uniformsProvider.getUniforms(common), this.uniformsProvider.getUniforms(common),
this.distanceFieldFrameBuffer.textures this.distanceFieldFrameBuffer.textures

View file

@ -12,6 +12,7 @@ export const defaultRuntimeSettings: RuntimeSettings = {
distanceRenderScale: 0.5, distanceRenderScale: 0.5,
lightsRenderScale: 1, lightsRenderScale: 1,
colorPalette: [], colorPalette: [],
motionBlur: 0.3,
ambientLight: vec3.fromValues(0.25, 0.15, 0.25), ambientLight: vec3.fromValues(0.25, 0.15, 0.25),
textures: {}, textures: {},
}; };

View file

@ -65,6 +65,14 @@ export interface RuntimeSettings {
*/ */
lightsRenderScale: number; 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. * It is possible to use your own textures in your SDF definitions.
* *

View file

@ -2,6 +2,8 @@
precision lowp float; precision lowp float;
#define FLOAT_LINEAR_ENABLED {floatLinearEnabled}
uniform float maxMinDistance; uniform float maxMinDistance;
uniform float distanceNdcPixelSize; uniform float distanceNdcPixelSize;
in vec2 position; in vec2 position;
@ -28,6 +30,11 @@ void main() {
{functionCalls} {functionCalls}
#if FLOAT_LINEAR_ENABLED
distanceValue = minDistance; distanceValue = minDistance;
#else
distanceValue = minDistance * 8.0;
#endif
fragmentColor = color; fragmentColor = color;
} }

View file

@ -4,6 +4,7 @@ precision lowp float;
#define INTENSITY_INSIDE_RATIO {intensityInsideRatio} #define INTENSITY_INSIDE_RATIO {intensityInsideRatio}
#define SHADOW_TRACE_COUNT {shadowTraceCount} #define SHADOW_TRACE_COUNT {shadowTraceCount}
#define FLOAT_LINEAR_ENABLED {floatLinearEnabled}
{macroDefinitions} {macroDefinitions}
@ -23,7 +24,11 @@ vec4 getColor(vec2 target) {
} }
float getDistance(vec2 target) { float getDistance(vec2 target) {
#if FLOAT_LINEAR_ENABLED
return texture(distanceTexture, target)[0]; return texture(distanceTexture, target)[0];
#else
return texture(distanceTexture, target)[0] / 8.0;
#endif
} }
float shadowTransparency(float startingDistance, float lightCenterDistance, vec2 direction) { float shadowTransparency(float startingDistance, float lightCenterDistance, vec2 direction) {