9 // ////////////////////////////////////////////////////////////////////////// //
10 public struct LightInfo
{
17 // ////////////////////////////////////////////////////////////////////////// //
18 // raymarch global vars
19 public __gshared RmFloat worldtime
= 0; // seconds
20 public __gshared Vec3 vrp
; // view reference point
21 public __gshared Vec3 vuv
; // view up vector
22 public __gshared Vec3 prp
; // camera position
25 immutable Vec3 eps
= Vec3(rmFloat
!0.001, rmFloat
!0.0, rmFloat
!0.0);
26 immutable Vec3 exyy
= eps
.xyy
;
27 immutable Vec3 eyxy
= eps
.yxy
;
28 immutable Vec3 eyyx
= eps
.yyx
;
31 // ////////////////////////////////////////////////////////////////////////// //
32 // main raycaster routine
35 int obj
; // obj id or -1 if we doesn't hit anything
36 // the following fields are undefined if obj is -1
37 RmFloat objdist
; // in teh world, from ray origin to nearest object
38 RmFloat dist
; // how much we traveled?
39 Vec3 hitp
; // hitpoint
41 @property bool hit () const pure { pragma(inline
, true); return (obj
>= 0); }
45 void castRay() (ref RayCastRes res
, in auto ref Vec3 ro
, in auto ref Vec3 rd
, RmFloat tmin
=rmFloat
!1.0, RmFloat tmax
=rmFloat
!20.0) {
46 enum MaxSteps
= 1024; // arbitrary limit, it will be culled by precision
47 enum precis
= rmFloat
!0.002;
53 for (; i
< MaxSteps
; ++i
) {
55 odst
= mapWorld(rp
, obj
);
56 if (odst
< precis || t
> tmax
) break;
59 //if (i >= MaxSteps) t -= odst;
60 //if (i >= MaxSteps) t = tmax+rmFloat!1;
61 if (i
>= MaxSteps || t
> tmax
) {
63 //res.dist = tmax+rmFloat!1; // just in case
65 res
.obj
= (obj
< 0 ?
0 : obj
);
73 // ////////////////////////////////////////////////////////////////////////// //
74 // calc normal to the nearest hitpoint
75 Vec3
calcNormal() (in auto ref Vec3 pos
) {
77 mapWorld(pos
+exyy
)-mapWorld(pos
-exyy
),
78 mapWorld(pos
+eyxy
)-mapWorld(pos
-eyxy
),
79 mapWorld(pos
+eyyx
)-mapWorld(pos
-eyyx
)
84 // calc ambient occlusion
85 RmFloat
calcAO() (in auto ref Vec3 pos
, in auto ref Vec3 nor
) {
86 RmFloat occ
= rmFloat
!0.0;
87 RmFloat sca
= rmFloat
!1.0;
88 for (int i
= 0; i
< 5; ++i
) {
89 RmFloat hr
= rmFloat
!0.01+rmFloat
!0.12*cast(RmFloat
)i
/rmFloat
!4.0;
90 Vec3 aopos
= nor
*hr
+pos
;
91 RmFloat
dd = mapWorld(aopos
);
95 return clamp(rmFloat
!1.0-rmFloat
!3.0*occ
, rmFloat
!0.0, rmFloat
!1.0);
100 RmFloat
shadow() (in auto ref Vec3 ro
, in auto ref Vec3 rd
, RmFloat mint
, RmFloat tmax
) {
101 import std
.algorithm
: min
;
102 RmFloat res
= rmFloat
!1.0;
104 for (int i
= 0; i
< 16; ++i
) {
105 RmFloat h
= mapWorld(ro
+rd
*t
);
106 t
+= clamp(h
, rmFloat
!0.02, rmFloat
!0.10);
107 if (h
< rmFloat
!0.001 || t
> tmax
) return rmFloat
!0.0;
114 RmFloat
softshadow() (in auto ref Vec3 ro
, in auto ref Vec3 rd
, RmFloat mint
, RmFloat tmax
, RmFloat k
=rmFloat
!8.0) {
115 import std
.algorithm
: min
;
116 RmFloat res
= rmFloat
!1.0;
118 for (int i
= 0; i
< 16; ++i
) {
119 RmFloat h
= mapWorld(ro
+rd
*t
);
120 res
= min(res
, k
*h
/t
);
121 t
+= clamp(h
, rmFloat
!0.02, rmFloat
!0.10);
122 if (h
< rmFloat
!0.001 || t
> tmax
) break;
124 return clamp(res
, rmFloat
!0.0, rmFloat
!1.0);
128 // ////////////////////////////////////////////////////////////////////////// //
129 // compute screen space derivatives of positions analytically without dPdx()
130 void calcDpDxy() (in auto ref Vec3 ro
, in auto ref Vec3 rd
, in auto ref Vec3 rdx
, in auto ref Vec3 rdy
, RmFloat t
, in auto ref Vec3 nor
, ref Vec3 dpdx
, ref Vec3 dpdy
) {
131 dpdx
= (rdx
*rd
.dot(nor
)/rdx
.dot(nor
)-rd
)*t
;
132 dpdy
= (rdy
*rd
.dot(nor
)/rdy
.dot(nor
)-rd
)*t
;
135 // ////////////////////////////////////////////////////////////////////////// //
138 public void raymarch() (/*RmFloat x, RmFloat y,*/ in auto ref Vec3 rd
, const(LightInfo
)[] lights
, ref Vec3 color
, in auto ref Vec3 rdx
, in auto ref Vec3 rdy
) @nogc {
139 enum maxd
= rmFloat
!100.0; // max depth
141 RayCastRes rcres
= void;
143 castRay(rcres
, prp
, rd
, rmFloat
!1.0, maxd
);
145 // did we hit something?
147 import std
.math
: exp
, pow
;
149 Vec3 nor
= calcNormal(rcres
.hitp
);
150 Vec3 refl
= rd
.reflect(nor
);
152 Vec3 dposdx
= void, dposdy
= void;
153 calcDpDxy(prp
, rd
, rdx
, rdy
, rcres
.dist
, nor
, dposdx
, dposdy
);
154 // get primitive color
155 auto col
= getObjColor(rcres
.hitp
, rcres
.obj
);
158 //vec2 uv = textureMapping( pos, oid );
159 //Vec3 sur = texture( sampler, uv );
161 //vec2 (uv,duvdx,duvdy) = textureMapping( pos, dposdx, dposdy, oid );
162 //Vec3 sur = textureGrad( sampler, uv, dudvx, dudvy );
165 RmFloat occ
= calcAO(rcres
.hitp
, nor
);
166 foreach (immutable lidx
; 1..lights
.length
) {
167 auto lt
= lights
.ptr
+lidx
;
169 //Vec3 lig = Vec3(-rmFloat!0.6, rmFloat!0.7, -rmFloat!0.5).normalize;
170 Vec3 lig
= lt
.origin
.normalized
;
171 RmFloat amb
= clamp(rmFloat
!0.5+rmFloat
!0.5*nor
.y
, rmFloat
!0.0, rmFloat
!1.0);
172 RmFloat dif
= clamp(nor
.dot(lig
), rmFloat
!0.0, rmFloat
!1.0);
173 RmFloat bac
= clamp(nor
.dot(Vec3(-lig
.x
, rmFloat
!0.0, -lig
.z
).normalize
), rmFloat
!0.0, rmFloat
!1.0)*clamp(rmFloat
!1.0-rcres
.hitp
.y
, rmFloat
!0.0, rmFloat
!1.0);
174 RmFloat dom
= smoothstep(-rmFloat
!0.1, rmFloat
!0.1, refl
.y
);
175 RmFloat fre
= pow(clamp(rmFloat
!1.0+nor
.dot(rd
), rmFloat
!0.0, rmFloat
!1.0), rmFloat
!2.0);
176 RmFloat spe
= pow(clamp(refl
.dot(lig
), rmFloat
!0.0, rmFloat
!1.0), rmFloat
!16.0);
178 dif
*= softshadow(rcres
.hitp
, lig
, rmFloat
!0.02, maxd
);
179 dom
*= softshadow(rcres
.hitp
, refl
, rmFloat
!0.02, maxd
);
182 //immutable lc = Vec3(rmFloat!1.00, rmFloat!0.85, rmFloat!0.55);
183 //immutable lc = Vec3(rmFloat!0.0, rmFloat!0.0, rmFloat!0.0);
186 Vec3 lin
= Vec3(rmFloat
!0.0, rmFloat
!0.0, rmFloat
!0.0);
187 lin
+= (*lc
)*(rmFloat
!1.20*dif
);
188 lin
+= (*lc
)*(rmFloat
!1.20*spe
)*dif
;
190 lin
+= Vec3(rmFloat
!0.50, rmFloat
!0.70, rmFloat
!1.00)*(rmFloat
!0.20*amb
)*occ
;
191 lin
+= Vec3(rmFloat
!0.50, rmFloat
!0.70, rmFloat
!1.00)*(rmFloat
!0.30*dom
)*occ
;
192 lin
+= Vec3(rmFloat
!0.25, rmFloat
!0.25, rmFloat
!0.25)*(rmFloat
!0.30*bac
)*occ
;
193 lin
+= Vec3(rmFloat
!1.00, rmFloat
!1.00, rmFloat
!1.00)*(rmFloat
!0.40*fre
)*occ
;
197 if (lights
.length
&& lights
.ptr
[0].active
) {
199 col
= mix(col
, lights
.ptr
[0].color
, rmFloat
!1.0-exp(-rmFloat
!0.002*rcres
.dist
*rcres
.dist
));
205 color
= Vec3(rmFloat
!0.7, rmFloat
!0.9, rmFloat
!1.0)+rd
.y
*rmFloat
!0.8;