summaryrefslogtreecommitdiffstats
path: root/rorschach.cginc
blob: 3c274946456ed009ca54b3710b88deea5a634c16 (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
#ifndef __RORSCHACH_INC
#define __RORSCHACH_INC

#if defined(_RORSCHACH)

#include "globals.cginc"
#include "interpolators.cginc"
#include "iq_sdf.cginc"
#include "pema99.cginc"

struct RorschachPBR {
  float4 albedo;
};

float map_sdf(float3 p, float2 e, float3 period)
{
  float r = _Rorschach_Radius * min(period.x, min(period.y, period.z));
  float st = sin(_Time[1] * _Rorschach_Speed * e.y * e.y + e.x * 3.14159265 * 2);
  r *= st;
  float3 o = float3(
    (e.x - 0.5) * period.x,
    (e.y - 0.5) * period.y,
    0);
  //o *= _SinTime[1];
  o *= _Rorschach_Center_Randomization;
  return distance_from_sphere(p + o, r);
}

float map_dr(
    float3 p,
    float3 period,
    float3 count,
    out float3 which
    )
{
  which = round(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 (int xi = -2; xi < 3; xi++)
  for (int yi = -2; yi < 3; yi++)
  {
    float3 rid = which + float3(xi, yi, 0) * o;
    float3 r = p - period * rid;
    float2 e = float2(
        rand3(rid),
        rand3(rid + 1));
    float cur_d = map_sdf(r, e, period);
    which_tmp = cur_d < d ? rid : which;
    d = min(d, cur_d);
  }

  which = which_tmp;
  return d;
}

RorschachPBR get_rorschach(v2f i)
{
  RorschachPBR result;
  result.albedo = float4(0, 0, 0, 1);

  float3 ro = float3(i.uv0.x - 0.5, i.uv0.y - 0.5, 0);
  float3 rd = float3(0, 0, 1);

  float3 which;
  float3 period = float3(1 / (_Rorschach_Count_X+1), 1 / (_Rorschach_Count_Y+1), 1);
  float3 count = float3(_Rorschach_Count_X, _Rorschach_Count_Y, 1);
  float d = map_dr(ro, period, count, which);
  d -= map_dr(1 - ro, period, count, which) * 4;

  d = 1 - d;
  d *= d;
  d *= d;
  d *= d;
  d = 1 - d;

  d *= 3;
  d = saturate(d);

#if defined(_RORSCHACH_MASK)
  float mask = _Rorschach_Mask.SampleLevel(linear_repeat_s, i.uv0.xy, /*lod=*/0);
  mask = _Rorschach_Mask_Invert ? 1 - mask : mask;
  float mask_e = 0.1;
  // map mask onto [mask_e, 1 - mask_e]
  mask = clamp(mask, mask_e, 1.0 - mask_e);
  // map mask onto [0, 1 - 2 * mask_e]
  mask -= mask_e;
  // map mask onto [0, 1]
  mask /= (1 - 2 * mask_e);
  d *= mask;
#endif

  result.albedo.rgb = d;

  return result;
}

#endif  // _RORSCHACH
#endif  // __RORSCHACH_INC