7 Vec3
mix() (in auto ref Vec3 v0
, in auto ref Vec3 v1
, float t
) {
9 immutable float t1
= 1.0f-t
;
18 float mix() (float v0
, float v1
, float a
) {
20 immutable float t1
= 1.0f-t
;
25 // hermite interpolation
26 float smoothstep() (float edge0
, float edge1
, float x
) {
27 static if (__VERSION__
> 2067) pragma(inline
, true);
28 immutable float t
= clamp((x
-edge0
)/(edge1
-edge0
), 0.0f, 1.0f);
29 return t
*t
*(3.0f-2.0f*t
);
33 float clamp() (float x
, float minv
, float maxv
) {
34 //pragma(inline, true);
35 import std
.algorithm
: min
, max
;
36 return max(min(x
, maxv
), minv
);
40 float fract() (float x
) {
41 //pragma(inline, true);
42 import std
.math
: floor
;
48 float mod() (float x
, float y
) {
49 //pragma(inline, true);
50 import std
.math
: floor
;
51 // x minus the product of y and floor(x/y)
52 return x
-y
*floor(x
/y
);
56 // ////////////////////////////////////////////////////////////////////////// //
57 // raymarch composition functions
59 float objopRep(string objfunc
) (in auto ref Vec3 pp
, in auto ref Vec3 c
) {
60 static if (__VERSION__
> 2067) pragma(inline
, true);
61 // the following MUST be `p`
62 immutable auto p
= Vec3(mod(p
.x
, c
.x
), mod(p
.y
, c
.y
), mod(p
.z
, c
.z
))-c
*0.5f;
63 return mixin(objfunc
);
66 float objopScale(string objfunc
) (in auto ref Vec3 pp
, float s
) {
67 static if (__VERSION__
> 2067) pragma(inline
, true);
68 immutable auto p
= pp
/s
;
69 return mixin(objfunc
)*s
;
72 float objopShift(string objfunc
) (in auto ref Vec3 pp
, in auto ref Vec3 sv
) {
73 static if (__VERSION__
> 2067) pragma(inline
, true);
74 immutable auto p
= pp
+sv
;
75 return mixin(objfunc
);
78 // rotation/translation
80 Vec3 objopTx(string objfunc) (in auto ref Vec3 pp, in auto ref Mat4 mt) {
81 immutable auto p = m.invert*pp;
82 return mixin(objfunc);
86 float objopUnion() (float obj0
, float obj1
) {
87 static if (__VERSION__
> 2067) pragma(inline
, true);
88 return (obj0
< obj1 ? obj0
: obj1
); // min
91 float objopSub() (float a
, float b
) {
92 static if (__VERSION__
> 2067) pragma(inline
, true);
93 return (a
> -b ? a
: -b
);
97 float objopInter() (float a
, float b
) {
98 static if (__VERSION__
> 2067) pragma(inline
, true);
99 return (obj0
> obj1 ? obj0
: obj1
); // max
102 // returns object number
103 int objopUnion() (ref float dest
, float obj0
, float obj1
, int oid0
, int oid1
) {
104 static if (__VERSION__
> 2067) pragma(inline
, true);
114 // returns object number
115 int objopSub() (ref float dest
, float a
, float b
, int oid0
, int oid1
) {
116 static if (__VERSION__
> 2067) pragma(inline
, true);
127 // returns object number
128 int objopInter() (ref float dest
, float obj0
, float obj1
, int oid0
, int oid1
) {
129 static if (__VERSION__
> 2067) pragma(inline
, true);
140 // ////////////////////////////////////////////////////////////////////////// //
141 // raymarch composition functions that doesn't preserve distance
142 // you will probably need to decrease your step size, if you are using a raymarcher to sample this
143 // the displacement example below is using sin(20*p.x)*sin(20*p.y)*sin(20*p.z) as displacement pattern
145 float objopDisplace(string objfunc) (in auto ref Vec3 p) {
146 float d1 = mixin(objfunc);
147 float d2 = displacement(p);
153 // exponential smooth min (k = 32);
154 float sminExp (float a
, float b
, float k
) {
155 import std
.math
: exp
, log
;
156 float res
= exp(-k
*a
)+exp(-k
*b
);
160 // power smooth min (k = 8);
161 float sminPow (float a
, float b
, float k
) {
162 import std
.math
: pow
;
165 return pow((a
*b
)/(a
+b
), 1.0f/k
);
168 // polynomial smooth min (k = 0.1);
170 float sminPoly (float a, float b, float k) {
171 import std.math : clamp, exp, log;
172 float h = clamp(0.5f+0.5f*(b-a)/k, 0.0f, 1.0f);
173 return mix(b, a, h)-k*h*(1.0f-h);
177 float objopBlend(alias sminfn
, string objfunc0
, string objfunc1
) (in auto ref Vec3 p
) {
178 float d1
= mixin(objfunc0
);
179 float d2
= mixin(objfunc1
);
180 return sminfn(d1
, d2
);
184 float objopTwist (string objfunc
) (in auto ref Vec3 pp
) {
185 import std
.math
: cos
, sin
;
186 immutable float c
= cos(10.0f*pp
.z
+10.0f);
187 immutable float s
= sin(10.0f*pp
.z
+10.0f);
188 //immutable auto m = Mat2(c, -s, s, c);
196 // multiple matrix2 by vector2
197 //immutable auto p = Vec3(m*p.xz, p.y);
199 float v2x = mm.ptr[0].ptr[0]*pp.x+mm.ptr[0].ptr[1]*pp.z;
200 float v2y = mm.ptr[1].ptr[0]*pp.x+mm.ptr[1].ptr[1]*pp.z;
202 float v2x
= c
*pp
.x
-s
*pp
.y
;
203 float v2y
= s
*pp
.x
+c
*pp
.y
;
204 immutable auto p
= Vec3(v2x
, v2y
, pp
.z
);
205 return mixin(objfunc
);
209 // ////////////////////////////////////////////////////////////////////////// //
210 import std
.algorithm
: maxf
= max
, minf
= min
;
212 // raymarch object functions
213 // as our functions are very simple, use strings and `mixin` to simulate inlining ;-)
214 enum floorHeight
= 2.0f;
215 enum objfuncFloor
= q
{(p
.y
+floorHeight
)};
217 // n must be normalized (invalid formula, broken by k8)
218 static immutable planeN
= Vec3(0.0f, 0.0f, 0.0f);
220 enum objfuncPlane
= q
{(p
.dot(planeN
)+planeD
)};
222 enum torusOuterRadius
= 2.4f;
223 enum torusRadius
= 0.6f;
224 enum objfuncTorus
= q
{(Vec3
.length(p
.length
-torusOuterRadius
, p
.z
)-torusRadius
)};
227 enum shpereRadius
= 1.9f;
228 enum objfuncSphere
= q
{(p
.length
-shpereRadius
)};
230 // round box, unsigned
231 static immutable roundboxSize
= Vec3(2.0f, 0.7f, 2.0f);
232 enum roundboxRadius
= 0.2f;
233 enum objfuncRoundbox
= q
{((p
.abs
-roundboxSize
).minmax
!"max"(0.0f).length
-roundboxRadius
)};
235 // box, signed (interestingly, this is more complex than round box ;-)
236 static immutable boxSize
= Vec3(2.0f, 0.7f, 2.0f);
237 __gshared Vec3 boxTemp
;
238 enum objfuncBox
= q
{(boxTemp
= p
.abs
-boxSize
, minf(maxf(boxTemp
.x
, maxf(boxTemp
.y
, boxTemp
.z
)), 0.0f)+boxTemp
.minmax
!"max"(0.0f).length
)};
241 static immutable boxuSize
= Vec3(2.0f, 0.7f, 2.0f);
242 enum objfuncBoxu
= q
{((p
.abs
-boxuSize
).minmax
!"max"(0.0f).length
)};
245 static immutable cylParams
= Vec3(0.0f, 0.0f, 0.6f); // x, y, width
246 enum objfuncCyl
= q
{(Vec3
.length(p
.x
-cylParams
.x
, p
.z
-cylParams
.y
)-cylParams
.z
)};