yum-archive/SoggyShaders

Old Unity shaders.

git clone https://git.yummers.dev/yum-archive/SoggyShaders

yumFix normal calculation in displacement shader6a14a2d

master
7.0 KiB258 linesraw
1#ifndef DISPLACEMENT_LIGHTING
2#define DISPLACEMENT_LIGHTING
3
4#include "AutoLight.cginc"
5#include "iq_sdf.cginc"
6#include "math.cginc"
7#include "motion.cginc"
8#include "pbr.cginc"
9#include "poi.cginc"
10#include "shadertoy.cginc"
11
12sampler2D _BaseColor;
13sampler2D _Normal;
14sampler2D _Metallic;
15sampler2D _Roughness;
16
17bool _Disable_Normal_Texture;
18
19sampler2D _Height;
20float _Height_LOD;
21float _Height_Exponent;
22float _Height_Scale;
23float _Height_Speed_X;
24float _Height_Speed_Y;
25float _Height_AA_Sample_Scale;
26
27sampler2D _Height_Mask;
28float _Height_Mask_Exponent;
29
30float _Center_Out_Speed;
31float _Center_Out_Sharpness;
32float _Center_Out_Min_Radius;
33float _Center_Out_Max_Radius;
34
35struct appdata
36{
37  float4 position : POSITION;
38  float2 uv : TEXCOORD0;
39  float3 normal : NORMAL;
40};
41
42void getVertexLightColor(inout v2f i)
43{
44  #if defined(VERTEXLIGHT_ON)
45  float3 light_pos = float3(unity_4LightPosX0.x, unity_4LightPosY0.x,
46      unity_4LightPosZ0.x);
47  float3 light_float = light_pos - i.worldPos;
48  float3 light_dir = normalize(light_float);
49  float ndotl = DotClamped(i.normal, light_dir);
50  // Light fills an expanding sphere with surface area 4 * pi * r^2.
51  // By conservation of energy, this means that at distance r, light intensity
52  // is proportional to 1/(r^2).
53  float attenuation = 1 / (1 + dot(light_float, light_float) * unity_4LightAtten0.x);
54  i.vertexLightColor = unity_LightColor[0].rgb * ndotl * attenuation;
55
56  i.vertexLightColor = Shade4PointLights(
57    unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0,
58    unity_LightColor[0].rgb,
59    unity_LightColor[1].rgb,
60    unity_LightColor[2].rgb,
61    unity_LightColor[3].rgb,
62    unity_4LightAtten0, i.worldPos, i.normal
63  );
64  #endif
65}
66
67v2f vert(appdata v)
68{
69  v2f o;
70
71  o.objPos = v.position;
72  o.clipPos = UnityObjectToClipPos(v.position);
73  o.worldPos = mul(unity_ObjectToWorld, v.position);
74
75  o.normal = UnityObjectToWorldNormal(v.normal);
76  o.uv = 1.0 - v.uv;
77
78  getVertexLightColor(o);
79
80  return o;
81}
82
83float getDisplacement(float2 uv)
84{
85  // Manipulate vertex in world space.
86  float height = 0;
87
88  float2 traveling_uv = uv;
89  traveling_uv.x += _Time[0] * _Height_Speed_X;
90  traveling_uv.y += _Time[0] * _Height_Speed_Y;
91  traveling_uv = glsl_mod(traveling_uv, 1.0);
92
93  const float duv = _Height_AA_Sample_Scale;
94
95  float z0 = tex2Dlod(_Height, float4(traveling_uv.x, traveling_uv.y, _Height_LOD, 0));
96  #if HEIGHT_AA_LEVEL >= 1
97  float z1 = tex2Dlod(_Height, float4(traveling_uv.x + duv, traveling_uv.y + duv, _Height_LOD, 0));
98  float z2 = tex2Dlod(_Height, float4(traveling_uv.x + duv, traveling_uv.y - duv, _Height_LOD, 0));
99  float z3 = tex2Dlod(_Height, float4(traveling_uv.x - duv, traveling_uv.y - duv, _Height_LOD, 0));
100  float z4 = tex2Dlod(_Height, float4(traveling_uv.x - duv, traveling_uv.y + duv, _Height_LOD, 0));
101  #endif
102  #if HEIGHT_AA_LEVEL >= 2
103  float z5 = tex2Dlod(_Height, float4(traveling_uv.x + duv, traveling_uv.y, _Height_LOD, 0));
104  float z6 = tex2Dlod(_Height, float4(traveling_uv.x - duv, traveling_uv.y, _Height_LOD, 0));
105  float z7 = tex2Dlod(_Height, float4(traveling_uv.x, traveling_uv.y + duv, _Height_LOD, 0));
106  float z8 = tex2Dlod(_Height, float4(traveling_uv.x, traveling_uv.y - duv, _Height_LOD, 0));
107  #endif
108
109  #if HEIGHT_AA_LEVEL == 0
110  height += z0;
111  #elif HEIGHT_AA_LEVEL == 1
112  height += (z0 + z1 + z2 + z3 + z4) / 5.0;
113  #elif HEIGHT_AA_LEVEL == 2
114  height += (z0 + z1 + z2 + z3 + z4 + z5 + z6 + z7 + z8) / 9.0;
115  #endif
116
117  height = pow(height, _Height_Exponent);
118  height *= _Height_Scale;
119
120  {
121    float mask = tex2Dlod(_Height_Mask, float4(uv, _Height_LOD, 0));
122    mask = pow(mask, _Height_Mask_Exponent);
123    height *= mask;
124  }
125  
126  // 0 at middle, 1 or -1 at edges
127  if (_Center_Out_Speed > 0.0) {
128    float2 middle_out_uv = uv * 2.0 - 1.0;
129
130    float center_dist2 = length2(middle_out_uv);
131    float ring_radius = fmod(_Time[1] * _Center_Out_Speed,
132        _Center_Out_Max_Radius - _Center_Out_Min_Radius)
133        + _Center_Out_Min_Radius;
134
135    // How far am I from the desired ring?
136    float ring_dist = dabs(center_dist2 - ring_radius, _Center_Out_Sharpness);
137    float ring_scale = exp(-1.0 * ring_dist);
138
139    float middle_out_height = ring_scale;
140    height *= middle_out_height;
141  }
142
143  return height;
144}
145
146void displace(inout v2f vert)
147{
148  float height = getDisplacement(vert.uv);
149
150  vert.worldPos += height * vert.normal;
151  vert.objPos = mul(unity_WorldToObject, float4(vert.worldPos, 1.0));
152  vert.clipPos = UnityObjectToClipPos(vert.objPos);
153}
154
155float3 getNormal(
156    v2f v0,
157    v2f v1,
158    v2f v2,
159    float duv_scale) {
160  float2 duv_v0v1 = v1.uv - v0.uv;
161  float2 duv_v0v2 = v2.uv - v0.uv;
162
163  float h0 = getDisplacement(v0.uv);
164  float h1 = getDisplacement(v0.uv + duv_v0v1 * duv_scale);
165  float h2 = getDisplacement(v0.uv + duv_v0v2 * duv_scale);
166
167  float dh_v0v1 = h1 - h0;
168  float dh_v0v2 = h2 - h0;
169
170  float3 dpos_v0v1 = v1.worldPos - v0.worldPos;
171  float3 dpos_v0v2 = v2.worldPos - v0.worldPos;
172
173  float3 p0 = v0.worldPos + h0 * v0.normal;
174  float3 p1 = v0.worldPos + dpos_v0v1 * duv_scale + lerp(h0, h1, duv_scale) * v1.normal;
175  float3 p2 = v0.worldPos + dpos_v0v2 * duv_scale + lerp(h0, h2, duv_scale) * v2.normal;
176
177  float3 tangent = normalize(p1 - p0);
178  float3 bitangent = normalize(p2 - p0);
179  float3 new_normal = normalize(cross(tangent, bitangent));
180  return new_normal;
181}
182
183// maxvertexcount == the number of vertices we create
184[maxvertexcount(3)]
185void geom(triangle v2f tri_in[3],
186  uint pid: SV_PrimitiveID,
187  inout TriangleStream<v2f> tri_out)
188{
189  float dx = 0.5;
190
191  v2f t0 = tri_in[0];
192  v2f t1 = tri_in[1];
193  v2f t2 = tri_in[2];
194
195  displace(t0);
196  displace(t1);
197  displace(t2);
198
199  // Math from here:
200  //   http://tonfilm.blogspot.com/2007/01/calculate-normals-in-shader.html
201  for (int i = 0; i < 3; i++) {
202    v2f v0 = tri_in[(i + 0) % 3];
203    v2f v1 = tri_in[(i + 1) % 3];
204    v2f v2 = tri_in[(i + 2) % 3];
205
206    float3 aa_normal = 0;
207    aa_normal += getNormal(v0, v1, v2, 0.3);
208    aa_normal += getNormal(v0, v1, v2, 0.4);
209    aa_normal += getNormal(v0, v1, v2, 0.5);
210    aa_normal += getNormal(v0, v1, v2, 0.6);
211    aa_normal += getNormal(v0, v1, v2, 0.7);
212    aa_normal = normalize(aa_normal);
213
214    if (i == 0) {
215      t0.normal = aa_normal;
216    } else if (i == 1) {
217      t1.normal = aa_normal;
218    } else if (i == 2) {
219      t2.normal = aa_normal;
220    }
221  }
222
223  tri_out.Append(t0);
224  tri_out.Append(t1);
225  tri_out.Append(t2);
226
227  tri_out.RestartStrip();
228}
229
230float getWorldSpaceDepth(in const float3 worldPos)
231{
232  float4 clip_pos = mul(UNITY_MATRIX_VP, float4(worldPos, 1.0));
233  return clip_pos.z / clip_pos.w;
234}
235
236float4 effect(inout v2f i, out float depth)
237{
238  depth = -1000.0;
239
240  float4 albedo = tex2D(_BaseColor, i.uv);
241  float3 normal = _Disable_Normal_Texture ? i.normal : tex2D(_Normal, i.uv);
242  float metallic = tex2D(_Metallic, i.uv);
243  float roughness = tex2D(_Roughness, i.uv);
244  if (albedo.a > 0) {
245    depth = getWorldSpaceDepth(i.worldPos);
246  }
247
248  return getLitColor(i, albedo, i.worldPos, normal, metallic, 1.0 - roughness,
249      /*custom_cubemap=*/true);
250}
251
252fixed4 frag(v2f i, out float depth : SV_DepthLessEqual) : SV_Target
253{
254  return effect(i, depth);
255}
256
257#endif  // DISPLACEMENT_LIGHTING
258