Jelajahi Sumber

De duplicate imports when generating a shader from shader nodes

Nehon 7 tahun lalu
induk
melakukan
171007693b

+ 23 - 6
jme3-core/src/main/java/com/jme3/shader/ShaderGenerator.java

@@ -31,14 +31,15 @@
  */
 package com.jme3.shader;
 
-import com.jme3.asset.AssetKey;
 import com.jme3.asset.AssetManager;
 import com.jme3.material.ShaderGenerationInfo;
-import com.jme3.material.Technique;
 import com.jme3.material.TechniqueDef;
 import com.jme3.shader.Shader.ShaderType;
-import java.util.List;
-import java.util.regex.*;
+import com.jme3.shader.plugins.ShaderAssetKey;
+
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * This class is the base for a shader generator using the ShaderNodes system,
@@ -66,6 +67,8 @@ public abstract class ShaderGenerator {
      */
     Pattern extensions = Pattern.compile("(#extension.*\\s+)");
 
+    private Map<String, String> imports = new LinkedHashMap<>();
+
     /**
      * Build a shaderGenerator
      *
@@ -126,7 +129,9 @@ public abstract class ShaderGenerator {
             // Too much code assumes that type is either Vertex or Fragment
             return null;
         }
-        
+
+        imports.clear();
+
         indent = 0;
 
         StringBuilder sourceDeclaration = new StringBuilder();
@@ -145,6 +150,12 @@ public abstract class ShaderGenerator {
 
         generateEndOfMainSection(source, info, type);
 
+        //insert imports backward
+        int insertIndex = sourceDeclaration.length();
+        for (String importSource : imports.values()) {
+            sourceDeclaration.insert(insertIndex, importSource);
+        }
+
         sourceDeclaration.append(source);
 
         return moveExtensionsUp(sourceDeclaration);
@@ -186,7 +197,13 @@ public abstract class ShaderGenerator {
             if (shaderNode.getDefinition().getType() == type) {
                 int index = findShaderIndexFromVersion(shaderNode, type);
                 String shaderPath = shaderNode.getDefinition().getShadersPath().get(index);
-                String loadedSource = (String) assetManager.loadAsset(new AssetKey(shaderPath));
+                Map<String, String> sources = (Map<String, String>) assetManager.loadAsset(new ShaderAssetKey(shaderPath, false));
+                String loadedSource = sources.get("[main]");
+                for (String name : sources.keySet()) {
+                    if (!name.equals("[main]")) {
+                        imports.put(name, sources.get(name));
+                    }
+                }
                 appendNodeDeclarationAndMain(loadedSource, sourceDeclaration, source, shaderNode, info, shaderPath);
             }
         }

+ 47 - 22
jme3-core/src/plugins/java/com/jme3/shader/plugins/GLSLLoader.java

@@ -34,10 +34,7 @@ package com.jme3.shader.plugins;
 import com.jme3.asset.*;
 import com.jme3.asset.cache.AssetCache;
 
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.Reader;
+import java.io.*;
 import java.util.*;
 
 /**
@@ -129,11 +126,11 @@ public class GLSLLoader implements AssetLoader {
 
     private ShaderDependencyNode nextIndependentNode() throws IOException {
         Collection<ShaderDependencyNode> allNodes = dependCache.values();
-        
+
         if (allNodes.isEmpty()) {
             return null;
         }
-        
+
         for (ShaderDependencyNode node : allNodes) {
             if (node.getDependOnMe().isEmpty()) {
                 return node;
@@ -144,11 +141,11 @@ public class GLSLLoader implements AssetLoader {
         for (ShaderDependencyNode node : allNodes){
             System.out.println(node.getName());
         }
-        
+
         throw new IOException("Circular dependency.");
     }
 
-    private String resolveDependencies(ShaderDependencyNode node, Set<ShaderDependencyNode> alreadyInjectedSet, StringBuilder extensions) {
+    private String resolveDependencies(ShaderDependencyNode node, Set<ShaderDependencyNode> alreadyInjectedSet, StringBuilder extensions, boolean injectDependencies) {
         if (alreadyInjectedSet.contains(node)) {
             return "// " + node.getName() + " was already injected at the top.\n";
         } else {
@@ -160,18 +157,27 @@ public class GLSLLoader implements AssetLoader {
         if (node.getDependencies().isEmpty()) {
             return node.getSource();
         } else {
-            StringBuilder sb = new StringBuilder(node.getSource());
-            List<String> resolvedShaderNodes = new ArrayList<>();
+            if (injectDependencies) {
+                StringBuilder sb = new StringBuilder(node.getSource());
+                List<String> resolvedShaderNodes = new ArrayList<>();
 
-            for (ShaderDependencyNode dependencyNode : node.getDependencies()) {
-                resolvedShaderNodes.add(resolveDependencies(dependencyNode, alreadyInjectedSet, extensions));
-            }
-            List<Integer> injectIndices = node.getDependencyInjectIndices();
-            for (int i = resolvedShaderNodes.size() - 1; i >= 0; i--) {
-                // Must insert them backwards ..
-                sb.insert(injectIndices.get(i), resolvedShaderNodes.get(i));
+                for (ShaderDependencyNode dependencyNode : node.getDependencies()) {
+                    resolvedShaderNodes.add(resolveDependencies(dependencyNode, alreadyInjectedSet, extensions, injectDependencies));
+                }
+
+                List<Integer> injectIndices = node.getDependencyInjectIndices();
+                for (int i = resolvedShaderNodes.size() - 1; i >= 0; i--) {
+                    // Must insert them backwards ..
+                    sb.insert(injectIndices.get(i), resolvedShaderNodes.get(i));
+                }
+                return sb.toString();
+            } else {
+                for (ShaderDependencyNode dependencyNode : node.getDependencies()) {
+                    resolveDependencies(dependencyNode, alreadyInjectedSet, extensions, injectDependencies);
+                }
+                return null;
             }
-            return sb.toString();
+
         }
     }
 
@@ -181,6 +187,10 @@ public class GLSLLoader implements AssetLoader {
         // to retrieve the fragment shader, use the content manager
         this.assetManager = info.getManager();
         Reader reader = new InputStreamReader(info.openStream());
+        boolean injectDependencies = true;
+        if (info.getKey() instanceof ShaderAssetKey) {
+            injectDependencies = ((ShaderAssetKey) info.getKey()).isInjectDependencies();
+        }
         if (info.getKey().getExtension().equals("glsllib")) {
             // NOTE: Loopback, GLSLLIB is loaded by this loader
             // and needs data as InputStream
@@ -188,10 +198,25 @@ public class GLSLLoader implements AssetLoader {
         } else {
             ShaderDependencyNode rootNode = loadNode(reader, "[main]");
             StringBuilder extensions = new StringBuilder();
-            String code = resolveDependencies(rootNode, new HashSet<ShaderDependencyNode>(), extensions);
-            extensions.append(code);
-            dependCache.clear();
-            return extensions.toString();
+            if (injectDependencies) {
+                String code = resolveDependencies(rootNode, new HashSet<ShaderDependencyNode>(), extensions, injectDependencies);
+                extensions.append(code);
+                dependCache.clear();
+                return extensions.toString();
+            } else {
+                Map<String, String> files = new LinkedHashMap<>();
+                HashSet<ShaderDependencyNode> dependencies = new HashSet<>();
+                String code = resolveDependencies(rootNode, dependencies, extensions, injectDependencies);
+                extensions.append(code);
+                files.put("[main]", extensions.toString());
+
+                for (ShaderDependencyNode dependency : dependencies) {
+                    files.put(dependency.getName(), dependency.getSource());
+                }
+
+                dependCache.clear();
+                return files;
+            }
         }
     }
 }

+ 24 - 0
jme3-core/src/plugins/java/com/jme3/shader/plugins/ShaderAssetKey.java

@@ -0,0 +1,24 @@
+package com.jme3.shader.plugins;
+
+import com.jme3.asset.AssetKey;
+
+/**
+ * Created by Nehon on 28/10/2017.
+ */
+public class ShaderAssetKey extends AssetKey {
+
+    private boolean injectDependencies = false;
+
+    public ShaderAssetKey(String name, boolean injectDependencies) {
+        super(name);
+        this.injectDependencies = injectDependencies;
+    }
+
+    public boolean isInjectDependencies() {
+        return injectDependencies;
+    }
+
+    public void setInjectDependencies(boolean injectDependencies) {
+        this.injectDependencies = injectDependencies;
+    }
+}