completely new tracer; now it does correct lights
[raymarch.git] / raytracer.d
blobc1aa5e24f1c9fb4c421e316ac36e3487234f07cf
1 module raytracer;
3 private:
4 import objfn;
5 import vecs;
6 import world;
9 // ////////////////////////////////////////////////////////////////////////// //
10 // raymarch global vars
11 public __gshared float worldtime = 0; // seconds
12 public __gshared Vec3 vrp; // view reference point
13 public __gshared Vec3 vuv; // view up vector
14 public __gshared Vec3 prp; // camera position
17 immutable Vec3 eps = Vec3(0.001f, 0.0f, 0.0f);
18 immutable Vec3 exyy = eps.xyy;
19 immutable Vec3 eyxy = eps.yxy;
20 immutable Vec3 eyyx = eps.yyx;
23 // ////////////////////////////////////////////////////////////////////////// //
24 Vec3 calcNormal() (in auto ref Vec3 pos) {
25 return Vec3(
26 mapWorld(pos+exyy)-mapWorld(pos-exyy),
27 mapWorld(pos+eyxy)-mapWorld(pos-eyxy),
28 mapWorld(pos+eyyx)-mapWorld(pos-eyyx)
29 ).normalize;
33 float calcAO() (in auto ref Vec3 pos, in auto ref Vec3 nor) {
34 float occ = 0.0f;
35 float sca = 1.0f;
36 for (int i = 0; i < 5; ++i) {
37 float hr = 0.01f+0.12f*cast(float)i/4.0f;
38 Vec3 aopos = nor*hr+pos;
39 float dd = mapWorld(aopos);
40 occ += -(dd-hr)*sca;
41 sca *= 0.95f;
43 return clamp(1.0f-3.0f*occ, 0.0f, 1.0f);
47 float castRay() (ref int obj, out float dx, ref Vec3 ro, in auto ref Vec3 rd, float tmin, float tmax) {
48 //float tmin = 1.0f;
49 //float tmax = 20.0f;
50 float precis = 0.002f;
51 float t = tmin;
52 float m = -1.0f;
53 auto orig = ro;
54 for (int i = 0; i < 50; ++i) {
55 ro = orig+rd*t;
56 float res = mapWorld(ro, obj);
57 dx = res;
58 if (res < precis || t > tmax) break;
59 t += res;
61 if (t > tmax) obj = -1;
62 return t;
66 float shadow() (in auto ref Vec3 ro, in auto ref Vec3 rd, float mint, float tmax) {
67 import std.algorithm : min;
68 float res = 1.0f;
69 float t = mint;
70 for (int i = 0; i < 16; ++i) {
71 float h = mapWorld(ro+rd*t);
72 t += clamp(h, 0.02f, 0.10f);
73 if (h < 0.001f || t > tmax) return 0.0f;
75 return 1.0f;
79 float softshadow() (in auto ref Vec3 ro, in auto ref Vec3 rd, float mint, float tmax, float k=8.0f) {
80 import std.algorithm : min;
81 float res = 1.0f;
82 float t = mint;
83 for (int i = 0; i < 16; ++i) {
84 float h = mapWorld(ro+rd*t);
85 res = min(res, k*h/t);
86 t += clamp(h, 0.02f, 0.10f);
87 if (h < 0.001f || t > tmax) break;
89 return clamp(res, 0.0f, 1.0f);
93 // ////////////////////////////////////////////////////////////////////////// //
94 // raymarching
95 // L: light
96 public void raymarch() (/*float x, float y,*/ in auto ref Vec3 rd, in auto ref Vec3 L, ref Vec3 color) @nogc {
97 import std.math : exp, pow;
99 enum maxd = 100.0f; // max depth
101 //Vec3 col = Vec3(0.7f, 0.9f, 1.0f)+rd.y*0.8;
103 int obj;
104 Vec3 pos = prp;
105 float dx = void;
106 float t = castRay(obj, dx, pos, rd, 1.0f, maxd);
108 // did we hit something?
109 if (obj >= 0) {
110 // get primitive color
111 auto col = getObjColor(pos, obj);
113 Vec3 nor = calcNormal(pos);
114 Vec3 refl = rd.reflect(nor);
116 // lighitng
117 float occ = calcAO(pos, nor);
118 //Vec3 lig = Vec3(-0.6f, 0.7f, -0.5f).normalize;
119 Vec3 lig = L.normalized;
120 float amb = clamp(0.5f+0.5f*nor.y, 0.0f, 1.0f);
121 float dif = clamp(nor.dot(lig), 0.0f, 1.0f);
122 float bac = clamp(nor.dot(Vec3(-lig.x, 0.0f, -lig.z).normalize), 0.0f, 1.0f)*clamp(1.0f-pos.y, 0.0f, 1.0f);
123 float dom = smoothstep(-0.1f, 0.1f, refl.y);
124 float fre = pow(clamp(1.0f+nor.dot(rd), 0.0f, 1.0f), 2.0f);
125 float spe = pow(clamp(refl.dot(lig), 0.0f, 1.0f), 16.0f);
127 dif *= softshadow(pos, lig, 0.02f, maxd);
128 dom *= softshadow(pos, refl, 0.02f, maxd);
130 Vec3 lin = Vec3(0.0f, 0.0f, 0.0f);
131 lin += Vec3(1.00f, 0.85f, 0.55f)*(1.20f*dif);
132 lin += Vec3(1.00f, 0.85f, 0.55f)*(1.20f*spe)*dif;
133 lin += Vec3(0.50f, 0.70f, 1.00f)*(0.20f*amb)*occ;
134 lin += Vec3(0.50f, 0.70f, 1.00f)*(0.30f*dom)*occ;
135 lin += Vec3(0.25f, 0.25f, 0.25f)*(0.30f*bac)*occ;
136 lin += Vec3(1.00f, 1.00f, 1.00f)*(0.40f*fre)*occ;
137 col = col*lin;
138 col = mix(col, Vec3(0.8f, 0.9f, 1.0f), 1.0f-exp(-0.002f*t*t));
139 color = col;
140 } else {
141 // background color
142 color = Vec3(0.7f, 0.9f, 1.0f)+rd.y*0.8f;