From 389d5b0f606e1e9e75cb68abfba52f21cb97d915 Mon Sep 17 00:00:00 2001 From: Martin Valigursky Date: Thu, 30 Nov 2023 12:05:16 +0000 Subject: [PATCH] Fringing / Chromatic Aberration added to render pass compose --- .../src/examples/graphics/post-processing.mjs | 30 ++++++++++++ extras/render-passes/render-pass-compose.js | 47 ++++++++++++++++++- 2 files changed, 75 insertions(+), 2 deletions(-) diff --git a/examples/src/examples/graphics/post-processing.mjs b/examples/src/examples/graphics/post-processing.mjs index e5a55394eac..252f05f6563 100644 --- a/examples/src/examples/graphics/post-processing.mjs +++ b/examples/src/examples/graphics/post-processing.mjs @@ -157,6 +157,24 @@ function controls({ observer, ReactPCUI, React, jsx, fragment }) { precision: 2 }) ) + ), + jsx(Panel, { headerText: 'Fringing' }, + jsx(LabelGroup, { text: 'enabled' }, + jsx(BooleanInput, { + type: 'toggle', + binding: new BindingTwoWay(), + link: { observer, path: 'data.fringing.enabled' } + }) + ), + jsx(LabelGroup, { text: 'intensity' }, + jsx(SliderInput, { + binding: new BindingTwoWay(), + link: { observer, path: 'data.fringing.intensity' }, + min: 0, + max: 100, + precision: 0 + }) + ) ) ); } @@ -520,6 +538,14 @@ async function example({ canvas, deviceType, assetPath, glslangPath, twgslPath, composePass.vignetteIntensity = value; } } + if (pathArray[1] === 'fringing') { + if (pathArray[2] === 'enabled') { + composePass.fringingEnabled = value; + } + if (pathArray[2] === 'intensity') { + composePass.fringingIntensity = value; + } + } }); data.set('data', { @@ -546,6 +572,10 @@ async function example({ canvas, deviceType, assetPath, glslangPath, twgslPath, outer: 1.0, curvature: 0.5, intensity: 0.3 + }, + fringing: { + enabled: false, + intensity: 50 } }); diff --git a/extras/render-passes/render-pass-compose.js b/extras/render-passes/render-pass-compose.js index ce2cf3f937d..49695ee80a2 100644 --- a/extras/render-passes/render-pass-compose.js +++ b/extras/render-passes/render-pass-compose.js @@ -51,10 +51,31 @@ const fragmentShader = ` #endif + #ifdef FRINGING + + uniform float fringingIntensity; + + vec3 fringing(vec2 uv, vec3 color) { + + // offset depends on the direction from the center, raised to power to make it stronger away from the center + vec2 centerDistance = uv0 - 0.5; + vec2 offset = fringingIntensity * pow(centerDistance, vec2(2.0, 2.0)); + + color.r = texture2D(sceneTexture, uv0 - offset).r; + color.b = texture2D(sceneTexture, uv0 + offset).b; + return color; + } + + #endif + void main() { vec4 scene = texture2D(sceneTexture, uv0); vec3 result = scene.rgb; + #ifdef FRINGING + result = fringing(uv0, result); + #endif + #ifdef BLOOM vec3 bloom = texture2D(bloomTexture, uv0).rgb; result += bloom * bloomIntensity; @@ -105,6 +126,10 @@ class RenderPassCompose extends RenderPassShaderQuad { vignetteIntensity = 0.3; + _fringingEnabled = false; + + fringingIntensity = 10; + _key = ''; constructor(graphicsDevice) { @@ -115,6 +140,7 @@ class RenderPassCompose extends RenderPassShaderQuad { this.bloomIntensityId = graphicsDevice.scope.resolve('bloomIntensity'); this.bcsId = graphicsDevice.scope.resolve('brightnessContrastSaturation'); this.vignetterParamsId = graphicsDevice.scope.resolve('vignetterParams'); + this.fringingIntensityId = graphicsDevice.scope.resolve('fringingIntensity'); } set bloomTexture(value) { @@ -150,6 +176,17 @@ class RenderPassCompose extends RenderPassShaderQuad { return this._vignetteEnabled; } + set fringingEnabled(value) { + if (this._fringingEnabled !== value) { + this._fringingEnabled = value; + this._shaderDirty = true; + } + } + + get fringingEnabled() { + return this._fringingEnabled; + } + set toneMapping(value) { if (this._toneMapping !== value) { this._toneMapping = value; @@ -187,7 +224,8 @@ class RenderPassCompose extends RenderPassShaderQuad { const key = `${this.toneMapping}` + `-${this.bloomTexture ? 'bloom' : 'nobloom'}` + `-${this.gradingEnabled ? 'grading' : 'nograding'}` + - `-${this.vignetteEnabled ? 'vignette' : 'novignette'}`; + `-${this.vignetteEnabled ? 'vignette' : 'novignette'}` + + `-${this.fringingEnabled ? 'fringing' : 'nofringing'}`; if (this._key !== key) { this._key = key; @@ -195,7 +233,8 @@ class RenderPassCompose extends RenderPassShaderQuad { const defines = (this.bloomTexture ? `#define BLOOM\n` : '') + (this.gradingEnabled ? `#define GRADING\n` : '') + - (this.vignetteEnabled ? `#define VIGNETTE\n` : ''); + (this.vignetteEnabled ? `#define VIGNETTE\n` : '') + + (this.fringingEnabled ? `#define FRINGING\n` : ''); const fsChunks = shaderChunks.decodePS + @@ -224,6 +263,10 @@ class RenderPassCompose extends RenderPassShaderQuad { this.vignetterParamsId.setValue([this.vignetteInner, this.vignetteOuter, this.vignetteCurvature, this.vignetteIntensity]); } + if (this._fringingEnabled) { + this.fringingIntensityId.setValue(this.fringingIntensity / this.sceneTexture.height); + } + super.execute(); } }