|
|
|
|
|
|
using System.Linq; |
|
|
|
using UnityEngine; |
|
|
|
using UnityEditor.Graphing; |
|
|
|
using System.Collections.Generic; |
|
|
|
using UnityEditor.ShaderGraph.Drawing.Slots; |
|
|
|
using UnityEngine.Experimental.UIElements; |
|
|
|
[Title("Utility", "Heightmap To Normalmap")] |
|
|
|
public class HeightToNormalNode : AbstractMaterialNode, IGeneratesBodyCode, IMayRequireMeshUV |
|
|
|
[Title("Artistic", "Normal", "Normal Create")] |
|
|
|
public class NormalCreateNode : AbstractMaterialNode, IGeneratesBodyCode, IGeneratesFunction, IGenerateProperties, IMayRequireMeshUV |
|
|
|
public const int TextureInput = 0; |
|
|
|
public const int TexCoordInput = 1; |
|
|
|
public const int TexOffsetInput = 2; |
|
|
|
public const int StrengthInput = 3; |
|
|
|
public const int NormalOutput = 4; |
|
|
|
public const int TextureInputId = 0; |
|
|
|
public const int UVInputId = 1; |
|
|
|
public const int SamplerInputId = 2; |
|
|
|
public const int OffsetInputId = 3; |
|
|
|
public const int StrengthInputId = 4; |
|
|
|
public const int OutputSlotId = 5; |
|
|
|
const string TextureInputName = "Texture"; |
|
|
|
const string TexCoordInputName = "UV"; |
|
|
|
const string TexOffsetInputName = "Offset"; |
|
|
|
const string StrengthInputName = "Strength"; |
|
|
|
const string NormalOutputName = "Normal"; |
|
|
|
const string kTextureInputName = "Texture"; |
|
|
|
const string kUVInputName = "UV"; |
|
|
|
const string kSamplerInputName = "Sampler"; |
|
|
|
const string kOffsetInputName = "Offset"; |
|
|
|
const string kStrengthInputName = "Strength"; |
|
|
|
const string kOutputSlotName = "Out"; |
|
|
|
public HeightToNormalNode() |
|
|
|
public NormalCreateNode() |
|
|
|
name = "HeightToNormal"; |
|
|
|
name = "Normal Create"; |
|
|
|
string GetFunctionName() |
|
|
|
{ |
|
|
|
return string.Format("Unity_NormalCreate_{0}", precision); |
|
|
|
} |
|
|
|
|
|
|
|
public override bool hasPreview { get { return true; } } |
|
|
|
|
|
|
|
AddSlot(new Texture2DMaterialSlot(TextureInput, TextureInputName, TextureInputName, SlotType.Input)); |
|
|
|
AddSlot(new UVMaterialSlot(TexCoordInput, TexCoordInputName, TexCoordInputName, UVChannel.uv0)); |
|
|
|
AddSlot(new Vector1MaterialSlot(TexOffsetInput, TexOffsetInputName, TexOffsetInputName, SlotType.Input, 0.005f)); |
|
|
|
AddSlot(new Vector1MaterialSlot(StrengthInput, StrengthInputName, StrengthInputName, SlotType.Input, 8f)); |
|
|
|
AddSlot(new Vector3MaterialSlot(NormalOutput, NormalOutputName, NormalOutputName, SlotType.Output, Vector3.zero)); |
|
|
|
AddSlot(new Texture2DInputMaterialSlot(TextureInputId, kTextureInputName, kTextureInputName)); |
|
|
|
AddSlot(new UVMaterialSlot(UVInputId, kUVInputName, kUVInputName, UVChannel.uv0)); |
|
|
|
AddSlot(new SamplerStateMaterialSlot(SamplerInputId, kSamplerInputName, kSamplerInputName, SlotType.Input)); |
|
|
|
AddSlot(new Vector1MaterialSlot(OffsetInputId, kOffsetInputName, kOffsetInputName, SlotType.Input, 0.5f)); |
|
|
|
AddSlot(new Vector1MaterialSlot(StrengthInputId, kStrengthInputName, kStrengthInputName, SlotType.Input, 8f)); |
|
|
|
AddSlot(new Vector3MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, Vector3.zero)); |
|
|
|
RemoveSlotsNameNotMatching(new[] { TextureInputId, UVInputId, SamplerInputId, OffsetInputId, StrengthInputId, OutputSlotId }); |
|
|
|
} |
|
|
|
|
|
|
|
string GetFunctionPrototype(string textureIn, string samplerIn, string uvIn, string offsetIn, string strengthIn, string argOut) |
|
|
|
{ |
|
|
|
return string.Format("void {0} ({1} {2}, {3} {4}, {5} {6}, {7} {8}, {9} {10}, out {11} {12})", GetFunctionName(), |
|
|
|
ConvertConcreteSlotValueTypeToString(precision, FindInputSlot<MaterialSlot>(TextureInputId).concreteValueType), textureIn, |
|
|
|
ConvertConcreteSlotValueTypeToString(precision, FindInputSlot<MaterialSlot>(SamplerInputId).concreteValueType), samplerIn, |
|
|
|
ConvertConcreteSlotValueTypeToString(precision, FindInputSlot<MaterialSlot>(UVInputId).concreteValueType), uvIn, |
|
|
|
ConvertConcreteSlotValueTypeToString(precision, FindInputSlot<MaterialSlot>(OffsetInputId).concreteValueType), offsetIn, |
|
|
|
ConvertConcreteSlotValueTypeToString(precision, FindInputSlot<MaterialSlot>(StrengthInputId).concreteValueType), strengthIn, |
|
|
|
ConvertConcreteSlotValueTypeToString(precision, FindOutputSlot<MaterialSlot>(OutputSlotId).concreteValueType), argOut); |
|
|
|
var textureInput = GetSlotValue(TextureInput, generationMode); |
|
|
|
var texCoordInput = GetSlotValue(TexCoordInput, generationMode); |
|
|
|
var texOffsetInput = GetSlotValue(TexOffsetInput, generationMode); |
|
|
|
var strengthInput = GetSlotValue(StrengthInput, generationMode); |
|
|
|
var normalOutput = GetVariableNameForSlot(NormalOutput); |
|
|
|
string textureValue = GetSlotValue(TextureInputId, generationMode); |
|
|
|
string uvValue = GetSlotValue(UVInputId, generationMode); |
|
|
|
string offsetValue = GetSlotValue(OffsetInputId, generationMode); |
|
|
|
string strengthValue = GetSlotValue(StrengthInputId, generationMode); |
|
|
|
string outputValue = GetSlotValue(OutputSlotId, generationMode); |
|
|
|
visitor.AddShaderChunk(string.Format("{0}3 {1};", precision, normalOutput), true); |
|
|
|
visitor.AddShaderChunk("{", false); |
|
|
|
visitor.Indent(); |
|
|
|
{ |
|
|
|
visitor.AddShaderChunk(string.Format("{0}2 offsetU = float2({1}.x + {2}, {1}.y);", precision, texCoordInput, texOffsetInput), true); |
|
|
|
visitor.AddShaderChunk(string.Format("{0}2 offsetV = float2({1}.x, {1}.y + {2});", precision, texCoordInput, texOffsetInput), true); |
|
|
|
var samplerSlot = FindInputSlot<MaterialSlot>(SamplerInputId); |
|
|
|
var edgesSampler = owner.GetEdges(samplerSlot.slotReference); |
|
|
|
string samplerValue; |
|
|
|
if (edgesSampler.Any()) |
|
|
|
samplerValue = GetSlotValue(SamplerInputId, generationMode); |
|
|
|
else |
|
|
|
samplerValue = string.Format("sampler{0}", GetSlotValue(TextureInputId, generationMode)); |
|
|
|
visitor.AddShaderChunk(string.Format("{0} normalSample = UNITY_SAMPLE_TEX2D({1}, {2});", precision, textureInput, texCoordInput), true); |
|
|
|
visitor.AddShaderChunk(string.Format("{0} uSample = UNITY_SAMPLE_TEX2D({1}, offsetU);", precision, textureInput), true); |
|
|
|
visitor.AddShaderChunk(string.Format("{0} vSample = UNITY_SAMPLE_TEX2D({1}, offsetV);", precision, textureInput), true); |
|
|
|
visitor.AddShaderChunk(string.Format("{0} {1};", ConvertConcreteSlotValueTypeToString(precision, FindOutputSlot<MaterialSlot>(OutputSlotId).concreteValueType), GetVariableNameForSlot(OutputSlotId)), true); |
|
|
|
visitor.AddShaderChunk(GetFunctionCallBody(textureValue, samplerValue, uvValue, offsetValue, strengthValue, outputValue), true); |
|
|
|
} |
|
|
|
visitor.AddShaderChunk(string.Format("{0}3 va = float3(1, 0, (uSample - normalSample) * {1});", precision, strengthInput), true); |
|
|
|
visitor.AddShaderChunk(string.Format("{0}3 vb = float3(0, 1, (vSample - normalSample) * {1});", precision, strengthInput), true); |
|
|
|
visitor.AddShaderChunk(string.Format("{0} = cross(va, vb);", normalOutput), true); |
|
|
|
} |
|
|
|
visitor.Deindent(); |
|
|
|
visitor.AddShaderChunk("}", false); |
|
|
|
string GetFunctionCallBody(string textureValue, string samplerValue, string uvValue, string offsetValue, string strengthValue, string outputValue) |
|
|
|
{ |
|
|
|
return GetFunctionName() + " (" + textureValue + ", " + samplerValue + ", " + uvValue + ", " + offsetValue + ", " + strengthValue + ", " + outputValue + ");"; |
|
|
|
public override bool hasPreview |
|
|
|
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode) |
|
|
|
get { return true; } |
|
|
|
visitor.AddShaderChunk(GetFunctionPrototype("Texture", "Sampler", "UV", "Offset", "Strength", "Out"), true); |
|
|
|
visitor.AddShaderChunk("{", true); |
|
|
|
visitor.Indent(); |
|
|
|
|
|
|
|
visitor.AddShaderChunk("Offset = pow(Offset, 3) * 0.1;", true); |
|
|
|
visitor.AddShaderChunk(string.Format("{0}2 offsetU = float2(UV.x + Offset, UV.y);", precision), true); |
|
|
|
visitor.AddShaderChunk(string.Format("{0}2 offsetV = float2(UV.x, UV.y + Offset);", precision), true); |
|
|
|
|
|
|
|
visitor.AddShaderChunk(string.Format("{0} normalSample = Texture.Sample(Sampler, UV);", precision), true); |
|
|
|
visitor.AddShaderChunk(string.Format("{0} uSample = Texture.Sample(Sampler, offsetU);", precision), true); |
|
|
|
visitor.AddShaderChunk(string.Format("{0} vSample = Texture.Sample(Sampler, offsetV);", precision), true); |
|
|
|
|
|
|
|
visitor.AddShaderChunk(string.Format("{0}3 va = float3(1, 0, (uSample - normalSample) * Strength);", precision), true); |
|
|
|
visitor.AddShaderChunk(string.Format("{0}3 vb = float3(0, 1, (vSample - normalSample) * Strength);", precision), true); |
|
|
|
visitor.AddShaderChunk("Out = normalize(cross(va, vb));", true); |
|
|
|
|
|
|
|
visitor.Deindent(); |
|
|
|
visitor.AddShaderChunk("}", true); |
|
|
|
} |
|
|
|
|
|
|
|
public bool RequiresMeshUV(UVChannel channel) |
|
|
|
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |