-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhalos.cginc
141 lines (117 loc) · 3.38 KB
/
halos.cginc
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
134
135
136
137
138
139
140
141
#include "globals.cginc"
#include "interpolators.cginc"
#include "math.cginc"
#ifndef __HALOS_INC
#define __HALOS_INC
#if defined(_GIMMICK_HALO_00)
struct Halo00Params {
float3 period;
float3 count;
float2 uv;
};
struct Halo00PBR {
float4 albedo;
float3 normal;
};
float halo00_map(float3 p, float2 e)
{
return length(p) - 0.1;
}
float halo00_map_dr(
float3 p,
Halo00Params params,
out float3 which
)
{
which = round(p / params.period);
// Direction to nearest neighboring cell.
float3 min_d = p - params.period * which;
float3 o = sign(min_d);
float d = 1E9;
float3 which_tmp = which;
for (int xi = 0; xi < 1; xi++)
for (int yi = 0; yi < 1; yi++)
{
float3 rid = which + float3(xi, yi, 0) * o;
rid = clamp(rid, ceil(-(params.count)*0.5), floor((params.count-1)*0.5));
float3 r = p - params.period * rid;
float2 e = 0;
/*
float2 e = float2(
rand3(rid / 100.0),
rand3(rid / 100.0 + 1));
*/
float cur_d = halo00_map(r, e);
which_tmp =
(cur_d < d ? rid : which_tmp);
d = min(d, cur_d);
}
which = which_tmp;
return d;
}
float3 halo00_calc_normal(float3 p, Halo00Params params)
{
const float3 small_step = float3(0.0001, 0.0, 0.0);
// TODO do we need full central differences?
float3 which;
float gradient_x = halo00_map_dr(p + small_step.xyy, params, which) -
halo00_map_dr(p - small_step.xyy, params, which);
float gradient_y = halo00_map_dr(p + small_step.yxy, params, which) -
halo00_map_dr(p - small_step.yxy, params, which);
float gradient_z = halo00_map_dr(p + small_step.yyx, params, which) -
halo00_map_dr(p - small_step.yyx, params, which);
float3 normal = float3(gradient_x, gradient_y, gradient_z);
return normalize(normal);
}
void __halo00_march(float3 ro, float3 rd, Halo00Params params, out Halo00PBR result)
{
float total_distance_traveled = 0.0;
const float MINIMUM_HIT_DISTANCE = 0.0001;
const float MAXIMUM_TRACE_DISTANCE = 10.0;
ro -= (1 - (params.count % 2)) * params.period * 0.5;
#define HALO00_MARCH_STEPS 30
float distance_to_closest;
float3 current_position;
float3 which;
for (int i = 0; i < HALO00_MARCH_STEPS; i++)
{
current_position = ro + total_distance_traveled * rd;
distance_to_closest = halo00_map_dr(current_position, params, which);
if (distance_to_closest < MINIMUM_HIT_DISTANCE)
{
break;
}
if (total_distance_traveled > MAXIMUM_TRACE_DISTANCE)
{
break;
}
total_distance_traveled += distance_to_closest;
}
if (distance_to_closest < MINIMUM_HIT_DISTANCE) {
result.albedo = 1;
result.normal = halo00_calc_normal(current_position, params);
return;
}
result.albedo = 0;
result.normal = 0;
return;
}
Halo00PBR halo00_march(float3 worldPos, float2 uv)
{
Halo00PBR result;
Halo00Params params;
params.period = 0.2;
params.count = 5;
params.uv = uv;
#define COORD_SCALE 2
#define SCALEF4(f4, scale) float4((f4).x * (scale), (f4).y * (scale), (f4).z * (scale), (f4).w)
#define F42OBJ(f4) mul(unity_WorldToObject, (SCALEF4(f4, COORD_SCALE))).xyz
float3 cam_pos = F42OBJ(float4(_WorldSpaceCameraPos, 1)).xyz;
float3 mesh_pos = F42OBJ(float4(worldPos, 1)).xyz;
float3 ro = cam_pos;
float3 rd = normalize((mesh_pos - cam_pos).xyz);
__halo00_march(ro, rd, params, result);
return result;
}
#endif // _GIMMICK_HALO_00
#endif // _HALOS_INC