Florent Guinier
8 年前
当前提交
085216ab
共有 6 个文件被更改,包括 288 次插入 和 311 次删除
-
147MaterialGraphProject/Assets/Matt&Andre/SplitChannelsNode.cs
-
141MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/CombineChannelsNode.cs
-
208MaterialGraphProject/Assets/Matt&Andre/ComponentSplitNode.cs
-
103MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/CombineNode.cs
-
0/MaterialGraphProject/Assets/Matt&Andre/SplitChannelsNode.cs.meta
-
0/MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/CombineChannelsNode.cs.meta
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
#if UNITY_EDITOR
|
|||
using UnityEditor; |
|||
#endif
|
|||
using UnityEngine.Graphing; |
|||
|
|||
namespace UnityEngine.MaterialGraph |
|||
{ |
|||
[Title("Channel/Split")] |
|||
public class SplitChannelsNode : PropertyNode, IGeneratesBodyCode |
|||
{ |
|||
protected const string kInputSlotName = "Input"; |
|||
protected const string kOutputSlotRName = "R"; |
|||
protected const string kOutputSlotGName = "G"; |
|||
protected const string kOutputSlotBName = "B"; |
|||
protected const string kOutputSlotAName = "A"; |
|||
protected const string kOutputSlotRGBName = "RGB"; |
|||
protected const string kOutputSlotRGName = "RG"; |
|||
|
|||
public const int InputSlotId = 0; |
|||
public const int OutputSlotRId = 1; |
|||
public const int OutputSlotGId = 2; |
|||
public const int OutputSlotBId = 3; |
|||
public const int OutputSlotAId = 4; |
|||
public const int OutputSlotRGBId = 5; |
|||
public const int OutputSlotRGId = 6; |
|||
|
|||
public SplitChannelsNode() |
|||
{ |
|||
name = "ComponentSplit"; |
|||
UpdateNodeAfterDeserialization(); |
|||
} |
|||
|
|||
public sealed override void UpdateNodeAfterDeserialization() |
|||
{ |
|||
AddSlot(new MaterialSlot(InputSlotId, kInputSlotName, kInputSlotName, SlotType.Input, SlotValueType.Dynamic, Vector4.zero)); |
|||
AddSlot(new MaterialSlot(OutputSlotRId, kOutputSlotRName, kOutputSlotRName, SlotType.Output, SlotValueType.Vector1, Vector4.zero)); |
|||
AddSlot(new MaterialSlot(OutputSlotGId, kOutputSlotGName, kOutputSlotGName, SlotType.Output, SlotValueType.Vector1, Vector4.zero)); |
|||
AddSlot(new MaterialSlot(OutputSlotBId, kOutputSlotBName, kOutputSlotBName, SlotType.Output, SlotValueType.Vector1, Vector4.zero)); |
|||
AddSlot(new MaterialSlot(OutputSlotAId, kOutputSlotAName, kOutputSlotAName, SlotType.Output, SlotValueType.Vector1, Vector4.zero)); |
|||
AddSlot(new MaterialSlot(OutputSlotRGBId, kOutputSlotRGBName, kOutputSlotRGBName, SlotType.Output, SlotValueType.Vector3, Vector4.zero)); |
|||
AddSlot(new MaterialSlot(OutputSlotRGId, kOutputSlotRGName, kOutputSlotRGName, SlotType.Output, SlotValueType.Vector2, Vector4.zero)); |
|||
RemoveSlotsNameNotMatching(validSlots); |
|||
} |
|||
|
|||
protected int[] validSlots |
|||
{ |
|||
get { return new[] { InputSlotId, OutputSlotRId, OutputSlotGId, OutputSlotBId, OutputSlotAId, OutputSlotRGBId, OutputSlotRGId }; } |
|||
} |
|||
|
|||
[SerializeField] |
|||
private Vector4 m_Value; |
|||
|
|||
public Vector4 value |
|||
{ |
|||
get { return m_Value; } |
|||
set |
|||
{ |
|||
if (m_Value == value) |
|||
return; |
|||
|
|||
m_Value = value; |
|||
|
|||
if (onModified != null) |
|||
onModified(this, ModificationScope.Node); |
|||
} |
|||
} |
|||
|
|||
public override PropertyType propertyType { get { return PropertyType.Vector4; } } |
|||
|
|||
public override void GeneratePropertyBlock(PropertyGenerator visitor, GenerationMode generationMode) |
|||
{ |
|||
if (exposedState == ExposedState.Exposed) |
|||
visitor.AddShaderProperty(new VectorPropertyChunk(propertyName, description, m_Value, PropertyChunk.HideState.Visible)); |
|||
} |
|||
|
|||
public override void GeneratePropertyUsages(ShaderGenerator visitor, GenerationMode generationMode) |
|||
{ |
|||
if (exposedState == ExposedState.Exposed || generationMode.IsPreview()) |
|||
visitor.AddShaderChunk(precision + "4 " + propertyName + ";", true); |
|||
} |
|||
|
|||
public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode) |
|||
{ |
|||
//if (exposedState == ExposedState.Exposed || generationMode.IsPreview())
|
|||
// return;
|
|||
var inputValue = GetSlotValue(InputSlotId, generationMode); |
|||
visitor.AddShaderChunk(precision + "4 " + propertyName + " = " + inputValue + ";", false); |
|||
//visitor.AddShaderChunk(precision + "4 " + propertyName + " = " + precision + "4 (" + m_Value.x + ", " + m_Value.y + ", " + m_Value.z + ", " + m_Value.w + ");", true);
|
|||
} |
|||
|
|||
protected virtual MaterialSlot GetInputSlot() |
|||
{ |
|||
return new MaterialSlot(InputSlotId, GetInputSlotName(), kInputSlotName, SlotType.Input, SlotValueType.Dynamic, Vector4.zero); |
|||
} |
|||
|
|||
protected virtual string GetInputSlotName() { return "Input"; } |
|||
|
|||
public override PreviewProperty GetPreviewProperty() |
|||
{ |
|||
return new PreviewProperty |
|||
{ |
|||
m_Name = propertyName, |
|||
m_PropType = PropertyType.Vector4, |
|||
m_Vector4 = m_Value |
|||
}; |
|||
} |
|||
|
|||
public override string GetVariableNameForSlot(int slotId) |
|||
{ |
|||
string slotOutput; |
|||
switch (slotId) |
|||
{ |
|||
case OutputSlotRId: |
|||
slotOutput = ".r"; |
|||
break; |
|||
case OutputSlotGId: |
|||
slotOutput = ".g"; |
|||
break; |
|||
case OutputSlotBId: |
|||
slotOutput = ".b"; |
|||
break; |
|||
case OutputSlotAId: |
|||
slotOutput = ".a"; |
|||
break; |
|||
case OutputSlotRGBId: |
|||
slotOutput = ".rgb"; |
|||
break; |
|||
case OutputSlotRGId: |
|||
slotOutput = ".rg"; |
|||
break; |
|||
default: |
|||
slotOutput = ""; |
|||
break; |
|||
} |
|||
return propertyName + slotOutput; |
|||
//return GetVariableNameForNode() + slotOutput;
|
|||
} |
|||
|
|||
public override void CollectPreviewMaterialProperties(List<PreviewProperty> properties) |
|||
{ |
|||
properties.Add(GetPreviewProperty()); |
|||
} |
|||
} |
|||
} |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using UnityEngine.Graphing; |
|||
|
|||
namespace UnityEngine.MaterialGraph |
|||
{ |
|||
[Title("Channel/Combine")] |
|||
public class CombineChannelsNode : PropertyNode, IGeneratesBodyCode |
|||
{ |
|||
protected const string kOutputSlot0Id = "Input0"; |
|||
protected const string kOutputSlot1Id = "Input1"; |
|||
protected const string kOutputSlot2Id = "Input2"; |
|||
protected const string kOutputSlot3Id = "Input3"; |
|||
|
|||
protected const string kOutputSlotRGBAName = "RGBA"; |
|||
protected const string kOutputSlotRGBSlotName = "RGB"; |
|||
protected const string kOutputSlotRGSlotName = "RG"; |
|||
|
|||
public const int InputSlot0Id = 0; |
|||
public const int InputSlot1Id = 1; |
|||
public const int InputSlot2Id = 2; |
|||
public const int InputSlot3Id = 3; |
|||
|
|||
public const int OutputSlotRGBAId = 4; |
|||
public const int OutputSlotRGBId = 5; |
|||
public const int OutputSlotRGId = 6; |
|||
|
|||
public CombineChannelsNode() |
|||
{ |
|||
name = "ChannelsCombine"; |
|||
UpdateNodeAfterDeserialization(); |
|||
} |
|||
|
|||
public sealed override void UpdateNodeAfterDeserialization() |
|||
{ |
|||
AddSlot(new MaterialSlot(InputSlot0Id, kOutputSlot0Id, kOutputSlot0Id, SlotType.Input, SlotValueType.Dynamic, Vector4.zero)); |
|||
AddSlot(new MaterialSlot(InputSlot1Id, kOutputSlot1Id, kOutputSlot1Id, SlotType.Input, SlotValueType.Dynamic, Vector4.zero)); |
|||
AddSlot(new MaterialSlot(InputSlot2Id, kOutputSlot2Id, kOutputSlot2Id, SlotType.Input, SlotValueType.Dynamic, Vector4.zero)); |
|||
AddSlot(new MaterialSlot(InputSlot3Id, kOutputSlot3Id, kOutputSlot3Id, SlotType.Input, SlotValueType.Dynamic, Vector4.zero)); |
|||
|
|||
AddSlot(new MaterialSlot(OutputSlotRGBAId, kOutputSlotRGBAName, kOutputSlotRGBAName, SlotType.Output, SlotValueType.Vector4, Vector4.zero)); |
|||
AddSlot(new MaterialSlot(OutputSlotRGBId, kOutputSlotRGBSlotName, kOutputSlotRGBSlotName, SlotType.Output, SlotValueType.Vector3, Vector4.zero)); |
|||
AddSlot(new MaterialSlot(OutputSlotRGId, kOutputSlotRGSlotName, kOutputSlotRGSlotName, SlotType.Output, SlotValueType.Vector2, Vector4.zero)); |
|||
RemoveSlotsNameNotMatching(validSlots); |
|||
} |
|||
|
|||
protected int[] validSlots |
|||
{ |
|||
get { return new[] { InputSlot0Id, InputSlot1Id, InputSlot2Id, InputSlot3Id, OutputSlotRGBAId, OutputSlotRGBId, OutputSlotRGId }; } |
|||
} |
|||
|
|||
[SerializeField] |
|||
private Vector4 m_Value; |
|||
|
|||
public Vector4 value |
|||
{ |
|||
get { return m_Value; } |
|||
set |
|||
{ |
|||
if (m_Value == value) |
|||
return; |
|||
|
|||
m_Value = value; |
|||
|
|||
if (onModified != null) |
|||
onModified(this, ModificationScope.Node); |
|||
} |
|||
} |
|||
|
|||
public override PropertyType propertyType { get { return PropertyType.Vector4; } } |
|||
|
|||
public override void GeneratePropertyBlock(PropertyGenerator visitor, GenerationMode generationMode) |
|||
{ |
|||
if (exposedState == ExposedState.Exposed) |
|||
visitor.AddShaderProperty(new VectorPropertyChunk(propertyName, description, m_Value, PropertyChunk.HideState.Visible)); |
|||
} |
|||
|
|||
public override void GeneratePropertyUsages(ShaderGenerator visitor, GenerationMode generationMode) |
|||
{ |
|||
if (exposedState == ExposedState.Exposed || generationMode.IsPreview()) |
|||
visitor.AddShaderChunk(precision + "4 " + propertyName + ";", true); |
|||
} |
|||
|
|||
public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode) |
|||
{ |
|||
//if (exposedState == ExposedState.Exposed || generationMode.IsPreview())
|
|||
// return;
|
|||
var inputValue = GetSlotValue(InputSlot0Id, generationMode); |
|||
visitor.AddShaderChunk(precision + "4 " + propertyName + " = " + inputValue + ";", false); |
|||
//visitor.AddShaderChunk(precision + "4 " + propertyName + " = " + precision + "4 (" + m_Value.x + ", " + m_Value.y + ", " + m_Value.z + ", " + m_Value.w + ");", true);
|
|||
} |
|||
|
|||
protected virtual MaterialSlot GetInputSlot() |
|||
{ |
|||
return new MaterialSlot(InputSlot0Id, GetInputSlotName(), kOutputSlot0Id, SlotType.Input, SlotValueType.Dynamic, Vector4.zero); |
|||
} |
|||
|
|||
protected virtual string GetInputSlotName() { return "Input"; } |
|||
|
|||
public override PreviewProperty GetPreviewProperty() |
|||
{ |
|||
return new PreviewProperty |
|||
{ |
|||
m_Name = propertyName, |
|||
m_PropType = PropertyType.Vector4, |
|||
m_Vector4 = m_Value |
|||
}; |
|||
} |
|||
|
|||
/*public override string GetVariableNameForSlot(int slotId) |
|||
{ |
|||
string slotOutput; |
|||
switch (slotId) |
|||
{ |
|||
case OutputSlotRId: |
|||
slotOutput = ".r"; |
|||
break; |
|||
case OutputSlotGId: |
|||
slotOutput = ".g"; |
|||
break; |
|||
case OutputSlotBId: |
|||
slotOutput = ".b"; |
|||
break; |
|||
case OutputSlotAId: |
|||
slotOutput = ".a"; |
|||
break; |
|||
default: |
|||
slotOutput = ""; |
|||
break; |
|||
} |
|||
return propertyName + slotOutput; |
|||
//return GetVariableNameForNode() + slotOutput;
|
|||
}*/ |
|||
|
|||
public override void CollectPreviewMaterialProperties(List<PreviewProperty> properties) |
|||
{ |
|||
properties.Add(GetPreviewProperty()); |
|||
} |
|||
} |
|||
} |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
#if UNITY_EDITOR
|
|||
using UnityEditor; |
|||
#endif
|
|||
using UnityEngine.Graphing; |
|||
|
|||
namespace UnityEngine.MaterialGraph |
|||
{ |
|||
[Title("Channels/Component Split")] |
|||
public class ComponentSplitNode : PropertyNode, IGeneratesBodyCode |
|||
{ |
|||
protected const string kInputSlotName = "Input"; |
|||
protected const string kOutputSlotRName = "R"; |
|||
protected const string kOutputSlotGName = "G"; |
|||
protected const string kOutputSlotBName = "B"; |
|||
protected const string kOutputSlotAName = "A"; |
|||
protected const string kOutputSlotRGBASlotName = "Output"; |
|||
|
|||
public const int InputSlotId = 0; |
|||
public const int OutputSlotRId = 1; |
|||
public const int OutputSlotGId = 2; |
|||
public const int OutputSlotBId = 3; |
|||
public const int OutputSlotAId = 4; |
|||
public const int OutputSlotRGBAId = 5; |
|||
|
|||
public ComponentSplitNode() |
|||
{ |
|||
name = "ComponentSplit"; |
|||
UpdateNodeAfterDeserialization(); |
|||
} |
|||
|
|||
public sealed override void UpdateNodeAfterDeserialization() |
|||
{ |
|||
AddSlot(new MaterialSlot(InputSlotId, kInputSlotName, kInputSlotName, SlotType.Input, SlotValueType.Vector4, Vector4.zero)); |
|||
AddSlot(new MaterialSlot(OutputSlotRId, kOutputSlotRName, kOutputSlotRName, SlotType.Output, SlotValueType.Vector1, Vector4.zero)); |
|||
AddSlot(new MaterialSlot(OutputSlotGId, kOutputSlotGName, kOutputSlotGName, SlotType.Output, SlotValueType.Vector1, Vector4.zero)); |
|||
AddSlot(new MaterialSlot(OutputSlotBId, kOutputSlotBName, kOutputSlotBName, SlotType.Output, SlotValueType.Vector1, Vector4.zero)); |
|||
AddSlot(new MaterialSlot(OutputSlotAId, kOutputSlotAName, kOutputSlotAName, SlotType.Output, SlotValueType.Vector1, Vector4.zero)); |
|||
AddSlot(new MaterialSlot(OutputSlotRGBAId, kOutputSlotRGBASlotName, kOutputSlotRGBASlotName, SlotType.Output, SlotValueType.Vector4, Vector4.zero)); |
|||
RemoveSlotsNameNotMatching(validSlots); |
|||
} |
|||
|
|||
protected int[] validSlots |
|||
{ |
|||
get { return new[] { InputSlotId, OutputSlotRId, OutputSlotGId, OutputSlotBId, OutputSlotAId, OutputSlotRGBAId }; } |
|||
} |
|||
|
|||
[SerializeField] |
|||
private Vector4 m_Value; |
|||
|
|||
public Vector4 value |
|||
{ |
|||
get { return m_Value; } |
|||
set |
|||
{ |
|||
if (m_Value == value) |
|||
return; |
|||
|
|||
m_Value = value; |
|||
|
|||
if (onModified != null) |
|||
onModified(this, ModificationScope.Node); |
|||
} |
|||
} |
|||
|
|||
public override PropertyType propertyType { get { return PropertyType.Vector4; } } |
|||
|
|||
public override void GeneratePropertyBlock(PropertyGenerator visitor, GenerationMode generationMode) |
|||
{ |
|||
if (exposedState == ExposedState.Exposed) |
|||
visitor.AddShaderProperty(new VectorPropertyChunk(propertyName, description, m_Value, PropertyChunk.HideState.Visible)); |
|||
} |
|||
|
|||
public override void GeneratePropertyUsages(ShaderGenerator visitor, GenerationMode generationMode) |
|||
{ |
|||
if (exposedState == ExposedState.Exposed || generationMode.IsPreview()) |
|||
visitor.AddShaderChunk(precision + "4 " + propertyName + ";", true); |
|||
} |
|||
|
|||
public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode) |
|||
{ |
|||
//if (exposedState == ExposedState.Exposed || generationMode.IsPreview())
|
|||
// return;
|
|||
var inputValue = GetSlotValue(InputSlotId, generationMode); |
|||
visitor.AddShaderChunk(precision + "4 " + propertyName + " = " + inputValue + ";", false); |
|||
//visitor.AddShaderChunk(precision + "4 " + propertyName + " = " + precision + "4 (" + m_Value.x + ", " + m_Value.y + ", " + m_Value.z + ", " + m_Value.w + ");", true);
|
|||
} |
|||
|
|||
protected virtual MaterialSlot GetInputSlot() |
|||
{ |
|||
return new MaterialSlot(InputSlotId, GetInputSlotName(), kInputSlotName, SlotType.Input, SlotValueType.Dynamic, Vector4.zero); |
|||
} |
|||
|
|||
protected virtual string GetInputSlotName() { return "Input"; } |
|||
|
|||
public override PreviewProperty GetPreviewProperty() |
|||
{ |
|||
return new PreviewProperty |
|||
{ |
|||
m_Name = propertyName, |
|||
m_PropType = PropertyType.Vector4, |
|||
m_Vector4 = m_Value |
|||
}; |
|||
} |
|||
|
|||
public override string GetVariableNameForSlot(int slotId) |
|||
{ |
|||
string slotOutput; |
|||
switch (slotId) |
|||
{ |
|||
case OutputSlotRId: |
|||
slotOutput = ".r"; |
|||
break; |
|||
case OutputSlotGId: |
|||
slotOutput = ".g"; |
|||
break; |
|||
case OutputSlotBId: |
|||
slotOutput = ".b"; |
|||
break; |
|||
case OutputSlotAId: |
|||
slotOutput = ".a"; |
|||
break; |
|||
default: |
|||
slotOutput = ""; |
|||
break; |
|||
} |
|||
return propertyName + slotOutput; |
|||
//return GetVariableNameForNode() + slotOutput;
|
|||
} |
|||
|
|||
public override void CollectPreviewMaterialProperties(List<PreviewProperty> properties) |
|||
{ |
|||
properties.Add(GetPreviewProperty()); |
|||
} |
|||
|
|||
/* TEXTURE |
|||
// Node generations
|
|||
public virtual void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode) |
|||
{ |
|||
var uvSlot = FindInputSlot<MaterialSlot>(UvSlotId); |
|||
if (uvSlot == null) |
|||
return; |
|||
|
|||
var uvName = string.Format("{0}.xy", UVChannel.uv0.GetUVName()); |
|||
var edges = owner.GetEdges(uvSlot.slotReference).ToList(); |
|||
|
|||
if (edges.Count > 0) |
|||
{ |
|||
var edge = edges[0]; |
|||
var fromNode = owner.GetNodeFromGuid<AbstractMaterialNode>(edge.outputSlot.nodeGuid); |
|||
uvName = ShaderGenerator.AdaptNodeOutput(fromNode, edge.outputSlot.slotId, ConcreteSlotValueType.Vector2, true); |
|||
} |
|||
|
|||
string body = "tex2D (" + propertyName + ", " + uvName + ")"; |
|||
if (m_TextureType == TextureType.Bump) |
|||
body = precision + "4(UnpackNormal(" + body + "), 0)"; |
|||
visitor.AddShaderChunk(precision + "4 " + GetVariableNameForNode() + " = " + body + ";", true); |
|||
} |
|||
|
|||
// Properties
|
|||
public override void GeneratePropertyBlock(PropertyGenerator visitor, GenerationMode generationMode) |
|||
{ |
|||
visitor.AddShaderProperty( |
|||
new TexturePropertyChunk( |
|||
propertyName, |
|||
description, |
|||
defaultTexture, m_TextureType, |
|||
PropertyChunk.HideState.Visible, |
|||
exposedState == ExposedState.Exposed ? |
|||
TexturePropertyChunk.ModifiableState.Modifiable |
|||
: TexturePropertyChunk.ModifiableState.NonModifiable)); |
|||
} |
|||
|
|||
public override void GeneratePropertyUsages(ShaderGenerator visitor, GenerationMode generationMode) |
|||
{ |
|||
visitor.AddShaderChunk("sampler2D " + propertyName + ";", true); |
|||
} |
|||
|
|||
public override PreviewProperty GetPreviewProperty() |
|||
{ |
|||
return new PreviewProperty |
|||
{ |
|||
m_Name = propertyName, |
|||
m_PropType = PropertyType.Texture2D, |
|||
m_Texture = defaultTexture |
|||
}; |
|||
} |
|||
|
|||
public override PropertyType propertyType { get { return PropertyType.Texture2D; } } |
|||
|
|||
public bool RequiresMeshUV(UVChannel channel) |
|||
{ |
|||
if (channel != UVChannel.uv0) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
var uvSlot = FindInputSlot<MaterialSlot>(UvSlotId); |
|||
if (uvSlot == null) |
|||
return true; |
|||
|
|||
var edges = owner.GetEdges(uvSlot.slotReference).ToList(); |
|||
return edges.Count == 0; |
|||
}*/ |
|||
} |
|||
} |
|
|||
namespace UnityEngine.MaterialGraph |
|||
{ |
|||
[Title("Art/Combine Node")] |
|||
public class CombineNode : Function2Input, IGeneratesFunction |
|||
{ |
|||
public CombineNode() |
|||
{ |
|||
name = "CombineNode"; |
|||
} |
|||
|
|||
// Based on information from:
|
|||
// http://photoblogstop.com/photoshop/photoshop-blend-modes-explained
|
|||
// http://www.venture-ware.com/kevin/coding/lets-learn-math-photoshop-blend-modes/
|
|||
// http://mouaif.wordpress.com/2009/01/05/photoshop-math-with-glsl-shaders/
|
|||
// http://dunnbypaul.net/blends/
|
|||
public enum Operation |
|||
{ |
|||
Darken, |
|||
Multiply, |
|||
ColorBurn, |
|||
LinearBurn, |
|||
// TODO: DarkerColor (Darken, but based on luminosity)
|
|||
Lighten, |
|||
Screen, |
|||
ColorDodge, |
|||
LinearDodge, |
|||
// TODO: LighterColor (Lighten, but based on luminosity)
|
|||
Overlay, |
|||
SoftLight, |
|||
HardLight, |
|||
VividLight, |
|||
LinearLight, |
|||
PinLight, |
|||
HardMix, |
|||
Difference, |
|||
Exclusion, |
|||
Subtract, |
|||
Divide, |
|||
} |
|||
|
|||
[SerializeField] |
|||
private Operation m_Operation; |
|||
|
|||
private static readonly string[] kOpNames = |
|||
{ |
|||
"darken", "mul", "cburn", "lburn", |
|||
"lighten", "screen", "cdodge", "ldodge", |
|||
"overlay", "softl", "hardl", "vividl", "linearl", "pinl", "hardmix", |
|||
"diff", "excl", "sub", "div" |
|||
}; |
|||
|
|||
public Operation operation |
|||
{ |
|||
get { return m_Operation; } |
|||
set { m_Operation = value; } |
|||
} |
|||
|
|||
protected override string GetFunctionName() { return "unity_combine_" + kOpNames[(int)m_Operation] + "_" + precision; } |
|||
|
|||
protected void AddOperationBody(ShaderGenerator visitor, string combineName, string body) |
|||
{ |
|||
var outputString = new ShaderGenerator(); |
|||
outputString.AddShaderChunk("inline " + precision + "4 unity_combine_" + combineName + "_" + precision + " (" + precision + "4 arg1, " + precision + "4 arg2)", false); |
|||
outputString.AddShaderChunk("{", false); |
|||
outputString.Indent(); |
|||
outputString.AddShaderChunk(body, false); |
|||
outputString.Deindent(); |
|||
outputString.AddShaderChunk("}", false); |
|||
|
|||
visitor.AddShaderChunk(outputString.GetShaderString(0), true); |
|||
} |
|||
|
|||
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode) |
|||
{ |
|||
// Darken group
|
|||
AddOperationBody(visitor, kOpNames[(int)Operation.Darken], "return min(arg1, arg2);"); |
|||
AddOperationBody(visitor, kOpNames[(int)Operation.Multiply], "return arg1 * arg2;"); |
|||
AddOperationBody(visitor, kOpNames[(int)Operation.ColorBurn], "return 1 - (1-arg1)/(arg2+1e-5);"); |
|||
AddOperationBody(visitor, kOpNames[(int)Operation.LinearBurn], "return arg1 + arg2 - 1;"); |
|||
|
|||
// Lighten group
|
|||
AddOperationBody(visitor, kOpNames[(int)Operation.Lighten], "return max(arg1, arg2);"); |
|||
AddOperationBody(visitor, kOpNames[(int)Operation.Screen], "return 1- (1-arg1) * (1-arg2);"); |
|||
AddOperationBody(visitor, kOpNames[(int)Operation.ColorDodge], "return arg1/(1-arg2+1e-5);"); |
|||
AddOperationBody(visitor, kOpNames[(int)Operation.LinearDodge], "return arg1 + arg2;"); |
|||
|
|||
// Contrast group
|
|||
AddOperationBody(visitor, kOpNames[(int)Operation.Overlay], "return (arg1 < 0.5)? arg1*arg2*2: 1-(1-arg1)*(1-arg2)*2;"); |
|||
AddOperationBody(visitor, kOpNames[(int)Operation.SoftLight], "return (1-arg1)*arg1*arg2 + arg1*(1- (1-arg1)*(1-arg2));"); |
|||
AddOperationBody(visitor, kOpNames[(int)Operation.HardLight], "return (arg2 < 0.5)? arg1*arg2*2: 1-(1-arg1)*(1-arg2)*2;"); |
|||
AddOperationBody(visitor, kOpNames[(int)Operation.VividLight], "return (arg2 < 0.5)? 1- (1-arg1)/(2*arg2+1e-5): arg1/(1-2*(arg2-0.5)+1e-5);"); |
|||
AddOperationBody(visitor, kOpNames[(int)Operation.LinearLight], "return (arg2 < 0.5)? arg1+(2*arg2)-1: arg1+2*(arg2-0.5);"); |
|||
AddOperationBody(visitor, kOpNames[(int)Operation.PinLight], "return (arg2 < 0.5)? min(arg1, 2*arg2): max(arg1, 2*(arg2-0.5));"); |
|||
AddOperationBody(visitor, kOpNames[(int)Operation.HardMix], "return (arg2 < 1-arg1)? " + precision + "(0):" + precision + "(1);"); |
|||
|
|||
// Inversion group
|
|||
AddOperationBody(visitor, kOpNames[(int)Operation.Difference], "return abs(arg2-arg1);"); |
|||
AddOperationBody(visitor, kOpNames[(int)Operation.Exclusion], "return arg1 + arg2 - arg1*arg2*2;"); |
|||
AddOperationBody(visitor, kOpNames[(int)Operation.Subtract], "return max(arg2-arg1, 0.0);"); |
|||
AddOperationBody(visitor, kOpNames[(int)Operation.Divide], "return arg1 / (arg2+1e-5);"); |
|||
} |
|||
} |
|||
} |
撰写
预览
正在加载...
取消
保存
Reference in new issue