summaryrefslogtreecommitdiffstats
path: root/eyes.cginc
blob: 81456d2687bb0f107a9f3a3a1b56d129405efa7e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#ifndef __EYES_INC
#define __EYES_INC

#include "globals.cginc"
#include "interpolators.cginc"
#include "math.cginc"
#include "oklab.cginc"
#include "quilez.cginc"

#if defined(_EYE_EFFECT_00)

struct EyeEffectOutput {
  float4 albedo;
  float3 emission;
  float3 normal;
  float3 worldPos;
  float4 fog;
  float2 uv;
  float metallic;
  float roughness;
};

float eye_effect_00_map(float3 p)
{
  float edge = _Gimmick_Eye_Effect_00_Edge_Length;
  float thickness = edge*10;
  return distance_from_round_box(p - float3(0, thickness*.99, 0), float3(edge, thickness, edge), edge * .1);
}

float3 eye_effect_00_nudge_p(float3 p, float3 which)
{
  float noise = _Gimmick_Eye_Effect_00_Noise.SampleLevel(linear_repeat_s, which.xz * _Gimmick_Eye_Effect_00_Period.xz * .005 + _Time[0] * .05, 0);
  return p - float3(0, noise * .01, 0);
}

float eye_effect_00_map_dr(
    float3 p,
    float3 period,
    float3 count,
    out float3 which
    )
{
  which = floor(p / period);
  // Direction to nearest neighboring cell.
  float3 min_d = p - period * which;
  float3 o = sign(min_d);

  float d = 1E9;
  float3 which_tmp = which;
  for (uint xi = 0; xi < 1; xi++)
  for (uint zi = 0; zi < 1; zi++)
  {
    float3 rid = which + float3(xi, 0, zi) * o;
    rid = clamp(rid, ceil(-(count)*0.5), floor((count-1)*0.5));
    float3 r = p - period * rid;
    r = eye_effect_00_nudge_p(r, rid);
    float cur_d = eye_effect_00_map(r);
    which_tmp = cur_d < d ? rid : which_tmp;
    d = min(d, cur_d);
  }

  which = which_tmp;
  return d;
}

float3 eye_effect_00_calc_normal(float3 p)
{
  float3 small_step = float3(1E-5, 0.0, 0.0);
  float3 which;
  float center = eye_effect_00_map_dr(p, _Gimmick_Eye_Effect_00_Period.xyz, _Gimmick_Eye_Effect_00_Count.xyz, which);
  return normalize(float3(
    eye_effect_00_map_dr(p + small_step.xyz, _Gimmick_Eye_Effect_00_Period.xyz, _Gimmick_Eye_Effect_00_Count.xyz, which) - center,
    eye_effect_00_map_dr(p + small_step.zxy, _Gimmick_Eye_Effect_00_Period.xyz, _Gimmick_Eye_Effect_00_Count.xyz, which) - center,
    eye_effect_00_map_dr(p + small_step.yzx, _Gimmick_Eye_Effect_00_Period.xyz, _Gimmick_Eye_Effect_00_Count.xyz, which) - center
  ));
}

// derived from downstairs_02.cginc effect 02
EyeEffectOutput EyeEffect_00(inout v2f i)
{
  float3 camera_position = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos, 1));
  float3 ro = i.objPos;
  float3 rd = normalize(i.objPos - camera_position);

  float2 warping_speed_vector = normalize(float2(97, 101));
  for (uint ii = 0; ii < _Gimmick_Eye_Effect_00_Domain_Warping_Octaves; ii++)
  {
      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;
      ro.xz += noise * _Gimmick_Eye_Effect_00_Domain_Warping_Strength;
  }

  #define eye_effect_00_MARCH_STEPS 1
  float total_distance_traveled = 0.0;
  const float MINIMUM_HIT_DISTANCE = 1E-4;
  const float MAXIMUM_TRACE_DISTANCE = 1E-1;
  float distance_to_closest;
  float3 which;
  [loop]
  for (uint ii = 0; ii < eye_effect_00_MARCH_STEPS; ii++)
  {
    float3 current_position = ro + total_distance_traveled * rd;
    distance_to_closest = eye_effect_00_map_dr(current_position, _Gimmick_Eye_Effect_00_Period.xyz, _Gimmick_Eye_Effect_00_Count.xyz, which);
    total_distance_traveled += distance_to_closest;
    if (distance_to_closest < MINIMUM_HIT_DISTANCE || 
        total_distance_traveled > MAXIMUM_TRACE_DISTANCE) {
      break;
    }
  }

  bool hit = distance_to_closest < MINIMUM_HIT_DISTANCE;
  float3 final_position = ro + total_distance_traveled * rd;
  float3 normal = hit ? UnityObjectToWorldNormal(eye_effect_00_calc_normal(final_position)) : i.normal;

  float3 color = hit ? 1 : 0;

  EyeEffectOutput o;
  o.albedo = float4(color, hit);
  o.emission = o.albedo;
  o.fog = 0;
  o.normal = normal;
  o.metallic = 0;
  o.roughness = 0;
  // Depth gets all fucked up unless we use i.objPos instead of ro, which is domain warped.
  o.worldPos = mul(unity_ObjectToWorld, float4(i.objPos + rd * total_distance_traveled, 1));
  o.uv = ((which.xz + _Gimmick_Eye_Effect_00_Count.xz * .5) / _Gimmick_Eye_Effect_00_Count.xz) * float2(1, -1);
  return o;
}

#endif  // _EYE_EFFECT_00

#endif  // __EYES_INC