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 floatLinearExtension = tryEnableExtension(gl, 'OES_texture_float_linear');
this.floatLinearEnabled = !!bufferFloatExtension && !!floatLinearExtension;
this.floatLinearEnabled = !!bufferFloatExtension && !!floatLinearExtension;
gl.insights.floatInterpolationEnabled = this.floatLinearEnabled;
}

View file

@ -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;

View file

@ -47,7 +47,8 @@ export class RendererImplementation implements Renderer {
private stopwatch?: WebGlStopwatch;
private textures: Array<Texture> = [];
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

View file

@ -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: {},
};

View file

@ -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.
*

View file

@ -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}
#if FLOAT_LINEAR_ENABLED
distanceValue = minDistance;
#else
distanceValue = minDistance * 8.0;
#endif
fragmentColor = color;
}

View file

@ -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) {