1 /*
2 The MIT License (MIT)
3 
4 Copyright (c) 2015 - 2017 Light Transport Entertainment, Inc.
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12 
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15 
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 THE SOFTWARE.
23 */
24 
25 #include "render.h"
26 
27 #include <algorithm>
28 #include <chrono>  // C++11
29 #include <sstream>
30 #include <thread>  // C++11
31 #include <vector>
32 
33 #include <iostream>
34 
35 #include "../../nanort.h"
36 #include "matrix.h"
37 
38 #include "trackball.h"
39 
40 extern "C" {
41 
42 #include "qrcodegen.h"
43 
44 }  // extern "C"
45 
46 namespace example {
47 
48 // PCG32 code / (c) 2014 M.E. O'Neill / pcg-random.org
49 // Licensed under Apache License 2.0 (NO WARRANTY, etc. see website)
50 // http://www.pcg-random.org/
51 typedef struct {
52   unsigned long long state;
53   unsigned long long inc;  // not used?
54 } pcg32_state_t;
55 
56 #define PCG32_INITIALIZER \
57   { 0x853c49e6748fea9bULL, 0xda3e39cb94b95bdbULL }
58 
pcg32_random(pcg32_state_t * rng)59 float pcg32_random(pcg32_state_t* rng) {
60   unsigned long long oldstate = rng->state;
61   rng->state = oldstate * 6364136223846793005ULL + rng->inc;
62   unsigned int xorshifted = ((oldstate >> 18u) ^ oldstate) >> 27u;
63   unsigned int rot = oldstate >> 59u;
64   unsigned int ret = (xorshifted >> rot) | (xorshifted << ((-rot) & 31));
65 
66   return (float)((double)ret / (double)4294967296.0);
67 }
68 
pcg32_srandom(pcg32_state_t * rng,uint64_t initstate,uint64_t initseq)69 void pcg32_srandom(pcg32_state_t* rng, uint64_t initstate, uint64_t initseq) {
70   rng->state = 0U;
71   rng->inc = (initseq << 1U) | 1U;
72   pcg32_random(rng);
73   rng->state += initstate;
74   pcg32_random(rng);
75 }
76 
77 const float kPI = 3.141592f;
78 
79 typedef struct {
80   std::vector<float> vertices;
81   std::vector<float> widths;
82 } Cubes;
83 
84 typedef nanort::real3<float> float3;
85 
86 // Predefined SAH predicator for cube.
87 class CubePred {
88  public:
CubePred(const float * vertices)89   CubePred(const float* vertices) : axis_(0), pos_(0.0f), vertices_(vertices) {}
90 
Set(int axis,float pos) const91   void Set(int axis, float pos) const {
92     axis_ = axis;
93     pos_ = pos;
94   }
95 
operator ()(unsigned int i) const96   bool operator()(unsigned int i) const {
97     int axis = axis_;
98     float pos = pos_;
99 
100     float3 p0(&vertices_[3 * i]);
101 
102     float center = p0[axis];
103 
104     return (center < pos);
105   }
106 
107  private:
108   mutable int axis_;
109   mutable float pos_;
110   const float* vertices_;
111 };
112 
113 class CubeGeometry {
114  public:
CubeGeometry(const float * vertices,const float * widths)115   CubeGeometry(const float* vertices, const float* widths)
116       : vertices_(vertices), widths_(widths) {}
117 
118   /// Compute bounding box for `prim_index`th cube.
119   /// This function is called for each primitive in BVH build.
BoundingBox(float3 * bmin,float3 * bmax,unsigned int prim_index) const120   void BoundingBox(float3* bmin, float3* bmax, unsigned int prim_index) const {
121     (*bmin)[0] = vertices_[3 * prim_index + 0] - widths_[prim_index];
122     (*bmin)[1] = vertices_[3 * prim_index + 1] - widths_[prim_index];
123     (*bmin)[2] = vertices_[3 * prim_index + 2] - widths_[prim_index];
124     (*bmax)[0] = vertices_[3 * prim_index + 0] + widths_[prim_index];
125     (*bmax)[1] = vertices_[3 * prim_index + 1] + widths_[prim_index];
126     (*bmax)[2] = vertices_[3 * prim_index + 2] + widths_[prim_index];
127   }
128 
129   const float* vertices_;
130   const float* widths_;
131   mutable float3 ray_org_;
132   mutable float3 ray_dir_;
133   mutable nanort::BVHTraceOptions trace_options_;
134 };
135 
136 class CubeIntersection {
137  public:
CubeIntersection()138   CubeIntersection() {}
139 
140   float normal[3];
141 
142   // Required member variables.
143   float t;
144   unsigned int prim_id;
145 };
146 
147 template <class I>
148 class CubeIntersector {
149  public:
CubeIntersector(const float * vertices,const float * widths)150   CubeIntersector(const float* vertices, const float* widths)
151       : vertices_(vertices), widths_(widths) {}
152 
153   /// Do ray interesection stuff for `prim_index` th primitive and return hit
154   /// distance `t`,
155   /// Returns true if there's intersection.
Intersect(float * t_inout,unsigned int prim_index) const156   bool Intersect(float* t_inout, unsigned int prim_index) const {
157     if ((prim_index < trace_options_.prim_ids_range[0]) ||
158         (prim_index >= trace_options_.prim_ids_range[1])) {
159       return false;
160     }
161 
162     const float3 center(&vertices_[3 * prim_index]);
163     const float width = widths_[prim_index];
164 
165     const float3 bmin = center - float3(width);
166     const float3 bmax = center + float3(width);
167 
168     float tmin, tmax;
169 
170     const float min_x = ray_dir_sign_[0] ? bmax[0] : bmin[0];
171     const float min_y = ray_dir_sign_[1] ? bmax[1] : bmin[1];
172     const float min_z = ray_dir_sign_[2] ? bmax[2] : bmin[2];
173     const float max_x = ray_dir_sign_[0] ? bmin[0] : bmax[0];
174     const float max_y = ray_dir_sign_[1] ? bmin[1] : bmax[1];
175     const float max_z = ray_dir_sign_[2] ? bmin[2] : bmax[2];
176 
177     // X
178     const float tmin_x = (min_x - ray_org_[0]) * ray_inv_dir_[0];
179     const float tmax_x = (max_x - ray_org_[0]) * ray_inv_dir_[0];
180 
181     // Y
182     const float tmin_y = (min_y - ray_org_[1]) * ray_inv_dir_[1];
183     const float tmax_y = (max_y - ray_org_[1]) * ray_inv_dir_[1];
184 
185     // Z
186     const float tmin_z = (min_z - ray_org_[2]) * ray_inv_dir_[2];
187     const float tmax_z = (max_z - ray_org_[2]) * ray_inv_dir_[2];
188 
189     tmin = nanort::safemax(tmin_z, nanort::safemax(tmin_y, tmin_x));
190     tmax = nanort::safemin(tmax_z, nanort::safemin(tmax_y, tmax_x));
191 
192     if (tmin > tmax) {
193       return false;
194     }
195 
196     const float t = tmin;
197 
198     if (t > (*t_inout)) {
199       return false;
200     }
201 
202     (*t_inout) = t;
203 
204     return true;
205   }
206 
207   /// Returns the nearest hit distance.
GetT() const208   float GetT() const { return t_; }
209 
210   /// Update is called when a nearest hit is found.
Update(float t,unsigned int prim_idx) const211   void Update(float t, unsigned int prim_idx) const {
212     t_ = t;
213     prim_id_ = prim_idx;
214   }
215 
216   /// Prepare BVH traversal(e.g. compute inverse ray direction)
217   /// This function is called only once in BVH traversal.
PrepareTraversal(const nanort::Ray<float> & ray,const nanort::BVHTraceOptions & trace_options) const218   void PrepareTraversal(const nanort::Ray<float>& ray,
219                         const nanort::BVHTraceOptions& trace_options) const {
220     ray_org_[0] = ray.org[0];
221     ray_org_[1] = ray.org[1];
222     ray_org_[2] = ray.org[2];
223 
224     ray_dir_[0] = ray.dir[0];
225     ray_dir_[1] = ray.dir[1];
226     ray_dir_[2] = ray.dir[2];
227 
228     // FIXME(syoyo): Consider zero div case.
229     ray_inv_dir_[0] = 1.0f / ray.dir[0];
230     ray_inv_dir_[1] = 1.0f / ray.dir[1];
231     ray_inv_dir_[2] = 1.0f / ray.dir[2];
232 
233     ray_dir_sign_[0] = ray.dir[0] < 0.0f ? 1 : 0;
234     ray_dir_sign_[1] = ray.dir[1] < 0.0f ? 1 : 0;
235     ray_dir_sign_[2] = ray.dir[2] < 0.0f ? 1 : 0;
236 
237     trace_options_ = trace_options;
238   }
239 
240   /// Post BVH traversal stuff(e.g. compute intersection point information)
241   /// This function is called only once in BVH traversal.
242   /// `hit` = true if there is something hit.
PostTraversal(const nanort::Ray<float> & ray,bool hit,CubeIntersection * isect) const243   void PostTraversal(const nanort::Ray<float>& ray, bool hit,
244                      CubeIntersection* isect) const {
245     if (hit) {
246       // compute normal. there should be valid intersection point.
247       const float3 center(&vertices_[3 * prim_id_]);
248       const float width = widths_[prim_id_];
249 
250       const float3 bmin = center - float3(width);
251       const float3 bmax = center + float3(width);
252 
253       float tmin, tmax;
254 
255       const float min_x = ray_dir_sign_[0] ? bmax[0] : bmin[0];
256       const float min_y = ray_dir_sign_[1] ? bmax[1] : bmin[1];
257       const float min_z = ray_dir_sign_[2] ? bmax[2] : bmin[2];
258       const float max_x = ray_dir_sign_[0] ? bmin[0] : bmax[0];
259       const float max_y = ray_dir_sign_[1] ? bmin[1] : bmax[1];
260       const float max_z = ray_dir_sign_[2] ? bmin[2] : bmax[2];
261 
262       // X
263       const float tmin_x = (min_x - ray_org_[0]) * ray_inv_dir_[0];
264 
265       // Y
266       const float tmin_y = (min_y - ray_org_[1]) * ray_inv_dir_[1];
267 
268       // Z
269       const float tmin_z = (min_z - ray_org_[2]) * ray_inv_dir_[2];
270 
271       int axis = 0;
272       tmin = tmin_x;
273       if (tmin < tmin_y) {
274         axis = 1;
275         tmin = tmin_y;
276       }
277       if (tmin < tmin_z) {
278         axis = 2;
279         tmin = tmin_z;
280       }
281 
282       isect->t = t_;
283       isect->prim_id = prim_id_;
284 
285       isect->normal[0] = 0.0f;
286       isect->normal[1] = 0.0f;
287       isect->normal[2] = 0.0f;
288 
289       isect->normal[axis] = ray_dir_sign_[axis] ? 1.0f : -1.0f;
290     }
291   }
292 
293   const float* vertices_;
294   const float* widths_;
295   mutable float3 ray_org_;
296   mutable float3 ray_dir_;
297   mutable float3 ray_inv_dir_;
298   mutable int ray_dir_sign_[3];
299   mutable nanort::BVHTraceOptions trace_options_;
300 
301   mutable float t_;
302   mutable unsigned int prim_id_;
303 };
304 
305 // @fixme { Do not defined as global variable }
306 Cubes gCubes;
307 nanort::BVHAccel<float> gAccel;
308 
Lerp3(float3 v0,float3 v1,float3 v2,float u,float v)309 inline float3 Lerp3(float3 v0, float3 v1, float3 v2, float u, float v) {
310   return (1.0f - u - v) * v0 + u * v1 + v * v2;
311 }
312 
CalcNormal(float3 & N,float3 v0,float3 v1,float3 v2)313 inline void CalcNormal(float3& N, float3 v0, float3 v1, float3 v2) {
314   float3 v10 = v1 - v0;
315   float3 v20 = v2 - v0;
316 
317   N = vcross(v20, v10);
318   N = vnormalize(N);
319 }
320 
BuildCameraFrame(float3 * origin,float3 * corner,float3 * u,float3 * v,float quat[4],float eye[3],float lookat[3],float up[3],float fov,int width,int height)321 void BuildCameraFrame(float3* origin, float3* corner, float3* u, float3* v,
322                       float quat[4], float eye[3], float lookat[3], float up[3],
323                       float fov, int width, int height) {
324   float e[4][4];
325 
326   Matrix::LookAt(e, eye, lookat, up);
327 
328   float r[4][4];
329   build_rotmatrix(r, quat);
330 
331   float3 lo;
332   lo[0] = lookat[0] - eye[0];
333   lo[1] = lookat[1] - eye[1];
334   lo[2] = lookat[2] - eye[2];
335   float dist = vlength(lo);
336 
337   float dir[3];
338   dir[0] = 0.0;
339   dir[1] = 0.0;
340   dir[2] = dist;
341 
342   Matrix::Inverse(r);
343 
344   float rr[4][4];
345   float re[4][4];
346   float zero[3] = {0.0f, 0.0f, 0.0f};
347   float localUp[3] = {0.0f, 1.0f, 0.0f};
348   Matrix::LookAt(re, dir, zero, localUp);
349 
350   // translate
351   re[3][0] += eye[0];  // 0.0; //lo[0];
352   re[3][1] += eye[1];  // 0.0; //lo[1];
353   re[3][2] += (eye[2] - dist);
354 
355   // rot -> trans
356   Matrix::Mult(rr, r, re);
357 
358   float m[4][4];
359   for (int j = 0; j < 4; j++) {
360     for (int i = 0; i < 4; i++) {
361       m[j][i] = rr[j][i];
362     }
363   }
364 
365   float vzero[3] = {0.0f, 0.0f, 0.0f};
366   float eye1[3];
367   Matrix::MultV(eye1, m, vzero);
368 
369   float lookat1d[3];
370   dir[2] = -dir[2];
371   Matrix::MultV(lookat1d, m, dir);
372   float3 lookat1(lookat1d[0], lookat1d[1], lookat1d[2]);
373 
374   float up1d[3];
375   Matrix::MultV(up1d, m, up);
376 
377   float3 up1(up1d[0], up1d[1], up1d[2]);
378 
379   // absolute -> relative
380   up1[0] -= eye1[0];
381   up1[1] -= eye1[1];
382   up1[2] -= eye1[2];
383   // printf("up1(after) = %f, %f, %f\n", up1[0], up1[1], up1[2]);
384 
385   // Use original up vector
386   // up1[0] = up[0];
387   // up1[1] = up[1];
388   // up1[2] = up[2];
389 
390   {
391     float flen =
392         (0.5f * (float)height / tanf(0.5f * (float)(fov * kPI / 180.0f)));
393     float3 look1;
394     look1[0] = lookat1[0] - eye1[0];
395     look1[1] = lookat1[1] - eye1[1];
396     look1[2] = lookat1[2] - eye1[2];
397     // vcross(u, up1, look1);
398     // flip
399     (*u) = nanort::vcross(look1, up1);
400     (*u) = vnormalize((*u));
401 
402     (*v) = vcross(look1, (*u));
403     (*v) = vnormalize((*v));
404 
405     look1 = vnormalize(look1);
406     look1[0] = flen * look1[0] + eye1[0];
407     look1[1] = flen * look1[1] + eye1[1];
408     look1[2] = flen * look1[2] + eye1[2];
409     (*corner)[0] = look1[0] - 0.5f * (width * (*u)[0] + height * (*v)[0]);
410     (*corner)[1] = look1[1] - 0.5f * (width * (*u)[1] + height * (*v)[1]);
411     (*corner)[2] = look1[2] - 0.5f * (width * (*u)[2] + height * (*v)[2]);
412 
413     (*origin)[0] = eye1[0];
414     (*origin)[1] = eye1[1];
415     (*origin)[2] = eye1[2];
416   }
417 }
418 
GenerateRay(const float3 & origin,const float3 & corner,const float3 & du,const float3 & dv,float u,float v)419 nanort::Ray<float> GenerateRay(const float3& origin, const float3& corner,
420                                const float3& du, const float3& dv, float u,
421                                float v) {
422   float3 dir;
423 
424   dir[0] = (corner[0] + u * du[0] + v * dv[0]) - origin[0];
425   dir[1] = (corner[1] + u * du[1] + v * dv[1]) - origin[1];
426   dir[2] = (corner[2] + u * du[2] + v * dv[2]) - origin[2];
427   dir = vnormalize(dir);
428 
429   float3 org;
430 
431   nanort::Ray<float> ray;
432   ray.org[0] = origin[0];
433   ray.org[1] = origin[1];
434   ray.org[2] = origin[2];
435   ray.dir[0] = dir[0];
436 
437   return ray;
438 }
439 
GetFilePathExtension(const std::string & FileName)440 static std::string GetFilePathExtension(const std::string& FileName) {
441   if (FileName.find_last_of(".") != std::string::npos)
442     return FileName.substr(FileName.find_last_of(".") + 1);
443   return "";
444 }
445 
GenQRData(Cubes * cubes,const std::string & text,float scale)446 bool GenQRData(Cubes* cubes, const std::string& text, float scale) {
447   double bmin[3], bmax[3];
448   bmin[0] = bmin[1] = bmin[2] = std::numeric_limits<double>::max();
449   bmax[0] = bmax[1] = bmax[2] = -std::numeric_limits<double>::max();
450 
451   cubes->vertices.clear();
452   cubes->widths.clear();
453 
454   enum qrcodegen_Ecc errCorLvl = qrcodegen_Ecc_LOW;  // Error correction level
455 
456   // Make QR Code symbol
457   uint8_t qrcode[qrcodegen_BUFFER_LEN_MAX];
458   uint8_t tempBuffer[qrcodegen_BUFFER_LEN_MAX];
459   bool ok = qrcodegen_encodeText(text.c_str(), tempBuffer, qrcode, errCorLvl,
460                                  qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX,
461                                  qrcodegen_Mask_AUTO, true);
462 
463   if (!ok) {
464     std::cerr << "Failed to make QR Code symbol" << std::endl;
465     return false;
466   }
467 
468   {
469     int size = qrcodegen_getSize(qrcode);
470     int border = 4;
471     for (int y = -border; y < size + border; y++) {
472       for (int x = -border; x < size + border; x++) {
473         if (qrcodegen_getModule(qrcode, x, y)) {
474           cubes->vertices.push_back(x);
475           cubes->vertices.push_back(y);
476           cubes->vertices.push_back(0.0f); // Z
477 
478           cubes->widths.push_back(0.5f);
479         }
480       }
481     }
482   }
483 
484   return true;
485 }
486 
GenQR(const std::string & text,float scene_scale)487 bool Renderer::GenQR(const std::string& text, float scene_scale) {
488   return GenQRData(&gCubes, text, scene_scale);
489 }
490 
BuildBVH()491 bool Renderer::BuildBVH() {
492   if (gCubes.widths.size() < 1) {
493     std::cout << "num_points == 0" << std::endl;
494     return false;
495   }
496 
497   std::cout << "[Build BVH] " << std::endl;
498 
499   nanort::BVHBuildOptions<float> build_options;  // Use default option
500   build_options.cache_bbox = false;
501 
502   printf("  BVH build option:\n");
503   printf("    # of leaf primitives: %d\n", build_options.min_leaf_primitives);
504   printf("    SAH binsize         : %d\n", build_options.bin_size);
505 
506   auto t_start = std::chrono::system_clock::now();
507 
508   CubeGeometry cube_geom(&gCubes.vertices.at(0), &gCubes.widths.at(0));
509   CubePred cube_pred(&gCubes.vertices.at(0));
510   bool ret =
511       gAccel.Build(gCubes.widths.size(), cube_geom, cube_pred, build_options);
512   assert(ret);
513 
514   auto t_end = std::chrono::system_clock::now();
515 
516   std::chrono::duration<double, std::milli> ms = t_end - t_start;
517   std::cout << "BVH build time: " << ms.count() << " [ms]\n";
518 
519   nanort::BVHBuildStatistics stats = gAccel.GetStatistics();
520 
521   printf("  BVH statistics:\n");
522   printf("    # of leaf   nodes: %d\n", stats.num_leaf_nodes);
523   printf("    # of branch nodes: %d\n", stats.num_branch_nodes);
524   printf("  Max tree depth     : %d\n", stats.max_tree_depth);
525   float bmin[3], bmax[3];
526   gAccel.BoundingBox(bmin, bmax);
527   printf("  Bmin               : %f, %f, %f\n", bmin[0], bmin[1], bmin[2]);
528   printf("  Bmax               : %f, %f, %f\n", bmax[0], bmax[1], bmax[2]);
529 
530   return true;
531 }
532 
Render(RenderLayer * layer,float quat[4],const RenderConfig & config,std::atomic<bool> & cancelFlag)533 bool Renderer::Render(RenderLayer* layer, float quat[4],
534                       const RenderConfig& config,
535                       std::atomic<bool>& cancelFlag) {
536   if (!gAccel.IsValid()) {
537     return false;
538   }
539 
540   int width = config.width;
541   int height = config.height;
542 
543   // camera
544   float eye[3] = {config.eye[0], config.eye[1], config.eye[2]};
545   float look_at[3] = {config.look_at[0], config.look_at[1], config.look_at[2]};
546   float up[3] = {config.up[0], config.up[1], config.up[2]};
547   float fov = config.fov;
548   float3 origin, corner, u, v;
549   BuildCameraFrame(&origin, &corner, &u, &v, quat, eye, look_at, up, fov, width,
550                    height);
551 
552   auto kCancelFlagCheckMilliSeconds = 300;
553 
554   std::vector<std::thread> workers;
555   std::atomic<int> i(0);
556 
557   uint32_t num_threads = std::max(1U, std::thread::hardware_concurrency());
558 
559   auto startT = std::chrono::system_clock::now();
560 
561   // Multi-threaded rendering using C++11 thread.
562   for (auto t = 0; t < num_threads; t++) {
563     workers.emplace_back(std::thread([&, t]() {
564       // Initialize RNG.
565       pcg32_state_t rng;
566       pcg32_srandom(&rng, config.pass,
567                     t);  // seed = combination of render pass + thread no.
568 
569       int y = 0;
570       while ((y = i++) < config.height) {
571         auto currT = std::chrono::system_clock::now();
572 
573         std::chrono::duration<double, std::milli> ms = currT - startT;
574         // Check cancel flag
575         if (ms.count() > kCancelFlagCheckMilliSeconds) {
576           if (cancelFlag) {
577             break;
578           }
579         }
580 
581         for (int x = 0; x < config.width; x++) {
582           nanort::Ray<float> ray;
583           ray.org[0] = origin[0];
584           ray.org[1] = origin[1];
585           ray.org[2] = origin[2];
586 
587           float u0 = pcg32_random(&rng);
588           float u1 = pcg32_random(&rng);
589 
590           float3 dir;
591           dir = corner + (float(x) + u0) * u +
592                 (float(config.height - y - 1) + u1) * v;
593           dir = vnormalize(dir);
594           ray.dir[0] = dir[0];
595           ray.dir[1] = dir[1];
596           ray.dir[2] = dir[2];
597 
598           float kFar = 1.0e+30f;
599           ray.min_t = 0.0f;
600           ray.max_t = kFar;
601 
602           CubeIntersector<CubeIntersection> cube_intersector(
603               reinterpret_cast<const float*>(gCubes.vertices.data()),
604               gCubes.widths.data());
605           CubeIntersection isect;
606           bool hit = gAccel.Traverse(ray, cube_intersector, &isect);
607           if (hit) {
608             float3 p;
609             p[0] = ray.org[0] + isect.t * ray.dir[0];
610             p[1] = ray.org[1] + isect.t * ray.dir[1];
611             p[2] = ray.org[2] + isect.t * ray.dir[2];
612 
613             layer->position[4 * (y * config.width + x) + 0] = p.x();
614             layer->position[4 * (y * config.width + x) + 1] = p.y();
615             layer->position[4 * (y * config.width + x) + 2] = p.z();
616             layer->position[4 * (y * config.width + x) + 3] = 1.0f;
617 
618             layer->varycoord[4 * (y * config.width + x) + 0] = 0.0f;
619             layer->varycoord[4 * (y * config.width + x) + 1] = 0.0f;
620             layer->varycoord[4 * (y * config.width + x) + 2] = 0.0f;
621             layer->varycoord[4 * (y * config.width + x) + 3] = 1.0f;
622 
623             unsigned int prim_id = isect.prim_id;
624 
625             float3 N;
626             N[0] = isect.normal[0];
627             N[1] = isect.normal[1];
628             N[2] = isect.normal[2];
629 
630             layer->normal[4 * (y * config.width + x) + 0] = 0.5 * N[0] + 0.5;
631             layer->normal[4 * (y * config.width + x) + 1] = 0.5 * N[1] + 0.5;
632             layer->normal[4 * (y * config.width + x) + 2] = 0.5 * N[2] + 0.5;
633             layer->normal[4 * (y * config.width + x) + 3] = 1.0f;
634 
635             layer->depth[4 * (y * config.width + x) + 0] = isect.t;
636             layer->depth[4 * (y * config.width + x) + 1] = isect.t;
637             layer->depth[4 * (y * config.width + x) + 2] = isect.t;
638             layer->depth[4 * (y * config.width + x) + 3] = 1.0f;
639 
640             float diffuse_col[3] = {0.5f, 0.5f, 0.5f};
641 
642             // TODO(LTE): Support specular color
643             float specular_col[3] = {0.0f, 0.0f, 0.0f};
644 
645             // Simple shading
646             float NdotV = fabsf(vdot(N, dir));
647 
648             if (config.pass == 0) {
649               layer->rgba[4 * (y * config.width + x) + 0] =
650                   NdotV * diffuse_col[0];
651               layer->rgba[4 * (y * config.width + x) + 1] =
652                   NdotV * diffuse_col[1];
653               layer->rgba[4 * (y * config.width + x) + 2] =
654                   NdotV * diffuse_col[2];
655               layer->rgba[4 * (y * config.width + x) + 3] = 1.0f;
656               layer->sample_counts[y * config.width + x] =
657                   1;  // Set 1 for the first pass
658             } else {  // additive.
659               layer->rgba[4 * (y * config.width + x) + 0] +=
660                   NdotV * diffuse_col[0];
661               layer->rgba[4 * (y * config.width + x) + 1] +=
662                   NdotV * diffuse_col[1];
663               layer->rgba[4 * (y * config.width + x) + 2] +=
664                   NdotV * diffuse_col[2];
665               layer->rgba[4 * (y * config.width + x) + 3] += 1.0f;
666               layer->sample_counts[y * config.width + x]++;
667             }
668 
669           } else {
670             {
671               if (config.pass == 0) {
672                 // clear pixel
673                 layer->rgba[4 * (y * config.width + x) + 0] = 0.0f;
674                 layer->rgba[4 * (y * config.width + x) + 1] = 0.0f;
675                 layer->rgba[4 * (y * config.width + x) + 2] = 0.0f;
676                 layer->rgba[4 * (y * config.width + x) + 3] = 0.0f;
677                 layer->sample_counts[y * config.width + x] =
678                     1;  // Set 1 for the first pass
679               } else {
680                 layer->sample_counts[y * config.width + x]++;
681               }
682 
683               // No super sampling
684               layer->normal[4 * (y * config.width + x) + 0] = 0.0f;
685               layer->normal[4 * (y * config.width + x) + 1] = 0.0f;
686               layer->normal[4 * (y * config.width + x) + 2] = 0.0f;
687               layer->normal[4 * (y * config.width + x) + 3] = 0.0f;
688               layer->position[4 * (y * config.width + x) + 0] = 0.0f;
689               layer->position[4 * (y * config.width + x) + 1] = 0.0f;
690               layer->position[4 * (y * config.width + x) + 2] = 0.0f;
691               layer->position[4 * (y * config.width + x) + 3] = 0.0f;
692               layer->depth[4 * (y * config.width + x) + 0] = 0.0f;
693               layer->depth[4 * (y * config.width + x) + 1] = 0.0f;
694               layer->depth[4 * (y * config.width + x) + 2] = 0.0f;
695               layer->depth[4 * (y * config.width + x) + 3] = 0.0f;
696               layer->texcoord[4 * (y * config.width + x) + 0] = 0.0f;
697               layer->texcoord[4 * (y * config.width + x) + 1] = 0.0f;
698               layer->texcoord[4 * (y * config.width + x) + 2] = 0.0f;
699               layer->texcoord[4 * (y * config.width + x) + 3] = 0.0f;
700               layer->varycoord[4 * (y * config.width + x) + 0] = 0.0f;
701               layer->varycoord[4 * (y * config.width + x) + 1] = 0.0f;
702               layer->varycoord[4 * (y * config.width + x) + 2] = 0.0f;
703               layer->varycoord[4 * (y * config.width + x) + 3] = 0.0f;
704             }
705           }
706         }
707       }
708     }));
709   }
710 
711   for (auto& t : workers) {
712     t.join();
713   }
714 
715   return (!cancelFlag);
716 };
717 
718 }  // namespace example
719