From 4019fa1498156e0fbfb82fc03aa32f845379282f Mon Sep 17 00:00:00 2001 From: Martin Valigursky Date: Thu, 5 Dec 2024 10:31:53 +0000 Subject: [PATCH 1/2] Updated the way shaders include tonemapping chunks --- .../render-passes/render-pass-compose.js | 44 ++++++++++--------- src/scene/constants.js | 11 +++++ src/scene/gsplat/gsplat-material.js | 12 +---- src/scene/shader-lib/chunks/chunks.js | 16 ++++--- .../common/frag/tonemapping/tonemapping.js | 17 +++++++ .../frag/{ => tonemapping}/tonemappingAces.js | 0 .../{ => tonemapping}/tonemappingAces2.js | 0 .../{ => tonemapping}/tonemappingFilmic.js | 0 .../frag/{ => tonemapping}/tonemappingHejl.js | 0 .../{ => tonemapping}/tonemappingLinear.js | 0 .../{ => tonemapping}/tonemappingNeutral.js | 0 .../frag/{ => tonemapping}/tonemappingNone.js | 0 .../shader-lib/chunks/gsplat/gsplatOutput.js | 14 +----- .../shader-lib/chunks/skybox/frag/skybox.js | 2 +- src/scene/shader-lib/programs/particle.js | 15 +++++-- .../programs/shader-generator-shader.js | 15 ++++--- src/scene/shader-lib/programs/skybox.js | 9 ++-- 17 files changed, 91 insertions(+), 64 deletions(-) create mode 100644 src/scene/shader-lib/chunks/common/frag/tonemapping/tonemapping.js rename src/scene/shader-lib/chunks/common/frag/{ => tonemapping}/tonemappingAces.js (100%) rename src/scene/shader-lib/chunks/common/frag/{ => tonemapping}/tonemappingAces2.js (100%) rename src/scene/shader-lib/chunks/common/frag/{ => tonemapping}/tonemappingFilmic.js (100%) rename src/scene/shader-lib/chunks/common/frag/{ => tonemapping}/tonemappingHejl.js (100%) rename src/scene/shader-lib/chunks/common/frag/{ => tonemapping}/tonemappingLinear.js (100%) rename src/scene/shader-lib/chunks/common/frag/{ => tonemapping}/tonemappingNeutral.js (100%) rename src/scene/shader-lib/chunks/common/frag/{ => tonemapping}/tonemappingNone.js (100%) diff --git a/src/extras/render-passes/render-pass-compose.js b/src/extras/render-passes/render-pass-compose.js index b2619a7b599..2f466b1d00e 100644 --- a/src/extras/render-passes/render-pass-compose.js +++ b/src/extras/render-passes/render-pass-compose.js @@ -2,9 +2,7 @@ import { math } from '../../core/math/math.js'; import { Color } from '../../core/math/color.js'; import { RenderPassShaderQuad } from '../../scene/graphics/render-pass-shader-quad.js'; import { shaderChunks } from '../../scene/shader-lib/chunks/chunks.js'; -import { TONEMAP_LINEAR } from '../../scene/constants.js'; -import { ShaderGenerator } from '../../scene/shader-lib/programs/shader-generator.js'; - +import { TONEMAP_LINEAR, tonemapNames } from '../../scene/constants.js'; // Contrast Adaptive Sharpening (CAS) is used to apply the sharpening. It's based on AMD's // FidelityFX CAS, WebGL implementation: https://www.shadertoy.com/view/wtlSWB. It's best to run it @@ -13,6 +11,11 @@ import { ShaderGenerator } from '../../scene/shader-lib/programs/shader-generato // before the tone-mapping. const fragmentShader = /* glsl */ ` + + #include "tonemappingPS" + #include "decodePS" + #include "gamma2_2PS" + varying vec2 uv0; uniform sampler2D sceneTexture; uniform vec2 sceneTextureInvRes; @@ -422,23 +425,24 @@ class RenderPassCompose extends RenderPassShaderQuad { if (this._key !== key) { this._key = key; - const defines = - (this.bloomTexture ? '#define BLOOM\n' : '') + - (this.ssaoTexture ? '#define SSAO\n' : '') + - (this.gradingEnabled ? '#define GRADING\n' : '') + - (this.vignetteEnabled ? '#define VIGNETTE\n' : '') + - (this.fringingEnabled ? '#define FRINGING\n' : '') + - (this.taaEnabled ? '#define TAA\n' : '') + - (this.isSharpnessEnabled ? '#define CAS\n' : '') + - (this._srgb ? '' : '#define GAMMA_CORRECT_OUTPUT\n') + - (this._debug ? `#define DEBUG_COMPOSE ${this._debug}\n` : ''); - - const fsChunks = - shaderChunks.decodePS + - shaderChunks.gamma2_2PS + - ShaderGenerator.tonemapCode(this.toneMapping); - - this.shader = this.createQuadShader(`ComposeShader-${key}`, defines + fsChunks + fragmentShader); + const defines = new Map(); + defines.set('TONEMAP', tonemapNames[this.toneMapping]); + if (this.bloomTexture) defines.set('BLOOM', true); + if (this.ssaoTexture) defines.set('SSAO', true); + if (this.gradingEnabled) defines.set('GRADING', true); + if (this.vignetteEnabled) defines.set('VIGNETTE', true); + if (this.fringingEnabled) defines.set('FRINGING', true); + if (this.taaEnabled) defines.set('TAA', true); + if (this.isSharpnessEnabled) defines.set('CAS', true); + if (!this._srgb) defines.set('GAMMA_CORRECT_OUTPUT', true); + if (this._debug) defines.set('DEBUG_COMPOSE', this._debug); + + const includes = new Map(Object.entries(shaderChunks)); + + this.shader = this.createQuadShader(`ComposeShader-${key}`, /*defines + */fragmentShader, { + fragmentIncludes: includes, + fragmentDefines: defines + }); } } } diff --git a/src/scene/constants.js b/src/scene/constants.js index bf67f5a7cdd..7665799f7d7 100644 --- a/src/scene/constants.js +++ b/src/scene/constants.js @@ -660,6 +660,17 @@ export const TONEMAP_NEUTRAL = 5; */ export const TONEMAP_NONE = 6; +// names of the tonemaps +export const tonemapNames = [ + 'LINEAR', + 'FILMIC', + 'HEJL', + 'ACES', + 'ACES2', + 'NEUTRAL', + 'NONE' +]; + /** * No specular occlusion. * diff --git a/src/scene/gsplat/gsplat-material.js b/src/scene/gsplat/gsplat-material.js index 08514b4c040..c2c60a70191 100644 --- a/src/scene/gsplat/gsplat-material.js +++ b/src/scene/gsplat/gsplat-material.js @@ -1,6 +1,6 @@ import { CULLFACE_NONE, SEMANTIC_ATTR13, SEMANTIC_POSITION } from '../../platform/graphics/constants.js'; import { ShaderProcessorOptions } from '../../platform/graphics/shader-processor-options.js'; -import { BLEND_NONE, BLEND_NORMAL, DITHER_NONE, GAMMA_NONE, GAMMA_SRGB, TONEMAP_ACES, TONEMAP_ACES2, TONEMAP_FILMIC, TONEMAP_HEJL, TONEMAP_LINEAR, TONEMAP_NEUTRAL, TONEMAP_NONE } from '../constants.js'; +import { BLEND_NONE, BLEND_NORMAL, DITHER_NONE, GAMMA_NONE, GAMMA_SRGB, TONEMAP_ACES, TONEMAP_ACES2, TONEMAP_FILMIC, TONEMAP_HEJL, TONEMAP_LINEAR, TONEMAP_NEUTRAL, TONEMAP_NONE, tonemapNames } from '../constants.js'; import { ShaderMaterial } from '../materials/shader-material.js'; import { getProgramLibrary } from '../shader-lib/get-program-library.js'; import { getMaterialShaderDefines } from '../shader-lib/utils.js'; @@ -10,16 +10,6 @@ import { ShaderGenerator } from '../shader-lib/programs/shader-generator.js'; import { ShaderPass } from '../shader-pass.js'; import { hashCode } from '../../core/hash.js'; -const tonemapNames = { - [TONEMAP_FILMIC]: 'FILMIC', - [TONEMAP_LINEAR]: 'LINEAR', - [TONEMAP_HEJL]: 'HEJL', - [TONEMAP_ACES]: 'ACES', - [TONEMAP_ACES2]: 'ACES2', - [TONEMAP_NEUTRAL]: 'NEUTRAL', - [TONEMAP_NONE]: 'NONE' -}; - const gammaNames = { [GAMMA_NONE]: 'NONE', [GAMMA_SRGB]: 'SRGB' diff --git a/src/scene/shader-lib/chunks/chunks.js b/src/scene/shader-lib/chunks/chunks.js index 7c2ca899c5d..e72977780ac 100644 --- a/src/scene/shader-lib/chunks/chunks.js +++ b/src/scene/shader-lib/chunks/chunks.js @@ -181,13 +181,14 @@ import TBNPS from './lit/frag/TBN.js'; import TBNderivativePS from './lit/frag/TBNderivative.js'; import TBNObjectSpacePS from './lit/frag/TBNObjectSpace.js'; import thicknessPS from './standard/frag/thickness.js'; -import tonemappingAcesPS from './common/frag/tonemappingAces.js'; -import tonemappingAces2PS from './common/frag/tonemappingAces2.js'; -import tonemappingFilmicPS from './common/frag/tonemappingFilmic.js'; -import tonemappingHejlPS from './common/frag/tonemappingHejl.js'; -import tonemappingLinearPS from './common/frag/tonemappingLinear.js'; -import tonemappingNeutralPS from './common/frag/tonemappingNeutral.js'; -import tonemappingNonePS from './common/frag/tonemappingNone.js'; +import tonemappingPS from './common/frag/tonemapping/tonemapping.js'; +import tonemappingAcesPS from './common/frag/tonemapping/tonemappingAces.js'; +import tonemappingAces2PS from './common/frag/tonemapping/tonemappingAces2.js'; +import tonemappingFilmicPS from './common/frag/tonemapping/tonemappingFilmic.js'; +import tonemappingHejlPS from './common/frag/tonemapping/tonemappingHejl.js'; +import tonemappingLinearPS from './common/frag/tonemapping/tonemappingLinear.js'; +import tonemappingNeutralPS from './common/frag/tonemapping/tonemappingNeutral.js'; +import tonemappingNonePS from './common/frag/tonemapping/tonemappingNone.js'; import transformVS from './common/vert/transform.js'; import transformCoreVS from './common/vert/transformCore.js'; import transformInstancingVS from './common/vert/transformInstancing.js'; @@ -390,6 +391,7 @@ const shaderChunks = { TBNderivativePS, TBNObjectSpacePS, thicknessPS, + tonemappingPS, tonemappingAcesPS, tonemappingAces2PS, tonemappingFilmicPS, diff --git a/src/scene/shader-lib/chunks/common/frag/tonemapping/tonemapping.js b/src/scene/shader-lib/chunks/common/frag/tonemapping/tonemapping.js new file mode 100644 index 00000000000..9127723e8cb --- /dev/null +++ b/src/scene/shader-lib/chunks/common/frag/tonemapping/tonemapping.js @@ -0,0 +1,17 @@ +export default /* glsl */` + +#if TONEMAP == FILMIC + #include "tonemappingFilmicPS" +#elif TONEMAP == LINEAR + #include "tonemappingLinearPS" +#elif TONEMAP == HEJL + #include "tonemappingHejlPS" +#elif TONEMAP == ACES + #include "tonemappingAcesPS" +#elif TONEMAP == ACES2 + #include "tonemappingAces2PS" +#elif TONEMAP == NEUTRAL + #include "tonemappingNeutralPS" +#endif + +`; diff --git a/src/scene/shader-lib/chunks/common/frag/tonemappingAces.js b/src/scene/shader-lib/chunks/common/frag/tonemapping/tonemappingAces.js similarity index 100% rename from src/scene/shader-lib/chunks/common/frag/tonemappingAces.js rename to src/scene/shader-lib/chunks/common/frag/tonemapping/tonemappingAces.js diff --git a/src/scene/shader-lib/chunks/common/frag/tonemappingAces2.js b/src/scene/shader-lib/chunks/common/frag/tonemapping/tonemappingAces2.js similarity index 100% rename from src/scene/shader-lib/chunks/common/frag/tonemappingAces2.js rename to src/scene/shader-lib/chunks/common/frag/tonemapping/tonemappingAces2.js diff --git a/src/scene/shader-lib/chunks/common/frag/tonemappingFilmic.js b/src/scene/shader-lib/chunks/common/frag/tonemapping/tonemappingFilmic.js similarity index 100% rename from src/scene/shader-lib/chunks/common/frag/tonemappingFilmic.js rename to src/scene/shader-lib/chunks/common/frag/tonemapping/tonemappingFilmic.js diff --git a/src/scene/shader-lib/chunks/common/frag/tonemappingHejl.js b/src/scene/shader-lib/chunks/common/frag/tonemapping/tonemappingHejl.js similarity index 100% rename from src/scene/shader-lib/chunks/common/frag/tonemappingHejl.js rename to src/scene/shader-lib/chunks/common/frag/tonemapping/tonemappingHejl.js diff --git a/src/scene/shader-lib/chunks/common/frag/tonemappingLinear.js b/src/scene/shader-lib/chunks/common/frag/tonemapping/tonemappingLinear.js similarity index 100% rename from src/scene/shader-lib/chunks/common/frag/tonemappingLinear.js rename to src/scene/shader-lib/chunks/common/frag/tonemapping/tonemappingLinear.js diff --git a/src/scene/shader-lib/chunks/common/frag/tonemappingNeutral.js b/src/scene/shader-lib/chunks/common/frag/tonemapping/tonemappingNeutral.js similarity index 100% rename from src/scene/shader-lib/chunks/common/frag/tonemappingNeutral.js rename to src/scene/shader-lib/chunks/common/frag/tonemapping/tonemappingNeutral.js diff --git a/src/scene/shader-lib/chunks/common/frag/tonemappingNone.js b/src/scene/shader-lib/chunks/common/frag/tonemapping/tonemappingNone.js similarity index 100% rename from src/scene/shader-lib/chunks/common/frag/tonemappingNone.js rename to src/scene/shader-lib/chunks/common/frag/tonemapping/tonemappingNone.js diff --git a/src/scene/shader-lib/chunks/gsplat/gsplatOutput.js b/src/scene/shader-lib/chunks/gsplat/gsplatOutput.js index 0866b306bec..06d2f2808ca 100644 --- a/src/scene/shader-lib/chunks/gsplat/gsplatOutput.js +++ b/src/scene/shader-lib/chunks/gsplat/gsplatOutput.js @@ -1,18 +1,6 @@ export default /* glsl */` -#if TONEMAP == FILMIC - #include "tonemappingFilmicPS" -#elif TONEMAP == LINEAR - #include "tonemappingLinearPS" -#elif TONEMAP == HEJL - #include "tonemappingHejlPS" -#elif TONEMAP == ACES - #include "tonemappingAcesPS" -#elif TONEMAP == ACES2 - #include "tonemappingAces2PS" -#elif TONEMAP == NEUTRAL - #include "tonemappingNeutralPS" -#endif +#include "tonemappingPS" #if TONEMAP != NONE #if GAMMA == SRGB diff --git a/src/scene/shader-lib/chunks/skybox/frag/skybox.js b/src/scene/shader-lib/chunks/skybox/frag/skybox.js index f0f86741727..68ac668774d 100644 --- a/src/scene/shader-lib/chunks/skybox/frag/skybox.js +++ b/src/scene/shader-lib/chunks/skybox/frag/skybox.js @@ -1,7 +1,7 @@ export default /* glsl */` #include "decodePS" #include "gamma" - #include "tonemapping" + #include "tonemappingPS" #include "envMultiplyPS" varying vec3 vViewDir; diff --git a/src/scene/shader-lib/programs/particle.js b/src/scene/shader-lib/programs/particle.js index 1b7613b3961..2279ac69265 100644 --- a/src/scene/shader-lib/programs/particle.js +++ b/src/scene/shader-lib/programs/particle.js @@ -1,5 +1,5 @@ import { ShaderUtils } from '../../../platform/graphics/shader-utils.js'; -import { BLEND_ADDITIVE, BLEND_MULTIPLICATIVE, BLEND_NORMAL } from '../../constants.js'; +import { BLEND_ADDITIVE, BLEND_MULTIPLICATIVE, BLEND_NORMAL, tonemapNames } from '../../constants.js'; import { shaderChunks } from '../chunks/chunks.js'; import { ShaderGenerator } from './shader-generator.js'; @@ -85,7 +85,7 @@ class ShaderGeneratorParticle extends ShaderGenerator { fshader += shaderChunks.decodePS; fshader += ShaderGenerator.gammaCode(options.gamma); - fshader += ShaderGenerator.tonemapCode(options.toneMap); + fshader += '#include "tonemappingPS"\n'; fshader += ShaderGenerator.fogCode(options.fog); if (options.normal === 2) fshader += '\nuniform sampler2D normalMap;\n'; @@ -105,11 +105,20 @@ class ShaderGeneratorParticle extends ShaderGenerator { } fshader += shaderChunks.particle_endPS; + const includes = new Map(Object.entries({ + ...shaderChunks, + ...options.chunks + })); + + const fragmentDefines = new Map(options.defines); + fragmentDefines.set('TONEMAP', tonemapNames[options.toneMap]); + return ShaderUtils.createDefinition(device, { name: 'ParticleShader', vertexCode: vshader, fragmentCode: fshader, - fragmentDefines: options.defines, + fragmentDefines: fragmentDefines, + fragmentIncludes: includes, vertexDefines: options.defines }); } diff --git a/src/scene/shader-lib/programs/shader-generator-shader.js b/src/scene/shader-lib/programs/shader-generator-shader.js index 69211813850..bacbce60187 100644 --- a/src/scene/shader-lib/programs/shader-generator-shader.js +++ b/src/scene/shader-lib/programs/shader-generator-shader.js @@ -1,6 +1,7 @@ import { hashCode } from '../../../core/hash.js'; import { SEMANTIC_ATTR15, SEMANTIC_BLENDINDICES, SEMANTIC_BLENDWEIGHT, SHADERLANGUAGE_WGSL } from '../../../platform/graphics/constants.js'; import { ShaderUtils } from '../../../platform/graphics/shader-utils.js'; +import { tonemapNames } from '../../constants.js'; import { ShaderPass } from '../../shader-pass.js'; import { shaderChunks } from '../chunks/chunks.js'; import { ShaderGenerator } from './shader-generator.js'; @@ -14,7 +15,7 @@ const fShader = ` #include "shaderPassDefines" #include "decodePS" #include "gamma" - #include "tonemapping" + #include "tonemappingPS" #include "fog" #include "userCode" `; @@ -109,16 +110,18 @@ class ShaderGeneratorShader extends ShaderGenerator { definitionOptions.fragmentCode = desc.fragmentCode; } else { - const includes = new Map(); - const defines = new Map(options.defines); + const includes = new Map(Object.entries({ + ...shaderChunks, + ...options.chunks + })); includes.set('shaderPassDefines', shaderPassInfo.shaderDefines); - includes.set('decodePS', shaderChunks.decodePS); includes.set('gamma', ShaderGenerator.gammaCode(options.gamma)); - includes.set('tonemapping', ShaderGenerator.tonemapCode(options.toneMapping)); includes.set('fog', ShaderGenerator.fogCode(options.fog)); includes.set('userCode', desc.fragmentCode); - includes.set('pick', shaderChunks.pickPS); + + const defines = new Map(options.defines); + defines.set('TONEMAP', tonemapNames[options.toneMapping]); definitionOptions.fragmentCode = fShader; definitionOptions.fragmentIncludes = includes; diff --git a/src/scene/shader-lib/programs/skybox.js b/src/scene/shader-lib/programs/skybox.js index 8313921bc53..e73221d6415 100644 --- a/src/scene/shader-lib/programs/skybox.js +++ b/src/scene/shader-lib/programs/skybox.js @@ -4,7 +4,7 @@ import { ChunkUtils } from '../chunk-utils.js'; import { ShaderUtils } from '../../../platform/graphics/shader-utils.js'; import { ShaderGenerator } from './shader-generator.js'; -import { SKYTYPE_INFINITE } from '../../constants.js'; +import { SKYTYPE_INFINITE, tonemapNames } from '../../constants.js'; class ShaderGeneratorSkybox extends ShaderGenerator { generateKey(options) { @@ -17,6 +17,7 @@ class ShaderGeneratorSkybox extends ShaderGenerator { // defines const defines = new Map(); + defines.set('TONEMAP', tonemapNames[options.toneMapping]); defines.set('SKYBOX_DECODE_FNC', ChunkUtils.decodeFunc(options.encoding)); if (options.skymesh !== SKYTYPE_INFINITE) defines.set('SKYMESH', ''); if (options.type === 'cubemap') { @@ -24,10 +25,12 @@ class ShaderGeneratorSkybox extends ShaderGenerator { } // includes - const includes = new Map(); + const includes = new Map(Object.entries({ + ...shaderChunks, + ...options.chunks + })); includes.set('decodePS', shaderChunks.decodePS); includes.set('gamma', ShaderGenerator.gammaCode(options.gamma)); - includes.set('tonemapping', ShaderGenerator.tonemapCode(options.toneMapping)); includes.set('envMultiplyPS', shaderChunks.envMultiplyPS); if (options.type !== 'cubemap') { From fd5a3673eae051e1aa84937dcc04d8b0b3ceeb46 Mon Sep 17 00:00:00 2001 From: Martin Valigursky Date: Thu, 5 Dec 2024 10:35:34 +0000 Subject: [PATCH 2/2] lint --- src/extras/render-passes/render-pass-compose.js | 4 ++-- src/scene/gsplat/gsplat-material.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/extras/render-passes/render-pass-compose.js b/src/extras/render-passes/render-pass-compose.js index 2f466b1d00e..7419f1b67a5 100644 --- a/src/extras/render-passes/render-pass-compose.js +++ b/src/extras/render-passes/render-pass-compose.js @@ -438,8 +438,8 @@ class RenderPassCompose extends RenderPassShaderQuad { if (this._debug) defines.set('DEBUG_COMPOSE', this._debug); const includes = new Map(Object.entries(shaderChunks)); - - this.shader = this.createQuadShader(`ComposeShader-${key}`, /*defines + */fragmentShader, { + + this.shader = this.createQuadShader(`ComposeShader-${key}`, fragmentShader, { fragmentIncludes: includes, fragmentDefines: defines }); diff --git a/src/scene/gsplat/gsplat-material.js b/src/scene/gsplat/gsplat-material.js index c2c60a70191..60e79f72397 100644 --- a/src/scene/gsplat/gsplat-material.js +++ b/src/scene/gsplat/gsplat-material.js @@ -1,6 +1,6 @@ import { CULLFACE_NONE, SEMANTIC_ATTR13, SEMANTIC_POSITION } from '../../platform/graphics/constants.js'; import { ShaderProcessorOptions } from '../../platform/graphics/shader-processor-options.js'; -import { BLEND_NONE, BLEND_NORMAL, DITHER_NONE, GAMMA_NONE, GAMMA_SRGB, TONEMAP_ACES, TONEMAP_ACES2, TONEMAP_FILMIC, TONEMAP_HEJL, TONEMAP_LINEAR, TONEMAP_NEUTRAL, TONEMAP_NONE, tonemapNames } from '../constants.js'; +import { BLEND_NONE, BLEND_NORMAL, DITHER_NONE, GAMMA_NONE, GAMMA_SRGB, tonemapNames } from '../constants.js'; import { ShaderMaterial } from '../materials/shader-material.js'; import { getProgramLibrary } from '../shader-lib/get-program-library.js'; import { getMaterialShaderDefines } from '../shader-lib/utils.js';