yum-archive/SoggyShaders

Old Unity shaders.

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

yumAdd iridescence to parallax shader5eda07e

master
9.9 KiB400 linesraw
1#ifndef PARALLAX_LIGHTING
2#define PARALLAX_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
11struct appdata
12{
13  float4 position : POSITION;
14  float2 uv : TEXCOORD0;
15  float3 normal : NORMAL;
16};
17
18float _Curvature_Step;
19float _Min_Hit_Dist;
20float _Max_Dist;
21float _Ray_March_Steps;
22
23#ifdef LAYER0_TEXTURES_ON
24sampler2D _Layer0_BaseColor;
25sampler2D _Layer0_Normal;
26sampler2D _Layer0_Metallic;
27sampler2D _Layer0_Roughness;
28#endif
29
30#ifdef LAYER1_TEXTURES_ON
31sampler2D _Layer1_BaseColor;
32sampler2D _Layer1_Normal;
33sampler2D _Layer1_Metallic;
34sampler2D _Layer1_Roughness;
35#endif
36
37#ifdef LAYER2_TEXTURES_ON
38sampler2D _Layer2_BaseColor;
39sampler2D _Layer2_Normal;
40sampler2D _Layer2_Metallic;
41sampler2D _Layer2_Roughness;
42#endif
43
44float _Layer0_Offset;
45float _Layer0_XScale;
46float _Layer0_YScale;
47float _Layer0_Emission;
48
49float _Layer1_Offset;
50float _Layer1_XScale;
51float _Layer1_YScale;
52float _Layer1_Emission;
53
54float _Layer2_Offset;
55float _Layer2_XScale;
56float _Layer2_YScale;
57float _Layer2_Emission;
58
59#ifdef IRIDESCENCE_TEXTURES_ON
60sampler2D _Iridescence_Ramp;
61sampler2D _Iridescence_Normal;
62float _Iridescence_Offset;
63#endif
64
65void getVertexLightColor(inout v2f i)
66{
67  #if defined(VERTEXLIGHT_ON)
68  float3 light_pos = float3(unity_4LightPosX0.x, unity_4LightPosY0.x,
69      unity_4LightPosZ0.x);
70  float3 light_float = light_pos - i.worldPos;
71  float3 light_dir = normalize(light_float);
72  float ndotl = DotClamped(i.normal, light_dir);
73  // Light fills an expanding sphere with surface area 4 * pi * r^2.
74  // By conservation of energy, this means that at distance r, light intensity
75  // is proportional to 1/(r^2).
76  float attenuation = 1 / (1 + dot(light_float, light_float) * unity_4LightAtten0.x);
77  i.vertexLightColor = unity_LightColor[0].rgb * ndotl * attenuation;
78
79  i.vertexLightColor = Shade4PointLights(
80    unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0,
81    unity_LightColor[0].rgb,
82    unity_LightColor[1].rgb,
83    unity_LightColor[2].rgb,
84    unity_LightColor[3].rgb,
85    unity_4LightAtten0, i.worldPos, i.normal
86  );
87  #endif
88}
89
90v2f vert(appdata v)
91{
92  v2f o;
93  o.position = UnityObjectToClipPos(v.position);
94  o.worldPos = mul(unity_ObjectToWorld, v.position);
95  o.normal = UnityObjectToWorldNormal(v.normal);
96  o.uv.xy = float2(0, 0);
97  o.uv.zw = 1.0 - v.uv;
98  getVertexLightColor(o);
99  return o;
100}
101
102float getWorldSpaceDepth(in const float3 worldPos)
103{
104  float4 clip_pos = mul(UNITY_MATRIX_VP, float4(worldPos, 1.0));
105  return clip_pos.z / clip_pos.w;
106}
107
108float4 getLayerBaseColor(in float2 uv, in int layer)
109{
110  [forcecase]
111  switch (layer) {
112    #ifdef LAYER0_TEXTURES_ON
113    case 0:
114      return tex2Dgrad(_Layer0_BaseColor, uv, ddx(uv.x), ddy(uv.y));
115    #endif
116    #ifdef LAYER1_TEXTURES_ON
117    case 1:
118      return tex2Dgrad(_Layer1_BaseColor, uv, ddx(uv.x), ddy(uv.y));
119    #endif
120    #ifdef LAYER2_TEXTURES_ON
121    case 2:
122      return tex2Dgrad(_Layer2_BaseColor, uv, ddx(uv.x), ddy(uv.y));
123    #endif
124    default:
125      return 0.0;
126  }
127}
128
129float3 getLayerNormal(in float2 uv, in int layer)
130{
131  [forcecase]
132  switch (layer) {
133    #ifdef LAYER0_TEXTURES_ON
134    case 0:
135      return tex2Dgrad(_Layer0_Normal, uv, ddx(uv.x), ddy(uv.y));
136    #endif
137    #ifdef LAYER1_TEXTURES_ON
138    case 1:
139      return tex2Dgrad(_Layer1_Normal, uv, ddx(uv.x), ddy(uv.y));
140    #endif
141    #ifdef LAYER2_TEXTURES_ON
142    case 2:
143      return tex2Dgrad(_Layer2_Normal, uv, ddx(uv.x), ddy(uv.y));
144    #endif
145    default:
146      return 0.0;
147  }
148}
149
150float getLayerMetallic(in float2 uv, in int layer)
151{
152  [forcecase]
153  switch (layer) {
154    #ifdef LAYER0_TEXTURES_ON
155    case 0:
156      return tex2Dgrad(_Layer0_Metallic, uv, ddx(uv.x), ddy(uv.y));
157    #endif
158    #ifdef LAYER1_TEXTURES_ON
159    case 1:
160      return tex2Dgrad(_Layer1_Metallic, uv, ddx(uv.x), ddy(uv.y));
161    #endif
162    #ifdef LAYER2_TEXTURES_ON
163    case 2:
164      return tex2Dgrad(_Layer2_Metallic, uv, ddx(uv.x), ddy(uv.y));
165    #endif
166    default:
167      return 0.0;
168  }
169}
170
171float getLayerRoughness(in float2 uv, in int layer)
172{
173  [forcecase]
174  switch (layer) {
175    #ifdef LAYER0_TEXTURES_ON
176    case 0:
177      return tex2Dgrad(_Layer0_Roughness, uv, ddx(uv.x), ddy(uv.y));
178    #endif
179    #ifdef LAYER1_TEXTURES_ON
180    case 1:
181      return tex2Dgrad(_Layer1_Roughness, uv, ddx(uv.x), ddy(uv.y));
182    #endif
183    #ifdef LAYER2_TEXTURES_ON
184    case 2:
185      return tex2Dgrad(_Layer2_Roughness, uv, ddx(uv.x), ddy(uv.y));
186    #endif
187    default:
188      return 0.0;
189  }
190}
191
192float getLayerOffset(in int layer)
193{
194  [forcecase]
195  switch (layer) {
196    case 0:
197      return _Layer0_Offset;
198    case 1:
199      return _Layer1_Offset;
200    case 2:
201      return _Layer2_Offset;
202    default:
203      return 0.0;
204  }
205}
206
207float getLayerXScale(in int layer)
208{
209  [forcecase]
210  switch (layer) {
211    case 0:
212      return _Layer0_XScale;
213    case 1:
214      return _Layer1_XScale;
215    case 2:
216      return _Layer2_XScale;
217    default:
218      return 0.0;
219  }
220}
221
222float getLayerYScale(in int layer)
223{
224  [forcecase]
225  switch (layer) {
226    case 0:
227      return _Layer0_YScale;
228    case 1:
229      return _Layer1_YScale;
230    case 2:
231      return _Layer2_YScale;
232    default:
233      return 0.0;
234  }
235}
236
237float getLayerEmission(in int layer)
238{
239  [forcecase]
240  switch (layer) {
241    case 0:
242      return _Layer0_Emission;
243    case 1:
244      return _Layer1_Emission;
245    case 2:
246      return _Layer2_Emission;
247    default:
248      return 0.0;
249  }
250}
251
252float2 getLayerScale(in int layer)
253{
254  return float2(getLayerXScale(layer), getLayerYScale(layer));
255}
256
257float4 effect(inout v2f i, out float depth)
258{
259  float4 clip_pos = mul(UNITY_MATRIX_VP, float4(i.worldPos, 1.0));
260  depth = clip_pos.z / clip_pos.w;
261
262  float3 camera_position = _WorldSpaceCameraPos.xyz;
263  float3 view_dir = normalize(_WorldSpaceCameraPos - i.worldPos);
264
265  const float3 ro = i.worldPos;
266  const float3 rd = view_dir * -1.0;
267
268  static const float MIN_D = _Min_Hit_Dist;
269  static const float MAX_D = _Max_Dist;
270
271  float4 result = float4(1.0, 1.0, 1.0, 0.0);
272
273  float foreground_depth = -100.0;
274  bool ray_hit = false;
275
276  float3 object_offset = transpose(unity_ObjectToWorld)[3].xyz;
277
278  float4x4 object_rotate = float4x4(
279      unity_ObjectToWorld[0].xyz, 0,
280      unity_ObjectToWorld[1].xyz, 0,
281      unity_ObjectToWorld[2].xyz, 0,
282      0, 0, 0, 1
283      );
284  float3 object_scale_vec = float3(
285      length(float3(unity_ObjectToWorld[0].x, unity_ObjectToWorld[1].x, unity_ObjectToWorld[2].x)),
286      length(float3(unity_ObjectToWorld[0].y, unity_ObjectToWorld[1].y, unity_ObjectToWorld[2].y)),
287      length(float3(unity_ObjectToWorld[0].z, unity_ObjectToWorld[1].z, unity_ObjectToWorld[2].z))
288      );
289  float object_scale = min(object_scale_vec.x, min(object_scale_vec.y, object_scale_vec.z));
290
291  for (float layer = 3 - 1; layer >= 0; layer--) {
292    bool shade_out = false;
293    float3 layer_offset = float3(0.0, 0.0, 1.0) * getLayerOffset(layer) * object_scale;
294    float2 layer_scale = getLayerScale(layer);
295
296    float cum_dist = 0.0;
297    float3 bbox = float3(1.0, 1.0, 0.0) * 0.2;
298    float3 pp;
299    for (int ii = 0; ii < _Ray_March_Steps; ii++) {
300      pp = ro + rd * cum_dist - object_offset;
301      pp = mul(transpose(object_rotate), float4(pp, 1.0)).xyz;
302      pp /= object_scale_vec;
303
304      const float3 off = layer_offset;
305      pp += off;
306
307      pp.xy /= layer_scale;
308
309      float d0 = distance_from_box(pp / object_scale, bbox) * object_scale;
310      if (d0 < MIN_D) {
311        foreground_depth = getWorldSpaceDepth(pp);
312        shade_out = true;
313        ray_hit = true;
314        break;
315      }
316      cum_dist += d0;
317      if (cum_dist >= MAX_D) {
318        break;
319      }
320    }
321    if (shade_out) {
322      float2 uv = pp.xy;
323      uv /= (bbox.xy * 2.0) * object_scale;
324      uv.x += 0.5;
325      uv.y += 0.5;
326      // Render textures left-to-right when looking in the mirror.
327      if (isInMirror()) {
328        uv.x = 1.0 - uv.x;
329      }
330      uv = clamp(uv, 0.0, 1.0);
331
332      float4 color = getLayerBaseColor(uv, (int) layer);
333      if (color.a < 0.9) {
334        color.a = 0.0;
335      }
336      float3 normal = getLayerNormal(uv, (int) layer);
337      const float metallic = getLayerMetallic(uv, (int) layer);
338      const float smoothness = 1.0 - getLayerRoughness(uv, (int) layer);
339
340      bool custom_cubemap = true;
341
342      // Iridescence
343#ifdef IRIDESCENCE_TEXTURES_ON
344      if (smoothness > 0.0)
345      {
346        float3 ir_normal = normalize(tex2Dgrad(_Iridescence_Normal, uv, ddx(uv.x), ddy(uv.y)));
347
348        float3 camera_position = _WorldSpaceCameraPos.xyz;
349
350        float3 obj_normal = i.normal;
351
352        float ndotl = dot(view_dir, normalize(normal + obj_normal));
353        ndotl = glsl_mod(ndotl + _Iridescence_Offset, 1.0);
354
355        float3 ir_color = tex2Dgrad(_Iridescence_Ramp, ndotl, ddx(ndotl), ddy(ndotl));
356        color.rgb = lerp(color.rgb, ir_color, dot(ir_color, ir_color));
357        normal = lerp(normal, ir_normal, dot(ir_color, ir_color));
358      }
359#endif
360
361      // Hack: Bright cubemaps cause glare on rough surfaces. To prevent this,
362      // switch to unlit shading when shading a perfectly rough material.
363      float4 lit_color;
364      if (smoothness == 0.0) {
365        lit_color = color;
366      } else {
367        lit_color = getLitColor(i, color, pp, normal, metallic, smoothness, custom_cubemap);
368      }
369
370      lit_color.rgb += color.rgb * getLayerEmission(layer);
371
372      result.rgb = lerp(result.rgb, lit_color.rgb, lit_color.a);
373
374      float a_remainder = abs(result.a - color.a);
375      float a_increment = a_remainder * color.a;
376      result.a += a_increment;
377    }
378  }
379
380  // No ray hit: return default material
381  float base_depth = depth;
382  float metallic = 1.0;
383  float smoothness = 0.5;
384  bool custom_cubemap = true;
385  float4 bg_color = float4(1.0, 1.0, 1.0, 1.0);
386  bg_color = getLitColor(i, bg_color, i.worldPos, i.normal, metallic, smoothness, custom_cubemap);
387
388  result.rgb = lerp(bg_color.rgb, result.rgb, result.a);
389  result.a = 1.0;
390
391  return result;
392}
393
394fixed4 frag(v2f i, out float depth : SV_DepthLessEqual) : SV_Target
395{
396  return effect(i, depth);
397}
398
399#endif  // PARALLAX_LIGHTING
400