123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 |
- using System.Linq;
- using UnityEngine;
- using UnityEditor.Graphing;
- using UnityEditor.ShaderGraph.Drawing.Controls;
- using UnityEditor.ShaderGraph.Internal;
- namespace UnityEditor.ShaderGraph
- {
- [Title("UV", "Triplanar")]
- class TriplanarNode : AbstractMaterialNode, IGeneratesBodyCode, IMayRequirePosition, IMayRequireNormal, IMayRequireTangent, IMayRequireBitangent
- {
- public const int OutputSlotId = 0;
- public const int TextureInputId = 1;
- public const int SamplerInputId = 2;
- public const int PositionInputId = 3;
- public const int NormalInputId = 4;
- public const int TileInputId = 5;
- public const int BlendInputId = 6;
- const string kOutputSlotName = "Out";
- const string kTextureInputName = "Texture";
- const string kSamplerInputName = "Sampler";
- const string kPositionInputName = "Position";
- const string kNormalInputName = "Normal";
- const string kTileInputName = "Tile";
- const string kBlendInputName = "Blend";
- public override bool hasPreview { get { return true; } }
- public override PreviewMode previewMode
- {
- get { return PreviewMode.Preview3D; }
- }
- public TriplanarNode()
- {
- name = "Triplanar";
- UpdateNodeAfterDeserialization();
- }
- [SerializeField]
- private TextureType m_TextureType = TextureType.Default;
- [EnumControl("Type")]
- public TextureType textureType
- {
- get { return m_TextureType; }
- set
- {
- if (m_TextureType == value)
- return;
- m_TextureType = value;
- Dirty(ModificationScope.Graph);
- ValidateNode();
- }
- }
- public sealed override void UpdateNodeAfterDeserialization()
- {
- AddSlot(new Vector4MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, Vector4.zero, ShaderStageCapability.Fragment));
- AddSlot(new Texture2DInputMaterialSlot(TextureInputId, kTextureInputName, kTextureInputName));
- AddSlot(new SamplerStateMaterialSlot(SamplerInputId, kSamplerInputName, kSamplerInputName, SlotType.Input));
- AddSlot(new PositionMaterialSlot(PositionInputId, kPositionInputName, kPositionInputName, CoordinateSpace.AbsoluteWorld));
- AddSlot(new NormalMaterialSlot(NormalInputId, kNormalInputName, kNormalInputName, CoordinateSpace.World));
- AddSlot(new Vector1MaterialSlot(TileInputId, kTileInputName, kTileInputName, SlotType.Input, 1));
- AddSlot(new Vector1MaterialSlot(BlendInputId, kBlendInputName, kBlendInputName, SlotType.Input, 1));
- RemoveSlotsNameNotMatching(new[] { OutputSlotId, TextureInputId, SamplerInputId, PositionInputId, NormalInputId, TileInputId, BlendInputId });
- }
- public override void ValidateNode()
- {
- var textureSlot = FindInputSlot<Texture2DInputMaterialSlot>(TextureInputId);
- textureSlot.defaultType = (textureType == TextureType.Normal ? Texture2DShaderProperty.DefaultType.Bump : Texture2DShaderProperty.DefaultType.White);
- base.ValidateNode();
- }
- // Node generations
- public virtual void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
- {
- sb.AppendLine("$precision3 {0}_UV = {1} * {2};", GetVariableNameForNode(),
- GetSlotValue(PositionInputId, generationMode), GetSlotValue(TileInputId, generationMode));
- //Sampler input slot
- var samplerSlot = FindInputSlot<MaterialSlot>(SamplerInputId);
- var edgesSampler = owner.GetEdges(samplerSlot.slotReference);
- var id = GetSlotValue(TextureInputId, generationMode);
- switch (textureType)
- {
- // Whiteout blend method
- // https://medium.com/@bgolus/normal-mapping-for-a-triplanar-shader-10bf39dca05a
- case TextureType.Normal:
- sb.AppendLine("$precision3 {0}_Blend = max(pow(abs({1}), {2}), 0);"
- , GetVariableNameForNode()
- , GetSlotValue(NormalInputId, generationMode)
- , GetSlotValue(BlendInputId, generationMode));
- sb.AppendLine("{0}_Blend /= ({0}_Blend.x + {0}_Blend.y + {0}_Blend.z ).xxx;", GetVariableNameForNode());
- sb.AppendLine("$precision3 {0}_X = UnpackNormal(SAMPLE_TEXTURE2D({1}, {2}, {0}_UV.zy));"
- , GetVariableNameForNode()
- , id
- , edgesSampler.Any() ? GetSlotValue(SamplerInputId, generationMode) : "sampler" + id);
- sb.AppendLine("$precision3 {0}_Y = UnpackNormal(SAMPLE_TEXTURE2D({1}, {2}, {0}_UV.xz));"
- , GetVariableNameForNode()
- , id
- , edgesSampler.Any() ? GetSlotValue(SamplerInputId, generationMode) : "sampler" + id);
- sb.AppendLine("$precision3 {0}_Z = UnpackNormal(SAMPLE_TEXTURE2D({1}, {2}, {0}_UV.xy));"
- , GetVariableNameForNode()
- , id
- , edgesSampler.Any() ? GetSlotValue(SamplerInputId, generationMode) : "sampler" + id);
- sb.AppendLine("{0}_X = $precision3({0}_X.xy + {1}.zy, abs({0}_X.z) * {1}.x);"
- , GetVariableNameForNode()
- , GetSlotValue(NormalInputId, generationMode));
- sb.AppendLine("{0}_Y = $precision3({0}_Y.xy + {1}.xz, abs({0}_Y.z) * {1}.y);"
- , GetVariableNameForNode()
- , GetSlotValue(NormalInputId, generationMode));
- sb.AppendLine("{0}_Z = $precision3({0}_Z.xy + {1}.xy, abs({0}_Z.z) * {1}.z);"
- , GetVariableNameForNode()
- , GetSlotValue(NormalInputId, generationMode));
- sb.AppendLine("$precision4 {0} = $precision4(normalize({1}_X.zyx * {1}_Blend.x + {1}_Y.xzy * {1}_Blend.y + {1}_Z.xyz * {1}_Blend.z), 1);"
- , GetVariableNameForSlot(OutputSlotId)
- , GetVariableNameForNode());
- sb.AppendLine("$precision3x3 {0}_Transform = $precision3x3(IN.WorldSpaceTangent, IN.WorldSpaceBiTangent, IN.WorldSpaceNormal);", GetVariableNameForNode());
- sb.AppendLine("{0}.rgb = TransformWorldToTangent({0}.rgb, {1}_Transform);"
- , GetVariableNameForSlot(OutputSlotId)
- , GetVariableNameForNode());
- break;
- default:
- sb.AppendLine("$precision3 {0}_Blend = pow(abs({1}), {2});"
- , GetVariableNameForNode()
- , GetSlotValue(NormalInputId, generationMode)
- , GetSlotValue(BlendInputId, generationMode));
- sb.AppendLine("{0}_Blend /= dot({0}_Blend, 1.0);", GetVariableNameForNode());
- sb.AppendLine("$precision4 {0}_X = SAMPLE_TEXTURE2D({1}, {2}, {0}_UV.zy);"
- , GetVariableNameForNode()
- , id
- , edgesSampler.Any() ? GetSlotValue(SamplerInputId, generationMode) : "sampler" + id);
- sb.AppendLine("$precision4 {0}_Y = SAMPLE_TEXTURE2D({1}, {2}, {0}_UV.xz);"
- , GetVariableNameForNode()
- , id
- , edgesSampler.Any() ? GetSlotValue(SamplerInputId, generationMode) : "sampler" + id);
- sb.AppendLine("$precision4 {0}_Z = SAMPLE_TEXTURE2D({1}, {2}, {0}_UV.xy);"
- , GetVariableNameForNode()
- , id
- , edgesSampler.Any() ? GetSlotValue(SamplerInputId, generationMode) : "sampler" + id);
- sb.AppendLine("$precision4 {0} = {1}_X * {1}_Blend.x + {1}_Y * {1}_Blend.y + {1}_Z * {1}_Blend.z;"
- , GetVariableNameForSlot(OutputSlotId)
- , GetVariableNameForNode());
- break;
- }
- }
- public NeededCoordinateSpace RequiresPosition(ShaderStageCapability stageCapability)
- {
- return CoordinateSpace.AbsoluteWorld.ToNeededCoordinateSpace() | CoordinateSpace.World.ToNeededCoordinateSpace();
- }
- public NeededCoordinateSpace RequiresNormal(ShaderStageCapability stageCapability)
- {
- return CoordinateSpace.World.ToNeededCoordinateSpace();
- }
- public NeededCoordinateSpace RequiresTangent(ShaderStageCapability stageCapability)
- {
- switch (m_TextureType)
- {
- case TextureType.Normal:
- return CoordinateSpace.World.ToNeededCoordinateSpace();
- default:
- return NeededCoordinateSpace.None;
- }
- }
- public NeededCoordinateSpace RequiresBitangent(ShaderStageCapability stageCapability)
- {
- switch (m_TextureType)
- {
- case TextureType.Normal:
- return CoordinateSpace.World.ToNeededCoordinateSpace();
- default:
- return NeededCoordinateSpace.None;
- }
- }
- }
- }
|