diff --git a/src/scene/materials/lit-material-options-builder.js b/src/scene/materials/lit-material-options-builder.js index 078b963cef6..af95e06ca34 100644 --- a/src/scene/materials/lit-material-options-builder.js +++ b/src/scene/materials/lit-material-options-builder.js @@ -50,7 +50,6 @@ class LitMaterialOptionsBuilder { static updateMaterialOptions(litOptions, material) { litOptions.separateAmbient = false; // store ambient light color in separate variable, instead of adding it to diffuse directly - litOptions.customFragmentShader = null; litOptions.pixelSnap = material.pixelSnap; litOptions.ambientSH = material.ambientSH; diff --git a/src/scene/materials/standard-material-options-builder.js b/src/scene/materials/standard-material-options-builder.js index 35cffdd1b13..883e103fa8d 100644 --- a/src/scene/materials/standard-material-options-builder.js +++ b/src/scene/materials/standard-material-options-builder.js @@ -262,7 +262,6 @@ class StandardMaterialOptionsBuilder { // LIT OPTIONS options.litOptions.separateAmbient = false; // store ambient light color in separate variable, instead of adding it to diffuse directly - options.litOptions.customFragmentShader = stdMat.customFragmentShader; options.litOptions.pixelSnap = stdMat.pixelSnap; options.litOptions.ambientSH = !!stdMat.ambientSH; diff --git a/src/scene/shader-lib/chunks-wgsl/chunks-wgsl.js b/src/scene/shader-lib/chunks-wgsl/chunks-wgsl.js index 1d76ca6b4f7..3a0a325c32a 100644 --- a/src/scene/shader-lib/chunks-wgsl/chunks-wgsl.js +++ b/src/scene/shader-lib/chunks-wgsl/chunks-wgsl.js @@ -80,6 +80,7 @@ import litForwardDeclarationPS from './lit/frag/pass-forward/litForwardDeclarati import litForwardMainPS from './lit/frag/pass-forward/litForwardMain.js'; import litForwardPostCodePS from './lit/frag/pass-forward/litForwardPostCode.js'; import litForwardPreCodePS from './lit/frag/pass-forward/litForwardPreCode.js'; +import litMainPS from './lit/frag/litMain.js'; import litMainVS from './lit/vert/litMain.js'; import litOtherMainPS from './lit/frag/pass-other/litOtherMain.js'; import litShaderArgsPS from './standard/frag/litShaderArgs.js'; @@ -253,6 +254,8 @@ const shaderChunksWGSL = { floatAsUintPS, fogPS, fresnelSchlickPS, + frontendCodePS: '', // empty chunk, supplied by the shader generator + frontendDeclPS: '', // empty chunk, supplied by the shader generator fullscreenQuadVS, gammaPS, glossPS, @@ -293,11 +296,20 @@ const shaderChunksWGSL = { litForwardMainPS, litForwardPostCodePS, litForwardPreCodePS, + litMainPS, litMainVS, litOtherMainPS, litShaderArgsPS, litShaderCorePS, litShadowMainPS, + litUserDeclarationPS: '', // empty chunk allowing user to add custom code + litUserDeclarationVS: '', // empty chunk allowing user to add custom code + litUserCodePS: '', // empty chunk allowing user to add custom code + litUserCodeVS: '', // empty chunk allowing user to add custom code + litUserMainStartPS: '', // empty chunk allowing user to add custom code + litUserMainStartVS: '', // empty chunk allowing user to add custom code + litUserMainEndPS: '', // empty chunk allowing user to add custom code + litUserMainEndVS: '', // empty chunk allowing user to add custom code ltcPS, metalnessPS, metalnessModulatePS, diff --git a/src/scene/shader-lib/chunks-wgsl/lit/frag/litMain.js b/src/scene/shader-lib/chunks-wgsl/lit/frag/litMain.js new file mode 100644 index 00000000000..bb3b596a5b8 --- /dev/null +++ b/src/scene/shader-lib/chunks-wgsl/lit/frag/litMain.js @@ -0,0 +1,32 @@ +// main shader of the lit fragment shader +export default /* wgsl */` + +#include "varyingsPS" +#include "litUserDeclarationPS" +#include "frontendDeclPS" + +#if defined(PICK_PASS) || definde(PREPASS_PASS) + + #include "frontendCodePS" + #include "litUserCodePS" + #include "litOtherMainPS" + +#elif defined(SHADOW_PASS) + + #include "frontendCodePS" + #include "litUserCodePS" + #include "litShadowMainPS" + +#else // FORWARD_PASS + + #include "litForwardDeclarationPS" + #include "litForwardPreCodePS" + #include "frontendCodePS" + #include "litForwardPostCodePS" + #include "litForwardBackendPS" + #include "litUserCodePS" + #include "litForwardMainPS" + +#endif + +`; diff --git a/src/scene/shader-lib/chunks-wgsl/lit/frag/pass-forward/litForwardMain.js b/src/scene/shader-lib/chunks-wgsl/lit/frag/pass-forward/litForwardMain.js index 83a47d9f65b..9dc2c191930 100644 --- a/src/scene/shader-lib/chunks-wgsl/lit/frag/pass-forward/litForwardMain.js +++ b/src/scene/shader-lib/chunks-wgsl/lit/frag/pass-forward/litForwardMain.js @@ -4,6 +4,8 @@ export default /* wgsl */` @fragment fn fragmentMain(input: FragmentInput) -> FragmentOutput { + #include "litUserMainStartPS" + dReflection = vec4f(0.0); #ifdef LIT_CLEARCOAT @@ -45,6 +47,8 @@ fn fragmentMain(input: FragmentInput) -> FragmentOutput { var output: FragmentOutput = evaluateBackend(); + #include "litUserMainEndPS" + return output; } `; diff --git a/src/scene/shader-lib/chunks-wgsl/lit/frag/pass-other/litOtherMain.js b/src/scene/shader-lib/chunks-wgsl/lit/frag/pass-other/litOtherMain.js index a83e9236554..60e16905991 100644 --- a/src/scene/shader-lib/chunks-wgsl/lit/frag/pass-other/litOtherMain.js +++ b/src/scene/shader-lib/chunks-wgsl/lit/frag/pass-other/litOtherMain.js @@ -11,6 +11,9 @@ export default /* wgsl */` @fragment fn fragmentMain(input: FragmentInput) -> FragmentOutput { + + #include "litUserMainStartPS" + var output: FragmentOutput; evaluateFrontend(); @@ -23,6 +26,8 @@ fn fragmentMain(input: FragmentInput) -> FragmentOutput { output.color = float2vec4(vLinearDepth); #endif + #include "litUserMainEndPS" + return output; } `; diff --git a/src/scene/shader-lib/chunks-wgsl/lit/frag/pass-shadow/litShadowMain.js b/src/scene/shader-lib/chunks-wgsl/lit/frag/pass-shadow/litShadowMain.js index 26e6d26e29f..94b531ab5da 100644 --- a/src/scene/shader-lib/chunks-wgsl/lit/frag/pass-shadow/litShadowMain.js +++ b/src/scene/shader-lib/chunks-wgsl/lit/frag/pass-shadow/litShadowMain.js @@ -12,6 +12,9 @@ export default /* wgsl */` @fragment fn fragmentMain(input: FragmentInput) -> FragmentOutput { + + #include "litUserMainStartPS" + var output: FragmentOutput; evaluateFrontend(); @@ -57,6 +60,8 @@ fn fragmentMain(input: FragmentInput) -> FragmentOutput { #endif #endif + #include "litUserMainEndPS" + return output; } `; diff --git a/src/scene/shader-lib/chunks-wgsl/lit/frag/refractionDynamic.js b/src/scene/shader-lib/chunks-wgsl/lit/frag/refractionDynamic.js index da3252a9026..6069fb17dca 100644 --- a/src/scene/shader-lib/chunks-wgsl/lit/frag/refractionDynamic.js +++ b/src/scene/shader-lib/chunks-wgsl/lit/frag/refractionDynamic.js @@ -86,4 +86,5 @@ fn addRefraction( #endif ); dDiffuseLight = mix(dDiffuseLight, refraction * transmittance * fresnel, transmission); -}`; +} +`; diff --git a/src/scene/shader-lib/chunks-wgsl/lit/vert/litMain.js b/src/scene/shader-lib/chunks-wgsl/lit/vert/litMain.js index 041b6f0ddff..0b9d8c30e33 100644 --- a/src/scene/shader-lib/chunks-wgsl/lit/vert/litMain.js +++ b/src/scene/shader-lib/chunks-wgsl/lit/vert/litMain.js @@ -1,5 +1,10 @@ // main shader of the lit vertex shader export default /* wgsl */` + +#include "varyingsVS" + +#include "litUserDeclarationVS" + #ifdef VERTEX_COLOR attribute vertex_color: vec4f; #endif @@ -59,8 +64,13 @@ var dModelMatrix: mat4x4f; #include "msdfVS" #endif +#include "litUserCodeVS" + @vertex fn vertexMain(input : VertexInput) -> VertexOutput { + + #include "litUserMainStartVS" + var output : VertexOutput; output.position = getPosition(); output.vPositionW = getWorldPosition(); @@ -116,6 +126,8 @@ fn vertexMain(input : VertexInput) -> VertexOutput { output.vTiledUv = dTiledUvGlobal; #endif + #include "litUserMainEndVS" + return output; } `; diff --git a/src/scene/shader-lib/chunks/chunks.js b/src/scene/shader-lib/chunks/chunks.js index a504e6e5545..d794695e5ba 100644 --- a/src/scene/shader-lib/chunks/chunks.js +++ b/src/scene/shader-lib/chunks/chunks.js @@ -85,6 +85,7 @@ import litForwardDeclarationPS from './lit/frag/pass-forward/litForwardDeclarati import litForwardMainPS from './lit/frag/pass-forward/litForwardMain.js'; import litForwardPostCodePS from './lit/frag/pass-forward/litForwardPostCode.js'; import litForwardPreCodePS from './lit/frag/pass-forward/litForwardPreCode.js'; +import litMainPS from './lit/frag/litMain.js'; import litMainVS from './lit/vert/litMain.js'; import litOtherMainPS from './lit/frag/pass-other/litOtherMain.js'; import litShaderArgsPS from './standard/frag/litShaderArgs.js'; @@ -258,6 +259,8 @@ const shaderChunks = { floatAsUintPS, fogPS, fresnelSchlickPS, + frontendCodePS: '', // empty chunk, supplied by the shader generator + frontendDeclPS: '', // empty chunk, supplied by the shader generator fullscreenQuadVS, gammaPS, gles3PS, @@ -303,11 +306,20 @@ const shaderChunks = { litForwardMainPS, litForwardPostCodePS, litForwardPreCodePS, + litMainPS, litMainVS, litOtherMainPS, litShaderArgsPS, litShaderCorePS, litShadowMainPS, + litUserDeclarationPS: '', // empty chunk allowing user to add custom code + litUserDeclarationVS: '', // empty chunk allowing user to add custom code + litUserCodePS: '', // empty chunk allowing user to add custom code + litUserCodeVS: '', // empty chunk allowing user to add custom code + litUserMainStartPS: '', // empty chunk allowing user to add custom code + litUserMainStartVS: '', // empty chunk allowing user to add custom code + litUserMainEndPS: '', // empty chunk allowing user to add custom code + litUserMainEndVS: '', // empty chunk allowing user to add custom code ltcPS, metalnessPS, metalnessModulatePS, @@ -423,6 +435,8 @@ const shaderChunks = { uvTransformVS, uvTransformUniformsPS, viewDirPS, + varyingsPS: '', // empty chunk, supplied by the shader generator + varyingsVS: '', // empty chunk, supplied by the shader generator webgpuPS, webgpuVS }; diff --git a/src/scene/shader-lib/chunks/lit/frag/litMain.js b/src/scene/shader-lib/chunks/lit/frag/litMain.js new file mode 100644 index 00000000000..a794cddf963 --- /dev/null +++ b/src/scene/shader-lib/chunks/lit/frag/litMain.js @@ -0,0 +1,32 @@ +// main shader of the lit fragment shader +export default /* glsl */` + +#include "varyingsPS" +#include "litUserDeclarationPS" +#include "frontendDeclPS" + +#if defined(PICK_PASS) || definde(PREPASS_PASS) + + #include "frontendCodePS" + #include "litUserCodePS" + #include "litOtherMainPS" + +#elif defined(SHADOW_PASS) + + #include "frontendCodePS" + #include "litUserCodePS" + #include "litShadowMainPS" + +#else // FORWARD_PASS + + #include "litForwardDeclarationPS" + #include "litForwardPreCodePS" + #include "frontendCodePS" + #include "litForwardPostCodePS" + #include "litForwardBackendPS" + #include "litUserCodePS" + #include "litForwardMainPS" + +#endif + +`; diff --git a/src/scene/shader-lib/chunks/lit/frag/pass-forward/litForwardMain.js b/src/scene/shader-lib/chunks/lit/frag/pass-forward/litForwardMain.js index 0e7a3b7c392..81d8e7c3d65 100644 --- a/src/scene/shader-lib/chunks/lit/frag/pass-forward/litForwardMain.js +++ b/src/scene/shader-lib/chunks/lit/frag/pass-forward/litForwardMain.js @@ -2,6 +2,9 @@ export default /* glsl */` void main(void) { + + #include "litUserMainStartPS" + dReflection = vec4(0); #ifdef LIT_CLEARCOAT @@ -42,5 +45,7 @@ void main(void) { #include "debugProcessFrontendPS" evaluateBackend(); + + #include "litUserMainEndPS" } `; diff --git a/src/scene/shader-lib/chunks/lit/frag/pass-other/litOtherMain.js b/src/scene/shader-lib/chunks/lit/frag/pass-other/litOtherMain.js index 8c6bae98385..068edad9cd0 100644 --- a/src/scene/shader-lib/chunks/lit/frag/pass-other/litOtherMain.js +++ b/src/scene/shader-lib/chunks/lit/frag/pass-other/litOtherMain.js @@ -10,6 +10,9 @@ export default /* glsl */` #endif void main(void) { + + #include "litUserMainStartPS" + evaluateFrontend(); #ifdef PICK_PASS @@ -19,5 +22,7 @@ void main(void) { #ifdef PREPASS_PASS gl_FragColor = float2vec4(vLinearDepth); #endif + + #include "litUserMainEndPS" } `; diff --git a/src/scene/shader-lib/chunks/lit/frag/pass-shadow/litShadowMain.js b/src/scene/shader-lib/chunks/lit/frag/pass-shadow/litShadowMain.js index 3a55c071be2..0ef552de431 100644 --- a/src/scene/shader-lib/chunks/lit/frag/pass-shadow/litShadowMain.js +++ b/src/scene/shader-lib/chunks/lit/frag/pass-shadow/litShadowMain.js @@ -11,6 +11,9 @@ export default /* glsl */` #endif void main(void) { + + #include "litUserMainStartPS" + evaluateFrontend(); // using non-standard depth, i.e gl_FragCoord.z @@ -53,5 +56,7 @@ void main(void) { gl_FragColor = vec4(1.0); #endif #endif + + #include "litUserMainEndPS" } `; diff --git a/src/scene/shader-lib/chunks/lit/vert/litMain.js b/src/scene/shader-lib/chunks/lit/vert/litMain.js index 3bf0416cd57..db05bcec249 100644 --- a/src/scene/shader-lib/chunks/lit/vert/litMain.js +++ b/src/scene/shader-lib/chunks/lit/vert/litMain.js @@ -1,5 +1,10 @@ // main shader of the lit vertex shader export default /* glsl */` + +#include "varyingsVS" + +#include "litUserDeclarationVS" + #ifdef VERTEX_COLOR attribute vec4 vertex_color; #endif @@ -56,7 +61,12 @@ mat4 dModelMatrix; #include "msdfVS" #endif +#include "litUserCodeVS" + void main(void) { + + #include "litUserMainStartVS" + gl_Position = getPosition(); vPositionW = getWorldPosition(); @@ -100,5 +110,7 @@ void main(void) { #ifdef MSDF unpackMsdfParams(); #endif + + #include "litUserMainEndVS" } `; diff --git a/src/scene/shader-lib/programs/lit-shader-options.js b/src/scene/shader-lib/programs/lit-shader-options.js index 1b4f3170c46..060666855ed 100644 --- a/src/scene/shader-lib/programs/lit-shader-options.js +++ b/src/scene/shader-lib/programs/lit-shader-options.js @@ -93,13 +93,6 @@ class LitShaderOptions { diffuseMapEnabled = false; - /** - * Replaced the whole fragment shader with this string. - * - * @type {string} - */ - customFragmentShader = null; - pixelSnap = false; /** diff --git a/src/scene/shader-lib/programs/lit-shader.js b/src/scene/shader-lib/programs/lit-shader.js index d85eecbcecf..50ff03872a6 100644 --- a/src/scene/shader-lib/programs/lit-shader.js +++ b/src/scene/shader-lib/programs/lit-shader.js @@ -72,6 +72,27 @@ class LitShader { */ shaderLanguage; + /** + * The vertex shader defines needed for the shader compilation. + * + * @type {Map} + */ + vDefines = new Map(); + + /** + * The fragment shader defines needed for the shader compilation. + * + * @type {Map} + */ + fDefines = new Map(); + + /** + * The vertex and fragment shader includes needed for the shader compilation. + * + * @type {Map} + */ + includes = new Map(); + /** * @param {GraphicsDevice} device - The graphics device. * @param {LitShaderOptions} options - The lit options. @@ -140,10 +161,6 @@ class LitShader { // generated by vshader this.vshader = null; - // defines set by the shader generation - this.vDefines = new Map(); - this.fDefines = new Map(); - // generated by fshader this.fshader = null; } @@ -307,8 +324,11 @@ class LitShader { `varying ${type} ${name};\n`; }); + // varyings code exposed as an include + this.includes.set('varyingsVS', this.varyingsCode); + this.includes.set('varyingsPS', this.varyingsCode); + this.vshader = ` - ${this.varyingsCode} #include "litMainVS" `; } @@ -507,54 +527,21 @@ class LitShader { generateFragmentShader(frontendDecl, frontendCode, lightingUv) { const options = this.options; - if (options.pass === SHADER_PICK || options.pass === SHADER_PREPASS) { - - Debug.assert(this.varyingsCode !== undefined && frontendCode !== undefined && frontendDecl !== undefined); - this.fshader = ` - - ${this.varyingsCode} - ${frontendDecl} - ${frontendCode} - #include "litOtherMainPS" - `; + // generated code is exposed as an include + this.includes.set('frontendDeclPS', frontendDecl ?? ''); + this.includes.set('frontendCodePS', frontendCode ?? ''); - } else if (this.shadowPass) { // SHADOW PASS - - Debug.assert(this.varyingsCode !== undefined && frontendCode !== undefined && frontendDecl !== undefined); + if (options.pass === SHADER_PICK || options.pass === SHADER_PREPASS) { + // nothing to prepare currently + } else if (this.shadowPass) { this.prepareShadowPass(); - this.fshader = ` - ${this.varyingsCode} - ${frontendDecl} - ${frontendCode} - #include "litShadowMainPS" - `; - - } else if (options.customFragmentShader) { // CUSTOM FRAGMENT SHADER - - Debug.assert(options.customFragmentShader); - this.fshader = ` - ${options.customFragmentShader} - `; - - } else { // FORWARD PASS - + } else { this.prepareForwardPass(lightingUv); - Debug.assert(this.varyingsCode !== undefined && frontendCode !== undefined && frontendDecl !== undefined); - this.fshader = ` - ${this.varyingsCode} - ${frontendDecl} - #include "litForwardDeclarationPS" - #include "litForwardPreCodePS" - ${frontendCode} - #include "litForwardPostCodePS" - #include "litForwardBackendPS" - #include "litForwardMainPS" - `; } - Debug.assert(!this.fshader.includes('litShaderArgs.'), 'Automatic compatibility with shaders using litShaderArgs has been removed. Please update the shader to use the new system.', { - fshader: this.fshader - }); + this.fshader = ` + #include "litMainPS" + `; } } diff --git a/src/scene/shader-lib/programs/lit.js b/src/scene/shader-lib/programs/lit.js index 8b32bc347dd..1660ae106d4 100644 --- a/src/scene/shader-lib/programs/lit.js +++ b/src/scene/shader-lib/programs/lit.js @@ -50,7 +50,8 @@ class ShaderGeneratorLit extends ShaderGenerator { const includes = new Map(Object.entries({ ...Object.getPrototypeOf(litShader.chunks), // the prototype stores the default chunks ...litShader.chunks, // user overrides are supplied as instance properties - ...options.litOptions.chunks + ...options.litOptions.chunks, + ...Object.fromEntries(litShader.includes) // includes generated by the lit shader })); const vDefines = litShader.vDefines; diff --git a/src/scene/shader-lib/programs/standard.js b/src/scene/shader-lib/programs/standard.js index d024889ff65..47a382a3de4 100644 --- a/src/scene/shader-lib/programs/standard.js +++ b/src/scene/shader-lib/programs/standard.js @@ -436,7 +436,8 @@ class ShaderGeneratorStandard extends ShaderGenerator { const includes = new Map(Object.entries({ ...Object.getPrototypeOf(litShader.chunks), // the prototype stores the default chunks ...litShader.chunks, // user overrides are supplied as instance properties - ...options.litOptions.chunks + ...options.litOptions.chunks, + ...Object.fromEntries(litShader.includes) // includes generated by the lit shader })); const vDefines = litShader.vDefines;