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