您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
143 行
7.7 KiB
143 行
7.7 KiB
using System.Linq;
|
|
using UnityEngine;
|
|
using UnityEditor.Graphing;
|
|
|
|
namespace UnityEditor.ShaderGraph
|
|
{
|
|
[FormerName("UnityEditor.ShaderGraph.NormalCreateNode")]
|
|
[Title("Artistic", "Normal", "Normal From Texture")]
|
|
public class NormalFromTextureNode : AbstractMaterialNode, IGeneratesBodyCode, IGeneratesFunction, IGenerateProperties, IMayRequireMeshUV
|
|
{
|
|
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 k_TextureInputName = "Texture";
|
|
const string k_UVInputName = "UV";
|
|
const string k_SamplerInputName = "Sampler";
|
|
const string k_OffsetInputName = "Offset";
|
|
const string k_StrengthInputName = "Strength";
|
|
const string k_OutputSlotName = "Out";
|
|
|
|
public NormalFromTextureNode()
|
|
{
|
|
name = "Normal From Texture";
|
|
UpdateNodeAfterDeserialization();
|
|
}
|
|
|
|
public override string documentationURL
|
|
{
|
|
get { return "https://github.com/Unity-Technologies/ShaderGraph/wiki/Normal-From-Texture-Node"; }
|
|
}
|
|
|
|
string GetFunctionName()
|
|
{
|
|
return string.Format("Unity_NormalFromTexture_{0}", precision);
|
|
}
|
|
|
|
public override bool hasPreview { get { return true; } }
|
|
|
|
public sealed override void UpdateNodeAfterDeserialization()
|
|
{
|
|
AddSlot(new Texture2DInputMaterialSlot(TextureInputId, k_TextureInputName, k_TextureInputName));
|
|
AddSlot(new UVMaterialSlot(UVInputId, k_UVInputName, k_UVInputName, UVChannel.UV0));
|
|
AddSlot(new SamplerStateMaterialSlot(SamplerInputId, k_SamplerInputName, k_SamplerInputName, SlotType.Input));
|
|
AddSlot(new Vector1MaterialSlot(OffsetInputId, k_OffsetInputName, k_OffsetInputName, SlotType.Input, 0.5f));
|
|
AddSlot(new Vector1MaterialSlot(StrengthInputId, k_StrengthInputName, k_StrengthInputName, SlotType.Input, 8f));
|
|
AddSlot(new Vector3MaterialSlot(OutputSlotId, k_OutputSlotName, k_OutputSlotName, SlotType.Output, Vector3.zero, ShaderStageCapability.Fragment));
|
|
RemoveSlotsNameNotMatching(new[] { TextureInputId, UVInputId, SamplerInputId, OffsetInputId, StrengthInputId, OutputSlotId });
|
|
}
|
|
|
|
public void GenerateNodeCode(ShaderGenerator visitor, GenerationMode generationMode)
|
|
{
|
|
var textureValue = GetSlotValue(TextureInputId, generationMode);
|
|
var uvValue = GetSlotValue(UVInputId, generationMode);
|
|
var offsetValue = GetSlotValue(OffsetInputId, generationMode);
|
|
var strengthValue = GetSlotValue(StrengthInputId, generationMode);
|
|
var outputValue = GetSlotValue(OutputSlotId, generationMode);
|
|
|
|
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));
|
|
|
|
var sb = new ShaderStringBuilder();
|
|
sb.AppendLine("{0} {1};", FindOutputSlot<MaterialSlot>(OutputSlotId).concreteValueType.ToString(precision), GetVariableNameForSlot(OutputSlotId));
|
|
sb.AppendLine("{0}({1}, {2}, {3}, {4}, {5}, {6});", GetFunctionName(), textureValue, samplerValue, uvValue, offsetValue, strengthValue, outputValue);
|
|
|
|
visitor.AddShaderChunk(sb.ToString(), false);
|
|
}
|
|
|
|
public void GenerateNodeFunction(ShaderGenerator visitor, GenerationMode generationMode)
|
|
{
|
|
var sb = new ShaderStringBuilder();
|
|
sb.AppendLine("void {0}({1} Texture, {2} Sampler, {3} UV, {4} Offset, {5} Strength, out {6} Out)", GetFunctionName(),
|
|
FindInputSlot<MaterialSlot>(TextureInputId).concreteValueType.ToString(precision),
|
|
FindInputSlot<MaterialSlot>(SamplerInputId).concreteValueType.ToString(precision),
|
|
FindInputSlot<MaterialSlot>(UVInputId).concreteValueType.ToString(precision),
|
|
FindInputSlot<MaterialSlot>(OffsetInputId).concreteValueType.ToString(precision),
|
|
FindInputSlot<MaterialSlot>(StrengthInputId).concreteValueType.ToString(precision),
|
|
FindOutputSlot<MaterialSlot>(OutputSlotId).concreteValueType.ToString(precision));
|
|
using (sb.BlockScope())
|
|
{
|
|
sb.AppendLine("Offset = pow(Offset, 3) * 0.1;");
|
|
sb.AppendLine("{0}2 offsetU = float2(UV.x + Offset, UV.y);", precision);
|
|
sb.AppendLine("{0}2 offsetV = float2(UV.x, UV.y + Offset);", precision);
|
|
|
|
sb.AppendLine("{0} normalSample = Texture.Sample(Sampler, UV).x;", precision);
|
|
sb.AppendLine("{0} uSample = Texture.Sample(Sampler, offsetU).x;", precision);
|
|
sb.AppendLine("{0} vSample = Texture.Sample(Sampler, offsetV).x;", precision);
|
|
|
|
sb.AppendLine("{0}3 va = float3(1, 0, (uSample - normalSample) * Strength);", precision);
|
|
sb.AppendLine("{0}3 vb = float3(0, 1, (vSample - normalSample) * Strength);", precision);
|
|
sb.AppendLine("Out = normalize(cross(va, vb));");
|
|
}
|
|
|
|
visitor.AddShaderChunk(sb.ToString(), true);
|
|
}
|
|
|
|
public void GenerateNodeFunction(FunctionRegistry registry, GraphContext graphContext, GenerationMode generationMode)
|
|
{
|
|
registry.ProvideFunction(GetFunctionName(), s =>
|
|
{
|
|
s.AppendLine("void {0}({1} Texture, {2} Sampler, {3} UV, {4} Offset, {5} Strength, out {6} Out)", GetFunctionName(),
|
|
FindInputSlot<MaterialSlot>(TextureInputId).concreteValueType.ToString(precision),
|
|
FindInputSlot<MaterialSlot>(SamplerInputId).concreteValueType.ToString(precision),
|
|
FindInputSlot<MaterialSlot>(UVInputId).concreteValueType.ToString(precision),
|
|
FindInputSlot<MaterialSlot>(OffsetInputId).concreteValueType.ToString(precision),
|
|
FindInputSlot<MaterialSlot>(StrengthInputId).concreteValueType.ToString(precision),
|
|
FindOutputSlot<MaterialSlot>(OutputSlotId).concreteValueType.ToString(precision));
|
|
using (s.BlockScope())
|
|
{
|
|
s.AppendLine("Offset = pow(Offset, 3) * 0.1;");
|
|
s.AppendLine("{0}2 offsetU = float2(UV.x + Offset, UV.y);", precision);
|
|
s.AppendLine("{0}2 offsetV = float2(UV.x, UV.y + Offset);", precision);
|
|
|
|
s.AppendLine("{0} normalSample = Texture.Sample(Sampler, UV);", precision);
|
|
s.AppendLine("{0} uSample = Texture.Sample(Sampler, offsetU);", precision);
|
|
s.AppendLine("{0} vSample = Texture.Sample(Sampler, offsetV);", precision);
|
|
|
|
s.AppendLine("{0}3 va = float3(1, 0, (uSample - normalSample) * Strength);", precision);
|
|
s.AppendLine("{0}3 vb = float3(0, 1, (vSample - normalSample) * Strength);", precision);
|
|
s.AppendLine("Out = normalize(cross(va, vb));");
|
|
}
|
|
});
|
|
}
|
|
|
|
public bool RequiresMeshUV(UVChannel channel, ShaderStageCapability stageCapability)
|
|
{
|
|
foreach (var slot in this.GetInputSlots<MaterialSlot>().OfType<IMayRequireMeshUV>())
|
|
{
|
|
if (slot.RequiresMeshUV(channel))
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
}
|