1
+ #pragma kernel CSMain
2
+
3
+ // textures
4
+ RWTexture2D<float4> Texture;
5
+ Texture2D<float4> Source;
6
+
7
+ // matrixes
8
+ float4x4 CamToWorld;
9
+ float4x4 CamInverseProjection;
10
+
11
+ // variables
12
+ int Iterations;
13
+ float Size;
14
+ float3 Offset;
15
+ float SizeDec;
16
+
17
+ // constants
18
+ static const int steps = 100;
19
+ static const float epsilon = 0.00001;
20
+ /*static const float PI = 3.14159265f;
21
+
22
+ // rotate functions https://en.wikipedia.org/wiki/Rotation_matrix
23
+ float DegToRad(float a) { return a * PI / 180; }
24
+ float4x4 rotateX(float a) {
25
+ a = DegToRad(a);
26
+ float c = cos(a); float s = sin(a);
27
+ return float4x4(float4(1, 0, 0, 0), float4(0, c, -s, 0), float4(0, s, c, 0), float4(0, 0, 0, 1));
28
+ }
29
+ float4x4 rotateY(float a) {
30
+ a = DegToRad(a);
31
+ float c = cos(a); float s = sin(a);
32
+ return float4x4(float4(c, 0, s, 0), float4(0, 1, 0, 0), float4(-s, 0, c, 0), float4(0, 0, 0, 1));
33
+ }
34
+ float4x4 rotateZ(float a) {
35
+ a = DegToRad(a);
36
+ float c = cos(a); float s = sin(a);
37
+ return float4x4(float4(c, -s, 0, 0), float4(s, c, 0, 0), float4(0, 0, 1, 0), float4(0, 0, 0, 1));
38
+ }
39
+ float3 transform(float3 p, float4x4 m) {
40
+ return mul(m, float4(p, 1.0)).xyz;
41
+ }
42
+
43
+ // box distance estimator from https://iquilezles.org/www/articles/distfunctions/distfunctions.htm
44
+ float DEBox(float3 p, float s) {
45
+ float3 q = abs(p) - float3(s, s, s);
46
+ return length(max(q, 0.0)) + min(max(q.x, max(q.y, q.z)), 0.0);
47
+ }
48
+
49
+ // 2D box distance estimator from https://iquilezles.org/www/articles/distfunctions2d/distfunctions2d.htm
50
+ float DEBox2D(float2 p, float s) {
51
+ float2 d = abs(p) - s;
52
+ return length(max(d, 0.0)) + min(max(d.x, d.y), 0);
53
+ }
54
+
55
+ // cross distance estimator from https://iquilezles.org/www/articles/distfunctions/distfunctions.htm
56
+ float DECross(float3 p, float s) {
57
+ s = s / 3;
58
+ float d = DEBox2D(p.xy, s);
59
+ d = min(d, DEBox2D(p.xz, s));
60
+ return min(d, DEBox2D(p.yz, s));
61
+ }
62
+
63
+ float DETest(float3 p, float s) {
64
+ return max(DEBox(p, s), -DECross(p, s*3));
65
+ }*/
66
+
67
+ // octahedron distance estimator from https://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm
68
+ float DEOctahedron(float3 p, float s) {
69
+ p = abs(p);
70
+ float m = p.x + p.y + p.z - s;
71
+ float3 q;
72
+ if (3.0 * p.x < m) q = p.xyz;
73
+ else if (3.0 * p.y < m) q = p.yzx;
74
+ else if (3.0 * p.z < m) q = p.zxy;
75
+ else return m * 0.57735027;
76
+
77
+ float k = clamp(0.5 * (q.z - q.y + s), 0.0, s);
78
+ return length(float3(q.x, q.y - s + k, q.z - k));
79
+ }
80
+
81
+ // fold space from http://blog.hvidtfeldts.net/index.php/2011/08/distance-estimated-3d-fractals-iii-folding-space
82
+ float3 Fold(float3 p, float3 n) {
83
+ return p - 2.0 * min(0.0, dot(p, n)) * n;
84
+ }
85
+
86
+ // distance to scene
87
+ float DE(float3 p) {
88
+ int i = 0;
89
+ while (i < Iterations) {
90
+ p *= SizeDec;
91
+ p = Fold(p, normalize(float3(0, 1, 1)));
92
+ p = Fold(p, normalize(float3(0, 1, -1)));
93
+ p = Fold(p, normalize(float3(1, 1, 0)));
94
+ p = Fold(p, normalize(float3(-1, 1, 0)));
95
+ p -= Offset * Size;
96
+ i++;
97
+ }
98
+ return DEOctahedron(p, Size) / pow(SizeDec, i);
99
+ }
100
+
101
+ // ray
102
+ struct Ray {
103
+ float3 origin;
104
+ float3 direction;
105
+ };
106
+
107
+ // from http://blog.three-eyed-games.com/2018/05/03/gpu-ray-tracing-in-unity-part-1/
108
+ Ray CreateRay(float3 origin, float3 direction) {
109
+ Ray ray;
110
+ ray.origin = origin;
111
+ ray.direction = direction;
112
+ return ray;
113
+ }
114
+
115
+ // from http://blog.three-eyed-games.com/2018/05/03/gpu-ray-tracing-in-unity-part-1/
116
+ Ray CreateCameraRay(float2 uv) {
117
+ float3 origin = mul(CamToWorld, float4(0, 0, 0, 1)).xyz;
118
+ float3 direction = mul(CamInverseProjection, float4(uv, 0, 1)).xyz;
119
+ direction = mul(CamToWorld, float4(direction, 0)).xyz;
120
+ direction = normalize(direction);
121
+ return CreateRay(origin, direction);
122
+ }
123
+
124
+ // cast a ray and return the result
125
+ float March(Ray ray) {
126
+ float d = 0;
127
+ float3 eye = ray.origin;
128
+
129
+ int s = 0;
130
+ while (s < steps) {
131
+ d = DE(ray.origin); // calculate distance
132
+ if (length(eye - ray.origin) > 200) s = steps; // to far away
133
+ if (d < epsilon) break; // hit
134
+ ray.origin += ray.direction * d; // march
135
+ s++; // next iteration
136
+ }
137
+
138
+ return 1 - float(s / float(steps));
139
+ }
140
+
141
+ [numthreads(8,8,1)]
142
+ void CSMain (uint3 id : SV_DispatchThreadID) {
143
+
144
+ // convert into range [-1, 1]
145
+ float w, h; Texture.GetDimensions(w, h);
146
+ float2 uv = id.xy / float2(w, h) * 2 - 1;
147
+
148
+ // create ray
149
+ Ray ray = CreateCameraRay(uv);
150
+
151
+ float res = March(ray);
152
+ //float4 ao = res * float4(0.1, 0.74, 0.61, 0);
153
+ float4 ao = res * float4(0.6, 0.6, 0.6, 0);
154
+ Texture[id.xy] = Source[id.xy] + ao;
155
+ }
0 commit comments