SampleTexture2DNode.cs 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. using System.Linq;
  2. using UnityEngine;
  3. using UnityEditor.Graphing;
  4. using UnityEditor.ShaderGraph.Drawing.Controls;
  5. using UnityEditor.ShaderGraph.Internal;
  6. namespace UnityEditor.ShaderGraph
  7. {
  8. enum TextureType
  9. {
  10. Default,
  11. Normal
  12. };
  13. [FormerName("UnityEditor.ShaderGraph.Texture2DNode")]
  14. [Title("Input", "Texture", "Sample Texture 2D")]
  15. class SampleTexture2DNode : AbstractMaterialNode, IGeneratesBodyCode, IMayRequireMeshUV
  16. {
  17. public const int OutputSlotRGBAId = 0;
  18. public const int OutputSlotRId = 4;
  19. public const int OutputSlotGId = 5;
  20. public const int OutputSlotBId = 6;
  21. public const int OutputSlotAId = 7;
  22. public const int TextureInputId = 1;
  23. public const int UVInput = 2;
  24. public const int SamplerInput = 3;
  25. const string kOutputSlotRGBAName = "RGBA";
  26. const string kOutputSlotRName = "R";
  27. const string kOutputSlotGName = "G";
  28. const string kOutputSlotBName = "B";
  29. const string kOutputSlotAName = "A";
  30. const string kTextureInputName = "Texture";
  31. const string kUVInputName = "UV";
  32. const string kSamplerInputName = "Sampler";
  33. public override bool hasPreview { get { return true; } }
  34. public SampleTexture2DNode()
  35. {
  36. name = "Sample Texture 2D";
  37. UpdateNodeAfterDeserialization();
  38. }
  39. [SerializeField]
  40. private TextureType m_TextureType = TextureType.Default;
  41. [EnumControl("Type")]
  42. public TextureType textureType
  43. {
  44. get { return m_TextureType; }
  45. set
  46. {
  47. if (m_TextureType == value)
  48. return;
  49. m_TextureType = value;
  50. Dirty(ModificationScope.Graph);
  51. ValidateNode();
  52. }
  53. }
  54. [SerializeField]
  55. private NormalMapSpace m_NormalMapSpace = NormalMapSpace.Tangent;
  56. [EnumControl("Space")]
  57. public NormalMapSpace normalMapSpace
  58. {
  59. get { return m_NormalMapSpace; }
  60. set
  61. {
  62. if (m_NormalMapSpace == value)
  63. return;
  64. m_NormalMapSpace = value;
  65. Dirty(ModificationScope.Graph);
  66. }
  67. }
  68. public sealed override void UpdateNodeAfterDeserialization()
  69. {
  70. AddSlot(new Vector4MaterialSlot(OutputSlotRGBAId, kOutputSlotRGBAName, kOutputSlotRGBAName, SlotType.Output, Vector4.zero, ShaderStageCapability.Fragment));
  71. AddSlot(new Vector1MaterialSlot(OutputSlotRId, kOutputSlotRName, kOutputSlotRName, SlotType.Output, 0, ShaderStageCapability.Fragment));
  72. AddSlot(new Vector1MaterialSlot(OutputSlotGId, kOutputSlotGName, kOutputSlotGName, SlotType.Output, 0, ShaderStageCapability.Fragment));
  73. AddSlot(new Vector1MaterialSlot(OutputSlotBId, kOutputSlotBName, kOutputSlotBName, SlotType.Output, 0, ShaderStageCapability.Fragment));
  74. AddSlot(new Vector1MaterialSlot(OutputSlotAId, kOutputSlotAName, kOutputSlotAName, SlotType.Output, 0, ShaderStageCapability.Fragment));
  75. AddSlot(new Texture2DInputMaterialSlot(TextureInputId, kTextureInputName, kTextureInputName));
  76. AddSlot(new UVMaterialSlot(UVInput, kUVInputName, kUVInputName, UVChannel.UV0));
  77. AddSlot(new SamplerStateMaterialSlot(SamplerInput, kSamplerInputName, kSamplerInputName, SlotType.Input));
  78. RemoveSlotsNameNotMatching(new[] { OutputSlotRGBAId, OutputSlotRId, OutputSlotGId, OutputSlotBId, OutputSlotAId, TextureInputId, UVInput, SamplerInput });
  79. }
  80. public override void ValidateNode()
  81. {
  82. var textureSlot = FindInputSlot<Texture2DInputMaterialSlot>(TextureInputId);
  83. textureSlot.defaultType = (textureType == TextureType.Normal ? Texture2DShaderProperty.DefaultType.Bump : Texture2DShaderProperty.DefaultType.White);
  84. base.ValidateNode();
  85. }
  86. // Node generations
  87. public virtual void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMode)
  88. {
  89. var uvName = GetSlotValue(UVInput, generationMode);
  90. //Sampler input slot
  91. var samplerSlot = FindInputSlot<MaterialSlot>(SamplerInput);
  92. var edgesSampler = owner.GetEdges(samplerSlot.slotReference);
  93. var id = GetSlotValue(TextureInputId, generationMode);
  94. var result = string.Format("$precision4 {0} = SAMPLE_TEXTURE2D({1}, {2}, {3});"
  95. , GetVariableNameForSlot(OutputSlotRGBAId)
  96. , id
  97. , edgesSampler.Any() ? GetSlotValue(SamplerInput, generationMode) : "sampler" + id
  98. , uvName);
  99. sb.AppendLine(result);
  100. if (textureType == TextureType.Normal)
  101. {
  102. if (normalMapSpace == NormalMapSpace.Tangent)
  103. {
  104. sb.AppendLine(string.Format("{0}.rgb = UnpackNormal({0});", GetVariableNameForSlot(OutputSlotRGBAId)));
  105. }
  106. else
  107. {
  108. sb.AppendLine(string.Format("{0}.rgb = UnpackNormalRGB({0});", GetVariableNameForSlot(OutputSlotRGBAId)));
  109. }
  110. }
  111. sb.AppendLine(string.Format("$precision {0} = {1}.r;", GetVariableNameForSlot(OutputSlotRId), GetVariableNameForSlot(OutputSlotRGBAId)));
  112. sb.AppendLine(string.Format("$precision {0} = {1}.g;", GetVariableNameForSlot(OutputSlotGId), GetVariableNameForSlot(OutputSlotRGBAId)));
  113. sb.AppendLine(string.Format("$precision {0} = {1}.b;", GetVariableNameForSlot(OutputSlotBId), GetVariableNameForSlot(OutputSlotRGBAId)));
  114. sb.AppendLine(string.Format("$precision {0} = {1}.a;", GetVariableNameForSlot(OutputSlotAId), GetVariableNameForSlot(OutputSlotRGBAId)));
  115. }
  116. public bool RequiresMeshUV(UVChannel channel, ShaderStageCapability stageCapability)
  117. {
  118. using (var tempSlots = PooledList<MaterialSlot>.Get())
  119. {
  120. GetInputSlots(tempSlots);
  121. var result = false;
  122. foreach (var slot in tempSlots)
  123. {
  124. if (slot.RequiresMeshUV(channel))
  125. {
  126. result = true;
  127. break;
  128. }
  129. }
  130. tempSlots.Clear();
  131. return result;
  132. }
  133. }
  134. }
  135. }