2
0
Эх сурвалжийг харах

Added global and inputs to shaders, added safeties for loading

Clement Espeute 2 жил өмнө
parent
commit
1eb2ea7073

+ 3 - 3
hide/view/shadereditor/ShaderEditor.hx

@@ -1039,7 +1039,7 @@ class ShaderEditor extends hide.view.Graph {
 		}
 		try {
 			beforeChange();
-			if (shaderGraph.addEdge({ idOutput: startLinkBox.getId(), nameOutput: startLinkNode.attr("field"), idInput: endLinkBox.getId(), nameInput: endLinkNode.attr("field") })) {
+			if (shaderGraph.addEdge({ outputNodeId: startLinkBox.getId(), nameOutput: startLinkNode.attr("field"), inputNodeId: endLinkBox.getId(), nameInput: endLinkNode.attr("field") })) {
 				afterChange();
 				createEdgeInEditorGraph(newEdge);
 				currentLink.removeClass("draft");
@@ -1459,9 +1459,9 @@ class ShaderEditor extends hide.view.Graph {
 			if( instancedBoxes[edge.fromIdx] == null || instancedBoxes[edge.toIdx] == null )
 				continue;
 			var toCreate = {
-				idOutput: instancedBoxes[edge.fromIdx].getId(),
+				outputNodeId: instancedBoxes[edge.fromIdx].getId(),
 				nameOutput: edge.fromName,
-				idInput: instancedBoxes[edge.toIdx].getId(),
+				inputNodeId: instancedBoxes[edge.toIdx].getId(),
 				nameInput: edge.toName,
 			}
 			if( !shaderGraph.addEdge(toCreate) ) {

+ 14 - 1
hrt/shgraph/ShaderGlobalInput.hx

@@ -6,13 +6,26 @@ using hxsl.Ast;
 @description("Global Inputs")
 @group("Property")
 @color("#0e8826")
-class ShaderGlobalInput extends ShaderInput {
+class ShaderGlobalInput extends ShaderNode {
+
+	@prop("Variable") public var variable : TVar = globalInputs[0];
+
 
 	static public var globalInputs = [	{ parent: null, id: 0, kind: Global, name: "global.time", type: TFloat },
 										{ parent: null, id: 0, kind: Global, name: "global.pixelSize", type: TVec(2, VFloat) },
 										{ parent: null, id: 0, kind: Global, name: "global.modelView", type: TMat4 },
 										{ parent: null, id: 0, kind: Global, name: "global.modelViewInverse", type: TMat4 } ];
 
+	override function getShaderDef():hrt.shgraph.ShaderGraph.ShaderNodeDef {
+		var pos : Position = {file: "", min: 0, max: 0};
+
+		var inVar : TVar = variable;
+		var output : TVar = {name: "output", id:1, type: this.variable.type, kind: Local, qualifiers: [SgOutput]};
+		var finalExpr : TExpr = {e: TBinop(OpAssign, {e:TVar(output), p:pos, t:output.type}, {e: TVar(inVar), p: pos, t: output.type}), p: pos, t: output.type};
+
+		return {expr: finalExpr, inVars: [], outVars:[output], externVars: [inVar, output], inits: []};
+	}
+
 	override public function loadProperties(props : Dynamic) {
 		var paramVariable : String = Reflect.field(props, "variable");
 		for (c in ShaderGlobalInput.globalInputs) {

+ 65 - 17
hrt/shgraph/ShaderGraph.hx

@@ -26,10 +26,12 @@ typedef Node = {
 };
 
 private typedef Edge = {
-	idOutput : Int,
+	outputNodeId : Int,
 	nameOutput : String,
-	idInput : Int,
-	nameInput : String
+	?outputId : Int, // Fallback if name has changed
+	inputNodeId : Int,
+	nameInput : String,
+	?inputId : Int, // Fallback if name has changed
 };
 
 typedef Connection = {
@@ -129,40 +131,68 @@ class ShaderGraph {
 		if (nodes[nodes.length-1] != null)
 			this.current_node_id = nodes[nodes.length-1].id+1;
 
+		// Migration patch
+		for (e in edges) {
+			if (e.inputNodeId == null)
+				e.inputNodeId = (e:Dynamic).idInput;
+			if (e.outputNodeId == null)
+				e.outputNodeId = (e:Dynamic).idOutput;
+		}
+
 		for (e in edges) {
 			addEdge(e);
 		}
 	}
 
 	public function addEdge(edge : Edge) {
-		var node = this.nodes.get(edge.idInput);
-		var output = this.nodes.get(edge.idOutput);
+		var node = this.nodes.get(edge.inputNodeId);
+		var output = this.nodes.get(edge.outputNodeId);
 
 		var inputs = node.instance.getInputs2();
 		var outputs = output.instance.getOutputs2();
 
-		if (!output.instance.getOutputs2().exists(edge.nameOutput) || !node.instance.getInputs2().exists(edge.nameInput)) {
-			return false;
+		var inputName = edge.nameInput;
+		var outputName = edge.nameOutput;
+
+		// Patch I/O if name have changed
+		if (!outputs.exists(outputName)) {
+			var def = output.instance.getShaderDef();
+			if(edge.outputId != null && def.outVars.length > edge.outputId) {
+				outputName = def.outVars[edge.outputId].name;
+			}
+			else {
+				return false;
+			}
 		}
 
-		var connection : Connection = {from: output, fromName: edge.nameOutput};
-		node.instance.connections.set(edge.nameInput, connection);
+		if (!inputs.exists(inputName)) {
+			var def = node.instance.getShaderDef();
+			if (edge.inputId != null && def.inVars.length > edge.inputId) {
+				inputName = def.inVars[edge.inputId].name;
+			}
+			else {
+				return false;
+			}
+		}
+
+		var connection : Connection = {from: output, fromName: outputName};
+		node.instance.connections.set(inputName, connection);
 
 		#if editor
 		if (hasCycle()){
-			removeEdge(edge.idInput, edge.nameInput, false);
+			removeEdge(edge.inputNodeId, inputName, false);
 			return false;
 		}
 
-		var inputType = inputs[edge.nameInput].type;
-		var outputType = outputs[edge.nameOutput].type;
+		var inputType = inputs[inputName].type;
+		var outputType = outputs[outputName].type;
 
 		if (!areTypesCompatible(inputType, outputType)) {
-			removeEdge(edge.idInput, edge.nameInput);
+			removeEdge(edge.inputNodeId, inputName);
 		}
 		try {
 		} catch (e : Dynamic) {
-			removeEdge(edge.idInput, edge.nameInput);
+			removeEdge(edge.inputNodeId, inputName);
 			throw e;
 		}
 		#end
@@ -427,11 +457,11 @@ class ShaderGraph {
 							}
 						}
 						else {
-							externs.push(nodeVar);
+							externs.pushUnique(nodeVar);
 						}
 					}
 					else {
-						externs.push(nodeVar);
+						externs.pushUnique(nodeVar);
 					}
 				}
 
@@ -626,7 +656,25 @@ class ShaderGraph {
 		var edgesJson : Array<Edge> = [];
 		for (n in nodes) {
 			for (inputName => connection in n.instance.connections) {
-				edgesJson.push({ idOutput: connection.from.id, nameOutput: connection.fromName, idInput: n.id, nameInput: inputName });
+				var def = n.instance.getShaderDef();
+				var inputId = null;
+				for (i => inVar in def.inVars) {
+					if (inVar.name == inputName) {
+						inputId = i;
+						break;
+					}
+				}
+
+				var def = connection.from.instance.getShaderDef();
+				var outputId = null;
+				for (i => outVar in def.outVars) {
+					if (outVar.name == connection.fromName) {
+						outputId = i;
+						break;
+					}
+				}
+
+				edgesJson.push({ outputNodeId: connection.from.id, nameOutput: connection.fromName, inputNodeId: n.id, nameInput: inputName, inputId: inputId, outputId: outputId });
 			}
 		}
 		var json = haxe.Json.stringify({

+ 12 - 1
hrt/shgraph/ShaderInput.hx

@@ -9,7 +9,7 @@ using hxsl.Ast;
 class ShaderInput extends ShaderNode {
 
 
-	@prop("Variable") public var variable : TVar;
+	@prop("Variable") public var variable : TVar = availableInputs[0];
 
 	// override public function getOutput(key : String) : TVar {
 	// 	return variable;
@@ -19,6 +19,17 @@ class ShaderInput extends ShaderNode {
 	// 	return null;
 	// }
 
+	override function getShaderDef():hrt.shgraph.ShaderGraph.ShaderNodeDef {
+		var pos : Position = {file: "", min: 0, max: 0};
+
+		var inVar : TVar = variable;
+		var output : TVar = {name: "output", id:1, type: this.variable.type, kind: Local, qualifiers: [SgOutput]};
+		var finalExpr : TExpr = {e: TBinop(OpAssign, {e:TVar(output), p:pos, t:output.type}, {e: TVar(inVar), p: pos, t: output.type}), p: pos, t: output.type};
+
+
+		return {expr: finalExpr, inVars: [], outVars:[output], externVars: [inVar, output], inits: []};
+	}
+
 	public static var availableInputs : Array<TVar> = [
 									{ parent: null, id: 0, kind: Input, name: "position", type: TVec(3, VFloat) },
 									{ parent: null, id: 0, kind: Input, name: "color", type: TVec(3, VFloat) },

+ 7 - 2
hrt/shgraph/nodes/Sampler.hx

@@ -10,10 +10,15 @@ class Sampler extends ShaderNodeHxsl {
 	static var SRC = {
 		@sginput var texture : Sampler2D;
 		@sginput var uv : Vec2;
-		@sgoutput var output : Vec4;
+		@sgoutput var RGBA : Vec4;
+		@sgoutput var RGB : Vec3;
+		@sgoutput var A : Float;
+
 
 		function fragment() {
-			output = texture.get(uv);
+			RGBA = texture.get(uv);
+			RGB = RGBA.rgb;
+			A = RGBA.a;
 		}
 	}