De duplicate imports when generating a shader from shader nodes

empirephoenix-patch-1
Nehon 7 years ago
parent eb6ce4d4b4
commit 171007693b
  1. 27
      jme3-core/src/main/java/com/jme3/shader/ShaderGenerator.java
  2. 63
      jme3-core/src/plugins/java/com/jme3/shader/plugins/GLSLLoader.java
  3. 24
      jme3-core/src/plugins/java/com/jme3/shader/plugins/ShaderAssetKey.java

@ -31,14 +31,15 @@
*/ */
package com.jme3.shader; package com.jme3.shader;
import com.jme3.asset.AssetKey;
import com.jme3.asset.AssetManager; import com.jme3.asset.AssetManager;
import com.jme3.material.ShaderGenerationInfo; import com.jme3.material.ShaderGenerationInfo;
import com.jme3.material.Technique;
import com.jme3.material.TechniqueDef; import com.jme3.material.TechniqueDef;
import com.jme3.shader.Shader.ShaderType; import com.jme3.shader.Shader.ShaderType;
import java.util.List; import com.jme3.shader.plugins.ShaderAssetKey;
import java.util.regex.*;
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, * 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+)"); Pattern extensions = Pattern.compile("(#extension.*\\s+)");
private Map<String, String> imports = new LinkedHashMap<>();
/** /**
* Build a shaderGenerator * Build a shaderGenerator
* *
@ -127,6 +130,8 @@ public abstract class ShaderGenerator {
return null; return null;
} }
imports.clear();
indent = 0; indent = 0;
StringBuilder sourceDeclaration = new StringBuilder(); StringBuilder sourceDeclaration = new StringBuilder();
@ -145,6 +150,12 @@ public abstract class ShaderGenerator {
generateEndOfMainSection(source, info, type); generateEndOfMainSection(source, info, type);
//insert imports backward
int insertIndex = sourceDeclaration.length();
for (String importSource : imports.values()) {
sourceDeclaration.insert(insertIndex, importSource);
}
sourceDeclaration.append(source); sourceDeclaration.append(source);
return moveExtensionsUp(sourceDeclaration); return moveExtensionsUp(sourceDeclaration);
@ -186,7 +197,13 @@ public abstract class ShaderGenerator {
if (shaderNode.getDefinition().getType() == type) { if (shaderNode.getDefinition().getType() == type) {
int index = findShaderIndexFromVersion(shaderNode, type); int index = findShaderIndexFromVersion(shaderNode, type);
String shaderPath = shaderNode.getDefinition().getShadersPath().get(index); 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); appendNodeDeclarationAndMain(loadedSource, sourceDeclaration, source, shaderNode, info, shaderPath);
} }
} }

@ -34,10 +34,7 @@ package com.jme3.shader.plugins;
import com.jme3.asset.*; import com.jme3.asset.*;
import com.jme3.asset.cache.AssetCache; import com.jme3.asset.cache.AssetCache;
import java.io.BufferedReader; import java.io.*;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.*; import java.util.*;
/** /**
@ -148,7 +145,7 @@ public class GLSLLoader implements AssetLoader {
throw new IOException("Circular dependency."); 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)) { if (alreadyInjectedSet.contains(node)) {
return "// " + node.getName() + " was already injected at the top.\n"; return "// " + node.getName() + " was already injected at the top.\n";
} else { } else {
@ -160,18 +157,27 @@ public class GLSLLoader implements AssetLoader {
if (node.getDependencies().isEmpty()) { if (node.getDependencies().isEmpty()) {
return node.getSource(); return node.getSource();
} else { } else {
StringBuilder sb = new StringBuilder(node.getSource()); if (injectDependencies) {
List<String> resolvedShaderNodes = new ArrayList<>(); StringBuilder sb = new StringBuilder(node.getSource());
List<String> resolvedShaderNodes = new ArrayList<>();
for (ShaderDependencyNode dependencyNode : node.getDependencies()) { for (ShaderDependencyNode dependencyNode : node.getDependencies()) {
resolvedShaderNodes.add(resolveDependencies(dependencyNode, alreadyInjectedSet, extensions)); resolvedShaderNodes.add(resolveDependencies(dependencyNode, alreadyInjectedSet, extensions, injectDependencies));
} }
List<Integer> injectIndices = node.getDependencyInjectIndices();
for (int i = resolvedShaderNodes.size() - 1; i >= 0; i--) { List<Integer> injectIndices = node.getDependencyInjectIndices();
// Must insert them backwards .. for (int i = resolvedShaderNodes.size() - 1; i >= 0; i--) {
sb.insert(injectIndices.get(i), resolvedShaderNodes.get(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 // to retrieve the fragment shader, use the content manager
this.assetManager = info.getManager(); this.assetManager = info.getManager();
Reader reader = new InputStreamReader(info.openStream()); 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")) { if (info.getKey().getExtension().equals("glsllib")) {
// NOTE: Loopback, GLSLLIB is loaded by this loader // NOTE: Loopback, GLSLLIB is loaded by this loader
// and needs data as InputStream // and needs data as InputStream
@ -188,10 +198,25 @@ public class GLSLLoader implements AssetLoader {
} else { } else {
ShaderDependencyNode rootNode = loadNode(reader, "[main]"); ShaderDependencyNode rootNode = loadNode(reader, "[main]");
StringBuilder extensions = new StringBuilder(); StringBuilder extensions = new StringBuilder();
String code = resolveDependencies(rootNode, new HashSet<ShaderDependencyNode>(), extensions); if (injectDependencies) {
extensions.append(code); String code = resolveDependencies(rootNode, new HashSet<ShaderDependencyNode>(), extensions, injectDependencies);
dependCache.clear(); extensions.append(code);
return extensions.toString(); 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;
}
} }
} }
} }

@ -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;
}
}
Loading…
Cancel
Save