Adds an alternative way to declare shader nodes definitions
This commit is contained in:
parent
7055de4531
commit
9f9edee332
@ -36,6 +36,7 @@ import com.jme3.material.ShaderGenerationInfo;
|
|||||||
import com.jme3.material.plugins.ConditionParser;
|
import com.jme3.material.plugins.ConditionParser;
|
||||||
import com.jme3.shader.Shader.ShaderType;
|
import com.jme3.shader.Shader.ShaderType;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
@ -231,8 +232,6 @@ public class Glsl100ShaderGenerator extends ShaderGenerator {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void generateNodeMainSection(StringBuilder source, ShaderNode shaderNode, String nodeSource, ShaderGenerationInfo info) {
|
protected void generateNodeMainSection(StringBuilder source, ShaderNode shaderNode, String nodeSource, ShaderGenerationInfo info) {
|
||||||
|
|
||||||
|
|
||||||
source.append("\n");
|
source.append("\n");
|
||||||
comment(source, shaderNode, "");
|
comment(source, shaderNode, "");
|
||||||
startCondition(shaderNode.getCondition(), source);
|
startCondition(shaderNode.getCondition(), source);
|
||||||
@ -243,13 +242,14 @@ public class Glsl100ShaderGenerator extends ShaderGenerator {
|
|||||||
appendIndent(b);
|
appendIndent(b);
|
||||||
b.append(definition.getName()).append("(");
|
b.append(definition.getName()).append("(");
|
||||||
boolean isFirst = true;
|
boolean isFirst = true;
|
||||||
|
List<VariableMapping> maps = new ArrayList<>();
|
||||||
for (ShaderNodeVariable v : definition.getParams()) {
|
for (ShaderNodeVariable v : definition.getParams()) {
|
||||||
if (!isFirst) {
|
if (!isFirst) {
|
||||||
b.append(", ");
|
b.append(", ");
|
||||||
}
|
}
|
||||||
if (definition.getInputs().contains(v)) {
|
if (definition.getInputs().contains(v)) {
|
||||||
|
|
||||||
List<VariableMapping> maps = shaderNode.getInputMapping(v.getName());
|
shaderNode.getInputMapping(v.getName(), maps);
|
||||||
|
|
||||||
boolean declared = false;
|
boolean declared = false;
|
||||||
for (VariableMapping m : maps) {
|
for (VariableMapping m : maps) {
|
||||||
@ -267,6 +267,7 @@ public class Glsl100ShaderGenerator extends ShaderGenerator {
|
|||||||
b.append(v.getDefaultValue());
|
b.append(v.getDefaultValue());
|
||||||
} else {
|
} else {
|
||||||
// no default value, construct a variable with the proper type and dummy value and raise a warning
|
// no default value, construct a variable with the proper type and dummy value and raise a warning
|
||||||
|
b.append("/*UNMAPPED_").append(v.getName()).append("*/ ");
|
||||||
b.append(getConstructor(v.getType()));
|
b.append(getConstructor(v.getType()));
|
||||||
log.log(Level.WARNING, "No input defined for variable " + v.getName() + " on shader node " + shaderNode.getName());
|
log.log(Level.WARNING, "No input defined for variable " + v.getName() + " on shader node " + shaderNode.getName());
|
||||||
}
|
}
|
||||||
@ -291,28 +292,28 @@ public class Glsl100ShaderGenerator extends ShaderGenerator {
|
|||||||
for (VariableMapping mapping : maps) {
|
for (VariableMapping mapping : maps) {
|
||||||
map(mapping, source, true);
|
map(mapping, source, true);
|
||||||
}
|
}
|
||||||
b.append(shaderNode.getName())
|
appendVariable(shaderNode.getName(), b, v);
|
||||||
.append("_")
|
|
||||||
.append(v.getName());
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// outputs
|
// outputs
|
||||||
String name = shaderNode.getName() + "_" + v.getName();
|
declareOutput(source, shaderNode.getName(), info, v);
|
||||||
// if the output is not a varying (already declared) we declare it)
|
|
||||||
if (!isVarying(info, name)) {
|
|
||||||
appendIndent(source);
|
|
||||||
source.append(v.getType()).append(" ").append(name).append(";\n");
|
|
||||||
}
|
|
||||||
// append the variable to the function call
|
// append the variable to the function call
|
||||||
b.append(shaderNode.getName())
|
appendVariable(shaderNode.getName(), b, v);
|
||||||
.append("_")
|
|
||||||
.append(v.getName());
|
|
||||||
}
|
}
|
||||||
isFirst = false;
|
isFirst = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
b.append(");\n");
|
b.append(");\n");
|
||||||
|
|
||||||
|
if(!definition.getReturnType().equals("void")){
|
||||||
|
// non void return type, the first output is the result
|
||||||
|
ShaderNodeVariable v = definition.getOutputs().get(0);
|
||||||
|
declareOutput(source, shaderNode.getName(), info, v);
|
||||||
|
appendIndent(source);
|
||||||
|
appendVariable(shaderNode.getName(), source, v);
|
||||||
|
source.append(" =");
|
||||||
|
}
|
||||||
|
|
||||||
// Map any output to global output.
|
// Map any output to global output.
|
||||||
for (VariableMapping mapping : shaderNode.getOutputMapping()) {
|
for (VariableMapping mapping : shaderNode.getOutputMapping()) {
|
||||||
map(mapping, b, false);
|
map(mapping, b, false);
|
||||||
@ -322,6 +323,19 @@ public class Glsl100ShaderGenerator extends ShaderGenerator {
|
|||||||
endCondition(shaderNode.getCondition(), source);
|
endCondition(shaderNode.getCondition(), source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void declareOutput(StringBuilder source, String nameSpace, ShaderGenerationInfo info, ShaderNodeVariable v) {
|
||||||
|
String name = nameSpace + "_" + v.getName();
|
||||||
|
// if the output is not a varying (already declared) we declare it)
|
||||||
|
if (!isVarying(info, name)) {
|
||||||
|
appendIndent(source);
|
||||||
|
source.append(v.getType()).append(" ").append(name).append(";\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void appendVariable(String nameSpace, StringBuilder b, ShaderNodeVariable v) {
|
||||||
|
b.append(nameSpace).append("_").append(v.getName());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a proper constructor call for a given type
|
* Returns a proper constructor call for a given type
|
||||||
* @param type
|
* @param type
|
||||||
|
@ -104,6 +104,15 @@ public final class Shader extends NativeObject {
|
|||||||
return extension;
|
return extension;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ShaderType fromExtention(String ext){
|
||||||
|
for (ShaderType shaderType : values()) {
|
||||||
|
if(shaderType.extension.equals(ext)){
|
||||||
|
return shaderType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private ShaderType(String extension) {
|
private ShaderType(String extension) {
|
||||||
this.extension = extension;
|
this.extension = extension;
|
||||||
}
|
}
|
||||||
|
@ -219,11 +219,14 @@ public abstract class ShaderGenerator {
|
|||||||
// Nodes are functions added to the declaration part of the shader
|
// Nodes are functions added to the declaration part of the shader
|
||||||
// Multiple nodes may use the same definition and we don't want to declare it several times.
|
// Multiple nodes may use the same definition and we don't want to declare it several times.
|
||||||
// Also nodes can have #ifdef conditions so we need to properly merge this conditions to declare the Node function.
|
// Also nodes can have #ifdef conditions so we need to properly merge this conditions to declare the Node function.
|
||||||
NodeDeclaration nd = declaredNodes.get(shaderNode.getDefinition().getName());
|
NodeDeclaration nd = declaredNodes.get(shaderPath);
|
||||||
loadedSource = functionize(loadedSource, shaderNode.getDefinition());
|
|
||||||
if(nd == null){
|
if(nd == null){
|
||||||
|
if(!shaderNode.getDefinition().getPath().equals(shaderPath)) {
|
||||||
|
// old style shader node definition
|
||||||
|
loadedSource = functionize(loadedSource, shaderNode.getDefinition());
|
||||||
|
}
|
||||||
nd = new NodeDeclaration(shaderNode.getCondition(), loadedSource);
|
nd = new NodeDeclaration(shaderNode.getCondition(), loadedSource);
|
||||||
declaredNodes.put(shaderNode.getDefinition().getName(), nd);
|
declaredNodes.put(shaderPath, nd);
|
||||||
} else {
|
} else {
|
||||||
nd.condition = ConditionParser.mergeConditions(nd.condition, shaderNode.getCondition(), "||");
|
nd.condition = ConditionParser.mergeConditions(nd.condition, shaderNode.getCondition(), "||");
|
||||||
}
|
}
|
||||||
@ -237,7 +240,7 @@ public abstract class ShaderGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tuns old style shader node code into a proper function so that it can be appended to the declarative sectio.
|
* Turns old style shader node code into a proper function so that it can be appended to the declarative section.
|
||||||
* Note that this only needed for nodes coming from a j3sn file.
|
* Note that this only needed for nodes coming from a j3sn file.
|
||||||
* @param source
|
* @param source
|
||||||
* @param def
|
* @param def
|
||||||
|
@ -148,14 +148,13 @@ public class ShaderNode implements Savable, Cloneable {
|
|||||||
*
|
*
|
||||||
* @return the input mappings.
|
* @return the input mappings.
|
||||||
*/
|
*/
|
||||||
public List<VariableMapping> getInputMapping(String varName) {
|
public void getInputMapping(String varName, List<VariableMapping> list) {
|
||||||
List<VariableMapping> list = new ArrayList<>();
|
list.clear();
|
||||||
for (VariableMapping v : inputMapping) {
|
for (VariableMapping v : inputMapping) {
|
||||||
if (v.getLeftVariable().getName().equals(varName)){
|
if (v.getLeftVariable().getName().equals(varName)){
|
||||||
list.add(v);
|
list.add(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -31,6 +31,15 @@
|
|||||||
*/
|
*/
|
||||||
package com.jme3.shader;
|
package com.jme3.shader;
|
||||||
|
|
||||||
|
import com.jme3.asset.AssetManager;
|
||||||
|
import com.jme3.shader.plugins.ShaderAssetKey;
|
||||||
|
|
||||||
|
import java.io.StringReader;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
public class ShaderUtils {
|
public class ShaderUtils {
|
||||||
|
|
||||||
public static String convertToGLSL130(String input, boolean isFrag) {
|
public static String convertToGLSL130(String input, boolean isFrag) {
|
||||||
@ -136,4 +145,116 @@ public class ShaderUtils {
|
|||||||
public static boolean isSwizzlable(String type) {
|
public static boolean isSwizzlable(String type) {
|
||||||
return type.indexOf("vec4")>-1 || type.indexOf("vec3")>-1 || type.indexOf("vec2")>-1 || type.equals("float");
|
return type.indexOf("vec4")>-1 || type.indexOf("vec3")>-1 || type.indexOf("vec2")>-1 || type.equals("float");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final static Pattern defaultsPattern = Pattern.compile("defaults\\s*\\(\\s*(.*)\\s*\\)");
|
||||||
|
// matches "<type> <functionName>("
|
||||||
|
private final static Pattern typeNamePattern = Pattern.compile("(\\w+)\\s+(\\w+)\\s*\\(");
|
||||||
|
// matches "const? <in/out> <type> <parmaName>,"
|
||||||
|
private final static Pattern paramsPattern = Pattern.compile("((const)?\\s*(\\w+)\\s+(\\w+)\\s+(\\w+)\\s*[,\\)])");
|
||||||
|
|
||||||
|
public static List<ShaderNodeDefinition> parseDefinitions(String glsl) throws ParseException {
|
||||||
|
List<ShaderNodeDefinition> defs = new ArrayList<>();
|
||||||
|
String nodesCode[] = glsl.split("#pragma ShaderNode");
|
||||||
|
for (String code : nodesCode) {
|
||||||
|
if (code.trim().length() == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int firstCr = code.indexOf("\n");
|
||||||
|
int firstBracket = code.indexOf("{");
|
||||||
|
String pragma = code.substring(0, firstCr);
|
||||||
|
Matcher m1 = defaultsPattern.matcher(pragma);
|
||||||
|
String[] defaults = null;
|
||||||
|
if (m1.find()) {
|
||||||
|
defaults = m1.group(1).split(",");
|
||||||
|
}
|
||||||
|
|
||||||
|
code = code.substring(firstCr + 1, firstBracket);
|
||||||
|
|
||||||
|
Matcher m = typeNamePattern.matcher(code);
|
||||||
|
|
||||||
|
String returnType = null;
|
||||||
|
String functionName = null;
|
||||||
|
while (m.find()) {
|
||||||
|
returnType = m.group(1);
|
||||||
|
functionName = m.group(2);
|
||||||
|
}
|
||||||
|
if (returnType == null || functionName == null) {
|
||||||
|
throw new ParseException("Unmatched return type or function name in \n" + code, firstCr + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ShaderNodeDefinition def = new ShaderNodeDefinition();
|
||||||
|
def.setName(functionName);
|
||||||
|
def.setReturnType(returnType);
|
||||||
|
|
||||||
|
m.reset();
|
||||||
|
m.usePattern(paramsPattern);
|
||||||
|
|
||||||
|
List<ShaderNodeVariable> inputs = new ArrayList<>();
|
||||||
|
List<ShaderNodeVariable> outputs = new ArrayList<>();
|
||||||
|
List<ShaderNodeVariable> params = new ArrayList<>();
|
||||||
|
|
||||||
|
if (!returnType.equals("void")) {
|
||||||
|
ShaderNodeVariable result = new ShaderNodeVariable(returnType, "result");
|
||||||
|
outputs.add(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cpt = 0;
|
||||||
|
while (m.find()) {
|
||||||
|
String dir = m.group(3);
|
||||||
|
String type = m.group(4);
|
||||||
|
String varName = m.group(5);
|
||||||
|
ShaderNodeVariable v = new ShaderNodeVariable(type, varName);
|
||||||
|
params.add(v);
|
||||||
|
String defVal = null;
|
||||||
|
if (defaults != null && defaults.length > cpt) {
|
||||||
|
defVal = defaults[cpt].trim();
|
||||||
|
defVal = defVal.isEmpty() ? null : defVal;
|
||||||
|
}
|
||||||
|
v.setDefaultValue(defVal);
|
||||||
|
switch (dir) {
|
||||||
|
case "in":
|
||||||
|
inputs.add(v);
|
||||||
|
break;
|
||||||
|
case "out":
|
||||||
|
outputs.add(v);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ParseException("Missing in or out keyword for variable " + varName + " in function " + functionName, m.start());
|
||||||
|
}
|
||||||
|
cpt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
def.setParams(params);
|
||||||
|
def.setInputs(inputs);
|
||||||
|
if (outputs.isEmpty()) {
|
||||||
|
def.setNoOutput(true);
|
||||||
|
} else {
|
||||||
|
def.setOutputs(outputs);
|
||||||
|
}
|
||||||
|
|
||||||
|
defs.add(def);
|
||||||
|
}
|
||||||
|
|
||||||
|
return defs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Shader.ShaderType getShaderType(String shaderPath) {
|
||||||
|
String ext = shaderPath.substring(shaderPath.lastIndexOf(".") + 1);
|
||||||
|
return Shader.ShaderType.fromExtention(ext);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<ShaderNodeDefinition> loadSahderNodeDefinition(AssetManager assetManager, String definitionPath) throws ParseException {
|
||||||
|
Map<String, String> sources = (Map<String, String>) assetManager.loadAsset(new ShaderAssetKey(definitionPath, false));
|
||||||
|
String glsl = sources.get("[main]");
|
||||||
|
List<ShaderNodeDefinition> defs = ShaderUtils.parseDefinitions(glsl);
|
||||||
|
Shader.ShaderType type = ShaderUtils.getShaderType(definitionPath);
|
||||||
|
for (ShaderNodeDefinition d : defs) {
|
||||||
|
d.setType(type);
|
||||||
|
d.getShadersLanguage().add("GLSL100");
|
||||||
|
d.setPath(definitionPath);
|
||||||
|
d.getShadersPath().add(definitionPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
return defs;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,9 +40,11 @@ import com.jme3.material.ShaderGenerationInfo;
|
|||||||
import com.jme3.material.TechniqueDef;
|
import com.jme3.material.TechniqueDef;
|
||||||
import com.jme3.shader.Shader.ShaderType;
|
import com.jme3.shader.Shader.ShaderType;
|
||||||
import com.jme3.shader.*;
|
import com.jme3.shader.*;
|
||||||
|
import com.jme3.shader.plugins.ShaderAssetKey;
|
||||||
import com.jme3.util.blockparser.Statement;
|
import com.jme3.util.blockparser.Statement;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.text.ParseException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -996,9 +998,15 @@ public class ShaderNodeLoaderDelegate {
|
|||||||
|
|
||||||
List<ShaderNodeDefinition> defs;
|
List<ShaderNodeDefinition> defs;
|
||||||
try {
|
try {
|
||||||
defs = assetManager.loadAsset(new ShaderNodeDefinitionKey(definitionPath));
|
if(definitionPath.endsWith(".j3sn")) {
|
||||||
|
defs = assetManager.loadAsset(new ShaderNodeDefinitionKey(definitionPath));
|
||||||
|
} else {
|
||||||
|
defs = ShaderUtils.loadSahderNodeDefinition(assetManager, definitionPath);
|
||||||
|
}
|
||||||
} catch (final AssetNotFoundException e) {
|
} catch (final AssetNotFoundException e) {
|
||||||
throw new MatParseException("Couldn't find " + definitionPath, statement, e);
|
throw new MatParseException("Couldn't find " + definitionPath, statement, e);
|
||||||
|
} catch (ParseException e) {
|
||||||
|
throw new MatParseException("Error while loading shader node definition" + definitionPath, statement, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (final ShaderNodeDefinition definition : defs) {
|
for (final ShaderNodeDefinition definition : defs) {
|
||||||
|
@ -24,7 +24,7 @@ public class TestShaderNodes extends SimpleApplication {
|
|||||||
flyCam.setMoveSpeed(20);
|
flyCam.setMoveSpeed(20);
|
||||||
Logger.getLogger("com.jme3").setLevel(Level.WARNING);
|
Logger.getLogger("com.jme3").setLevel(Level.WARNING);
|
||||||
Box boxshape1 = new Box(1f, 1f, 1f);
|
Box boxshape1 = new Box(1f, 1f, 1f);
|
||||||
Geometry cube_tex = new Geometry("A Textured Box", boxshape1);
|
Geometry cube = new Geometry("A Box", boxshape1);
|
||||||
Texture tex = assetManager.loadTexture("Interface/Logo/Monkey.jpg");
|
Texture tex = assetManager.loadTexture("Interface/Logo/Monkey.jpg");
|
||||||
|
|
||||||
Material mat = new Material(assetManager, "Common/MatDefs/Misc/UnshadedNodes.j3md");
|
Material mat = new Material(assetManager, "Common/MatDefs/Misc/UnshadedNodes.j3md");
|
||||||
@ -37,7 +37,25 @@ public class TestShaderNodes extends SimpleApplication {
|
|||||||
|
|
||||||
mat.setColor("Color", ColorRGBA.Yellow);
|
mat.setColor("Color", ColorRGBA.Yellow);
|
||||||
mat.setTexture("ColorMap", tex);
|
mat.setTexture("ColorMap", tex);
|
||||||
cube_tex.setMaterial(mat);
|
cube.setMaterial(mat);
|
||||||
rootNode.attachChild(cube_tex);
|
cube.move(-2.5f,0,0);
|
||||||
|
rootNode.attachChild(cube);
|
||||||
|
|
||||||
|
|
||||||
|
cube = cube.clone();
|
||||||
|
mat = new Material(assetManager, "jme3test/matdefs/test.j3md");
|
||||||
|
mat.selectTechnique(TechniqueDef.DEFAULT_TECHNIQUE_NAME, renderManager);
|
||||||
|
t = mat.getActiveTechnique();
|
||||||
|
|
||||||
|
for (Shader.ShaderSource shaderSource : t.getDef().getShader(assetManager, renderer.getCaps(), t.getDynamicDefines()).getSources()) {
|
||||||
|
System.out.println(shaderSource.getSource());
|
||||||
|
}
|
||||||
|
|
||||||
|
mat.setColor("Color", ColorRGBA.Yellow);
|
||||||
|
//mat.setTexture("ColorMap", tex);
|
||||||
|
cube.setMaterial(mat);
|
||||||
|
cube.move(2.5f,0,0);
|
||||||
|
rootNode.attachChild(cube);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
#pragma ShaderNode defaults(vec4(1.0), ,vec4(1.0))
|
||||||
|
vec4 ColorMult(const in vec4 color1, const in vec4 color2, const in vec4 color3){
|
||||||
|
return color1 * color2 * color3;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
|||||||
|
#pragma ShaderNode
|
||||||
|
vec4 CommonVert(const in mat4 worldViewProjectionMatrix, const in vec3 modelPosition){
|
||||||
|
return worldViewProjectionMatrix * vec4(modelPosition, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma ShaderNode
|
||||||
|
vec4 DoThing( in vec4 color ){
|
||||||
|
return color * 0.1;
|
||||||
|
}
|
45
jme3-examples/src/main/resources/jme3test/matdefs/test.j3md
Normal file
45
jme3-examples/src/main/resources/jme3test/matdefs/test.j3md
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
MaterialDef Simple {
|
||||||
|
MaterialParameters {
|
||||||
|
Vector4 Color
|
||||||
|
}
|
||||||
|
|
||||||
|
Technique {
|
||||||
|
WorldParameters {
|
||||||
|
WorldViewProjectionMatrix
|
||||||
|
}
|
||||||
|
|
||||||
|
VertexShaderNodes {
|
||||||
|
ShaderNode CommonVert {
|
||||||
|
Definition: CommonVert: jme3test/matdefs/CommonVert.vert
|
||||||
|
InputMappings{
|
||||||
|
worldViewProjectionMatrix = WorldParam.WorldViewProjectionMatrix
|
||||||
|
modelPosition = Attr.inPosition
|
||||||
|
}
|
||||||
|
OutputMappings{
|
||||||
|
Global.position = result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ShaderNode ColorStuff {
|
||||||
|
Definition: DoThing: jme3test/matdefs/CommonVert.vert
|
||||||
|
InputMappings{
|
||||||
|
color = MatParam.Color
|
||||||
|
}
|
||||||
|
OutputMappings{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FragmentShaderNodes {
|
||||||
|
ShaderNode ColorMult {
|
||||||
|
Definition: ColorMult: jme3test/matdefs/ColorMult.frag
|
||||||
|
InputMappings{
|
||||||
|
color2 = ColorStuff.result
|
||||||
|
}
|
||||||
|
OutputMappings{
|
||||||
|
Global.color = result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user