浏览代码

converting nodes to new system.

/main
Tim Cooper 7 年前
当前提交
e8c71321
共有 33 个文件被更改,包括 1003 次插入1454 次删除
  1. 405
      MaterialGraphProject/Assets/NewNodes/WIP/POMNode.cs
  2. 475
      MaterialGraphProject/Assets/Rinaldo/BlendModeNode.cs
  3. 10
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Testing/UnitTests/MaterialSlotTests.cs
  4. 71
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Art/Adjustments/SaturationNode.cs
  5. 401
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/HLSLNode.cs
  6. 2
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/MaterialSlot.cs
  7. 42
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Math/Advanced/FmodNode.cs
  8. 28
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Math/Advanced/PosterizeNode.cs
  9. 28
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Math/Basic/AddNode.cs
  10. 28
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Math/Basic/DivNode.cs
  11. 28
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Math/Basic/MultiplyNode.cs
  12. 22
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Math/Basic/PowerNode.cs
  13. 31
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Math/Basic/SubtractNode.cs
  14. 23
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Math/Range/MaxNode.cs
  15. 21
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Math/Range/MinNode.cs
  16. 25
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Math/Round/StepNode.cs
  17. 24
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Math/Trigonometry/ATan2Node.cs
  18. 24
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Math/Vector/CrossNode.cs
  19. 26
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Math/Vector/Distance.cs
  20. 30
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Math/Vector/DotNode.cs
  21. 40
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Math/Vector/FresnelNode.cs
  22. 46
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Math/Vector/ReflectNode.cs
  23. 42
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Normal/BlendNormalNode.cs
  24. 60
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Procedural/GradientRampNode.cs
  25. 61
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Procedural/HexNode.cs
  26. 59
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Procedural/ParticleNode.cs
  27. 56
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Procedural/PulseNode.cs
  28. 58
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Procedural/RepeatingDotNode.cs
  29. 61
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/UV/TwistNode.cs
  30. 118
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/UV/UVRotatorNode.cs
  31. 57
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/UV/UVTileNode.cs
  32. 27
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/VectorProjectionNode.cs
  33. 28
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/VectorRejectionNode.cs

405
MaterialGraphProject/Assets/NewNodes/WIP/POMNode.cs


using UnityEngine.Graphing;
using System.Reflection;
public class ParallaxOcclusionMappingNode :
AbstractMaterialNode,
IGeneratesBodyCode,
IGeneratesFunction,
IMayRequireMeshUV,
IMayRequireViewDirection,
IMayRequireNormal,
IMayRequireViewDirectionTangentSpace
public class ParallaxOcclusionMappingNode : CodeFunctionNode
protected const string kInputHeightScaleShaderName = "HeightScale";
protected const string kTextureSlotShaderName = "Texture";
protected const string kOutputSlotShaderName = "UV";
public const int HeightScaleSlotId = 0; // 'height_scale'
public const int TextureSlotId = 1; // 'tex'
public const int OutputSlotId = 2;
public override bool hasPreview
protected override MethodInfo GetFunctionToConvert()
get { return true; }
return GetType().GetMethod("Unity_POM", BindingFlags.Static | BindingFlags.NonPublic);
public override PreviewMode previewMode
static string Unity_POM(
[Slot(1, Binding.None)] Sampler2D tex,
[Slot(2, Binding.None)] Vector1 heightScale,
[Slot(3, Binding.MeshUV0)] Vector2 UVs,
[Slot(4, Binding.ViewDirectionTangentSpace)] Vector3 viewTangentSpace,
[Slot(5, Binding.Normal)] Vector3 worldSpaceNormal,
[Slot(6, Binding.ViewDirection)] Vector3 worldSpaceViewDirection,
[Slot(7, Binding.None)] out Vector2 result)
get
{
return PreviewMode.Preview3D;
}
}
result = Vector2.zero;
public ParallaxOcclusionMappingNode()
{
name = "ParallaxOcclusionMapping";
UpdateNodeAfterDeserialization();
}
return
@"
{
float2 height_map_dimensions = float2(256.0f, 256.0f); //HARDCODE
//height_map.tex.GetDimensions(height_map_dimensions.x, height_map_dimensions.y);
public string GetFunctionName()
{
return "unity_parallax_occlusion_mapping_" + precision;
}
float2 texcoord= UVs;
public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(GetInputHeightScaleSlot());
AddSlot(GetTextureSlot());
AddSlot(GetOutputSlot());
// Compute the current gradients:
float2 texcoords_per_size = texcoord * height_map_dimensions;
RemoveSlotsNameNotMatching(validSlots);
}
// Compute all 4 derivatives in x and y in a single instruction to optimize:
float2 dx, dy;
float4 temp_ddx = ddx(float4(texcoords_per_size, texcoord));
dx.xy = temp_ddx.zw;
float4 temp_ddy = ddy(float4(texcoords_per_size, texcoord));
dy.xy = temp_ddy.zw;
protected int[] validSlots
{
get { return new[] { HeightScaleSlotId, TextureSlotId, OutputSlotId }; }
}
protected virtual string GetInputHeightScaleName()
{
return kInputHeightScaleShaderName;
}
protected virtual MaterialSlot GetInputHeightScaleSlot()
{
return new MaterialSlot(
HeightScaleSlotId, GetInputHeightScaleName(), kInputHeightScaleShaderName, SlotType.Input, SlotValueType.Vector1, Vector4.zero);
}
protected virtual MaterialSlot GetTextureSlot()
{
return new MaterialSlot(TextureSlotId, GetTextureSlotName(), kTextureSlotShaderName, SlotType.Input, SlotValueType.Sampler2D, Vector4.zero);
}
// Start the current sample located at the input texture coordinate, which would correspond
// to computing a bump mapping result:
float2 result_texcoord = texcoord;
protected virtual MaterialSlot GetOutputSlot()
{
return new MaterialSlot(OutputSlotId, GetOutputSlotName(), kOutputSlotShaderName, SlotType.Output, SlotValueType.Vector2, Vector4.zero);
}
float height_scale_value = heightScale;
float height_scale_adjust = height_scale_value;
protected virtual string GetTextureSlotName()
{
return kTextureSlotShaderName;
}
protected virtual string GetOutputSlotName()
{
return kOutputSlotShaderName;
}
float per_pixel_height_scale_value = height_scale_value * heightScale;
private string inputHeightScaleDimension
{
get { return ConvertConcreteSlotValueTypeToString(FindInputSlot<MaterialSlot>(HeightScaleSlotId).concreteValueType); }
}
// Parallax occlusion mapping offset computation
//--------------
protected virtual string GetFunctionPrototype(
string heightScale, string tex, string UVs, string viewTangentSpace, string worldSpaceNormal, string worldSpaceViewDirection)
{
return "inline " + precision + "2 " + GetFunctionName() + " (" +
precision + inputHeightScaleDimension + " " + heightScale + ", " +
"sampler2D " + tex + ", " +
precision + "2 " + UVs + ", " +
precision + "3 " + viewTangentSpace + ", " +
precision + "3 " + worldSpaceNormal + ", " +
precision + "3 " + worldSpaceViewDirection + ")";
}
// Utilize dynamic flow control to change the number of samples per ray
// depending on the viewing angle for the surface. Oblique angles require
// smaller step sizes to achieve more accurate precision for computing displacement.
// We express the sampling rate as a linear function of the angle between
// the geometric normal and the view direction ray:
float max_samples = 30.0f;
float min_samples = 4.0f;
public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode)
{
NodeUtils.SlotConfigurationExceptionIfBadConfiguration(
this,
new[] { HeightScaleSlotId, TextureSlotId },
new[] { OutputSlotId });
string heightScaleValue = GetSlotValue(HeightScaleSlotId, generationMode);
string textureValue = GetSlotValue(TextureSlotId, generationMode);
float view_dot_normal= dot(worldSpaceNormal, worldSpaceViewDirection);
visitor.AddShaderChunk(precision + "2 " + GetVariableNameForSlot(OutputSlotId) + " = " +
GetFunctionCallBody(heightScaleValue, textureValue) + ";", true);
}
int number_of_steps = (int)lerp(max_samples, min_samples, saturate(view_dot_normal));
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)
{
var outputString = new ShaderGenerator();
outputString.AddShaderChunk(
GetFunctionPrototype("heightScale", "tex", "UVs", "viewTangentSpace", "worldSpaceNormal", "worldSpaceViewDirection" ),
false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
// Intersect the view ray with the height field profile along the direction of
// the parallax offset ray (computed in the vertex shader. Note that the code is
// designed specifically to take advantage of the dynamic flow control constructs
// in HLSL and is very sensitive to specific syntax. When converting to other examples,
// if still want to use dynamic flow control in the resulting assembly shader,
// care must be applied.
//
// In the below steps we approximate the height field profile as piecewise linear
// curve. We find the pair of endpoints between which the intersection between the
// height field profile and the view ray is found and then compute line segment
// intersection for the view ray and the line segment formed by the two endpoints.
// This intersection is the displacement offset from the original texture coordinate.
// See the above SI3D 06 paper for more details about the process and derivation.
//
outputString.AddShaderChunk(precision + "2 " + "height_map_dimensions = " + precision + "2" + "(256.0f, 256.0f); //HARDCODE", false);
//height_map.tex.GetDimensions(height_map_dimensions.x, height_map_dimensions.y);
float current_height = 0.0;
float step_size = 1.0 / (float)number_of_steps;
outputString.AddShaderChunk(precision + "2 texcoord= UVs;", false);
float previous_height = 1.0;
float next_height = 0.0;
// Compute the current gradients:
outputString.AddShaderChunk(precision + "2 " + " texcoords_per_size = texcoord * height_map_dimensions;", false);
// Compute all 4 derivatives in x and y in a single instruction to optimize:
outputString.AddShaderChunk("float2 dx, dy;", false);
int step_index = 0;
outputString.AddShaderChunk(" float4 temp_ddx = ddx(float4(texcoords_per_size, texcoord));", false);
// Optimization: this should move to vertex shader, however, we compute it here for simplicity of
// integration into our shaders for now.
float3 normalized_view_dir_in_tangent_space = normalize(viewTangentSpace.xyz);
outputString.AddShaderChunk("dx.xy = temp_ddx.zw;", false);
// Compute initial parallax displacement direction:
float2 parallax_direction = normalize(viewTangentSpace.xy);
outputString.AddShaderChunk("float4 temp_ddy = ddy(float4(texcoords_per_size, texcoord));", false);
// The length of this vector determines the furthest amount of displacement:
float parallax_direction_length = length(normalized_view_dir_in_tangent_space);
outputString.AddShaderChunk("dy.xy = temp_ddy.zw;", false);
// Start the current sample located at the input texture coordinate, which would correspond
// to computing a bump mapping result:
outputString.AddShaderChunk(precision + "2 " + "result_texcoord = texcoord;", false);
float max_parallax_amount = sqrt(parallax_direction_length * parallax_direction_length - viewTangentSpace.z * viewTangentSpace.z) / viewTangentSpace.z;
outputString.AddShaderChunk("float height_scale_value = heightScale;", false);
outputString.AddShaderChunk("float height_scale_adjust = height_scale_value;", false);
// Compute the actual reverse parallax displacement vector:
float2 parallax_offset_in_tangent_space = parallax_direction * max_parallax_amount;
// Need to scale the amount of displacement to account for different height ranges
// in height maps. This is controlled by an artist-editable parameter:
parallax_offset_in_tangent_space *= saturate(heightScale);
float2 texcoord_offset_per_step = step_size * parallax_offset_in_tangent_space;
outputString.AddShaderChunk("float per_pixel_height_scale_value = height_scale_value * heightScale;", false);
// Parallax occlusion mapping offset computation
//--------------
float2 current_texcoord_offset = texcoord;
float current_bound = 1.0;
float current_parallax_amount = 0.0;
// Utilize dynamic flow control to change the number of samples per ray
// depending on the viewing angle for the surface. Oblique angles require
// smaller step sizes to achieve more accurate precision for computing displacement.
// We express the sampling rate as a linear function of the angle between
// the geometric normal and the view direction ray:
outputString.AddShaderChunk("float max_samples = 30.0f;", false);
outputString.AddShaderChunk("float min_samples = 4.0f;", false);
outputString.AddShaderChunk("float view_dot_normal= dot(worldSpaceNormal, worldSpaceViewDirection);", false);
outputString.AddShaderChunk("int number_of_steps = (int)lerp(max_samples, min_samples, saturate(view_dot_normal));", false);
// Intersect the view ray with the height field profile along the direction of
// the parallax offset ray (computed in the vertex shader. Note that the code is
// designed specifically to take advantage of the dynamic flow control constructs
// in HLSL and is very sensitive to specific syntax. When converting to other examples,
// if still want to use dynamic flow control in the resulting assembly shader,
// care must be applied.
//
// In the below steps we approximate the height field profile as piecewise linear
// curve. We find the pair of endpoints between which the intersection between the
// height field profile and the view ray is found and then compute line segment
// intersection for the view ray and the line segment formed by the two endpoints.
// This intersection is the displacement offset from the original texture coordinate.
// See the above SI3D 06 paper for more details about the process and derivation.
//
outputString.AddShaderChunk("float current_height = 0.0;", false);
outputString.AddShaderChunk("float step_size = 1.0 / (float)number_of_steps;", false);
outputString.AddShaderChunk("float previous_height = 1.0;", false);
outputString.AddShaderChunk("float next_height = 0.0;", false);
outputString.AddShaderChunk("int step_index = 0;", false);
// Optimization: this should move to vertex shader, however, we compute it here for simplicity of
// integration into our shaders for now.
outputString.AddShaderChunk("float3 normalized_view_dir_in_tangent_space = normalize(viewTangentSpace.xyz);", false);
// Compute initial parallax displacement direction:
outputString.AddShaderChunk("float2 parallax_direction = normalize(viewTangentSpace.xy);", false);
// The length of this vector determines the furthest amount of displacement:
outputString.AddShaderChunk("float parallax_direction_length = length(normalized_view_dir_in_tangent_space);", false);
outputString.AddShaderChunk(
"float max_parallax_amount = sqrt(parallax_direction_length * parallax_direction_length - viewTangentSpace.z * viewTangentSpace.z) / viewTangentSpace.z;", false);
// Compute the actual reverse parallax displacement vector:
outputString.AddShaderChunk("float2 parallax_offset_in_tangent_space = parallax_direction * max_parallax_amount;", false);
// Need to scale the amount of displacement to account for different height ranges
// in height maps. This is controlled by an artist-editable parameter:
outputString.AddShaderChunk("parallax_offset_in_tangent_space *= saturate(heightScale);", false);
outputString.AddShaderChunk("float2 texcoord_offset_per_step = step_size * parallax_offset_in_tangent_space;", false);
outputString.AddShaderChunk(precision + "2 " + "current_texcoord_offset = texcoord;", false);
outputString.AddShaderChunk("float current_bound = 1.0;", false);
outputString.AddShaderChunk("float current_parallax_amount = 0.0;", false);
outputString.AddShaderChunk("float2 pt1 = 0;", false);
outputString.AddShaderChunk("float2 pt2 = 0;", false);
outputString.AddShaderChunk(precision + "2 " + "temp_texcoord_offset = 0;", false);
outputString.AddShaderChunk("while (step_index < number_of_steps)", false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("current_texcoord_offset -= texcoord_offset_per_step;", false);
// Sample height map which in this case is stored in the alpha channel of the normal map:
outputString.AddShaderChunk("current_height = tex2Dgrad(tex, current_texcoord_offset, dx, dy).r;", false);
outputString.AddShaderChunk("current_bound -= step_size;", false);
outputString.AddShaderChunk("if (current_height > current_bound)", false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("pt1 = float2(current_bound, current_height);", false);
outputString.AddShaderChunk("pt2 = float2(current_bound + step_size, previous_height);", false);
outputString.AddShaderChunk("temp_texcoord_offset = current_texcoord_offset - texcoord_offset_per_step;", false);
outputString.AddShaderChunk("step_index = number_of_steps + 1;", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
outputString.AddShaderChunk("else", false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
float2 pt1 = 0;
float2 pt2 = 0;
outputString.AddShaderChunk("step_index++;", false);
outputString.AddShaderChunk("previous_height = current_height;", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
float2 temp_texcoord_offset = 0;
outputString.Deindent();
outputString.AddShaderChunk("} // End of while ( step_index < number_of_steps)", false);
while (step_index < number_of_steps)
{
current_texcoord_offset -= texcoord_offset_per_step;
// Sample height map which in this case is stored in the alpha channel of the normal map:
current_height = tex2Dgrad(tex, current_texcoord_offset, dx, dy).r;
outputString.AddShaderChunk("float delta2 = pt2.x - pt2.y;", false);
outputString.AddShaderChunk("float delta1 = pt1.x - pt1.y;", false);
current_bound -= step_size;
outputString.AddShaderChunk("float denominator = delta2 - delta1;", false);
if (current_height > current_bound)
{
pt1 = float2(current_bound, current_height);
pt2 = float2(current_bound + step_size, previous_height);
temp_texcoord_offset = current_texcoord_offset - texcoord_offset_per_step;
step_index = number_of_steps + 1;
}
else
{
step_index++;
previous_height = current_height;
}
} // End of while ( step_index < number_of_steps)
// SM 3.0 and above requires a check for divide by zero since that operation
// will generate an 'Inf' number instead of 0
outputString.AddShaderChunk("if (denominator== 0.0f) ", false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("current_parallax_amount= 0.0f;", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
outputString.AddShaderChunk("else", false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("current_parallax_amount= (pt1.x* delta2 - pt2.x* delta1) / denominator;", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
outputString.AddShaderChunk("float2 parallax_offset = parallax_offset_in_tangent_space * (1.0f - current_parallax_amount);", false);
float delta2 = pt2.x - pt2.y;
float delta1 = pt1.x - pt1.y;
// The computed texture offset for the displaced point on the pseudo-extruded surface:
outputString.AddShaderChunk("float2 parallaxed_texcoord = texcoord - parallax_offset;", false);
float denominator = delta2 - delta1;
outputString.AddShaderChunk("return parallaxed_texcoord;", false);
// SM 3.0 and above requires a check for divide by zero since that operation
// will generate an 'Inf' number instead of 0
if (denominator== 0.0f)
{
current_parallax_amount= 0.0f;
}
else
{
current_parallax_amount= (pt1.x* delta2 - pt2.x* delta1) / denominator;
}
outputString.Deindent();
outputString.AddShaderChunk("}", false);
float2 parallax_offset = parallax_offset_in_tangent_space * (1.0f - current_parallax_amount);
visitor.AddShaderChunk(outputString.GetShaderString(0), true);
}
protected virtual string GetFunctionCallBody(string heightScale, string texValue)
{
var channel = UVChannel.uv0;
return GetFunctionName() + " (" +
heightScale + ", " +
texValue + ", " +
channel.GetUVName() + ", " +
ShaderGeneratorNames.TangentSpaceViewDirection + ", " +
ShaderGeneratorNames.WorldSpaceNormal + ", " +
ShaderGeneratorNames.WorldSpaceViewDirection + ")";
}
// The computed texture offset for the displaced point on the pseudo-extruded surface:
float2 parallaxed_texcoord = texcoord - parallax_offset;
public bool RequiresMeshUV(UVChannel channel)
{
return channel == UVChannel.uv0;
}
public bool RequiresViewDirectionTangentSpace()
{
return true;
}
public bool RequiresNormal()
{
return true;
}
public bool RequiresViewDirection()
{
return true;
result = parallaxed_texcoord;
}
";
}
}
}

475
MaterialGraphProject/Assets/Rinaldo/BlendModeNode.cs


using UnityEngine.Graphing;
using System.Reflection;
using UnityEngine.Graphing;
public class BlendModeNode : Function2Input, IGeneratesFunction
public class BlendModeNode : CodeFunctionNode
protected override string GetFunctionName()
{
return "unity_blendmode_" + System.Enum.GetName(typeof(BlendModesEnum), m_BlendMode);
}
protected override string GetInputSlot1Name()
{
return "A|Blend/Src";
}
protected override string GetInputSlot2Name()
string GetCurrentBlendName()
return "B|Base/Dest";
return System.Enum.GetName(typeof(BlendModesEnum), m_BlendMode);
}
[SerializeField]

}
}
}
/*This is to overide input to be vector 3, not really necessary */
/*
protected override MaterialSlot GetInputSlot1()
protected override MethodInfo GetFunctionToConvert()
{
return GetType().GetMethod(string.Format("Unity_Blend{0}", GetCurrentBlendName()),
BindingFlags.Static | BindingFlags.NonPublic);
}
static string Unity_BlendBurn(
[Slot(0, Binding.None)] DynamicDimensionVector top,
[Slot(1, Binding.None)] DynamicDimensionVector bottom,
[Slot(2, Binding.None)] out DynamicDimensionVector result)
{
return
@"
{
result = 1.0 - (1.0 - bottom)/top;
}";
}
static string Unity_BlendDarken(
[Slot(0, Binding.None)] DynamicDimensionVector top,
[Slot(1, Binding.None)] DynamicDimensionVector bottom,
[Slot(2, Binding.None)] out DynamicDimensionVector result)
{
return
@"
{
result = min(bottom, top);
}";
}
static string Unity_BlendDifference(
[Slot(0, Binding.None)] DynamicDimensionVector top,
[Slot(1, Binding.None)] DynamicDimensionVector bottom,
[Slot(2, Binding.None)] out DynamicDimensionVector result)
{
return
@"
{
result = abs(bottom-top);
}";
}
static string Unity_BlendDodge(
[Slot(0, Binding.None)] DynamicDimensionVector top,
[Slot(1, Binding.None)] DynamicDimensionVector bottom,
[Slot(2, Binding.None)] out DynamicDimensionVector result)
{
return
@"
{
result = bottom / (1.0 - top);
}";
}
static string Unity_BlendDivide(
[Slot(0, Binding.None)] DynamicDimensionVector top,
[Slot(1, Binding.None)] DynamicDimensionVector bottom,
[Slot(2, Binding.None)] out DynamicDimensionVector result)
{
return
@"
{
result = botom / (top + 0.000000000001);
}";
}
static string Unity_BlendExclusion(
[Slot(0, Binding.None)] DynamicDimensionVector top,
[Slot(1, Binding.None)] DynamicDimensionVector bottom,
[Slot(2, Binding.None)] out DynamicDimensionVector result)
{
return
@"
{
result = bottom + top - (2.0 * bottom * top);;
}";
}
static string Unity_BlendHardLight(
[Slot(0, Binding.None)] DynamicDimensionVector top,
[Slot(1, Binding.None)] DynamicDimensionVector bottom,
[Slot(2, Binding.None)] out DynamicDimensionVector result)
return new MaterialSlot(InputSlot1Id, GetInputSlot1Name(), kInputSlot1ShaderName, SlotType.Input, SlotValueType.Vector3, Vector4.zero);
return
@"
{
{precision}{dimension2} result1 = 1.0 - 2.0 * (1.0 - top) * (1.0 - bottom);
{precision}{dimension2} result2 = 2.0 * top * bottom;
{precision}{dimension2} zeroOrOne = step(top, 0.5);
result = result2 * zeroOrOne + (1 - zeroOrOne) * result1;
}";
}
static string Unity_BlendHardMix(
[Slot(0, Binding.None)] DynamicDimensionVector top,
[Slot(1, Binding.None)] DynamicDimensionVector bottom,
[Slot(2, Binding.None)] out DynamicDimensionVector result)
{
return
@"
{
result = step(1-top, bottom)
}";
}
static string Unity_BlendHardLighten(
[Slot(0, Binding.None)] DynamicDimensionVector top,
[Slot(1, Binding.None)] DynamicDimensionVector bottom,
[Slot(2, Binding.None)] out DynamicDimensionVector result)
{
return
@"
{
result = max(bottom, top);
}";
}
static string Unity_BlendLinearBurn(
[Slot(0, Binding.None)] DynamicDimensionVector top,
[Slot(1, Binding.None)] DynamicDimensionVector bottom,
[Slot(2, Binding.None)] out DynamicDimensionVector result)
{
return
@"
{
result = top + bottom - 1.0;
}";
}
static string Unity_BlendLinearDodge(
[Slot(0, Binding.None)] DynamicDimensionVector top,
[Slot(1, Binding.None)] DynamicDimensionVector bottom,
[Slot(2, Binding.None)] out DynamicDimensionVector result)
{
return
@"
{
result = top + bottom;
}";
}
static string Unity_BlendLinearLight_AddSub(
[Slot(0, Binding.None)] DynamicDimensionVector top,
[Slot(1, Binding.None)] DynamicDimensionVector bottom,
[Slot(2, Binding.None)] out DynamicDimensionVector result)
{
return
@"
{
result = bottom + 2.0 * top - 1.0;
}";
}
static string Unity_BlendMultiply(
[Slot(0, Binding.None)] DynamicDimensionVector top,
[Slot(1, Binding.None)] DynamicDimensionVector bottom,
[Slot(2, Binding.None)] out DynamicDimensionVector result)
{
return
@"
{
result = top * bottom;
}";
}
static string Unity_BlendNegation(
[Slot(0, Binding.None)] DynamicDimensionVector top,
[Slot(1, Binding.None)] DynamicDimensionVector bottom,
[Slot(2, Binding.None)] out DynamicDimensionVector result)
{
return
@"
{
result = 1.0 - abs(1.0 - bottom - top);;
}";
}
static string Unity_BlendScreen(
[Slot(0, Binding.None)] DynamicDimensionVector top,
[Slot(1, Binding.None)] DynamicDimensionVector bottom,
[Slot(2, Binding.None)] out DynamicDimensionVector result)
{
return
@"
{
result = 1.0 - (1.0-bottom) * (1.0 - top);
}";
}
static string Unity_BlendOverlay(
[Slot(0, Binding.None)] DynamicDimensionVector top,
[Slot(1, Binding.None)] DynamicDimensionVector bottom,
[Slot(2, Binding.None)] out DynamicDimensionVector result)
{
return
@"
{
{precision}{dimension2} result1 = 1.0 - 2.0 * (1.0 - top) * (1.0 - bottom);
{precision}{dimension2} result2 = 2.0 * top * bottom;
{precision}{dimension2} zeroOrOne = step(bottom, 0.5);
result = result2 * zeroOrOne + (1 - zeroOrOne) * result1;
}
";
}
static string Unity_BlendPinLight(
[Slot(0, Binding.None)] DynamicDimensionVector top,
[Slot(1, Binding.None)] DynamicDimensionVector bottom,
[Slot(2, Binding.None)] out DynamicDimensionVector result)
{
return
@"
{
{precision}{dimension2} check = step (0.5, top);
{precision}{dimension2} result1 = check * max(2.0*(top - 0.5), bottom);
result = result1 + (1.0 - check) * min(2.0 * top, bottom);
}
";
protected override MaterialSlot GetInputSlot2()
static string Unity_BlendSoftLight(
[Slot(0, Binding.None)] DynamicDimensionVector top,
[Slot(1, Binding.None)] DynamicDimensionVector bottom,
[Slot(2, Binding.None)] out DynamicDimensionVector result)
return new MaterialSlot(InputSlot2Id, GetInputSlot2Name(), kInputSlot2ShaderName, SlotType.Input, SlotValueType.Vector3, Vector4.zero);
return
@"
{
{precision}{dimension2} result1= 2.0 * bottom * top +bottom*top - 2.0 * bottom*bottom*top;
{precision}{dimension2} result2= 2.0* sqrt(bottom) * top - sqrt(bottom) + 2.0 * bottom - 2.0 * bottom*top;
{precision}{dimension2} zeroOrOne = step(0.5, top);
result = result2 * zeroOrOne + (1 - zeroOrOne) * result1;
}
";
protected override MaterialSlot GetOutputSlot()
static string Unity_BlendVividLight(
[Slot(0, Binding.None)] DynamicDimensionVector top,
[Slot(1, Binding.None)] DynamicDimensionVector bottom,
[Slot(2, Binding.None)] out DynamicDimensionVector result)
return new MaterialSlot(OutputSlotId, GetOutputSlotName(), kOutputSlotShaderName, SlotType.Output, SlotValueType.Vector3, Vector4.zero);
return
@"
{
{precision}{dimension2} result1 = 1.0-(1.0-bottom)/(2.0*top);
{precision}{dimension2} result2 = bottom/(2.0*(1.0-top));
{precision}{dimension2} zeroOrOne = step(0.5, top);
result = result2 * zeroOrOne + (1 - zeroOrOne) * result1;
}
";
*/
public override bool hasPreview { get { return true; } }
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)
static string Unity_BlendSubtract(
[Slot(0, Binding.None)] DynamicDimensionVector top,
[Slot(1, Binding.None)] DynamicDimensionVector bottom,
[Slot(2, Binding.None)] out DynamicDimensionVector result)
var outputString = new ShaderGenerator();
switch (m_BlendMode)
{
/* case BlendModesEnum.AddSub:
outputString.AddShaderChunk(GetFunctionPrototype("arg1", "arg2"), false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("return 2.0 * arg1 + arg2 - 1.0;", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
break;
*/
case BlendModesEnum.Burn:
outputString.AddShaderChunk(GetFunctionPrototype("arg1", "arg2"), false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("return 1.0 - (1.0 - arg2)/arg1;", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
break;
case BlendModesEnum.Darken:
outputString.AddShaderChunk(GetFunctionPrototype("arg1", "arg2"), false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("return min(arg2,arg1);", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
break;
case BlendModesEnum.Difference:
outputString.AddShaderChunk(GetFunctionPrototype("arg1", "arg2"), false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("return abs(arg2-arg1);", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
break;
case BlendModesEnum.Dodge:
outputString.AddShaderChunk(GetFunctionPrototype("arg1", "arg2"), false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("return arg2 / (1.0 - arg1);", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
break;
case BlendModesEnum.Divide:
outputString.AddShaderChunk(GetFunctionPrototype("arg1", "arg2"), false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("return arg2 / (arg1 + 0.000000000001);", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
break;
case BlendModesEnum.Exclusion:
outputString.AddShaderChunk(GetFunctionPrototype("arg1", "arg2"), false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
// outputString.AddShaderChunk("return arg2 + arg1 - (" + precision + "3(2.0,2.0,2.0)*arg2*arg1);", false);
outputString.AddShaderChunk("return arg2 + arg1 - (2.0 *arg2*arg1);", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
break;
case BlendModesEnum.HardLight:
outputString.AddShaderChunk(GetFunctionPrototype("arg1", "arg2"), false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk(precision + outputDimension + " result1 = 1.0 - 2.0 * (1.0 - arg1) * (1.0 - arg2);", false);
outputString.AddShaderChunk(precision + outputDimension + " result2 = 2.0 * arg1 * arg2;", false);
outputString.AddShaderChunk(precision + outputDimension + " zeroOrOne = step(arg1, 0.5);", false);
outputString.AddShaderChunk("return result2 * zeroOrOne + (1 - zeroOrOne) * result1;", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
break;
case BlendModesEnum.HardMix:
outputString.AddShaderChunk(GetFunctionPrototype("arg1", "arg2"), false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("return step(1-arg1, arg2);", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
break;
case BlendModesEnum.Lighten:
outputString.AddShaderChunk(GetFunctionPrototype("arg1", "arg2"), false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("return max(arg2,arg1);", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
break;
case BlendModesEnum.LinearBurn:
outputString.AddShaderChunk(GetFunctionPrototype("arg1", "arg2"), false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("return arg1 + arg2 - 1.0;", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
break;
case BlendModesEnum.LinearDodge:
outputString.AddShaderChunk(GetFunctionPrototype("arg1", "arg2"), false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("return arg1 + arg2;", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
break;
case BlendModesEnum.LinearLight_AddSub:
outputString.AddShaderChunk(GetFunctionPrototype("arg1", "arg2"), false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("return arg2 + 2.0 * arg1 - 1.0;", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
break;
case BlendModesEnum.Multiply:
outputString.AddShaderChunk(GetFunctionPrototype("arg1", "arg2"), false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("return arg1 * arg2;", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
break;
case BlendModesEnum.Negation:
outputString.AddShaderChunk(GetFunctionPrototype("arg1", "arg2"), false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("return 1.0 - abs(1.0 - arg2 - arg1);", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
break;
case BlendModesEnum.Overlay:
outputString.AddShaderChunk(GetFunctionPrototype("arg1", "arg2"), false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk(precision + outputDimension + " result1 = 1.0 - 2.0 * (1.0 - arg1) * (1.0 - arg2);", false);
outputString.AddShaderChunk(precision + outputDimension + " result2 = 2.0 * arg1 * arg2;", false);
outputString.AddShaderChunk(precision + outputDimension + " zeroOrOne = step(arg2, 0.5);", false);
outputString.AddShaderChunk("return result2 * zeroOrOne + (1 - zeroOrOne) * result1;", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
break;
case BlendModesEnum.PinLight:
outputString.AddShaderChunk(GetFunctionPrototype("arg1", "arg2"), false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk(precision + outputDimension + " check = step (0.5, arg1);", false);
outputString.AddShaderChunk(precision + outputDimension + " result = check * max(2.0*(arg1 - 0.5), arg2);", false);
outputString.AddShaderChunk("return result += (1.0 - check) * min(2.0 * arg1,arg2);", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
break;
case BlendModesEnum.Screen:
outputString.AddShaderChunk(GetFunctionPrototype("arg1", "arg2"), false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("return 1.0 - (1.0-arg2) * (1.0 - arg1);", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
break;
case BlendModesEnum.SoftLight:
outputString.AddShaderChunk(GetFunctionPrototype("arg1", "arg2"), false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk(precision + outputDimension + " result1= 2.0 * arg2 * arg1 + arg2*arg2 - 2.0 * arg2*arg2*arg1;", false);
outputString.AddShaderChunk(precision + outputDimension + " result2= 2.0* sqrt(arg2) * arg1 - sqrt(arg2) + 2.0 * arg2 - 2.0 * arg2*arg1;", false);
outputString.AddShaderChunk(precision + outputDimension + " zeroOrOne = step(0.5, arg1);", false);
outputString.AddShaderChunk("return result2 * zeroOrOne + (1 - zeroOrOne) * result1;", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
break;
case BlendModesEnum.Substract:
outputString.AddShaderChunk(GetFunctionPrototype("arg1", "arg2"), false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("return arg2 - arg1;", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
break;
case BlendModesEnum.VividLight:
outputString.AddShaderChunk(GetFunctionPrototype("arg1", "arg2"), false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk(precision + outputDimension + " result1= 1.0-(1.0-arg2)/(2.0*arg1);", false);
outputString.AddShaderChunk(precision + outputDimension + " result2= arg2/(2.0*(1.0-arg1));", false);
outputString.AddShaderChunk(precision + outputDimension + " zeroOrOne = step(0.5, arg1);", false);
outputString.AddShaderChunk("return result2 * zeroOrOne + (1 - zeroOrOne) * result1;", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
break;
}
visitor.AddShaderChunk(outputString.GetShaderString(0), true);
return
@"
{
result = bottom - top;
}
";
}
}
}

10
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Testing/UnitTests/MaterialSlotTests.cs


}
[Test]
public void CanUpdateMaterialShaderOutputName()
{
var shaderName = "NewShaderOutputName";
var slot = m_NodeA.slot;
slot.shaderOutputName = shaderName;
Assert.AreEqual(shaderName, slot.shaderOutputName);
}
[Test]
public void MaterialSlotCanGeneratePropertyUsagesForPreview()
{
string expected = string.Format("{0} {1};{2}", m_NodeA.precision, m_NodeA.GetVariableNameForSlot(TestNode.V1In), Environment.NewLine);

71
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Art/Adjustments/SaturationNode.cs


using UnityEngine.Graphing;
using System.Reflection;
[Title ("Art/Adjustments/Saturation")]
public class SaturationNode : Function2Input, IGeneratesFunction
{
public SaturationNode()
{
name = "Saturation";
}
protected override string GetFunctionName ()
{
return "unity_saturation_" + precision;
}
protected override MaterialSlot GetInputSlot1 ()
{
return new MaterialSlot (InputSlot1Id, GetInputSlot1Name (), kInputSlot1ShaderName, SlotType.Input, SlotValueType.Vector3, Vector4.zero);
}
protected override MaterialSlot GetInputSlot2()
[Title("Art/Adjustments/Saturation")]
public class SaturationNode : CodeFunctionNode
{
public SaturationNode()
return new MaterialSlot(InputSlot2Id, GetInputSlot2Name(), kInputSlot2ShaderName, SlotType.Input, SlotValueType.Vector1, Vector4.zero);
name = "Saturation";
protected override MaterialSlot GetOutputSlot ()
{
return new MaterialSlot (OutputSlotId, GetOutputSlotName (), kOutputSlotShaderName, SlotType.Output, SlotValueType.Vector3, Vector4.zero);
}
protected override string GetInputSlot2Name()
protected override MethodInfo GetFunctionToConvert()
return "Saturation";
return GetType().GetMethod("Unity_Saturation", BindingFlags.Static | BindingFlags.NonPublic);
// RGB Saturation (closer to a vibrance effect than actual saturation)
// Recommended workspace: ACEScg (linear)
// Optimal range: [0.0, 2.0]
// From PostProcessing
public void GenerateNodeFunction (ShaderGenerator visitor, GenerationMode generationMode)
{
var outputString = new ShaderGenerator ();
outputString.AddShaderChunk (GetFunctionPrototype ("arg1", "arg2"), false);
outputString.AddShaderChunk ("{", false);
outputString.Indent ();
outputString.AddShaderChunk(precision+" luma = dot(arg1, " + precision + outputDimension + "(0.2126729, 0.7151522, 0.0721750));", false);
outputString.AddShaderChunk ("return luma.xxx + arg2.xxx * (arg1 - luma.xxx);", false);
outputString.Deindent ();
outputString.AddShaderChunk ("}", false);
static string Unity_Saturation(
[Slot(0, Binding.None)] Vector3 first,
[Slot(1, Binding.None)] Vector1 second,
[Slot(2, Binding.None)] out Vector3 result)
{
result = Vector3.zero;
visitor.AddShaderChunk (outputString.GetShaderString (0), true);
}
}
return @"
{
// RGB Saturation (closer to a vibrance effect than actual saturation)
// Recommended workspace: ACEScg (linear)
// Optimal range: [0.0, 2.0]
// From PostProcessing
{precision} luma = dot(first, {precision}3(0.2126729, 0.7151522, 0.0721750));
result = luma.xxx + first.xxx * (second - luma.xxx);
}
";
}
}
}

401
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/HLSLNode.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using JetBrains.Annotations;
using UnityEngine.Graphing;

[Title("TEST/Add Node")]
public class SnippetAddNode : SimpleNode
{
protected override MethodInfo GetFunctionToConvert()
{
return GetType().GetMethod("Unity_Add", BindingFlags.Static | BindingFlags.NonPublic);
}
static void Unity_Add(out DynamicDimensionVector result, [Bind(BindChannel.MeshUV0)]DynamicDimensionVector first, DynamicDimensionVector second)
{
}
protected override string GetFunctionBody()
{
return
@"
{
result = first + second;
}
";
}
}
[Title("TEST/POM Node")]
public class SnippetPOMNode : SimpleNode
{
protected override MethodInfo GetFunctionToConvert()
{
return GetType().GetMethod("Unity_POM", BindingFlags.Static | BindingFlags.NonPublic);
}
static void Unity_POM(
out Vector2 result,
Sampler2D tex,
ShaderSingle heightScale,
[Bind(BindChannel.MeshUV0)] Vector2 UVs,
[Bind(BindChannel.ViewDirectionTangentSpace)] Vector3 viewTangentSpace,
[Bind(BindChannel.Normal)] Vector3 worldSpaceNormal,
[Bind(BindChannel.ViewDirection)] Vector3 worldSpaceViewDirection)
{
result = Vector2.zero;
}
protected override string GetFunctionBody()
{
return
@"
{
float2 height_map_dimensions = float2(256.0f, 256.0f); //HARDCODE
//height_map.tex.GetDimensions(height_map_dimensions.x, height_map_dimensions.y);
float2 texcoord= UVs;
// Compute the current gradients:
float2 texcoords_per_size = texcoord * height_map_dimensions;
// Compute all 4 derivatives in x and y in a single instruction to optimize:
float2 dx, dy;
float4 temp_ddx = ddx(float4(texcoords_per_size, texcoord));
dx.xy = temp_ddx.zw;
float4 temp_ddy = ddy(float4(texcoords_per_size, texcoord));
dy.xy = temp_ddy.zw;
// Start the current sample located at the input texture coordinate, which would correspond
// to computing a bump mapping result:
float2 result_texcoord = texcoord;
float height_scale_value = heightScale;
float height_scale_adjust = height_scale_value;
float per_pixel_height_scale_value = height_scale_value * heightScale;
// Parallax occlusion mapping offset computation
//--------------
// Utilize dynamic flow control to change the number of samples per ray
// depending on the viewing angle for the surface. Oblique angles require
// smaller step sizes to achieve more accurate precision for computing displacement.
// We express the sampling rate as a linear function of the angle between
// the geometric normal and the view direction ray:
float max_samples = 30.0f;
float min_samples = 4.0f;
float view_dot_normal= dot(worldSpaceNormal, worldSpaceViewDirection);
int number_of_steps = (int)lerp(max_samples, min_samples, saturate(view_dot_normal));
// Intersect the view ray with the height field profile along the direction of
// the parallax offset ray (computed in the vertex shader. Note that the code is
// designed specifically to take advantage of the dynamic flow control constructs
// in HLSL and is very sensitive to specific syntax. When converting to other examples,
// if still want to use dynamic flow control in the resulting assembly shader,
// care must be applied.
//
// In the below steps we approximate the height field profile as piecewise linear
// curve. We find the pair of endpoints between which the intersection between the
// height field profile and the view ray is found and then compute line segment
// intersection for the view ray and the line segment formed by the two endpoints.
// This intersection is the displacement offset from the original texture coordinate.
// See the above SI3D 06 paper for more details about the process and derivation.
//
float current_height = 0.0;
float step_size = 1.0 / (float)number_of_steps;
float previous_height = 1.0;
float next_height = 0.0;
int step_index = 0;
// Optimization: this should move to vertex shader, however, we compute it here for simplicity of
// integration into our shaders for now.
float3 normalized_view_dir_in_tangent_space = normalize(viewTangentSpace.xyz);
// Compute initial parallax displacement direction:
float2 parallax_direction = normalize(viewTangentSpace.xy);
// The length of this vector determines the furthest amount of displacement:
float parallax_direction_length = length(normalized_view_dir_in_tangent_space);
float max_parallax_amount = sqrt(parallax_direction_length * parallax_direction_length - viewTangentSpace.z * viewTangentSpace.z) / viewTangentSpace.z;
// Compute the actual reverse parallax displacement vector:
float2 parallax_offset_in_tangent_space = parallax_direction * max_parallax_amount;
// Need to scale the amount of displacement to account for different height ranges
// in height maps. This is controlled by an artist-editable parameter:
parallax_offset_in_tangent_space *= saturate(heightScale);
float2 texcoord_offset_per_step = step_size * parallax_offset_in_tangent_space;
float2 current_texcoord_offset = texcoord;
float current_bound = 1.0;
float current_parallax_amount = 0.0;
float2 pt1 = 0;
float2 pt2 = 0;
float2 temp_texcoord_offset = 0;
while (step_index < number_of_steps)
{
current_texcoord_offset -= texcoord_offset_per_step;
// Sample height map which in this case is stored in the alpha channel of the normal map:
current_height = tex2Dgrad(tex, current_texcoord_offset, dx, dy).r;
current_bound -= step_size;
if (current_height > current_bound)
{
pt1 = float2(current_bound, current_height);
pt2 = float2(current_bound + step_size, previous_height);
temp_texcoord_offset = current_texcoord_offset - texcoord_offset_per_step;
step_index = number_of_steps + 1;
}
else
{
step_index++;
previous_height = current_height;
}
} // End of while ( step_index < number_of_steps)
float delta2 = pt2.x - pt2.y;
float delta1 = pt1.x - pt1.y;
float denominator = delta2 - delta1;
// SM 3.0 and above requires a check for divide by zero since that operation
// will generate an 'Inf' number instead of 0
if (denominator== 0.0f)
{
current_parallax_amount= 0.0f;
}
else
{
current_parallax_amount= (pt1.x* delta2 - pt2.x* delta1) / denominator;
}
float2 parallax_offset = parallax_offset_in_tangent_space * (1.0f - current_parallax_amount);
// The computed texture offset for the displaced point on the pseudo-extruded surface:
float2 parallaxed_texcoord = texcoord - parallax_offset;
result = parallaxed_texcoord;
}
";
}
}
public abstract class SimpleNode : AbstractMaterialNode
public abstract class CodeFunctionNode : AbstractMaterialNode
, IGeneratesBodyCode
, IGeneratesFunction
, IMayRequireNormal

, IMayRequireVertexColor
, IMayRequireViewDirectionTangentSpace
{
private List<KeyValuePair<int, ParameterInfo>> m_ParamMap = new List<KeyValuePair<int, ParameterInfo>>();
[NonSerialized]
private List<SlotAttribute> m_Slots = new List<SlotAttribute>();
public override bool hasPreview
{

public SimpleNode()
public CodeFunctionNode()
protected struct ShaderSingle
protected struct Vector1
{}
protected struct Texture2D

protected struct DynamicDimensionVector
{}
protected enum BindChannel
protected enum Binding
{
None,
Normal,

ViewDirectionTangentSpace
}
private static string BindChannelToShaderName(BindChannel channel)
private static string BindChannelToShaderName(Binding channel)
case BindChannel.None:
case Binding.None:
case BindChannel.Normal:
case Binding.Normal:
case BindChannel.Tangent:
case Binding.Tangent:
case BindChannel.Bitangent:
case Binding.Bitangent:
case BindChannel.MeshUV0:
case Binding.MeshUV0:
case BindChannel.MeshUV1:
case Binding.MeshUV1:
case BindChannel.MeshUV2:
case Binding.MeshUV2:
case BindChannel.MeshUV3:
case Binding.MeshUV3:
case BindChannel.ScreenPosition:
case Binding.ScreenPosition:
case BindChannel.ViewDirection:
case Binding.ViewDirection:
case BindChannel.WorldPosition:
case Binding.WorldPosition:
case BindChannel.VertexColor:
case Binding.VertexColor:
case BindChannel.ViewDirectionTangentSpace:
case Binding.ViewDirectionTangentSpace:
return ShaderGeneratorNames.TangentSpaceViewDirection;
default:
throw new ArgumentOutOfRangeException("channel", channel, null);

[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)]
protected class BindAttribute : Attribute
protected class SlotAttribute : Attribute
public BindChannel channel { get; private set; }
public int slotId { get; private set; }
public Binding binding { get; private set; }
public BindAttribute(BindChannel mChannel)
public SlotAttribute(int mslotId, Binding mImplicitBinding)
channel = mChannel;
slotId = mslotId;
binding = mImplicitBinding;
protected static MethodInfo GetMethodInfo(LambdaExpression expression)
{
MethodCallExpression outermostExpression = expression.Body as MethodCallExpression;
 
if (outermostExpression == null)
{
throw new ArgumentException("Invalid Expression. Expression should consist of a Method call only.");
}
 
return outermostExpression.Method;
}
protected abstract MethodInfo GetFunctionToConvert();
private static SlotValueType ConvertTypeToSlotValueType(ParameterInfo p)

t = p.ParameterType.GetElementType();
if (t == typeof(ShaderSingle))
if (t == typeof(Vector1))
{
return SlotValueType.Vector1;
}

public sealed override void UpdateNodeAfterDeserialization()
{
var method = GetFunctionToConvert();
var returnType = method.ReturnType;
if (returnType != typeof(void))
return;
if (method == null)
throw new ArgumentException("Mapped method is null on node" + this);
var inStart = 1;
var outStart = -1;
if (method.ReturnType != typeof(string))
throw new ArgumentException("Mapped function should return string");
// validate no duplicates
var slotAtributes = method.GetParameters().Select(GetSlotAttribute).ToList();
if (slotAtributes.Any(x => x == null))
throw new ArgumentException("Missing SlotAttribute does not exist on " + method.Name);
if(slotAtributes.GroupBy(x=>x.slotId).Any(x => x.Count() > 1))
throw new ArgumentException("Duplicate SlotAttribute on " + method.Name);
if (par.IsOut)
{
slots.Add(new MaterialSlot(outStart, par.Name, par.Name, SlotType.Output,
var slotid = GetSlotAttribute(par);
slots.Add(new MaterialSlot(slotid.slotId, par.Name, par.Name, par.IsOut ? SlotType.Output : SlotType.Input,
m_ParamMap.Add(new KeyValuePair<int, ParameterInfo>(outStart, par));
outStart--;
}
else
{
slots.Add(new MaterialSlot(inStart, par.Name, par.Name, SlotType.Input,
ConvertTypeToSlotValueType(par), Vector4.zero));
m_ParamMap.Add(new KeyValuePair<int, ParameterInfo>(inStart, par));
inStart++;
}
m_Slots.Add(slotid);
}
foreach (var slot in slots)
{

{
foreach (var outSlot in GetOutputSlots<MaterialSlot>())
{
visitor.AddShaderChunk(GetParamName(outSlot) + " " + GetVariableNameForSlot(outSlot.id) + ";", true);
visitor.AddShaderChunk(GetParamTypeName(outSlot) + " " + GetVariableNameForSlot(outSlot.id) + ";", true);
foreach (var arg in GetSlots<MaterialSlot>())
foreach (var arg in GetSlots<MaterialSlot>().OrderBy(x => x.id))
{
if (!first)
{

var inEdges = owner.GetEdges(arg.slotReference);
if (!inEdges.Any())
{
var info = m_ParamMap.Where(x => x.Key == arg.id).Select(x => x.Value).FirstOrDefault();
var info = m_Slots.FirstOrDefault(x => x.slotId == arg.id);
var bindingInfo = GetSlotBinding(arg, info);
if (bindingInfo != BindChannel.None)
var bindingInfo = info.binding;
if (bindingInfo != Binding.None)
{
call += BindChannelToShaderName(bindingInfo);
continue;

visitor.AddShaderChunk(call, true);
}
private string GetParamName(MaterialSlot slot)
private string GetParamTypeName(MaterialSlot slot)
{
return ConvertConcreteSlotValueTypeToString(precision, slot.concreteValueType);
}

string header = "void " + GetFunctionName() + "(";
var first = true;
foreach (var kvp in m_ParamMap)
foreach (var slot in GetSlots<MaterialSlot>().OrderBy(x => x.id))
{
if (!first)
header += ", ";

var slot = FindSlot<MaterialSlot>(kvp.Key);
if (slot == null)
throw new ArgumentException("something is wrong");
if (slot.isOutputSlot)
header += "out ";
if (kvp.Value.IsOut)
header += "out ";
header += GetParamName(slot) + " " + kvp.Value.Name;
header += GetParamTypeName(slot) + " " + slot.shaderOutputName;
}
header += ")";

protected abstract string GetFunctionBody();
private static object GetDefault(Type type)
{
return type.IsValueType ? Activator.CreateInstance(type) : null;
}
private string GetFunctionBody(MethodInfo info)
{
var args = new List<object>();
foreach (var param in info.GetParameters())
args.Add(GetDefault(param.ParameterType));
return info.Invoke(this, args.ToArray()) as string;
}
string function = GetFunctionHeader() + GetFunctionBody();
string function = GetFunctionHeader() + GetFunctionBody(GetFunctionToConvert()).Replace("{precision}", precision.ToString());
private bool NodeRequiresBinding(BindChannel channel)
private bool NodeRequiresBinding(Binding channel)
foreach (var kvp in m_ParamMap)
foreach (var slot in GetSlots<MaterialSlot>())
var slot = FindSlot<MaterialSlot>(kvp.Key);
if (slot == null)
throw new ArgumentException("something is wrong");
if (SlotRequiresBinding(channel, slot, kvp.Value))
if (SlotRequiresBinding(channel, slot))
private bool SlotRequiresBinding(BindChannel channel, [NotNull]MaterialSlot slot, [NotNull]ParameterInfo info)
private bool SlotRequiresBinding(Binding channel, [NotNull]MaterialSlot slot)
{
if (slot.isOutputSlot)
return false;

return false;
foreach (var attr in info.GetCustomAttributes(typeof(BindAttribute), false).OfType<BindAttribute>())
{
if (attr.channel == channel)
return true;
}
var slotAttr = m_Slots.FirstOrDefault(x => x.slotId == slot.id);
if (slotAttr != null && slotAttr.binding == channel)
return true;
private static BindChannel GetSlotBinding([NotNull]MaterialSlot slot, [NotNull]ParameterInfo info)
private static SlotAttribute GetSlotAttribute([NotNull]ParameterInfo info)
if (slot.isOutputSlot)
return BindChannel.None;
var attrs = info.GetCustomAttributes(typeof(BindAttribute), false).OfType<BindAttribute>().ToList();
if (attrs.Count > 0)
return attrs.First().channel;
return BindChannel.None;
var attrs = info.GetCustomAttributes(typeof(SlotAttribute), false).OfType<SlotAttribute>().ToList();
return attrs.FirstOrDefault();
return NodeRequiresBinding(BindChannel.Normal);
return NodeRequiresBinding(Binding.Normal);
}
public bool RequiresMeshUV(UVChannel channel)

case UVChannel.uv0:
return NodeRequiresBinding(BindChannel.MeshUV0);
return NodeRequiresBinding(Binding.MeshUV0);
return NodeRequiresBinding(BindChannel.MeshUV1);
return NodeRequiresBinding(Binding.MeshUV1);
return NodeRequiresBinding(BindChannel.MeshUV2);
return NodeRequiresBinding(Binding.MeshUV2);
return NodeRequiresBinding(BindChannel.MeshUV3);
return NodeRequiresBinding(Binding.MeshUV3);
default:
throw new ArgumentOutOfRangeException("channel", channel, null);
}

{
return NodeRequiresBinding(BindChannel.ScreenPosition);
return NodeRequiresBinding(Binding.ScreenPosition);
return NodeRequiresBinding(BindChannel.ViewDirection);
return NodeRequiresBinding(Binding.ViewDirection);
return NodeRequiresBinding(BindChannel.ViewDirectionTangentSpace);
return NodeRequiresBinding(Binding.ViewDirectionTangentSpace);
return NodeRequiresBinding(BindChannel.WorldPosition);
return NodeRequiresBinding(Binding.WorldPosition);
return NodeRequiresBinding(BindChannel.Tangent);
return NodeRequiresBinding(Binding.Tangent);
return NodeRequiresBinding(BindChannel.Bitangent);
return NodeRequiresBinding(Binding.Bitangent);
return NodeRequiresBinding(BindChannel.VertexColor);
}
/*
public string outputDimension
{
get { return ConvertConcreteSlotValueTypeToString(FindOutputSlot<MaterialSlot>(OutputSlotId).concreteValueType); }
return NodeRequiresBinding(Binding.VertexColor);
public string inputDimension
{
get { return ConvertConcreteSlotValueTypeToString(FindInputSlot<MaterialSlot>(InputSlotId).concreteValueType); }
}*/
}
}

2
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/MaterialSlot.cs


public string shaderOutputName
{
get { return m_ShaderOutputName; }
set { m_ShaderOutputName = value; }
private set { m_ShaderOutputName = value; }
}
public bool showValue

42
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Math/Advanced/FmodNode.cs


namespace UnityEngine.MaterialGraph
using System;
using System.Reflection;
namespace UnityEngine.MaterialGraph
[Title ("Math/Advanced/Fmod")]
public class FmodNode : Function2Input
{
public FmodNode ()
{
name = "Fmod";
}
[Title("Math/Advanced/Fmod")]
public class FmodNode : CodeFunctionNode
{
public FmodNode()
{
name = "Fmod";
}
protected override string GetFunctionName ()
{
return "fmod";
}
}
protected override MethodInfo GetFunctionToConvert()
{
return GetType().GetMethod("Unity_Fmod", BindingFlags.Static | BindingFlags.NonPublic);
}
static string Unity_Fmod(
[Slot(0, Binding.None)] DynamicDimensionVector first,
[Slot(1, Binding.None)] DynamicDimensionVector second,
[Slot(2, Binding.None)] out DynamicDimensionVector result)
{
return
@"
{
result = fmod(first, second);
}
";
}
}
}

28
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Math/Advanced/PosterizeNode.cs


using System.Reflection;
class PosterizeNode : Function2Input, IGeneratesFunction
class PosterizeNode : CodeFunctionNode
{
public PosterizeNode()
{

protected override string GetFunctionName() {return "unity_posterize_" + precision; }
protected override MethodInfo GetFunctionToConvert()
{
return GetType().GetMethod("Unity_Posterize", BindingFlags.Static | BindingFlags.NonPublic);
}
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)
static string Unity_Posterize(
[Slot(0, Binding.None)] DynamicDimensionVector input,
[Slot(1, Binding.None)] DynamicDimensionVector stepsize,
[Slot(2, Binding.None)] out DynamicDimensionVector result)
var outputString = new ShaderGenerator();
outputString.AddShaderChunk(GetFunctionPrototype("input", "stepsize"), false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("return floor(input / stepsize) * stepsize;", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
visitor.AddShaderChunk(outputString.GetShaderString(0), true);
return
@"
{
result = floor(input / stepsize) * stepsize;;
}
";
}
}
}

28
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Math/Basic/AddNode.cs


using System.Reflection;
public class AddNode : Function2Input, IGeneratesFunction
public class AddNode : CodeFunctionNode
{
public AddNode()
{

protected override string GetFunctionName()
protected override MethodInfo GetFunctionToConvert()
return "unity_add_" + precision;
return GetType().GetMethod("Unity_Add", BindingFlags.Static | BindingFlags.NonPublic);
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)
static string Unity_Add(
[Slot(0, Binding.None)] DynamicDimensionVector first,
[Slot(1, Binding.None)] DynamicDimensionVector second,
[Slot(2, Binding.None)] out DynamicDimensionVector result)
var outputString = new ShaderGenerator();
outputString.AddShaderChunk(GetFunctionPrototype("arg1", "arg2"), false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("return arg1 + arg2;", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
visitor.AddShaderChunk(outputString.GetShaderString(0), true);
return
@"
{
result = first + second;
}
";
}
}
}

28
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Math/Basic/DivNode.cs


using System.Reflection;
public class DivNode : Function2Input, IGeneratesFunction
public class DivNode : CodeFunctionNode
{
public DivNode()
{

protected override string GetFunctionName() {return "unity_div_" + precision; }
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)
protected override MethodInfo GetFunctionToConvert()
var outputString = new ShaderGenerator();
outputString.AddShaderChunk(GetFunctionPrototype("arg1", "arg2"), false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("return arg1 / arg2;", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
return GetType().GetMethod("Unity_Div", BindingFlags.Static | BindingFlags.NonPublic);
}
visitor.AddShaderChunk(outputString.GetShaderString(0), true);
static string Unity_Div(
[Slot(0, Binding.None)] DynamicDimensionVector first,
[Slot(1, Binding.None)] DynamicDimensionVector second,
[Slot(2, Binding.None)] out DynamicDimensionVector result)
{
return @"
{
result = first / second;
}
";
}
}
}

28
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Math/Basic/MultiplyNode.cs


using System.Reflection;
public class MultiplyNode : Function2Input, IGeneratesFunction
public class MultiplyNode : CodeFunctionNode
{
public MultiplyNode()
{

protected override string GetFunctionName()
protected override MethodInfo GetFunctionToConvert()
return "unity_multiply_" + precision;
return GetType().GetMethod("Unity_Multiply", BindingFlags.Static | BindingFlags.NonPublic);
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)
static string Unity_Multiply(
[Slot(0, Binding.None)] DynamicDimensionVector first,
[Slot(1, Binding.None)] DynamicDimensionVector second,
[Slot(2, Binding.None)] out DynamicDimensionVector result)
var outputString = new ShaderGenerator();
outputString.AddShaderChunk(GetFunctionPrototype("arg1", "arg2"), false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("return arg1 * arg2;", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
visitor.AddShaderChunk(outputString.GetShaderString(0), true);
return
@"
{
result = first * second;
}
";
}
}
}

22
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Math/Basic/PowerNode.cs


using System.Reflection;
public class PowerNode : Function2Input
public class PowerNode : CodeFunctionNode
{
public PowerNode()
{

protected override string GetFunctionName() { return "pow"; }
protected override MethodInfo GetFunctionToConvert()
{
return GetType().GetMethod("Unity_Pow", BindingFlags.Static | BindingFlags.NonPublic);
}
static string Unity_Pow(
[Slot(0, Binding.None)] DynamicDimensionVector first,
[Slot(1, Binding.None)] DynamicDimensionVector second,
[Slot(2, Binding.None)] out DynamicDimensionVector result)
{
return
@"
{
result = pow(first, second);
}
";
}
}
}

31
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Math/Basic/SubtractNode.cs


using System.Reflection;
class SubtractNode : Function2Input, IGeneratesFunction
class SubtractNode : CodeFunctionNode
{
public SubtractNode()
{

protected override string GetFunctionName() {return "unity_subtract_" + precision; }
protected override MethodInfo GetFunctionToConvert()
{
return GetType().GetMethod("Unity_Subtract", BindingFlags.Static | BindingFlags.NonPublic);
}
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)
static string Unity_Subtract(
[Slot(0, Binding.None)] DynamicDimensionVector first,
[Slot(1, Binding.None)] DynamicDimensionVector second,
[Slot(2, Binding.None)] out DynamicDimensionVector result)
var outputString = new ShaderGenerator();
outputString.AddShaderChunk(GetFunctionPrototype("arg1", "arg2"), false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("return arg1 - arg2;", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
visitor.AddShaderChunk(outputString.GetShaderString(0), true);
return
@"
{
result = first - second;
}
";
}
}
}

23
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Math/Range/MaxNode.cs


using System.Reflection;
public class MaximumNode : Function2Input
public class MaximumNode : CodeFunctionNode
{
public MaximumNode()
{

protected override string GetFunctionName() { return "max"; }
protected override MethodInfo GetFunctionToConvert()
{
return GetType().GetMethod("Unity_Max", BindingFlags.Static | BindingFlags.NonPublic);
}
static string Unity_Max(
[Slot(0, Binding.None)] DynamicDimensionVector first,
[Slot(1, Binding.None)] DynamicDimensionVector second,
[Slot(2, Binding.None)] out DynamicDimensionVector result)
{
return
@"
{
result = max(first, second);
}
";
}
}
}

21
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Math/Range/MinNode.cs


using System.Reflection;
public class MinimumNode : Function2Input
public class MinimumNode : CodeFunctionNode
{
public MinimumNode()
{

protected override string GetFunctionName() { return "min"; }
protected override MethodInfo GetFunctionToConvert()
{
return GetType().GetMethod("Unity_Min", BindingFlags.Static | BindingFlags.NonPublic);
}
static string Unity_Min(
[Slot(0, Binding.None)] DynamicDimensionVector first,
[Slot(1, Binding.None)] DynamicDimensionVector second,
[Slot(2, Binding.None)] out DynamicDimensionVector result)
{
return
@"
{
result = min(first, second);
};";
}
}
}

25
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Math/Round/StepNode.cs


namespace UnityEngine.MaterialGraph
using System.Linq.Expressions;
using System.Reflection;
namespace UnityEngine.MaterialGraph
public class StepNode : Function2Input
public class StepNode : CodeFunctionNode
{
public StepNode()
{

protected override string GetFunctionName() { return "step"; }
protected override MethodInfo GetFunctionToConvert()
{
return GetType().GetMethod("Unity_Step", BindingFlags.Static | BindingFlags.NonPublic);
}
static string Unity_Step(
[Slot(0, Binding.None)] DynamicDimensionVector first,
[Slot(1, Binding.None)] DynamicDimensionVector second,
[Slot(2, Binding.None)] out DynamicDimensionVector result)
{
return
@"
{
result = step(first, second);
}
";
}
}
}

24
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Math/Trigonometry/ATan2Node.cs


namespace UnityEngine.MaterialGraph
using System.Reflection;
namespace UnityEngine.MaterialGraph
public class ATan2Node : Function2Input
public class ATan2Node : CodeFunctionNode
{
public ATan2Node()
{

protected override string GetFunctionName() { return "atan2"; }
protected override MethodInfo GetFunctionToConvert()
{
return GetType().GetMethod("Unity_ATan2", BindingFlags.Static | BindingFlags.NonPublic);
}
static string Unity_ATan2(
[Slot(0, Binding.None)] DynamicDimensionVector first,
[Slot(1, Binding.None)] DynamicDimensionVector second,
[Slot(2, Binding.None)] out DynamicDimensionVector result)
{
return
@"
{
result = atan2(first, second);
}
";
}
}
}

24
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Math/Vector/CrossNode.cs


namespace UnityEngine.MaterialGraph
using System.Reflection;
namespace UnityEngine.MaterialGraph
public class CrossNode : Function2Input
public class CrossNode : CodeFunctionNode
{
public CrossNode()
{

protected override string GetFunctionName() { return "cross"; }
protected override MethodInfo GetFunctionToConvert()
{
return GetType().GetMethod("Unity_CrossProduct", BindingFlags.Static | BindingFlags.NonPublic);
}
static string Unity_CrossProduct(
[Slot(0, Binding.None)] DynamicDimensionVector first,
[Slot(1, Binding.None)] DynamicDimensionVector second,
[Slot(2, Binding.None)] out DynamicDimensionVector result)
{
return
@"
{
result = cross(first, second);
}
";
}
}
}

26
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Math/Vector/Distance.cs


namespace UnityEngine.MaterialGraph
using System.Reflection;
namespace UnityEngine.MaterialGraph
public class DistanceNode : Function2Input
public class DistanceNode : CodeFunctionNode
{
public DistanceNode()
{

protected override string GetFunctionName() { return "distance"; }
}
protected override MethodInfo GetFunctionToConvert()
{
return GetType().GetMethod("Unity_Distance", BindingFlags.Static | BindingFlags.NonPublic);
}
static string Unity_Distance(
[Slot(0, Binding.None)] DynamicDimensionVector first,
[Slot(1, Binding.None)] DynamicDimensionVector second,
[Slot(2, Binding.None)] out DynamicDimensionVector result)
{
return
@"
{
result = distance(first, second);
}
";
}
}
}

30
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Math/Vector/DotNode.cs


using UnityEngine.Graphing;
using System.Reflection;
public class DotNode : Function2Input
public class DotNode : CodeFunctionNode
{
public DotNode()
{

protected override string GetFunctionName()
{
return "dot";
}
protected override MaterialSlot GetInputSlot1()
{
return new MaterialSlot(InputSlot1Id, GetInputSlot1Name(), kInputSlot1ShaderName, SlotType.Input, SlotValueType.Vector3, Vector4.zero);
}
protected override MaterialSlot GetInputSlot2()
protected override MethodInfo GetFunctionToConvert()
return new MaterialSlot(InputSlot2Id, GetInputSlot2Name(), kInputSlot2ShaderName, SlotType.Input, SlotValueType.Vector3, Vector4.zero);
return GetType().GetMethod("Unity_DotProduct", BindingFlags.Static | BindingFlags.NonPublic);
protected override MaterialSlot GetOutputSlot()
static string Unity_DotProduct(
[Slot(0, Binding.None)] Vector3 first,
[Slot(1, Binding.None)] Vector3 second,
[Slot(2, Binding.None)] out Vector1 result)
return new MaterialSlot(OutputSlotId, GetOutputSlotName(), kOutputSlotShaderName, SlotType.Output, SlotValueType.Vector1, Vector4.zero);
return
@"
{
result = dot(first, second);
}
";
}
}
}

40
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Math/Vector/FresnelNode.cs


using UnityEngine.Graphing;
using System.Reflection;
class FresnelNode : Function2Input, IGeneratesFunction
class FresnelNode : CodeFunctionNode
{
public FresnelNode()
{

protected override MaterialSlot GetInputSlot1()
{
return new MaterialSlot(InputSlot1Id, GetInputSlot1Name(), kInputSlot1ShaderName, SlotType.Input, SlotValueType.Vector3, Vector4.zero);
}
protected override MaterialSlot GetInputSlot2()
{
return new MaterialSlot(InputSlot2Id, GetInputSlot2Name(), kInputSlot2ShaderName, SlotType.Input, SlotValueType.Vector3, Vector4.zero);
}
protected override MaterialSlot GetOutputSlot()
protected override MethodInfo GetFunctionToConvert()
return new MaterialSlot(OutputSlotId, GetOutputSlotName(), kOutputSlotShaderName, SlotType.Output, SlotValueType.Vector1, Vector4.zero);
return GetType().GetMethod("Unity_Fresnel", BindingFlags.Static | BindingFlags.NonPublic);
protected override string GetFunctionName() { return "unity_fresnel_" + precision; }
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)
static string Unity_Fresnel(
[Slot(0, Binding.None)] Vector3 first,
[Slot(1, Binding.None)] Vector3 second,
[Slot(2, Binding.None)] out Vector1 result)
var outputString = new ShaderGenerator();
outputString.AddShaderChunk(GetFunctionPrototype("arg1", "arg2"), false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("return (1.0 - dot (normalize (arg1), normalize (arg2)));", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
visitor.AddShaderChunk(outputString.GetShaderString(0), true);
return
@"
{
result = (1.0 - dot (normalize (first), normalize (second)));
}
";
}
}
}

46
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Math/Vector/ReflectNode.cs


using UnityEngine.Graphing;
using System.Reflection;
class ReflectNode : Function2Input, IGeneratesFunction
class ReflectNode : CodeFunctionNode
{
public ReflectNode()
{

protected override string GetInputSlot1Name() {return "Normal"; }
protected override string GetInputSlot2Name() {return "Direction"; }
protected override string GetOutputSlotName() {return "Reflection"; }
protected override MaterialSlot GetInputSlot1()
protected override MethodInfo GetFunctionToConvert()
return new MaterialSlot(InputSlot1Id, GetInputSlot1Name(), kInputSlot1ShaderName, SlotType.Input, SlotValueType.Vector3, Vector4.zero);
return GetType().GetMethod("Unity_Reflect", BindingFlags.Static | BindingFlags.NonPublic);
protected override MaterialSlot GetInputSlot2()
{
return new MaterialSlot(InputSlot2Id, GetInputSlot2Name(), kInputSlot2ShaderName, SlotType.Input, SlotValueType.Vector3, Vector4.zero);
}
protected override MaterialSlot GetOutputSlot()
{
return new MaterialSlot(OutputSlotId, GetOutputSlotName(), kOutputSlotShaderName, SlotType.Output, SlotValueType.Vector3, Vector4.zero);
}
protected override string GetFunctionName() {return "unity_reflect_" + precision; }
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)
static string Unity_Reflect(
[Slot(0, Binding.None)] Vector3 normal,
[Slot(1, Binding.None)] Vector3 direction,
[Slot(2, Binding.None)] out Vector3 reflection)
var outputString = new ShaderGenerator();
outputString.AddShaderChunk(GetFunctionPrototype("normal", "direction"), false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk(precision + "3 vn = normalize(normal);", false);
outputString.AddShaderChunk(precision + "3 vd = normalize(direction);", false);
outputString.AddShaderChunk("return 2 * dot(vn, vd) * vn - vd, 1.0;", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
reflection = Vector3.one;
visitor.AddShaderChunk(outputString.GetShaderString(0), true);
return @"
{
{precision}3 vn = normalize(normal);
{precision}3 vd = normalize(direction);
reflection = 2 * dot(vn, vd) * vn - vd, 1.0;
}";
}
}
}

42
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Normal/BlendNormalNode.cs


using UnityEngine.Graphing;
using System.Reflection;
public class BlendNormalNode : Function2Input, IGeneratesFunction
public class BlendNormalNode : CodeFunctionNode
{
public BlendNormalNode()
{

protected override string GetFunctionName()
{
return "unity_blendnormal_" + precision;
}
protected override MaterialSlot GetInputSlot1()
{
return new MaterialSlot(InputSlot1Id, GetInputSlot1Name(), kInputSlot1ShaderName, SlotType.Input, SlotValueType.Vector3, Vector4.zero);
}
protected override MaterialSlot GetInputSlot2()
{
return new MaterialSlot(InputSlot2Id, GetInputSlot2Name(), kInputSlot2ShaderName, SlotType.Input, SlotValueType.Vector3, Vector4.zero);
}
protected override MaterialSlot GetOutputSlot()
protected override MethodInfo GetFunctionToConvert()
return new MaterialSlot(OutputSlotId, GetOutputSlotName(), kOutputSlotShaderName, SlotType.Output, SlotValueType.Vector3, Vector4.zero);
return GetType().GetMethod("Unity_Blendnormal", BindingFlags.Static | BindingFlags.NonPublic);
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)
static string Unity_Blendnormal(
[Slot(0, Binding.None)] Vector3 first,
[Slot(1, Binding.None)] Vector3 second,
[Slot(2, Binding.None)] out Vector3 result)
var outputString = new ShaderGenerator();
outputString.AddShaderChunk(GetFunctionPrototype("arg1", "arg2"), false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("return normalize("+precision+"3(arg1.rg + arg2.rg, arg1.b * arg2.b));", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
result = Vector3.one;
visitor.AddShaderChunk(outputString.GetShaderString(0), true);
return @"
{
result = normalize({precision}3(first.rg + second.rg, first.b * second.b));
}
";
}
}
}

60
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Procedural/GradientRampNode.cs


namespace UnityEngine.MaterialGraph
using System.Reflection;
namespace UnityEngine.MaterialGraph
public class GradientRampNode : Function2Input, IGeneratesFunction
public class GradientRampNode : CodeFunctionNode
{
public GradientRampNode()
{

protected override string GetFunctionName()
{
return "unitygGradientramp_" + precision;
}
protected override string GetInputSlot1Name()
{
return "UV";
}
protected override string GetInputSlot2Name()
{
return "Stripe Count";
}
protected override MaterialSlot GetInputSlot1()
{
return new MaterialSlot(InputSlot1Id, GetInputSlot1Name(), kInputSlot1ShaderName, UnityEngine.Graphing.SlotType.Input, SlotValueType.Vector2, Vector4.zero);
}
protected override MaterialSlot GetInputSlot2()
{
return new MaterialSlot(InputSlot2Id, GetInputSlot2Name(), kInputSlot2ShaderName, UnityEngine.Graphing.SlotType.Input, SlotValueType.Vector1, Vector4.zero);
}
protected override MaterialSlot GetOutputSlot()
protected override MethodInfo GetFunctionToConvert()
return new MaterialSlot(OutputSlotId, GetOutputSlotName(), kOutputSlotShaderName, UnityEngine.Graphing.SlotType.Output, SlotValueType.Vector1, Vector2.zero);
return GetType().GetMethod("Unity_Gradientramp", BindingFlags.Static | BindingFlags.NonPublic);
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)
static string Unity_Gradientramp(
[Slot(0, Binding.None)] Vector2 uv,
[Slot(1, Binding.None)] Vector1 stripeCount,
[Slot(2, Binding.None)] out Vector1 result)
var outputString = new ShaderGenerator();
outputString.AddShaderChunk(GetFunctionPrototype("uv", "stripeCount"), false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("float widthOfEachStripe = 1.0 / stripeCount;", false);
outputString.AddShaderChunk("float t = fmod(floor(uv.x / widthOfEachStripe), stripeCount);", false);
outputString.AddShaderChunk("return lerp(0.0, 1.0, t / (stripeCount - 1.0));", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
visitor.AddShaderChunk(outputString.GetShaderString(0), true);
return @"
{
{precision} widthOfEachStripe = 1.0 / stripeCount;
{precision} t = fmod(floor(uv.x / widthOfEachStripe), stripeCount);
result = lerp(0.0, 1.0, t / (stripeCount - 1.0));;
}
";
}
}
}

61
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Procedural/HexNode.cs


namespace UnityEngine.MaterialGraph
using System.Reflection;
namespace UnityEngine.MaterialGraph
public class HexNode : Function2Input, IGeneratesFunction
public class HexNode : CodeFunctionNode
{
public HexNode()
{

protected override string GetFunctionName()
protected override MethodInfo GetFunctionToConvert()
return "unity_hex_" + precision;
return GetType().GetMethod("Unity_Hex", BindingFlags.Static | BindingFlags.NonPublic);
protected override string GetInputSlot1Name()
static string Unity_Hex(
[Slot(0, Binding.None)] Vector2 uv,
[Slot(1, Binding.None)] Vector1 thickness,
[Slot(2, Binding.None)] out Vector1 result)
return "UV";
}
protected override MaterialSlot GetInputSlot1()
{
return new MaterialSlot(InputSlot1Id, GetInputSlot1Name(), kInputSlot1ShaderName, UnityEngine.Graphing.SlotType.Input, SlotValueType.Vector2, Vector2.zero);
}
protected override string GetInputSlot2Name()
{
return "Thickness";
}
protected override MaterialSlot GetInputSlot2()
{
return new MaterialSlot(InputSlot2Id, GetInputSlot2Name(), kInputSlot2ShaderName, UnityEngine.Graphing.SlotType.Input, SlotValueType.Vector1, Vector2.zero);
}
protected override MaterialSlot GetOutputSlot()
{
return new MaterialSlot(OutputSlotId, GetOutputSlotName(), kOutputSlotShaderName, UnityEngine.Graphing.SlotType.Output, SlotValueType.Vector1, Vector2.zero);
}
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)
{
var outputString = new ShaderGenerator();
outputString.AddShaderChunk(GetFunctionPrototype("uv", "thickness"), false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("uv.y += fmod(floor(uv.x), 2.0) * 0.5;", false);
outputString.AddShaderChunk("uv = abs(frac(uv) - 0.5);", false);
outputString.AddShaderChunk("return step(thickness, abs(max(uv.x * 1.5 + uv.y, uv.y * 2.0) - 1.0));", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
visitor.AddShaderChunk(outputString.GetShaderString(0), true);
return
@"
{
uv.y += fmod(floor(uv.x), 2.0) * 0.5;
uv = abs(frac(uv) - 0.5);
result = step(thickness, abs(max(uv.x * 1.5 + uv.y, uv.y * 2.0) - 1.0));
}
";
}
}
}

59
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Procedural/ParticleNode.cs


namespace UnityEngine.MaterialGraph
using System.Reflection;
namespace UnityEngine.MaterialGraph
public class ParticleNode : Function2Input, IGeneratesFunction
public class ParticleNode : CodeFunctionNode
{
public ParticleNode()
{

protected override string GetFunctionName()
protected override MethodInfo GetFunctionToConvert()
return "unity_particle_" + precision;
}
protected override string GetInputSlot1Name()
{
return "UV";
return GetType().GetMethod("Unity_Particle", BindingFlags.Static | BindingFlags.NonPublic);
protected override string GetInputSlot2Name()
static string Unity_Particle(
[Slot(0, Binding.None)] Vector2 uv,
[Slot(1, Binding.None)] Vector1 scaleFactor,
[Slot(2, Binding.None)] out Vector1 result)
return "ScaleFactor";
}
protected override MaterialSlot GetInputSlot1()
{
return new MaterialSlot(InputSlot1Id, GetInputSlot1Name(), kInputSlot1ShaderName, UnityEngine.Graphing.SlotType.Input, SlotValueType.Vector2, Vector2.zero);
}
protected override MaterialSlot GetInputSlot2()
{
return new MaterialSlot(InputSlot2Id, GetInputSlot2Name(), kInputSlot2ShaderName, UnityEngine.Graphing.SlotType.Input, SlotValueType.Vector1, Vector2.zero);
}
protected override MaterialSlot GetOutputSlot()
{
return new MaterialSlot(OutputSlotId, GetOutputSlotName(), kOutputSlotShaderName, UnityEngine.Graphing.SlotType.Output, SlotValueType.Vector1, Vector2.zero);
}
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)
{
var outputString = new ShaderGenerator();
outputString.AddShaderChunk(GetFunctionPrototype("uv", "scaleFactor"), false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("uv = uv * 2.0 - 1.0;", false);
outputString.AddShaderChunk("return abs(1.0/length(uv * scaleFactor));", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
visitor.AddShaderChunk(outputString.GetShaderString(0), true);
return
@"
{
uv = uv * 2.0 - 1.0;;
result = abs(1.0/length(uv * scaleFactor));
}
";
}
}
}

56
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Procedural/PulseNode.cs


namespace UnityEngine.MaterialGraph
using System.Reflection;
namespace UnityEngine.MaterialGraph
public class PulseNode : Function2Input, IGeneratesFunction
public class PulseNode : CodeFunctionNode
{
public PulseNode()
{

protected override string GetFunctionName()
{
return "unity_pulsenode_" + precision;
}
protected override string GetInputSlot1Name()
{
return "X Value";
}
protected override string GetInputSlot2Name()
{
return "X Min and Max";
}
protected override MaterialSlot GetInputSlot1()
{
return new MaterialSlot(InputSlot1Id, GetInputSlot1Name(), kInputSlot1ShaderName, UnityEngine.Graphing.SlotType.Input, SlotValueType.Vector1, Vector2.zero);
}
protected override MaterialSlot GetInputSlot2()
{
return new MaterialSlot(InputSlot2Id, GetInputSlot2Name(), kInputSlot2ShaderName, UnityEngine.Graphing.SlotType.Input, SlotValueType.Vector2, Vector2.zero);
}
protected override MaterialSlot GetOutputSlot()
protected override MethodInfo GetFunctionToConvert()
return new MaterialSlot(OutputSlotId, GetOutputSlotName(), kOutputSlotShaderName, UnityEngine.Graphing.SlotType.Output, SlotValueType.Vector1, Vector2.zero);
return GetType().GetMethod("Unity_Pulse", BindingFlags.Static | BindingFlags.NonPublic);
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)
static string Unity_Pulse(
[Slot(0, Binding.None)] Vector1 x,
[Slot(1, Binding.None)] Vector1 xMinAndMax,
[Slot(2, Binding.None)] out Vector1 result)
var outputString = new ShaderGenerator();
outputString.AddShaderChunk(GetFunctionPrototype("xValue", "xMinAndMax"), false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("return step( xMinAndMax.x, xValue ) - step( xMinAndMax.y, xValue );", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
visitor.AddShaderChunk(outputString.GetShaderString(0), true);
return @"
{{
result = step( xMinAndMax.x, xValue ) - step( xMinAndMax.y, xValue );
}}
";
}
}
}

58
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Procedural/RepeatingDotNode.cs


namespace UnityEngine.MaterialGraph
using System.Reflection;
namespace UnityEngine.MaterialGraph
public class RepeatingDotNode : Function2Input, IGeneratesFunction
public class RepeatingDotNode : CodeFunctionNode
{
public RepeatingDotNode()
{

protected override string GetFunctionName()
{
return "unity_repreatingdot_" + precision;
}
protected override string GetInputSlot1Name()
{
return "UV";
}
protected override string GetInputSlot2Name()
{
return "Count";
}
protected override MaterialSlot GetInputSlot1()
{
return new MaterialSlot(InputSlot1Id, GetInputSlot1Name(), kInputSlot1ShaderName, UnityEngine.Graphing.SlotType.Input, SlotValueType.Vector2, Vector2.zero);
}
protected override MaterialSlot GetInputSlot2()
{
return new MaterialSlot(InputSlot2Id, GetInputSlot2Name(), kInputSlot2ShaderName, UnityEngine.Graphing.SlotType.Input, SlotValueType.Vector1, Vector4.zero);
}
protected override MaterialSlot GetOutputSlot()
protected override MethodInfo GetFunctionToConvert()
return new MaterialSlot(OutputSlotId, GetOutputSlotName(), kOutputSlotShaderName, UnityEngine.Graphing.SlotType.Output, SlotValueType.Vector1, Vector2.zero);
return GetType().GetMethod("Unity_Repreatingdot", BindingFlags.Static | BindingFlags.NonPublic);
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)
static string Unity_Repreatingdot(
[Slot(0, Binding.None)] Vector2 uv,
[Slot(1, Binding.None)] Vector1 count,
[Slot(2, Binding.None)] out Vector1 result)
var outputString = new ShaderGenerator();
outputString.AddShaderChunk(GetFunctionPrototype("uv", "count"), false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("uv *= 2.0 - 1.0;", false);
outputString.AddShaderChunk("uv = fmod(uv * count, 1.0) * 2.0 - 1.0;", false);
outputString.AddShaderChunk("return length(uv);", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
visitor.AddShaderChunk(outputString.GetShaderString(0), true);
return
@"
{
uv *= 2.0 - 1.0;
uv = fmod(uv * count, 1.0) * 2.0 - 1.0;
result = length(uv);
}";
}
}
}

61
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/UV/TwistNode.cs


using UnityEngine.Graphing;
using System.Reflection;
using UnityEngine.Graphing;
public class TwistNode : Function2Input, IGeneratesFunction
public class TwistNode : CodeFunctionNode
{
public TwistNode()
{

protected override string GetFunctionName()
protected override MethodInfo GetFunctionToConvert()
return "unity_twist_" + precision;
return GetType().GetMethod("Unity_Twist", BindingFlags.Static | BindingFlags.NonPublic);
protected override string GetInputSlot1Name()
static string Unity_Twist(
[Slot(0, Binding.None)] Vector2 uv,
[Slot(1, Binding.None)] Vector1 twist,
[Slot(2, Binding.None)] out Vector2 result)
return "UV";
}
result = Vector2.zero;
protected override string GetInputSlot2Name()
{
return "Twist";
}
protected override MaterialSlot GetInputSlot1()
{
return new MaterialSlot(InputSlot1Id, GetInputSlot1Name(), kInputSlot1ShaderName, SlotType.Input, SlotValueType.Vector2, Vector2.zero);
}
protected override MaterialSlot GetInputSlot2()
{
return new MaterialSlot(InputSlot2Id, GetInputSlot2Name(), kInputSlot2ShaderName, SlotType.Input, SlotValueType.Vector1, Vector2.zero);
}
protected override MaterialSlot GetOutputSlot()
{
return new MaterialSlot(OutputSlotId, GetOutputSlotName(), kOutputSlotShaderName, SlotType.Output, SlotValueType.Vector2, Vector2.zero);
}
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)
{
var outputString = new ShaderGenerator();
outputString.AddShaderChunk(GetFunctionPrototype("uv", "twist"), false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("float angle = twist * length(uv);", false);
outputString.AddShaderChunk("float x = cos(angle) * uv.x - sin(angle) * uv.y;", false);
outputString.AddShaderChunk("float y = sin(angle) * uv.x + cos(angle) * uv.y;", false);
outputString.AddShaderChunk("return float2(x, y);", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
visitor.AddShaderChunk(outputString.GetShaderString(0), true);
return
@"
{
{precision} angle = twist * length(uv);
{precision} x = cos(angle) * uv.x - sin(angle) * uv.y;
{precision} y = sin(angle) * uv.x + cos(angle) * uv.y;
result = float2(x, y);
}
";
}
}
}

118
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/UV/UVRotatorNode.cs


using UnityEngine.Graphing;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
public class UVRotatorNode : Function2Input, IGeneratesFunction, IMayRequireMeshUV
public class UVRotatorNode : CodeFunctionNode
private const string kUVSlotName = "UV";
private const string kRotationSlotName = "Rotation";
protected override string GetFunctionName()
{
return "unity_uvrotator_" + precision;
}
protected override MaterialSlot GetInputSlot1()
protected override MethodInfo GetFunctionToConvert()
return new MaterialSlot(InputSlot1Id, kUVSlotName, kUVSlotName, SlotType.Input, SlotValueType.Vector4, Vector4.zero);
return GetType().GetMethod("Unity_UVRotator", BindingFlags.Static | BindingFlags.NonPublic);
protected override MaterialSlot GetInputSlot2()
{
return new MaterialSlot(InputSlot2Id, kRotationSlotName, kRotationSlotName, SlotType.Input, SlotValueType.Vector1, Vector4.zero);
}
protected override MaterialSlot GetOutputSlot()
{
return new MaterialSlot(OutputSlotId, kUVSlotName, kOutputSlotShaderName, SlotType.Output, SlotValueType.Vector4, Vector4.zero);
}
protected override string GetFunctionCallBody(string input1Value, string input2Value)
{
//get input UV slot
var uvName = string.Format("{0}", UVChannel.uv0.GetUVName());
bool isConnected = false;
var uvSlot = FindInputSlot<MaterialSlot>(InputSlot1Id);
if (uvSlot != null)
{
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.Vector4, true);
isConnected = true;
}
}
if (isConnected)
return GetFunctionName() + " (" + input1Value + ", " + input2Value + ")";
else
return GetFunctionName() + " (" + uvName + ", " + input2Value + ")";
}
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)
static string Unity_UVRotator(
[Slot(0, Binding.MeshUV0)] Vector4 uv,
[Slot(1, Binding.None)] Vector1 rotation,
[Slot(2, Binding.None)] out Vector4 result)
var outputString = new ShaderGenerator();
result = Vector2.zero;
return
@"
{
//rotation matrix
uv.xy -= 0.5;
{0} s = sin(rotation);
{0} c = cos(rotation);
outputString.AddShaderChunk(GetFunctionPrototype("arg1", "arg2"), false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
//center texture's pivot
outputString.AddShaderChunk("arg1.xy -= 0.5;", false);
//center rotation matrix
{0}2x2 rMatrix = float2x2(c, -s, s, c);
rMatrix *= 0.5;
rMatrix += 0.5;
rMatrix = rMatrix*2 - 1
//rotation matrix
outputString.AddShaderChunk(precision + " s = sin(arg2);", false);
outputString.AddShaderChunk(precision + " c = cos(arg2);", false);
outputString.AddShaderChunk(precision + "2x2 rMatrix = float2x2(c, -s, s, c);", false);
//center rotation matrix
outputString.AddShaderChunk("rMatrix *= 0.5;", false);
outputString.AddShaderChunk("rMatrix += 0.5;", false);
outputString.AddShaderChunk("rMatrix = rMatrix*2 - 1;", false);
//multiply the UVs by the rotation matrix
outputString.AddShaderChunk("arg1.xy = mul(arg1.xy, rMatrix);", false);
outputString.AddShaderChunk("arg1.xy += 0.5;", false);
outputString.AddShaderChunk("return " + "arg1;", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
visitor.AddShaderChunk(outputString.GetShaderString(0), true);
}
public bool RequiresMeshUV(UVChannel channel)
{
if (channel != UVChannel.uv0)
{
return false;
}
var uvSlot = FindInputSlot<MaterialSlot>(InputSlot1Id);
if (uvSlot == null)
return true;
var edges = owner.GetEdges(uvSlot.slotReference).ToList();
return edges.Count == 0;
//multiply the UVs by the rotation matrix
uv.xy = mul(uv.xy, rMatrix);
uv.xy += 0.5;
result = uv;
}";
}
}
}

57
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/UV/UVTileNode.cs


namespace UnityEngine.MaterialGraph
using System.Reflection;
namespace UnityEngine.MaterialGraph
public class UVTileNode : Function2Input, IGeneratesFunction
public class UVTileNode : CodeFunctionNode
{
public UVTileNode()
{

protected override string GetFunctionName()
protected override MethodInfo GetFunctionToConvert()
return "unity_uvtile_" + precision;
return GetType().GetMethod("Unity_UVTile", BindingFlags.Static | BindingFlags.NonPublic);
protected override string GetInputSlot1Name()
static string Unity_UVTile(
[Slot(0, Binding.MeshUV0)] Vector2 uv,
[Slot(1, Binding.None)] Vector2 tileFactor,
[Slot(2, Binding.None)] out Vector2 result)
return "UV";
}
protected override MaterialSlot GetInputSlot1()
{
return new MaterialSlot(InputSlot1Id, GetInputSlot1Name(), kInputSlot1ShaderName, UnityEngine.Graphing.SlotType.Input, SlotValueType.Vector2, Vector2.zero);
}
protected override string GetInputSlot2Name()
{
return "Tile Factor (X,Y)";
}
protected override MaterialSlot GetInputSlot2()
{
return new MaterialSlot(InputSlot2Id, GetInputSlot2Name(), kInputSlot2ShaderName, UnityEngine.Graphing.SlotType.Input, SlotValueType.Vector2, new Vector2(2,2));
}
protected override MaterialSlot GetOutputSlot()
{
return new MaterialSlot(OutputSlotId, GetOutputSlotName(), kOutputSlotShaderName, UnityEngine.Graphing.SlotType.Output, SlotValueType.Vector2, Vector2.zero);
}
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)
{
var outputString = new ShaderGenerator();
outputString.AddShaderChunk(GetFunctionPrototype("uv", "tileFactor"), false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("return uv * tileFactor;", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
visitor.AddShaderChunk(outputString.GetShaderString(0), true);
result = Vector2.zero;
return
@"
{
result uv * tileFactor;
}";
}
}
}

27
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/VectorProjectionNode.cs


using System.Reflection;
public class VectorProjectionNode : Function2Input, IGeneratesFunction
public class VectorProjectionNode : CodeFunctionNode
{
public VectorProjectionNode()
{

protected override string GetFunctionName()
protected override MethodInfo GetFunctionToConvert()
return "unity_vector_projection_" + precision;
return GetType().GetMethod("Unity_VectorProjection", BindingFlags.Static | BindingFlags.NonPublic);
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)
static string Unity_VectorProjection(
[Slot(0, Binding.None)] DynamicDimensionVector first,
[Slot(1, Binding.None)] DynamicDimensionVector second,
[Slot(2, Binding.None)] out DynamicDimensionVector result)
var outputString = new ShaderGenerator();
outputString.AddShaderChunk(GetFunctionPrototype("arg1", "arg2"), false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("return arg2 * dot(arg1, arg2) / dot(arg2, arg2);", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
visitor.AddShaderChunk(outputString.GetShaderString(0), true);
return
@"
{
result = second * dot(first, second) / dot(second, second);
}";
}
}
}

28
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/VectorRejectionNode.cs


using System.Reflection;
public class VectorRejectionNode : Function2Input, IGeneratesFunction
public class VectorRejectionNode : CodeFunctionNode
{
public VectorRejectionNode()
{

protected override string GetFunctionName()
protected override MethodInfo GetFunctionToConvert()
return "unity_vector_rejection_" + precision;
return GetType().GetMethod("Unity_VectorRejection", BindingFlags.Static | BindingFlags.NonPublic);
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)
static string Unity_VectorRejection(
[Slot(0, Binding.None)] DynamicDimensionVector first,
[Slot(1, Binding.None)] DynamicDimensionVector second,
[Slot(2, Binding.None)] out DynamicDimensionVector result)
var outputString = new ShaderGenerator();
outputString.AddShaderChunk(GetFunctionPrototype("arg1", "arg2"), false);
outputString.AddShaderChunk("{", false);
outputString.Indent();
outputString.AddShaderChunk("return arg1 - (arg2 * dot(arg1, arg2) / dot(arg2, arg2));", false);
outputString.Deindent();
outputString.AddShaderChunk("}", false);
visitor.AddShaderChunk(outputString.GetShaderString(0), true);
return
@"
{
result = first - (second * dot(first, second) / dot(second, second));
}
";
}
}
}
正在加载...
取消
保存