1 // Copyright 2009-2021 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3
4 #include "intersection_filter_device.h"
5
6 namespace embree {
7
8 RTCScene g_scene = nullptr;
9 TutorialData data;
10
11 // FIXME: fast path for occlusionFilter
12
13 /******************************************************************************************/
14 /* Standard Mode */
15 /******************************************************************************************/
16
17 #define HIT_LIST_LENGTH 16
18
19 /* extended ray structure that includes total transparency along the ray */
20 struct Ray2
21 {
22 Ray ray;
23
24 // ray extensions
25 float transparency; //!< accumulated transparency value
26
27 // we remember up to 16 hits to ignore duplicate hits
28 unsigned int firstHit, lastHit;
29 unsigned int hit_geomIDs[HIT_LIST_LENGTH];
30 unsigned int hit_primIDs[HIT_LIST_LENGTH];
31 };
32
RTCRayHit_(Ray2 & ray)33 inline RTCRayHit* RTCRayHit_(Ray2& ray)
34 {
35 RTCRayHit* ray_ptr = (RTCRayHit*)&ray;
36 return ray_ptr;
37 }
38
RTCRay_(Ray2 & ray)39 inline RTCRay* RTCRay_(Ray2& ray)
40 {
41 RTCRay* ray_ptr = (RTCRay*)&ray;
42 return ray_ptr;
43 }
44
45 /* 3D procedural transparency */
transparencyFunction(Vec3fa & h)46 inline float transparencyFunction(Vec3fa& h)
47 {
48 float v = abs(sin(4.0f*h.x)*cos(4.0f*h.y)*sin(4.0f*h.z));
49 float T = clamp((v-0.1f)*3.0f,0.0f,1.0f);
50 return T;
51 //return 0.5f;
52 }
53
54
55 /* task that renders a single screen tile */
renderPixelStandard(const TutorialData & data,int x,int y,int * pixels,const unsigned int width,const unsigned int height,const float time,const ISPCCamera & camera,RayStats & stats)56 void renderPixelStandard(const TutorialData& data,
57 int x, int y,
58 int* pixels,
59 const unsigned int width,
60 const unsigned int height,
61 const float time,
62 const ISPCCamera& camera, RayStats& stats)
63 {
64 float weight = 1.0f;
65 Vec3fa color = Vec3fa(0.0f);
66
67 IntersectContext context;
68 InitIntersectionContext(&context);
69
70 /* initialize ray */
71 Ray2 primary;
72 init_Ray(primary.ray,Vec3fa(camera.xfm.p), Vec3fa(normalize(x*camera.xfm.l.vx + y*camera.xfm.l.vy + camera.xfm.l.vz)), 0.0f, inf);
73 primary.ray.id = 0; // needs to encode rayID for filter
74 primary.transparency = 0.0f;
75
76
77 while (true)
78 {
79 context.userRayExt = &primary;
80
81 /* intersect ray with scene */
82 rtcIntersect1(data.g_scene,&context.context,RTCRayHit_(primary));
83 RayStats_addRay(stats);
84
85 /* shade pixels */
86 if (primary.ray.geomID == RTC_INVALID_GEOMETRY_ID)
87 break;
88
89 float opacity = 1.0f-primary.transparency;
90 Vec3fa diffuse = data.colors[primary.ray.primID];
91 Vec3fa La = diffuse*0.5f;
92 color = color + weight*opacity*La;
93 Vec3fa lightDir = normalize(Vec3fa(-1,-1,-1));
94
95 /* initialize shadow ray */
96 Ray2 shadow;
97 init_Ray(shadow.ray, primary.ray.org + primary.ray.tfar*primary.ray.dir, neg(lightDir), 0.001f, inf);
98 shadow.ray.id = 0; // needs to encode rayID for filter
99 shadow.transparency = 1.0f;
100 shadow.firstHit = 0;
101 shadow.lastHit = 0;
102 context.userRayExt = &shadow;
103
104 /* trace shadow ray */
105 rtcOccluded1(data.g_scene,&context.context,RTCRay_(shadow));
106 RayStats_addShadowRay(stats);
107
108 /* add light contribution */
109 if (shadow.ray.tfar >= 0.0f) {
110 Vec3fa Ll = diffuse*shadow.transparency*clamp(-dot(lightDir,normalize(primary.ray.Ng)),0.0f,1.0f);
111 color = color + weight*opacity*Ll;
112 }
113
114 /* shoot transmission ray */
115 weight *= primary.transparency;
116 primary.ray.tnear() = 1.001f*primary.ray.tfar;
117 primary.ray.tfar = (float)(inf);
118 primary.ray.geomID = RTC_INVALID_GEOMETRY_ID;
119 primary.ray.primID = RTC_INVALID_GEOMETRY_ID;
120 primary.transparency = 0.0f;
121 }
122
123 /* write color to framebuffer */
124 unsigned int r = (unsigned int) (255.0f * clamp(color.x,0.0f,1.0f));
125 unsigned int g = (unsigned int) (255.0f * clamp(color.y,0.0f,1.0f));
126 unsigned int b = (unsigned int) (255.0f * clamp(color.z,0.0f,1.0f));
127 pixels[y*width+x] = (b << 16) + (g << 8) + r;
128 }
129
130 /* renders a single screen tile */
renderTileStandard(int taskIndex,int threadIndex,int * pixels,const unsigned int width,const unsigned int height,const float time,const ISPCCamera & camera,const int numTilesX,const int numTilesY)131 void renderTileStandard(int taskIndex,
132 int threadIndex,
133 int* pixels,
134 const unsigned int width,
135 const unsigned int height,
136 const float time,
137 const ISPCCamera& camera,
138 const int numTilesX,
139 const int numTilesY)
140 {
141 const unsigned int tileY = taskIndex / numTilesX;
142 const unsigned int tileX = taskIndex - tileY * numTilesX;
143 const unsigned int x0 = tileX * TILE_SIZE_X;
144 const unsigned int x1 = min(x0+TILE_SIZE_X,width);
145 const unsigned int y0 = tileY * TILE_SIZE_Y;
146 const unsigned int y1 = min(y0+TILE_SIZE_Y,height);
147
148 for (unsigned int y=y0; y<y1; y++) for (unsigned int x=x0; x<x1; x++)
149 {
150 renderPixelStandard(data,x,y,pixels,width,height,time,camera,g_stats[threadIndex]);
151 }
152 }
153
154 /******************************************************************************************/
155 /* Stream Mode */
156 /******************************************************************************************/
157
gather(float & ptr,const unsigned int stride,const unsigned int pid,const unsigned int rid)158 inline float gather(float& ptr, const unsigned int stride, const unsigned int pid, const unsigned int rid)
159 {
160 float* uptr = (float*) (((char*)&ptr) + pid*stride);
161 return uptr[rid];
162 }
163
gather(unsigned int & ptr,const unsigned int stride,const unsigned int pid,const unsigned int rid)164 inline unsigned int gather(unsigned int& ptr, const unsigned int stride, const unsigned int pid, const unsigned int rid)
165 {
166 unsigned int* uptr = (unsigned int*) (((char*)&ptr) + pid*stride);
167 return uptr[rid];
168 }
169
gather(unsigned int & ptr,const unsigned int idx,const unsigned int stride,const unsigned int pid,const unsigned int rid)170 inline unsigned int gather(unsigned int& ptr, const unsigned int idx, const unsigned int stride, const unsigned int pid, const unsigned int rid)
171 {
172 unsigned int* uptr = (unsigned int*) (((char*)&ptr) + pid*stride);
173 return uptr[rid + 1*idx];
174 }
175
scatter(float & ptr,const unsigned int stride,const unsigned int pid,const unsigned int rid,float v)176 inline void scatter(float& ptr, const unsigned int stride, const unsigned int pid, const unsigned int rid, float v) {
177 ((float*)(((char*)&ptr) + pid*stride))[rid] = v;
178 }
179
scatter(unsigned int & ptr,const unsigned int stride,const unsigned int pid,const unsigned int rid,unsigned int v)180 inline void scatter(unsigned int& ptr, const unsigned int stride, const unsigned int pid, const unsigned int rid, unsigned int v) {
181 ((unsigned int*)(((char*)&ptr) + pid*stride))[rid] = v;
182 }
183
scatter(unsigned int & ptr,const unsigned int idx,const unsigned int stride,const unsigned int pid,const unsigned int rid,unsigned int v)184 inline void scatter(unsigned int& ptr, const unsigned int idx, const unsigned int stride, const unsigned int pid, const unsigned int rid, unsigned int v) {
185 ((unsigned int*)(((char*)&ptr) + pid*stride))[rid+1*idx] = v;
186 }
187
188
189 /* intersection filter function for single rays and packets */
intersectionFilter(const RTCFilterFunctionNArguments * args)190 void intersectionFilter(const RTCFilterFunctionNArguments* args)
191 {
192 /* avoid crashing when debug visualizations are used */
193 if (args->context == nullptr) return;
194
195 assert(args->N == 1);
196 int* valid = args->valid;
197 const IntersectContext* context = (const IntersectContext*) args->context;
198 Ray* ray = (Ray*)args->ray;
199 //RTCHit* hit = (RTCHit*)args->hit;
200
201 /* ignore inactive rays */
202 if (valid[0] != -1) return;
203
204 /* calculate transparency */
205 Vec3fa h = ray->org + ray->dir * ray->tfar;
206 float T = transparencyFunction(h);
207
208 /* ignore hit if completely transparent */
209 if (T >= 1.0f)
210 valid[0] = 0;
211 /* otherwise accept hit and remember transparency */
212 else
213 {
214 Ray2* eray = (Ray2*) context->userRayExt;
215 eray->transparency = T;
216 }
217 }
218
219 /* intersection filter function for streams of general packets */
intersectionFilterN(const RTCFilterFunctionNArguments * args)220 void intersectionFilterN(const RTCFilterFunctionNArguments* args)
221 {
222 int* valid = args->valid;
223 const IntersectContext* context = (const IntersectContext*) args->context;
224 struct RTCRayHitN* rayN = (struct RTCRayHitN*)args->ray;
225 //struct RTCHitN* hitN = args->hit;
226 const unsigned int N = args->N;
227
228 /* avoid crashing when debug visualizations are used */
229 if (context == nullptr) return;
230
231 /* iterate over all rays in ray packet */
232 for (unsigned int ui=0; ui<N; ui+=1)
233 {
234 /* calculate loop and execution mask */
235 unsigned int vi = ui+0;
236 if (vi>=N) continue;
237
238 /* ignore inactive rays */
239 if (valid[vi] != -1) continue;
240
241 /* read ray/hit from ray structure */
242 RTCRayHit rtc_ray = rtcGetRayHitFromRayHitN(rayN,N,ui);
243 Ray* ray = (Ray*)&rtc_ray;
244
245 /* calculate transparency */
246 Vec3fa h = ray->org + ray->dir * ray->tfar;
247 float T = transparencyFunction(h);
248
249 /* ignore hit if completely transparent */
250 if (T >= 1.0f)
251 valid[vi] = 0;
252 /* otherwise accept hit and remember transparency */
253 else
254 {
255 /* decode ray IDs */
256 const unsigned int pid = ray->id / 1;
257 const unsigned int rid = ray->id % 1;
258 Ray2* ray2 = (Ray2*) context->userRayExt;
259 assert(ray2);
260 scatter(ray2->transparency,sizeof(Ray2),pid,rid,T);
261 }
262 }
263 }
264
265 /* occlusion filter function for single rays and packets */
occlusionFilter(const RTCFilterFunctionNArguments * args)266 void occlusionFilter(const RTCFilterFunctionNArguments* args)
267 {
268 /* avoid crashing when debug visualizations are used */
269 if (args->context == nullptr) return;
270
271 assert(args->N == 1);
272 int* valid = args->valid;
273 const IntersectContext* context = (const IntersectContext*) args->context;
274 Ray* ray = (Ray*)args->ray;
275 RTCHit* hit = (RTCHit*)args->hit;
276
277 /* ignore inactive rays */
278 if (valid[0] != -1) return;
279
280 Ray2* ray2 = (Ray2*) context->userRayExt;
281 assert(ray2);
282
283 for (unsigned int i=ray2->firstHit; i<ray2->lastHit; i++) {
284 unsigned slot= i%HIT_LIST_LENGTH;
285 if (ray2->hit_geomIDs[slot] == hit->geomID && ray2->hit_primIDs[slot] == hit->primID) {
286 valid[0] = 0; return; // ignore duplicate intersections
287 }
288 }
289 /* store hit in hit list */
290 unsigned int slot = ray2->lastHit%HIT_LIST_LENGTH;
291 ray2->hit_geomIDs[slot] = hit->geomID;
292 ray2->hit_primIDs[slot] = hit->primID;
293 ray2->lastHit++;
294 if (ray2->lastHit - ray2->firstHit >= HIT_LIST_LENGTH)
295 ray2->firstHit++;
296
297 Vec3fa h = ray->org + ray->dir * ray->tfar;
298
299 /* calculate and accumulate transparency */
300 float T = transparencyFunction(h);
301 T *= ray2->transparency;
302 ray2->transparency = T;
303 if (T != 0.0f)
304 valid[0] = 0;
305 }
306
307 /* intersection filter function for streams of general packets */
occlusionFilterN(const RTCFilterFunctionNArguments * args)308 void occlusionFilterN(const RTCFilterFunctionNArguments* args)
309 {
310 int* valid = args->valid;
311 const IntersectContext* context = (const IntersectContext*) args->context;
312 struct RTCRayHitN* rayN = (struct RTCRayHitN*)args->ray;
313 struct RTCHitN* hitN = args->hit;
314 const unsigned int N = args->N;
315
316 /* avoid crashing when debug visualizations are used */
317 if (context == nullptr) return;
318
319 /* iterate over all rays in ray packet */
320 for (unsigned int ui=0; ui<N; ui+=1)
321 {
322 /* calculate loop and execution mask */
323 unsigned int vi = ui+0;
324 if (vi>=N) continue;
325
326 /* ignore inactive rays */
327 if (valid[vi] != -1) continue;
328
329 /* read ray/hit from ray structure */
330 RTCRayHit rtc_ray = rtcGetRayHitFromRayHitN(rayN,N,ui);
331 Ray* ray = (Ray*)&rtc_ray;
332
333 RTCHit hit = rtcGetHitFromHitN(hitN,N,ui);
334 const unsigned int hit_geomID = hit.geomID;
335 const unsigned int hit_primID = hit.primID;
336
337 /* decode ray IDs */
338 const unsigned int pid = ray->id / 1;
339 const unsigned int rid = ray->id % 1;
340 Ray2* ray2 = (Ray2*) context->userRayExt;
341 assert(ray2);
342
343 /* The occlusion filter function may be called multiple times with
344 * the same hit. We remember the last N hits, and skip duplicates. */
345 unsigned int ray2_firstHit = gather(ray2->firstHit,sizeof(Ray2),pid,rid);
346 unsigned int ray2_lastHit = gather(ray2->lastHit ,sizeof(Ray2),pid,rid);
347 for (unsigned int i=ray2_firstHit; i<ray2_lastHit; i++)
348 {
349 unsigned int slot= i%HIT_LIST_LENGTH;
350 unsigned int last_geomID = gather(ray2->hit_geomIDs[0],slot,sizeof(Ray2),pid,rid);
351 unsigned int last_primID = gather(ray2->hit_primIDs[0],slot,sizeof(Ray2),pid,rid);
352 if (last_geomID == hit_geomID && last_primID == hit_primID) {
353 valid[vi] = 0; break; // ignore duplicate intersections
354 }
355 }
356 if (!valid[vi]) continue;
357
358 /* store hit in hit list */
359 unsigned int slot = ray2_lastHit%HIT_LIST_LENGTH;
360 scatter(ray2->hit_geomIDs[0],slot,sizeof(Ray2),pid,rid,hit_geomID);
361 scatter(ray2->hit_primIDs[0],slot,sizeof(Ray2),pid,rid,hit_primID);
362 ray2_lastHit++;
363 scatter(ray2->lastHit,sizeof(Ray2),pid,rid,ray2_lastHit);
364 if (ray2_lastHit - ray2_firstHit >= HIT_LIST_LENGTH)
365 scatter(ray2->firstHit,sizeof(Ray2),pid,rid,ray2_firstHit+1);
366
367 /* calculate transparency */
368 Vec3fa h = ray->org + ray->dir * ray->tfar;
369 float T = transparencyFunction(h);
370
371 /* accumulate transparency and store inside ray extensions */
372 T *= gather(ray2->transparency,sizeof(Ray2),pid,rid);
373 scatter(ray2->transparency,sizeof(Ray2),pid,rid,T);
374
375 /* reject a hit if not fully opqaue */
376 if (T != 0.0f)
377 valid[vi] = 0;
378 }
379 }
380
381 /* renders a single screen tile */
renderTileStandardStream(int taskIndex,int threadIndex,int * pixels,const unsigned int width,const unsigned int height,const float time,const ISPCCamera & camera,const int numTilesX,const int numTilesY)382 void renderTileStandardStream(int taskIndex,
383 int threadIndex,
384 int* pixels,
385 const unsigned int width,
386 const unsigned int height,
387 const float time,
388 const ISPCCamera& camera,
389 const int numTilesX,
390 const int numTilesY)
391 {
392 const unsigned int tileY = taskIndex / numTilesX;
393 const unsigned int tileX = taskIndex - tileY * numTilesX;
394 const unsigned int x0 = tileX * TILE_SIZE_X;
395 const unsigned int x1 = min(x0+TILE_SIZE_X,width);
396 const unsigned int y0 = tileY * TILE_SIZE_Y;
397 const unsigned int y1 = min(y0+TILE_SIZE_Y,height);
398
399 RayStats& stats = g_stats[threadIndex];
400
401 Ray2 primary_stream[TILE_SIZE_X*TILE_SIZE_Y];
402 Ray2 shadow_stream[TILE_SIZE_X*TILE_SIZE_Y];
403 Vec3fa color_stream[TILE_SIZE_X*TILE_SIZE_Y];
404 float weight_stream[TILE_SIZE_X*TILE_SIZE_Y];
405 bool valid_stream[TILE_SIZE_X*TILE_SIZE_Y];
406
407 /* generate stream of primary rays */
408 int N = 0;
409 int numActive = 0;
410 for (unsigned int y=y0; y<y1; y++) for (unsigned int x=x0; x<x1; x++)
411 {
412 /* ISPC workaround for mask == 0 */
413
414
415 /* initialize variables */
416 numActive++;
417 color_stream[N] = Vec3fa(0.0f);
418 weight_stream[N] = 1.0f;
419 bool mask = 1; { valid_stream[N] = mask; }
420
421 /* initialize ray */
422 Ray2& primary = primary_stream[N];
423 mask = 1; { // invalidates inactive rays
424 primary.ray.tnear() = mask ? 0.0f : (float)(pos_inf);
425 primary.ray.tfar = mask ? (float)(inf) : (float)(neg_inf);
426 }
427 init_Ray(primary.ray, Vec3fa(camera.xfm.p), Vec3fa(normalize((float)x*camera.xfm.l.vx + (float)y*camera.xfm.l.vy + camera.xfm.l.vz)), primary.ray.tnear(), primary.ray.tfar);
428
429 primary.ray.id = N*1 + 0;
430 primary.transparency = 0.0f;
431
432 N++;
433 RayStats_addRay(stats);
434 }
435
436 Vec3fa lightDir = normalize(Vec3fa(-1,-1,-1));
437
438 while (numActive)
439 {
440 /* trace rays */
441 IntersectContext primary_context;
442 InitIntersectionContext(&primary_context);
443 primary_context.context.flags = g_iflags_coherent;
444 primary_context.userRayExt = &primary_stream;
445 rtcIntersect1M(data.g_scene,&primary_context.context,(RTCRayHit*)&primary_stream,N,sizeof(Ray2));
446
447 /* terminate rays and update color */
448 N = -1;
449 for (unsigned int y=y0; y<y1; y++) for (unsigned int x=x0; x<x1; x++)
450 {
451 N++;
452 /* ISPC workaround for mask == 0 */
453
454
455 /* invalidate shadow rays by default */
456 Ray2& shadow = shadow_stream[N];
457 {
458 shadow.ray.tnear() = (float)(pos_inf);
459 shadow.ray.tfar = (float)(neg_inf);
460 }
461
462 /* ignore invalid rays */
463 if (valid_stream[N] == false) continue;
464
465 /* terminate rays that hit nothing */
466 if (primary_stream[N].ray.geomID == RTC_INVALID_GEOMETRY_ID) {
467 valid_stream[N] = false;
468 continue;
469 }
470
471 /* update color */
472 Ray2& primary = primary_stream[N];
473 float opacity = 1.0f-primary.transparency;
474 Vec3fa diffuse = data.colors[primary.ray.primID];
475 Vec3fa La = diffuse*0.5f;
476 color_stream[N] = color_stream[N] + weight_stream[N]*opacity*La;
477
478 /* initialize shadow ray */
479 bool mask = 1; {
480 shadow.ray.tnear() = mask ? 0.001f : (float)(pos_inf);
481 shadow.ray.tfar = mask ? (float)(inf) : (float)(neg_inf);
482 }
483 init_Ray(shadow.ray, primary.ray.org + primary.ray.tfar*primary.ray.dir, neg(lightDir), shadow.ray.tnear(), shadow.ray.tfar);
484 shadow.ray.id = N*1 + 0;
485 shadow.transparency = 1.0f;
486 shadow.firstHit = 0;
487 shadow.lastHit = 0;
488 RayStats_addShadowRay(stats);
489 }
490 N++;
491
492 /* trace shadow rays */
493 IntersectContext shadow_context;
494 InitIntersectionContext(&shadow_context);
495 shadow_context.context.flags = g_iflags_coherent;
496 shadow_context.userRayExt = &shadow_stream;
497 rtcOccluded1M(data.g_scene,&shadow_context.context,(RTCRay*)&shadow_stream,N,sizeof(Ray2));
498
499 /* add light contribution and generate transmission ray */
500 N = -1;
501 numActive = 0;
502 for (unsigned int y=y0; y<y1; y++) for (unsigned int x=x0; x<x1; x++)
503 {
504 N++;
505 /* ISPC workaround for mask == 0 */
506
507
508 /* invalidate rays by default */
509 Ray2& primary = primary_stream[N];
510 float primary_tfar = primary.ray.tfar;
511 {
512 primary.ray.tnear() = (float)(pos_inf);
513 primary.ray.tfar = (float)(neg_inf);
514 }
515
516 /* ignore invalid rays */
517 if (valid_stream[N] == false) continue;
518 numActive++;
519
520 /* add light contrinution */
521 float opacity = 1.0f-primary.transparency;
522 Vec3fa diffuse = data.colors[primary.ray.primID];
523 Ray2& shadow = shadow_stream[N];
524 if (shadow.ray.tfar >= 0.0f) {
525 Vec3fa Ll = diffuse*shadow.transparency*clamp(-dot(lightDir,normalize(primary.ray.Ng)),0.0f,1.0f);
526 color_stream[N] = color_stream[N] + weight_stream[N]*opacity*Ll;
527 }
528
529 /* initialize transmission ray */
530 weight_stream[N] *= primary.transparency;
531 bool mask = 1; {
532 primary.ray.tnear() = mask ? 1.001f*primary_tfar : (float)(pos_inf);
533 primary.ray.tfar = mask ? (float)(inf) : (float)(neg_inf);
534 }
535 primary.ray.geomID = RTC_INVALID_GEOMETRY_ID;
536 primary.ray.primID = RTC_INVALID_GEOMETRY_ID;
537 primary.transparency = 0.0f;
538 RayStats_addRay(stats);
539 }
540 N++;
541 }
542
543 /* framebuffer writeback */
544 N = 0;
545 for (unsigned int y=y0; y<y1; y++) for (unsigned int x=x0; x<x1; x++)
546 {
547 /* ISPC workaround for mask == 0 */
548
549
550 /* write color to framebuffer */
551 unsigned int r = (unsigned int) (255.0f * clamp(color_stream[N].x,0.0f,1.0f));
552 unsigned int g = (unsigned int) (255.0f * clamp(color_stream[N].y,0.0f,1.0f));
553 unsigned int b = (unsigned int) (255.0f * clamp(color_stream[N].z,0.0f,1.0f));
554 pixels[y*width+x] = (b << 16) + (g << 8) + r;
555 N++;
556 }
557 }
558
559 /******************************************************************************************/
560 /* Scene Creation */
561 /******************************************************************************************/
562
563 #define NUM_VERTICES 8
564 #define NUM_QUAD_INDICES 24
565 #define NUM_TRI_INDICES 36
566 #define NUM_QUAD_FACES 6
567 #define NUM_TRI_FACES 12
568
569 __aligned(16) float cube_vertices[NUM_VERTICES][4] =
570 {
571 { -1, -1, -1, 0 },
572 { -1, -1, +1, 0 },
573 { -1, +1, -1, 0 },
574 { -1, +1, +1, 0 },
575 { +1, -1, -1, 0 },
576 { +1, -1, +1, 0 },
577 { +1, +1, -1, 0 },
578 { +1, +1, +1, 0 },
579 };
580
581 unsigned int cube_quad_indices[NUM_QUAD_INDICES] = {
582 0, 1, 3, 2,
583 5, 4, 6, 7,
584 0, 4, 5, 1,
585 6, 2, 3, 7,
586 0, 2, 6, 4,
587 3, 1, 5, 7
588 };
589
590 unsigned int cube_tri_indices[NUM_TRI_INDICES] = {
591 0, 1, 2, 2, 1, 3,
592 5, 4, 7, 7, 4, 6,
593 0, 4, 1, 1, 4, 5,
594 6, 2, 7, 7, 2, 3,
595 0, 2, 4, 4, 2, 6,
596 3, 1, 7, 7, 1, 5
597 };
598
599 unsigned int cube_quad_faces[NUM_QUAD_FACES] = {
600 4, 4, 4, 4, 4, 4
601 };
602
603 /* adds a cube to the scene */
addCube(RTCScene scene_i,const Vec3fa & offset,const Vec3fa & scale,float rotation)604 unsigned int addCube (RTCScene scene_i, const Vec3fa& offset, const Vec3fa& scale, float rotation)
605 {
606 /* create a triangulated cube with 12 triangles and 8 vertices */
607 RTCGeometry geom = rtcNewGeometry (g_device, RTC_GEOMETRY_TYPE_TRIANGLE);
608 //rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_VERTEX, cube_vertices, 0, sizeof(Vec3fa ), NUM_VERTICES);
609 Vec3fa* ptr = (Vec3fa*) rtcSetNewGeometryBuffer(geom, RTC_BUFFER_TYPE_VERTEX, 0, RTC_FORMAT_FLOAT3, sizeof(Vec3fa), NUM_VERTICES);
610 for (unsigned int i=0; i<NUM_VERTICES; i++) {
611 float x = cube_vertices[i][0];
612 float y = cube_vertices[i][1];
613 float z = cube_vertices[i][2];
614 Vec3fa vtx = Vec3fa(x,y,z);
615 ptr[i] = Vec3fa(offset+LinearSpace3fa::rotate(Vec3fa(0,1,0),rotation)*LinearSpace3fa::scale(scale)*vtx);
616 }
617 rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT3, cube_tri_indices, 0, 3*sizeof(unsigned int), NUM_TRI_FACES);
618
619 /* create per-triangle color array */
620 data.colors = (Vec3fa*) alignedMalloc(12*sizeof(Vec3fa),16);
621 data.colors[0] = Vec3fa(1,0,0); // left side
622 data.colors[1] = Vec3fa(1,0,0);
623 data.colors[2] = Vec3fa(0,1,0); // right side
624 data.colors[3] = Vec3fa(0,1,0);
625 data.colors[4] = Vec3fa(0.5f); // bottom side
626 data.colors[5] = Vec3fa(0.5f);
627 data.colors[6] = Vec3fa(1.0f); // top side
628 data.colors[7] = Vec3fa(1.0f);
629 data.colors[8] = Vec3fa(0,0,1); // front side
630 data.colors[9] = Vec3fa(0,0,1);
631 data.colors[10] = Vec3fa(1,1,0); // back side
632 data.colors[11] = Vec3fa(1,1,0);
633
634 /* set intersection filter for the cube */
635 if (g_mode == MODE_NORMAL && nativePacketSupported(g_device))
636 {
637 rtcSetGeometryIntersectFilterFunction(geom,intersectionFilter);
638 rtcSetGeometryOccludedFilterFunction(geom,occlusionFilter);
639 }
640 else
641 {
642 rtcSetGeometryIntersectFilterFunction(geom,intersectionFilterN);
643 rtcSetGeometryOccludedFilterFunction(geom,occlusionFilterN);
644 }
645
646 rtcCommitGeometry(geom);
647 unsigned int geomID = rtcAttachGeometry(scene_i,geom);
648 rtcReleaseGeometry(geom);
649 return geomID;
650 }
651
652 /* adds a cube to the scene */
addSubdivCube(RTCScene scene_i)653 unsigned int addSubdivCube (RTCScene scene_i)
654 {
655 RTCGeometry geom = rtcNewGeometry(g_device, RTC_GEOMETRY_TYPE_SUBDIVISION);
656 rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_VERTEX, 0, RTC_FORMAT_FLOAT3, cube_vertices, 0, sizeof(Vec3fa), NUM_VERTICES);
657 rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT, cube_quad_indices, 0, sizeof(unsigned int), NUM_QUAD_INDICES);
658 rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_FACE, 0, RTC_FORMAT_UINT, cube_quad_faces, 0, sizeof(unsigned int), NUM_QUAD_FACES);
659
660 float* level = (float*) rtcSetNewGeometryBuffer(geom, RTC_BUFFER_TYPE_LEVEL, 0, RTC_FORMAT_FLOAT, sizeof(float), NUM_QUAD_INDICES);
661 for (unsigned int i=0; i<NUM_QUAD_INDICES; i++) level[i] = 4;
662
663 /* create face color array */
664 data.colors = (Vec3fa*) alignedMalloc(6*sizeof(Vec3fa),16);
665 data.colors[0] = Vec3fa(1,0,0); // left side
666 data.colors[1] = Vec3fa(0,1,0); // right side
667 data.colors[2] = Vec3fa(0.5f); // bottom side
668 data.colors[3] = Vec3fa(1.0f); // top side
669 data.colors[4] = Vec3fa(0,0,1); // front side
670 data.colors[5] = Vec3fa(1,1,0); // back side
671
672 /* set intersection filter for the cube */
673 if (g_mode == MODE_NORMAL && nativePacketSupported(g_device))
674 {
675 rtcSetGeometryIntersectFilterFunction(geom,intersectionFilter);
676 rtcSetGeometryOccludedFilterFunction(geom,occlusionFilter);
677 }
678 else
679 {
680 rtcSetGeometryIntersectFilterFunction(geom,intersectionFilterN);
681 rtcSetGeometryOccludedFilterFunction(geom,occlusionFilterN);
682 }
683
684 rtcCommitGeometry(geom);
685 unsigned int geomID = rtcAttachGeometry(scene_i,geom);
686 rtcReleaseGeometry(geom);
687 return geomID;
688 }
689
690 /* adds a ground plane to the scene */
addGroundPlane(RTCScene scene_i)691 unsigned int addGroundPlane (RTCScene scene_i)
692 {
693 /* create a triangulated plane with 2 triangles and 4 vertices */
694 RTCGeometry geom = rtcNewGeometry (g_device, RTC_GEOMETRY_TYPE_TRIANGLE);
695
696 /* set vertices */
697 Vertex* vertices = (Vertex*) rtcSetNewGeometryBuffer(geom,RTC_BUFFER_TYPE_VERTEX,0,RTC_FORMAT_FLOAT3,sizeof(Vertex),4);
698 vertices[0].x = -10; vertices[0].y = -2; vertices[0].z = -10;
699 vertices[1].x = -10; vertices[1].y = -2; vertices[1].z = +10;
700 vertices[2].x = +10; vertices[2].y = -2; vertices[2].z = -10;
701 vertices[3].x = +10; vertices[3].y = -2; vertices[3].z = +10;
702
703 /* set triangles */
704 Triangle* triangles = (Triangle*) rtcSetNewGeometryBuffer(geom,RTC_BUFFER_TYPE_INDEX,0,RTC_FORMAT_UINT3,sizeof(Triangle),2);
705 triangles[0].v0 = 0; triangles[0].v1 = 1; triangles[0].v2 = 2;
706 triangles[1].v0 = 1; triangles[1].v1 = 3; triangles[1].v2 = 2;
707
708 rtcCommitGeometry(geom);
709 unsigned int geomID = rtcAttachGeometry(scene_i,geom);
710 rtcReleaseGeometry(geom);
711 return geomID;
712 }
713
714 /* called by the C++ code for initialization */
device_init(char * cfg)715 extern "C" void device_init (char* cfg)
716 {
717 /* create scene */
718 g_scene = data.g_scene = rtcNewScene(g_device);
719 rtcSetSceneBuildQuality(data.g_scene, RTC_BUILD_QUALITY_HIGH); // high quality mode to test if we filter out duplicated intersections
720
721 /* add cube */
722 addCube(data.g_scene,Vec3fa(0.0f,0.0f,0.0f),Vec3fa(10.0f,1.0f,1.0f),45.0f);
723 //addSubdivCube(data.g_scene);
724
725 /* add ground plane */
726 addGroundPlane(data.g_scene);
727
728 /* commit changes to scene */
729 rtcCommitScene (data.g_scene);
730 }
731
732 /* task that renders a single screen tile */
renderTileTask(int taskIndex,int threadIndex,int * pixels,const unsigned int width,const unsigned int height,const float time,const ISPCCamera & camera,const int numTilesX,const int numTilesY)733 void renderTileTask (int taskIndex, int threadIndex, int* pixels,
734 const unsigned int width,
735 const unsigned int height,
736 const float time,
737 const ISPCCamera& camera,
738 const int numTilesX,
739 const int numTilesY)
740 {
741 if (g_mode == MODE_NORMAL)
742 renderTileStandard(taskIndex,threadIndex,pixels,width,height,time,camera,numTilesX,numTilesY);
743 else
744 renderTileStandardStream(taskIndex,threadIndex,pixels,width,height,time,camera,numTilesX,numTilesY);
745 }
746
renderFrameStandard(int * pixels,const unsigned int width,const unsigned int height,const float time,const ISPCCamera & camera)747 extern "C" void renderFrameStandard (int* pixels,
748 const unsigned int width,
749 const unsigned int height,
750 const float time,
751 const ISPCCamera& camera)
752 {
753 const int numTilesX = (width +TILE_SIZE_X-1)/TILE_SIZE_X;
754 const int numTilesY = (height+TILE_SIZE_Y-1)/TILE_SIZE_Y;
755 parallel_for(size_t(0),size_t(numTilesX*numTilesY),[&](const range<size_t>& range) {
756 const int threadIndex = (int)TaskScheduler::threadIndex();
757 for (size_t i=range.begin(); i<range.end(); i++)
758 renderTileTask((int)i,threadIndex,pixels,width,height,time,camera,numTilesX,numTilesY);
759 });
760 }
761
762 /* called by the C++ code to render */
device_render(int * pixels,const unsigned int width,const unsigned int height,const float time,const ISPCCamera & camera)763 extern "C" void device_render (int* pixels,
764 const unsigned int width,
765 const unsigned int height,
766 const float time,
767 const ISPCCamera& camera)
768 {
769 }
770
771 /* called by the C++ code for cleanup */
device_cleanup()772 extern "C" void device_cleanup ()
773 {
774 TutorialData_Destructor(&data);
775 }
776
777 } // namespace embree
778