yum-archive/2ner

A toon shader for Unity's BIRP.

git clone https://git.yummers.dev/yum-archive/2ner

yumadd eye shader72806ff

master
4.4 KiB133 linesraw
1#ifndef __EYES_INC
2#define __EYES_INC
3
4#include "globals.cginc"
5#include "interpolators.cginc"
6#include "math.cginc"
7#include "oklab.cginc"
8#include "quilez.cginc"
9
10#if defined(_EYE_EFFECT_00)
11
12struct EyeEffectOutput {
13  float4 albedo;
14  float3 emission;
15  float3 normal;
16  float3 worldPos;
17  float4 fog;
18  float2 uv;
19  float metallic;
20  float roughness;
21};
22
23float eye_effect_00_map(float3 p)
24{
25  float edge = _Gimmick_Eye_Effect_00_Edge_Length;
26  float thickness = edge*10;
27  return distance_from_round_box(p - float3(0, thickness*.99, 0), float3(edge, thickness, edge), edge * .1);
28}
29
30float3 eye_effect_00_nudge_p(float3 p, float3 which)
31{
32  float noise = _Gimmick_Eye_Effect_00_Noise.SampleLevel(linear_repeat_s, which.xz * _Gimmick_Eye_Effect_00_Period.xz * .005 + _Time[0] * .05, 0);
33  return p - float3(0, noise * .01, 0);
34}
35
36float eye_effect_00_map_dr(
37    float3 p,
38    float3 period,
39    float3 count,
40    out float3 which
41    )
42{
43  which = floor(p / period);
44  // Direction to nearest neighboring cell.
45  float3 min_d = p - period * which;
46  float3 o = sign(min_d);
47
48  float d = 1E9;
49  float3 which_tmp = which;
50  for (uint xi = 0; xi < 1; xi++)
51  for (uint zi = 0; zi < 1; zi++)
52  {
53    float3 rid = which + float3(xi, 0, zi) * o;
54    rid = clamp(rid, ceil(-(count)*0.5), floor((count-1)*0.5));
55    float3 r = p - period * rid;
56    r = eye_effect_00_nudge_p(r, rid);
57    float cur_d = eye_effect_00_map(r);
58    which_tmp = cur_d < d ? rid : which_tmp;
59    d = min(d, cur_d);
60  }
61
62  which = which_tmp;
63  return d;
64}
65
66float3 eye_effect_00_calc_normal(float3 p)
67{
68  float3 small_step = float3(1E-5, 0.0, 0.0);
69  float3 which;
70  float center = eye_effect_00_map_dr(p, _Gimmick_Eye_Effect_00_Period.xyz, _Gimmick_Eye_Effect_00_Count.xyz, which);
71  return normalize(float3(
72    eye_effect_00_map_dr(p + small_step.xyz, _Gimmick_Eye_Effect_00_Period.xyz, _Gimmick_Eye_Effect_00_Count.xyz, which) - center,
73    eye_effect_00_map_dr(p + small_step.zxy, _Gimmick_Eye_Effect_00_Period.xyz, _Gimmick_Eye_Effect_00_Count.xyz, which) - center,
74    eye_effect_00_map_dr(p + small_step.yzx, _Gimmick_Eye_Effect_00_Period.xyz, _Gimmick_Eye_Effect_00_Count.xyz, which) - center
75  ));
76}
77
78// derived from downstairs_02.cginc effect 02
79EyeEffectOutput EyeEffect_00(inout v2f i)
80{
81  float3 camera_position = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos, 1));
82  float3 ro = i.objPos;
83  float3 rd = normalize(i.objPos - camera_position);
84
85  float2 warping_speed_vector = normalize(float2(97, 101));
86  for (uint ii = 0; ii < _Gimmick_Eye_Effect_00_Domain_Warping_Octaves; ii++)
87  {
88      float2 noise = _Gimmick_Eye_Effect_00_Noise.SampleLevel(linear_repeat_s, ro.xz * _Gimmick_Eye_Effect_00_Domain_Warping_Scale + _Time[0] * _Gimmick_Eye_Effect_00_Domain_Warping_Speed * warping_speed_vector, 0) * 2 - 1;
89      ro.xz += noise * _Gimmick_Eye_Effect_00_Domain_Warping_Strength;
90  }
91
92  #define eye_effect_00_MARCH_STEPS 1
93  float total_distance_traveled = 0.0;
94  const float MINIMUM_HIT_DISTANCE = 1E-4;
95  const float MAXIMUM_TRACE_DISTANCE = 1E-1;
96  float distance_to_closest;
97  float3 which;
98  [loop]
99  for (uint ii = 0; ii < eye_effect_00_MARCH_STEPS; ii++)
100  {
101    float3 current_position = ro + total_distance_traveled * rd;
102    distance_to_closest = eye_effect_00_map_dr(current_position, _Gimmick_Eye_Effect_00_Period.xyz, _Gimmick_Eye_Effect_00_Count.xyz, which);
103    total_distance_traveled += distance_to_closest;
104    if (distance_to_closest < MINIMUM_HIT_DISTANCE || 
105        total_distance_traveled > MAXIMUM_TRACE_DISTANCE) {
106      break;
107    }
108  }
109
110  bool hit = distance_to_closest < MINIMUM_HIT_DISTANCE;
111  float3 final_position = ro + total_distance_traveled * rd;
112  float3 normal = hit ? UnityObjectToWorldNormal(eye_effect_00_calc_normal(final_position)) : i.normal;
113
114  float3 color = hit ? 1 : 0;
115
116  EyeEffectOutput o;
117  o.albedo = float4(color, hit);
118  o.emission = o.albedo;
119  o.fog = 0;
120  o.normal = normal;
121  o.metallic = 0;
122  o.roughness = 0;
123  // Depth gets all fucked up unless we use i.objPos instead of ro, which is domain warped.
124  o.worldPos = mul(unity_ObjectToWorld, float4(i.objPos + rd * total_distance_traveled, 1));
125  o.uv = ((which.xz + _Gimmick_Eye_Effect_00_Count.xz * .5) / _Gimmick_Eye_Effect_00_Count.xz) * float2(1, -1);
126  return o;
127}
128
129#endif  // _EYE_EFFECT_00
130
131#endif  // __EYES_INC
132
133