SampleTexture2DLODNode.cs 6.5 KB

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