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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
|
#ifndef __RAY_MARCHING_INC
#define __RAY_MARCHING_INC
#include "math.cginc"
#include "ray_marching_maps.hlsl"
#include "texture_utils.cginc"
#include "vertex.cginc"
struct RayMarchResult {
float3 objPos;
float3 objNorm;
float3 objTan;
};
float3 getObjPos(v2f i)
{
return i.objPos_orig;
}
void GetRoRd(v2f i, out float3 ro, out float3 rd) {
ro = getObjPos(i);
float3 rd_world = normalize(i.worldPos.xyz - _WorldSpaceCameraPos);
rd = mul((float3x3)unity_WorldToObject, rd_world);
}
float map(float3 p) {
float d = 1e9;
#if defined(_RAY_MARCHING_BALL)
{
float r = _Ray_Marching_Ball_Radius;
d = min(d, map_ball(p, _Ray_Marching_Ball_Radius));
}
#endif
#if defined(_RAY_MARCHING_HEXAGON)
{
float r = _Ray_Marching_Hexagon_Radius;
float h = _Ray_Marching_Hexagon_Height;
d = min(d, map_hexagon(p, float2(r, h)));
}
#endif
return d;
}
float domain_repeat(inout float3 p) {
float d;
#if defined(_RAY_MARCHING_CART_GRID)
{
float3 count = float3(_Ray_Marching_Cart_Grid_Count_X, _Ray_Marching_Cart_Grid_Count_Y, _Ray_Marching_Cart_Grid_Count_Z);
float3 period = 1.0f / count;
period *= 2;
float3 half_period = period*0.5f;
float3 which = floor((p + half_period) / period);
if (any(abs(which) > count/2)) {
p = 1e6;
} else {
p = glsl_mod(p + half_period, period) - half_period;
}
d = map(p);
}
#elif defined(_RAY_MARCHING_HEX_GRID)
{
const float3 count = _Ray_Marching_Hex_Grid_Count * 0.5f;
const float3 period = 1.0f / count;
const float3 hex = cart_to_hex(p.xy);
float half_period = period * 0.5;
float3 which = floor((hex + half_period) / period);
// The original code here was this:
// p_hex = glsl_mod(p_hex + half_period, period) - half_period;
//
// But you can simplify it. Given the definition of glsl_mod:
// #define glsl_mod(x,y) (((x)-(y)*floor((x)/(y))))
//
// You can plug in terms:
// (p_hex + half_period) - (period) * floor((p_hex + half_period) / period)
// = p_hex + half_period - period * floor(p_hex/period + 0.5)
//
// For all x,
// round(x) = floor(x + 0.5)
//
// Continuing to simplify:
// (p_hex + half_period - period * round(p_hex/period)) - half_period
// = p_hex - period * round(p_hex / period)
const float3 hex_inst = hex - period * round_hex(hex / period);
p.xy = (any(abs(which) > count/2) ? 1e9 : hex_to_cart(hex_inst));
d = map(p);
}
#endif
return d;
}
void ray_march(inout v2f i) {
#if defined(_RAY_MARCHING)
float3 ro, rd;
GetRoRd(i, ro, rd);
#if defined(_VERTEX_DEFORMATION)
// TODO optimize, we don't need to pass in `dummy`.
float3 dummy = 0;
float3 tmp_pos = ro;
undeform_normal(tmp_pos, dummy, rd);
rd = normalize(rd);
#endif
const float kMinDist = _Ray_Marching_Min_Dist;
const float kMaxDist = _Ray_Marching_Max_Dist;
const uint kMaxIter = _Ray_Marching_Max_Iter;
float d_cur;
float d_acc = 0;
float3 hit_pos;
for (uint ii = 0; ii < kMaxIter; ++ii) {
float3 p = ro + rd * d_acc;
d_cur = domain_repeat(p);
#if defined(_RAY_MARCHING_OVERSTEP)
d_cur *= (d_cur > 0 ? _Ray_Marching_Overstepping_Factor : 1.0f);
#endif
d_acc += d_cur;
if (abs(d_cur) < kMinDist) {
hit_pos = p;
break;
}
if (d_acc > kMaxDist) {
break;
}
}
if (abs(d_cur) > kMinDist) {
discard;
}
float3 lclPos = hit_pos;
float3 lclNorm;
float3 lclTan;
#if defined(_RAY_MARCHING_BALL)
{
float r = _Ray_Marching_Ball_Radius;
map_ball_normal(r, lclPos, lclNorm, lclTan);
}
#endif
#if defined(_RAY_MARCHING_HEXAGON)
{
float r = _Ray_Marching_Hexagon_Radius;
float h = _Ray_Marching_Hexagon_Height;
map_hexagon_normal(float2(r, h), lclPos, lclNorm, lclTan);
}
#endif
i.objPos = lclPos;
i.normal = lclNorm;
i.tangent.xyz = lclTan;
#endif // _RAY_MARCHING
}
#endif // __RAY_MARCHING_INC
|