David Catuhe 6 лет назад
Родитель
Сommit
b2687aa034

+ 4 - 3
dist/preview release/what's new.md

@@ -7,6 +7,9 @@
 ## Updates
 - Support Vive Focus 3Dof controller ([TrevorDev](https://github.com/TrevorDev))
 
+### Engine
+- Added preprocessors for shaders to improve how shaders are compiled for WebGL1/2 or WebGPU ([Deltakosh](https://github.com/deltakosh/))
+
 ### Inspector
 - Added support for `ShadowGenerator` ([Deltakosh](https://github.com/deltakosh/))
 - Added support for scene normalization ([Deltakosh](https://github.com/deltakosh/))
@@ -14,13 +17,11 @@
 
 ### Tools
 - Added `Color3.toHSV()`, `Color3.toHSVToRef()` and `Color3.HSVtoRGBToRef()` ([Deltakosh](https://github.com/deltakosh/))
+- Added `ShadowGenerator.onAfterShadowMapRenderObservable` and `ShadowGenerator.onAfterShadowMapMeshRenderObservable` ([Deltakosh](https://github.com/deltakosh/))
 
 ### Meshes
 - Added new CreateTiledPlane and CreateTiledBox ([JohnK](https://github.com/BabylonJSGuide/))
 
-### Tools
-- Added `ShadowGenerator.onAfterShadowMapRenderObservable` and `ShadowGenerator.onAfterShadowMapMeshRenderObservable` ([Deltakosh](https://github.com/deltakosh/))
-
 ## Bug fixes
 - Added support for `AnimationGroup` serialization ([Drigax](https://github.com/drigax/))
 - Removing assetContainer from scene will also remove gui layers ([TrevorDev](https://github.com/TrevorDev))

+ 1 - 0
src/Engines/Processors/iShaderProcessor.ts

@@ -2,5 +2,6 @@
 export interface IShaderProcessor {
     attributeProcessor?: (attribute: string) => string;
     varyingProcessor?: (varying: string, isFragment: boolean) => string;
+    preProcessor?: (code: string, defines: string[], isFragment: boolean) => string;
     postProcessor?: (code: string, defines: string[], isFragment: boolean) => string;
 }

+ 1 - 0
src/Engines/Processors/shaderProcessingOptions.ts

@@ -10,4 +10,5 @@ export interface ProcessingOptions {
     shadersRepository: string;
     includesShadersStore: { [key: string]: string };
     processor?: IShaderProcessor;
+    version: string;
 }

+ 52 - 36
src/Engines/Processors/shaderProcessor.ts

@@ -58,6 +58,10 @@ export class ShaderProcessor {
             }
         }
 
+        if (indexOperator === -1) {
+            return new ShaderDefineIsDefinedOperator(expression);
+        }
+
         let define = expression.substring(0, indexOperator).trim();
         let value = expression.substring(indexOperator + operator.length).trim();
 
@@ -132,40 +136,45 @@ export class ShaderProcessor {
         while (cursor.canRead) {
             cursor.lineIndex++;
             let line = cursor.currentLine;
-            let first0 = line[0];
-            let first1 = line[1];
-
-            // Check preprocessor commands
-            if (first0 === "#" && first1 !== "d") {
-                let first6 = line.substring(0, 6).toLowerCase();
-                let first5 = line.substring(0, 5).toLowerCase();
-                if (first6 === "#ifdef") {
-                    let newRootNode = new ShaderCodeConditionNode();
-                    rootNode.children.push(newRootNode);
-
-                    let ifNode = this._BuildExpression(line, 6);
-                    newRootNode.children.push(ifNode);
-                    this._MoveCursorWithinIf(cursor, newRootNode, ifNode);
-                } else if (first5 === "#else") {
-                    return true;
-                } else if (first5 === "#elif") {
-                    return true;
-                } else if (first6 === "#endif") {
-                    return false;
-                } else if (line.substring(0, 7).toLowerCase() === "#ifndef") {
-                    let newRootNode = new ShaderCodeConditionNode();
-                    rootNode.children.push(newRootNode);
-
-                    let ifNode = this._BuildExpression(line, 7);
-                    newRootNode.children.push(ifNode);
-                    this._MoveCursorWithinIf(cursor, newRootNode, ifNode);
-                } else if (line.substring(0, 3).toLowerCase() === "#if") {
-                    let newRootNode = new ShaderCodeConditionNode();
-                    let ifNode = this._BuildExpression(line, 3);
-                    rootNode.children.push(newRootNode);
-
-                    newRootNode.children.push(ifNode);
-                    this._MoveCursorWithinIf(cursor, newRootNode, ifNode);
+            const keywords = /(#ifdef)|(#else)|(#elif)|(#endif)|(#ifndef)|(#if)/
+            const matches = keywords.exec(line);
+
+            if (matches && matches.length) {
+                let keyword = matches[0];
+
+                switch (keyword) {
+                    case "#ifdef": {
+                        let newRootNode = new ShaderCodeConditionNode();
+                        rootNode.children.push(newRootNode);
+
+                        let ifNode = this._BuildExpression(line, 6);
+                        newRootNode.children.push(ifNode);
+                        this._MoveCursorWithinIf(cursor, newRootNode, ifNode);
+                        break;
+                    }
+                    case "#else":
+                    case "#elif":
+                        return true;
+                    case "#endif":
+                        return false;
+                    case "#ifndef": {
+                        let newRootNode = new ShaderCodeConditionNode();
+                        rootNode.children.push(newRootNode);
+
+                        let ifNode = this._BuildExpression(line, 7);
+                        newRootNode.children.push(ifNode);
+                        this._MoveCursorWithinIf(cursor, newRootNode, ifNode);
+                        break;
+                    }
+                    case "#if": {
+                        let newRootNode = new ShaderCodeConditionNode();
+                        let ifNode = this._BuildExpression(line, 3);
+                        rootNode.children.push(newRootNode);
+
+                        newRootNode.children.push(ifNode);
+                        this._MoveCursorWithinIf(cursor, newRootNode, ifNode);
+                        break;
+                    }
                 }
             }
             else {
@@ -174,7 +183,7 @@ export class ShaderProcessor {
                 rootNode.children.push(newNode);
 
                 // Detect additional defines
-                if (first0 === "#" && first1 === "d") {
+                if (line[0] === "#" && line[1] === "d") {
                     let split = line.replace(";", "").split(" ");
                     newNode.additionalDefineKey = split[1];
 
@@ -219,11 +228,18 @@ export class ShaderProcessor {
         let preprocessors: { [key: string]: string } = {};
 
         for (var define of defines) {
-            let keyValue = define.replace("#define", "").trim();
+            let keyValue = define.replace("#define", "").replace(";", "").trim();
             let split = keyValue.split(" ");
             preprocessors[split[0]] = split.length > 1 ? split[1] : "";
         }
 
+        preprocessors["GL_ES"] = "true";
+        preprocessors["__VERSION__"] = options.version;
+
+        if (options.processor.preProcessor) {
+            preparedSourceCode = options.processor.preProcessor(preparedSourceCode, defines, options.isFragment);
+        }
+
         preparedSourceCode = this._EvaluatePreProcessors(preparedSourceCode, preprocessors, options);
 
         // Add multiview setup to top of file when defined

+ 3 - 5
src/Engines/WebGL/webGL2ShaderProcessors.ts

@@ -11,17 +11,15 @@ export class WebGL2ShaderProcessor implements IShaderProcessor {
     }
 
     public postProcessor(code: string, defines: string[], isFragment: boolean) {
+        const hasDrawBuffersExtension = code.search(/#extension.+GL_EXT_draw_buffers.+require/) !== -1;
+
         // Remove extensions
-        // #extension GL_OES_standard_derivatives : enable
-        // #extension GL_EXT_shader_texture_lod : enable
-        // #extension GL_EXT_frag_depth : enable
-        // #extension GL_EXT_draw_buffers : require
         var regex = /#extension.+(GL_OVR_multiview2|GL_OES_standard_derivatives|GL_EXT_shader_texture_lod|GL_EXT_frag_depth|GL_EXT_draw_buffers).+(enable|require)/g;
         code = code.replace(regex, "");
 
+        // Replace instructions
         code = code.replace(/texture2D\s*\(/g, "texture(");
         if (isFragment) {
-            const hasDrawBuffersExtension = code.search(/#extension.+GL_EXT_draw_buffers.+require/) !== -1;
             code = code.replace(/texture2DLodEXT\s*\(/g, "textureLod(");
             code = code.replace(/textureCubeLodEXT\s*\(/g, "textureLod(");
             code = code.replace(/textureCube\s*\(/g, "texture(");

+ 1 - 0
src/Materials/effect.ts

@@ -357,6 +357,7 @@ export class Effect implements IDisposable {
             supportsUniformBuffers: this._engine.supportsUniformBuffers,
             shadersRepository: Effect.ShadersRepository,
             includesShadersStore: Effect.IncludesShadersStore,
+            version: (this._engine.webGLVersion * 100).toString()
         };
 
         this._loadVertexShader(vertexSource, (vertexCode) => {

+ 1 - 3
src/Shaders/vrMultiviewToSingleview.fragment.fx

@@ -1,6 +1,4 @@
-#ifdef GL_ES
-	precision mediump sampler2DArray;
-#endif
+precision mediump sampler2DArray;
 
 varying vec2 vUV;
 uniform sampler2DArray multiviewSampler;