1 //////////////////////////////////////////////////////////////////////
2 //
3 // Pixie
4 //
5 // Copyright � 1999 - 2003, Okan Arikan
6 //
7 // Contact: okan@cs.utexas.edu
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 //
23 ///////////////////////////////////////////////////////////////////////
24 ///////////////////////////////////////////////////////////////////////
25 //
26 // File : executeMisc.cpp
27 // Classes : -
28 // Description : This file implements the main shader execution
29 //
30 ////////////////////////////////////////////////////////////////////////
31 #include <math.h>
32 #include <float.h>
33
34 #include "common/global.h"
35 #include "bundles.h"
36 #include "memory.h"
37 #include "attributes.h"
38 #include "renderer.h"
39 #include "stats.h"
40 #include "surface.h"
41 #include "ri_config.h"
42
43 ///////////////////////////////////////////////////////////////////////////////////////////////////
44 //
45 // Misc. derivative functions
46 //
47 ///////////////////////////////////////////////////////////////////////////////////////////////////
48
49
50 ///////////////////////////////////////////////////////////////////////
51 // Class : CShadingContext
52 // Method : duFloat
53 // Description : Compute the u derivative
54 // Return Value : -
55 // Comments :
duFloat(float * dest,const float * src)56 void CShadingContext::duFloat(float *dest,const float *src) {
57 switch(currentShadingState->shadingDim) {
58
59
60 // Du executing on Points or Curves (note that curves are defined along v)
61 case SHADING_0D:
62 {
63 for (int j=currentShadingState->numVertices;j>0;--j) {
64 *dest++ = 0;
65 }
66 }
67 break;
68
69
70 // Du executing on a 2D grid
71 case SHADING_2D_GRID:
72 {
73 const int uVertices = currentShadingState->numUvertices;
74 const int vVertices = currentShadingState->numVvertices;
75 const float *u = currentShadingState->varying[VARIABLE_U];
76
77 assert(uVertices >= 2);
78 assert(vVertices >= 2);
79 assert(u[1] > u[0]);
80
81 // These values are constant accross a grid
82 const double invDu1 = 1.0 / ((double)u[1] - (double)u[0]);
83 const double invDu2 = 1.0 / (2.0*((double)u[1] - (double)u[0]));
84
85 // Compute the Du
86 for (int j=vVertices;j>0;--j) {
87
88 // Forward differencing
89 *dest++ = (float) (((double)src[1] - (double)src[0]) * invDu1);
90 ++src;
91
92 // Central differencing
93 for (int i=uVertices-2;i>0;--i) {
94 *dest++ = (float) (((double)src[1] - (double)src[-1]) * invDu2);
95 ++src;
96 }
97
98 // Backward differencing
99 *dest++ = (float) (((double)src[0] - (double)src[-1]) * invDu1);
100 ++src;
101 }
102 }
103 break;
104
105
106 // Du executing on a 2D raytraced surface
107 case SHADING_2D:
108 {
109 const int numRealVertices = currentShadingState->numRealVertices;
110 const float *dsrc = src + numRealVertices;
111 float *ddest = dest + numRealVertices;
112 const float *du = currentShadingState->varying[VARIABLE_DU];
113
114 for (int i=numRealVertices;i>0;--i) {
115
116 assert(*du != 0);
117
118 const float val = (float) (((double)dsrc[0] - (double)src[0]) / ((double)*du++));
119
120 ddest[0] = val;
121 ddest[1] = val;
122 dest[0] = val;
123
124 dest++;
125 src++;
126 ddest += 2;
127 dsrc += 2;
128 }
129 }
130 break;
131 }
132 }
133
134
135 ///////////////////////////////////////////////////////////////////////
136 // Class : CShadingContext
137 // Method : DuFloat
138 // Description : Compute the u differences
139 // Return Value : -
140 // Comments :
DuFloat(float * dest,const float * src)141 void CShadingContext::DuFloat(float *dest,const float *src) {
142 switch(currentShadingState->shadingDim) {
143
144
145 // Du executing on Points or Curves (note that curves are defined along v)
146 case SHADING_0D:
147 {
148 for (int j=currentShadingState->numVertices;j>0;--j) {
149 *dest++ = 0;
150 }
151 }
152 break;
153
154
155 // Du executing on a 2D grid
156 case SHADING_2D_GRID:
157 {
158 const int uVertices = currentShadingState->numUvertices;
159 const int vVertices = currentShadingState->numVvertices;
160
161 assert(uVertices >= 2);
162 assert(vVertices >= 2);
163
164 // Compute the Du
165 for (int j=vVertices;j>0;--j) {
166
167 // Forward differencing
168 *dest++ = (float) ((double)src[1] - (double)src[0]);
169 src++;
170
171 // Central differencing
172 for (int i=uVertices-2;i>0;--i) {
173 *dest++ = (float) (((double)src[1] - (double)src[-1]) * 0.5);
174 src++;
175 }
176
177 // Backward differencing
178 *dest++ = (float) ((double)src[0] - (double)src[-1]);
179 src++;
180 }
181 }
182 break;
183
184
185 // Du executing on a 2D raytraced surface
186 case SHADING_2D:
187 {
188 const int numRealVertices = currentShadingState->numRealVertices;
189 const float *dsrc = src + numRealVertices;
190 float *ddest = dest + numRealVertices;
191
192 for (int i=numRealVertices;i>0;--i) {
193
194 const float val = (float) ((double)dsrc[0] - (double)src[0]);
195
196 ddest[0] = val;
197 ddest[1] = val;
198 dest[0] = val;
199
200 dest++;
201 src++;
202 ddest += 2;
203 dsrc += 2;
204 }
205 }
206 break;
207 }
208 }
209
210
211
212
213 ///////////////////////////////////////////////////////////////////////
214 // Class : CShadingContext
215 // Method : dvFloat
216 // Description : Compute the v derivatives
217 // Return Value : -
218 // Comments :
dvFloat(float * dest,const float * src)219 void CShadingContext::dvFloat(float *dest,const float *src) {
220
221 switch(currentShadingState->shadingDim) {
222
223 // Dv executing on Points
224 case SHADING_0D:
225 {
226 for (int i=currentShadingState->numVertices;i>0;--i) {
227 *dest++ = 0;
228 }
229 }
230 break;
231
232
233 // Dv executing on a 2D grid
234 case SHADING_2D_GRID:
235 {
236 const int uVertices = currentShadingState->numUvertices;
237 const int vVertices = currentShadingState->numVvertices;
238 const float *v = currentShadingState->varying[VARIABLE_V];
239
240 assert(uVertices >= 2);
241 assert(vVertices >= 2);
242 assert(v[uVertices] > v[0]);
243
244 const double invDv1 = 1.0 / ((double)v[uVertices] - (double)v[0]);
245 const double invDv2 = 1.0 / (2.0*((double)v[uVertices] - (double)v[0]));
246
247 // Compute the DV
248 for (int j=0;j<uVertices;++j) {
249 float *cRes = dest + j;
250 const float *cOp = src + j;
251
252 // Forward differencing
253 cRes[0] = (float) ((double)(cOp[uVertices] - (double)cOp[0]) * invDv1);
254 cRes += uVertices;
255 cOp += uVertices;
256
257 // Central differencing
258 for (int i=vVertices-2;i>0;--i) {
259 cRes[0] = (float) (((double)cOp[uVertices] - (double)cOp[-uVertices]) * invDv2);
260 cRes += uVertices;
261 cOp += uVertices;
262 }
263
264 // Backward differencing
265 cRes[0] = (float) (((double)cOp[0] - (double)cOp[-uVertices]) * invDv1);
266 }
267 }
268 break;
269
270 // Dv executing on a 2D raytraced surface
271 case SHADING_2D:
272 {
273 const int numVertices = currentShadingState->numVertices;
274 const int numRealVertices = currentShadingState->numRealVertices;
275 const float *dsrc = src + numRealVertices;
276 float *ddest = dest + numRealVertices;
277 const float *dv = currentShadingState->varying[VARIABLE_DV];
278
279 assert(numVertices == numRealVertices*3);
280
281 for (int i=numRealVertices;i>0;--i) {
282
283 assert(*dv != 0);
284
285 const float val = (float) (((double)dsrc[1] - (double)src[0]) / ((double)*dv++));
286
287 ddest[0] = val;
288 ddest[1] = val;
289 dest[0] = val;
290
291 ++dest;
292 ++src;
293 ddest += 2;
294 dsrc += 2;
295 }
296 }
297 break;
298 }
299 }
300
301
302
303
304 ///////////////////////////////////////////////////////////////////////
305 // Class : CShadingContext
306 // Method : DvFloat
307 // Description : Compute the v differences
308 // Return Value : -
309 // Comments :
DvFloat(float * dest,const float * src)310 void CShadingContext::DvFloat(float *dest,const float *src) {
311
312 switch(currentShadingState->shadingDim) {
313
314 // Dv executing on Points
315 case SHADING_0D:
316 {
317 for (int i=currentShadingState->numVertices;i>0;--i) {
318 *dest++ = 0;
319 }
320 }
321 break;
322
323
324 // Dv executing on a 2D grid
325 case SHADING_2D_GRID:
326 {
327 const int uVertices = currentShadingState->numUvertices;
328 const int vVertices = currentShadingState->numVvertices;
329
330 assert(uVertices >= 2);
331 assert(vVertices >= 2);
332
333 // Compute the DV
334 for (int j=0;j<uVertices;++j) {
335 float *cRes = dest + j;
336 const float *cOp = src + j;
337
338 // Forward differencing
339 cRes[0] = (float) ((double)cOp[uVertices] - (double)cOp[0]);
340 cRes += uVertices;
341 cOp += uVertices;
342
343 // Central differencing
344 for (int i=vVertices-2;i>0;--i) {
345 cRes[0] = (float) (((double)cOp[uVertices] - (double)cOp[-uVertices]) * 0.5);
346 cRes += uVertices;
347 cOp += uVertices;
348 }
349
350 // Backward differencing
351 cRes[0] = (float) ((double)cOp[0] - (double)cOp[-uVertices]);
352 }
353 }
354 break;
355
356 // Dv executing on a 2D raytraced surface
357 case SHADING_2D:
358 {
359 const int numVertices = currentShadingState->numVertices;
360 const int numRealVertices = currentShadingState->numRealVertices;
361 const float *dsrc = src + numRealVertices;
362 float *ddest = dest + numRealVertices;
363
364 assert(numVertices == numRealVertices*3);
365
366 for (int i=numRealVertices;i>0;--i) {
367
368 const float val = (float) ((double)dsrc[1] - (double)src[0]);
369
370 ddest[0] = val;
371 ddest[1] = val;
372 dest[0] = val;
373
374 ++dest;
375 ++src;
376 ddest += 2;
377 dsrc += 2;
378 }
379 }
380 break;
381 }
382 }
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413 ///////////////////////////////////////////////////////////////////////
414 // Class : CShadingContext
415 // Method : duVector
416 // Description : Compute the u derivative
417 // Return Value : -
418 // Comments :
duVector(float * dest,const float * src)419 void CShadingContext::duVector(float *dest,const float *src) {
420 switch(currentShadingState->shadingDim) {
421
422
423 // Du executing on Points or Curves (note that curves are defined along v)
424 case SHADING_0D:
425 {
426 for (int j=currentShadingState->numVertices;j>0;--j) {
427 initv(dest,0);
428 dest+=3;
429 }
430 }
431 break;
432
433
434 // Du executing on a 2D grid
435 case SHADING_2D_GRID:
436 {
437 const int uVertices = currentShadingState->numUvertices;
438 const int vVertices = currentShadingState->numVvertices;
439 const float *u = currentShadingState->varying[VARIABLE_U];
440
441 assert(uVertices >= 2);
442 assert(vVertices >= 2);
443 assert(u[1] > u[0]);
444
445 const double invDu1 = 1.0 / ((double)u[1] - (double)u[0]);
446 const double invDu2 = 1.0 / (2.0*((double)u[1] - (double)u[0]));
447
448 for (int j=vVertices;j>0;--j) {
449
450 // Use forward difference
451 *dest++ = (float) (((double)src[3] - (double)src[0]) * invDu1);
452 *dest++ = (float) (((double)src[4] - (double)src[1]) * invDu1);
453 *dest++ = (float) (((double)src[5] - (double)src[2]) * invDu1);
454 src += 3;
455
456 // Use central difference
457 for (int i=uVertices-2;i>0;--i) {
458 *dest++ = (float) (((double)src[3] - (double)src[-3]) * invDu2);
459 *dest++ = (float) (((double)src[4] - (double)src[-2]) * invDu2);
460 *dest++ = (float) (((double)src[5] - (double)src[-1]) * invDu2);
461 src += 3;
462 }
463
464 // Use backward difference
465 *dest++ = (float) (((double)src[0] - (double)src[-3]) * invDu1);
466 *dest++ = (float) (((double)src[1] - (double)src[-2]) * invDu1);
467 *dest++ = (float) (((double)src[2] - (double)src[-1]) * invDu1);
468 src += 3;
469 }
470 }
471 break;
472
473
474 // Du executing on a 2D raytraced surface
475 case SHADING_2D:
476 {
477 const int numRealVertices = currentShadingState->numRealVertices;
478 const float *dsrc = src + numRealVertices*3;
479 float *ddest = dest + numRealVertices*3;
480 const float *du = currentShadingState->varying[VARIABLE_DU];
481
482 for (int i=numRealVertices;i>0;--i) {
483
484 assert(*du != 0);
485
486 const double invDu = 1 / ((double)*du++);
487 const float val0 = (float) (((double)dsrc[0] - (double)src[0]) * invDu);
488 const float val1 = (float) (((double)dsrc[1] - (double)src[1]) * invDu);
489 const float val2 = (float) (((double)dsrc[2] - (double)src[2]) * invDu);
490
491 ddest[0] = val0;
492 ddest[1] = val1;
493 ddest[2] = val2;
494 ddest[3] = val0;
495 ddest[4] = val1;
496 ddest[5] = val2;
497 dest[0] = val0;
498 dest[1] = val1;
499 dest[2] = val2;
500
501 assert(dotvv(dest,dest) >= 0);
502
503 dest += 3;
504 src += 3;
505 ddest += 6;
506 dsrc += 6;
507 }
508 }
509 break;
510 }
511 }
512
513
514 ///////////////////////////////////////////////////////////////////////
515 // Class : CShadingContext
516 // Method : DuVector
517 // Description : Compute the u differences
518 // Return Value : -
519 // Comments :
DuVector(float * dest,const float * src)520 void CShadingContext::DuVector(float *dest,const float *src) {
521 switch(currentShadingState->shadingDim) {
522
523
524 // Du executing on Points or Curves (note that curves are defined along v)
525 case SHADING_0D:
526 {
527 for (int j=currentShadingState->numVertices;j>0;--j) {
528 initv(dest,0);
529 dest+=3;
530 }
531 }
532 break;
533
534
535 // Du executing on a 2D grid
536 case SHADING_2D_GRID:
537 {
538 const int uVertices = currentShadingState->numUvertices;
539 const int vVertices = currentShadingState->numVvertices;
540
541 assert(uVertices >= 2);
542 assert(vVertices >= 2);
543
544 for (int j=vVertices;j>0;--j) {
545
546 // Use forward difference
547 *dest++ = (float) ((double)src[3] - (double)src[0]);
548 *dest++ = (float) ((double)src[4] - (double)src[1]);
549 *dest++ = (float) ((double)src[5] - (double)src[2]);
550 src += 3;
551
552 // Use central difference
553 for (int i=uVertices-2;i>0;--i) {
554 *dest++ = (float) (((double)src[3] - (double)src[-3]) * 0.5);
555 *dest++ = (float) (((double)src[4] - (double)src[-2]) * 0.5);
556 *dest++ = (float) (((double)src[5] - (double)src[-1]) * 0.5);
557 src += 3;
558 }
559
560 // Use backward difference
561 *dest++ = (float) ((double)src[0] - (double)src[-3]);
562 *dest++ = (float) ((double)src[1] - (double)src[-2]);
563 *dest++ = (float) ((double)src[2] - (double)src[-1]);
564 src += 3;
565 }
566 }
567 break;
568
569
570 // Du executing on a 2D raytraced surface
571 case SHADING_2D:
572 {
573 const int numRealVertices = currentShadingState->numRealVertices;
574 const float *dsrc = src + numRealVertices*3;
575 float *ddest = dest + numRealVertices*3;
576
577 for (int i=numRealVertices;i>0;--i) {
578
579 const float val0 = (float) ((double)dsrc[0] - (double)src[0]);
580 const float val1 = (float) ((double)dsrc[1] - (double)src[1]);
581 const float val2 = (float) ((double)dsrc[2] - (double)src[2]);
582
583 ddest[0] = val0;
584 ddest[1] = val1;
585 ddest[2] = val2;
586 ddest[3] = val0;
587 ddest[4] = val1;
588 ddest[5] = val2;
589 dest[0] = val0;
590 dest[1] = val1;
591 dest[2] = val2;
592
593 assert(dotvv(dest,dest) >= 0);
594
595 dest += 3;
596 src += 3;
597 ddest += 6;
598 dsrc += 6;
599 }
600 }
601 break;
602 }
603 }
604
605
606
607
608
609 ///////////////////////////////////////////////////////////////////////
610 // Class : CShadingContext
611 // Method : dvVector
612 // Description : Compute the v derivative
613 // Return Value : -
614 // Comments :
dvVector(float * dest,const float * src)615 void CShadingContext::dvVector(float *dest,const float *src) {
616 switch(currentShadingState->shadingDim) {
617
618 // Dv executing on Points
619 case SHADING_0D:
620 {
621 for (int i=currentShadingState->numVertices;i>0;--i) {
622 initv(dest,0);
623 dest+=3;
624 }
625 }
626 break;
627
628 // Dv executing on a 2D grid
629 case SHADING_2D_GRID:
630 {
631 const int uVertices = currentShadingState->numUvertices;
632 const int vVertices = currentShadingState->numVvertices;
633 const float *v = currentShadingState->varying[VARIABLE_V];
634
635 assert(uVertices >= 2);
636 assert(vVertices >= 2);
637 assert(v[uVertices] > v[0]);
638
639 const double invDv1 = 1.0 / ((double)v[uVertices] - (double)v[0]);
640 const double invDv2 = 1.0 / (2.0*((double)v[uVertices] - (double)v[0]));
641
642 for (int j=0;j<uVertices;++j) {
643 float *cRes = dest + j*3;
644 const float *cOp = src + j*3;
645
646 // Forward differencing
647 cRes[0] = (float) (((double)cOp[uVertices*3+0] - (double)cOp[0]) * invDv1);
648 cRes[1] = (float) (((double)cOp[uVertices*3+1] - (double)cOp[1]) * invDv1);
649 cRes[2] = (float) (((double)cOp[uVertices*3+2] - (double)cOp[2]) * invDv1);
650 cRes += uVertices*3;
651 cOp += uVertices*3;
652
653 // Central differencing
654 for (int i=vVertices-2;i>0;--i) {
655 cRes[0] = (float) (((double)cOp[uVertices*3+0] - (double)cOp[-uVertices*3+0]) * invDv2);
656 cRes[1] = (float) (((double)cOp[uVertices*3+1] - (double)cOp[-uVertices*3+1]) * invDv2);
657 cRes[2] = (float) (((double)cOp[uVertices*3+2] - (double)cOp[-uVertices*3+2]) * invDv2);
658 cRes += uVertices*3;
659 cOp += uVertices*3;
660 }
661
662 // Backward differencing
663 cRes[0] = (float) (((double)cOp[0] - (double)cOp[-uVertices*3+0]) * invDv1);
664 cRes[1] = (float) (((double)cOp[1] - (double)cOp[-uVertices*3+1]) * invDv1);
665 cRes[2] = (float) (((double)cOp[2] - (double)cOp[-uVertices*3+2]) * invDv1);
666 }
667 }
668 break;
669
670 // Dv executing on a 2D raytraced surface
671 case SHADING_2D:
672 {
673 const int numVertices = currentShadingState->numVertices;
674 const int numRealVertices = currentShadingState->numRealVertices;
675 const float *dsrc = src + numRealVertices*3;
676 float *ddest = dest + numRealVertices*3;
677 const float *dv = currentShadingState->varying[VARIABLE_DV];
678
679 assert(numVertices == numRealVertices*3);
680
681 for (int i=numRealVertices;i>0;--i) {
682
683 assert(*dv > 0);
684
685 const double invDv = 1 / ((double)*dv++);
686 const float val0 = (float) (((double)dsrc[3] - (double)src[0]) * invDv);
687 const float val1 = (float) (((double)dsrc[4] - (double)src[1]) * invDv);
688 const float val2 = (float) (((double)dsrc[5] - (double)src[2]) * invDv);
689
690 ddest[0] = val0;
691 ddest[1] = val1;
692 ddest[2] = val2;
693 ddest[3] = val0;
694 ddest[4] = val1;
695 ddest[5] = val2;
696 dest[0] = val0;
697 dest[1] = val1;
698 dest[2] = val2;
699
700 dest += 3;
701 src += 3;
702 ddest += 6;
703 dsrc += 6;
704 }
705 }
706 break;
707 }
708 }
709
710
711 ///////////////////////////////////////////////////////////////////////
712 // Class : CShadingContext
713 // Method : DvVector
714 // Description : Compute the v differences
715 // Return Value : -
716 // Comments :
DvVector(float * dest,const float * src)717 void CShadingContext::DvVector(float *dest,const float *src) {
718 switch(currentShadingState->shadingDim) {
719
720 // Dv executing on Points
721 case SHADING_0D:
722 {
723 for (int i=currentShadingState->numVertices;i>0;--i) {
724 initv(dest,0);
725 dest+=3;
726 }
727 }
728 break;
729
730 // Dv executing on a 2D grid
731 case SHADING_2D_GRID:
732 {
733 const int uVertices = currentShadingState->numUvertices;
734 const int vVertices = currentShadingState->numVvertices;
735
736 assert(uVertices >= 2);
737 assert(vVertices >= 2);
738
739 for (int j=0;j<uVertices;++j) {
740 float *cRes = dest + j*3;
741 const float *cOp = src + j*3;
742
743 // Forward differencing
744 cRes[0] = (float) ((double)cOp[uVertices*3+0] - (double)cOp[0]);
745 cRes[1] = (float) ((double)cOp[uVertices*3+1] - (double)cOp[1]);
746 cRes[2] = (float) ((double)cOp[uVertices*3+2] - (double)cOp[2]);
747 cRes += uVertices*3;
748 cOp += uVertices*3;
749
750 // Central differencing
751 for (int i=vVertices-2;i>0;--i) {
752 cRes[0] = (float) (((double)cOp[uVertices*3+0] - (double)cOp[-uVertices*3+0]) * 0.5);
753 cRes[1] = (float) (((double)cOp[uVertices*3+1] - (double)cOp[-uVertices*3+1]) * 0.5);
754 cRes[2] = (float) (((double)cOp[uVertices*3+2] - (double)cOp[-uVertices*3+2]) * 0.5);
755 cRes += uVertices*3;
756 cOp += uVertices*3;
757 }
758
759 // Backward differencing
760 cRes[0] = (float) ((double)cOp[0] - (double)cOp[-uVertices*3+0]);
761 cRes[1] = (float) ((double)cOp[1] - (double)cOp[-uVertices*3+1]);
762 cRes[2] = (float) ((double)cOp[2] - (double)cOp[-uVertices*3+2]);
763 }
764 }
765 break;
766
767 // Dv executing on a 2D raytraced surface
768 case SHADING_2D:
769 {
770 const int numVertices = currentShadingState->numVertices;
771 const int numRealVertices = currentShadingState->numRealVertices;
772 const float *dsrc = src + numRealVertices*3;
773 float *ddest = dest + numRealVertices*3;
774
775 assert(numVertices == numRealVertices*3);
776
777 for (int i=numRealVertices;i>0;--i) {
778
779 const float val0 = (float) ((double)dsrc[3] - (double)src[0]);
780 const float val1 = (float) ((double)dsrc[4] - (double)src[1]);
781 const float val2 = (float) ((double)dsrc[5] - (double)src[2]);
782
783 ddest[0] = val0;
784 ddest[1] = val1;
785 ddest[2] = val2;
786 ddest[3] = val0;
787 ddest[4] = val1;
788 ddest[5] = val2;
789 dest[0] = val0;
790 dest[1] = val1;
791 dest[2] = val2;
792
793 dest += 3;
794 src += 3;
795 ddest += 6;
796 dsrc += 6;
797 }
798 }
799 break;
800 }
801 }
802
803
804
805
806
807
808
809
810
811 // Common code for trace transmission and trace reflection
812 // Note: we are including the cone angle tangent here because
813 // there's no point finely tesselating if we have a large coneangle blur
814 #define computeRayDifferentials \
815 const float lD = lengthv(rays->D); \
816 const float da = ((lengthv(rays->dDdu) + lengthv(rays->dDdv))*0.5f + lD*tanConeAngle) / lD; \
817 const float db = (lengthv(rays->dPdu) + lengthv(rays->dPdv))*0.5f;
818
819 // Should we be using only ray-orthogonal components?
820 /*
821 vector t1,t2,nD; \
822 mulvf(t1,rays->dDdu,dotvv(rays->dDdu,rays->D)/lD); \
823 subvv(t1,rays->dDdu,t1); \
824 mulvf(t2,rays->dDdv,dotvv(rays->dDdv,rays->D)/lD); \
825 subvv(t2,rays->dDdv,t2); \
826 const float da = ((lengthv(t1) + lengthv(t2))*0.5f + lD*tanConeAngle) / lD; \
827 const float db = (lengthv(rays->dPdu) + lengthv(rays->dPdv))*0.5f;
828 */
829
830 #define sampleRay(__from,__dir) \
831 vector tmp0,tmp1; \
832 mulvf(tmp0,rays->dPdu,(urand()-0.5f)*rays->sampleBase); \
833 mulvf(tmp1,rays->dPdv,(urand()-0.5f)*rays->sampleBase); \
834 addvv(__from,tmp0,tmp1); \
835 addvv(__from,rays->P); \
836 mulvf(tmp0,rays->dDdu,urand()-0.5f); \
837 mulvf(tmp1,rays->dDdv,urand()-0.5f); \
838 addvv(__dir,tmp0,tmp1); \
839 addvv(__dir,rays->D);
840
841 ///////////////////////////////////////////////////////////////////////
842 // Class : CShadingContext
843 // Method : traceTransmission
844 // Description : Trace transmission rays
845 // Return Value : -
846 // Comments :
traceTransmission(int numRays,CTraceLocation * rays,int probeOnly)847 void CShadingContext::traceTransmission(int numRays,CTraceLocation *rays,int probeOnly) {
848 CTransmissionRay *rayBase;
849 CTransmissionRay **raysBase;
850 CTransmissionRay *cRay,**cRays;
851 const CShadingScratch *scratch = &(currentShadingState->scratch);
852 const int shootStep = CRenderer::shootStep;
853 int numRemaining = shootStep;
854 CTransmissionBundle bundle;
855
856 // Set the ray label we're tracing
857 if ((bundle.label = scratch->traceParams.label) == NULL) bundle.label = rayLabelTransmission;
858
859 // Allocate temp memory
860 cRay = rayBase = (CTransmissionRay *) ralloc(shootStep*sizeof(CTransmissionRay),threadMemory);
861 cRays = raysBase = (CTransmissionRay **) ralloc(shootStep*sizeof(CTransmissionRay*),threadMemory);
862
863 // We can not be in shadow at this stage
864 assert(inShadow == FALSE);
865
866 // We're in shadow
867 inShadow = TRUE;
868
869 // Are we sampling the motion in the reflections?
870 const int sampleMotion = currentShadingState->currentObject->attributes->flags & ATTRIBUTES_FLAGS_SAMPLEMOTION;
871
872 // For each ray
873 for (int i=numRays;i>0;--i,++rays) {
874 const int numSamples = rays->numSamples;
875 const float coneAngle = rays->coneAngle;
876 const float tanConeAngle = min(fabsf(tanf(coneAngle)),1.0f);
877 const float multiplier = 1 / (float) numSamples;
878
879 // Compute the ray differentials
880 computeRayDifferentials;
881
882 // Clear the transmission
883 initv(rays->C,0,0,0);
884 rays->t = 0;
885
886 // Sample
887 for (int currentSample=numSamples;currentSample>0;--currentSample) {
888 vector from,L,dir;
889
890 // Sample the ray
891 sampleRay(from,L);
892 subvv(L,from);
893 const float d = lengthv(L);
894 mulvf(dir,L,1/d);
895
896 // Sample a point in the cone
897 sampleHemisphere(cRay->dir,dir,coneAngle,random4d);
898 if (dotvv(cRay->dir,cRay->dir) > C_EPSILON) {
899
900 movvv(cRay->from,from);
901 cRay->t = min(rays->maxDist,d) - rays->bias;
902 cRay->tmin = rays->bias;
903 if (sampleMotion) cRay->time = (urand() + currentSample - 1) * multiplier;
904 else cRay->time = rays->time;
905 cRay->flags = ATTRIBUTES_FLAGS_TRANSMISSION_VISIBLE;
906 cRay->dest = rays->C;
907 cRay->multiplier = multiplier;
908 cRay->da = da; // The ray differential
909 cRay->db = db;
910
911 // Are we shooting this ray for real?
912 if (probeOnly) {
913
914 // No, just query an intersection and record the distance
915 trace(cRay);
916 rays->t += cRay->t*multiplier;
917 } else {
918 *cRays++ = cRay++;
919 if (--numRemaining == 0) {
920 numTransmissionRays += shootStep;
921 bundle.numRays = shootStep;
922 bundle.rays = (CRay **) raysBase;
923 bundle.depth = 0;
924 bundle.last = 0;
925 bundle.postShader = NULL;
926 traceEx(&bundle);
927 cRay = rayBase;
928 cRays = raysBase;
929 numRemaining = shootStep;
930 }
931 }
932 }
933 }
934 }
935
936 // Finish the bundle
937 if (numRemaining != shootStep) {
938 numTransmissionRays += shootStep-numRemaining;
939 bundle.numRays = shootStep-numRemaining;
940 bundle.rays = (CRay **) raysBase;
941 bundle.depth = 0;
942 bundle.last = 0;
943 bundle.postShader = NULL;
944 traceEx(&bundle);
945 }
946
947 inShadow = FALSE; // We're no longer in shadow
948 }
949
950 ///////////////////////////////////////////////////////////////////////
951 // Class : CShadingContext
952 // Method : traceReflection
953 // Description : Trace reflected rays
954 // Return Value : -
955 // Comments :
traceReflection(int numRays,CTraceLocation * rays,int probeOnly)956 void CShadingContext::traceReflection(int numRays,CTraceLocation *rays,int probeOnly) {
957 CTraceRay *interiorRayBase,*cInteriorRay;
958 CTraceRay *exteriorRayBase,*cExteriorRay;
959 CTraceRay **interiorRaysBase,**exteriorRaysBase,**cInteriorRays,**cExteriorRays;
960 const CShadingScratch *scratch = &(currentShadingState->scratch);
961 const int shootStep = CRenderer::shootStep;
962 int numInteriorRemaining = shootStep;
963 int numExteriorRemaining = shootStep;
964 CTraceBundle interiorBundle,exteriorBundle;
965
966 // Verify atmosphere shaders
967 CAttributes *cAttr = currentShadingState->currentObject->attributes;
968 CShaderInstance *interiorShader = cAttr->interior;
969 CShaderInstance *exteriorShader = cAttr->exterior;
970
971 // Set the ray label
972 if (scratch->traceParams.label == NULL) {
973 exteriorBundle.label = rayLabelTransmission;
974 interiorBundle.label = rayLabelTransmission;
975 } else {
976 exteriorBundle.label = scratch->traceParams.label;
977 interiorBundle.label = scratch->traceParams.label;
978 }
979
980 // Allocate temp memory
981 cExteriorRay = exteriorRayBase = (CTraceRay *) ralloc(shootStep*sizeof(CTraceRay),threadMemory);
982 cExteriorRays = exteriorRaysBase = (CTraceRay **) ralloc(shootStep*sizeof(CTraceRay*),threadMemory);
983
984 if (interiorShader != exteriorShader) {
985 cInteriorRay = interiorRayBase = (CTraceRay *) ralloc(shootStep*sizeof(CTraceRay),threadMemory);
986 cInteriorRays = interiorRaysBase = (CTraceRay **) ralloc(shootStep*sizeof(CTraceRay*),threadMemory);
987 }
988
989 // Are we sampling the motion in the reflections?
990 const int sampleMotion = cAttr->flags & ATTRIBUTES_FLAGS_SAMPLEMOTION;
991
992 // For each ray
993 for (int i=numRays;i>0;--i,++rays) {
994 const int numSamples = rays->numSamples;
995 const float coneAngle = rays->coneAngle;
996 const float tanConeAngle = min(fabsf(tanf(coneAngle)),1.0f);
997 const float multiplier = 1 / (float) numSamples;
998
999 // Compute the ray differentials
1000 computeRayDifferentials;
1001
1002 // Clear the reflection
1003 initv(rays->C,0,0,0);
1004 rays->t = 0;
1005
1006 // Sample
1007 for (int currentSample=numSamples;currentSample>0;--currentSample) {
1008 vector from,D,dir;
1009
1010 sampleRay(from,D);
1011
1012 normalizev(D);
1013
1014 sampleHemisphere(dir,D,coneAngle,random4d);
1015 if (dotvv(dir,dir) > C_EPSILON) {
1016 CTraceRay *cRay;
1017 int isExterior = (dotvv(dir,rays->N) > 0) || (interiorShader == exteriorShader);
1018
1019 if (isExterior) cRay = cExteriorRay;
1020 else cRay = cInteriorRay;
1021
1022 movvv(cRay->dir,dir);
1023 movvv(cRay->from,from);
1024 if (sampleMotion) cRay->time = (urand() + currentSample - 1) * multiplier;
1025 else cRay->time = rays->time;
1026 cRay->t = C_INFINITY;
1027 cRay->tmin = rays->bias;
1028 cRay->flags = ATTRIBUTES_FLAGS_SPECULAR_VISIBLE;
1029 cRay->dest = rays->C;
1030 cRay->multiplier = multiplier;
1031 cRay->da = da;
1032 cRay->db = db;
1033 if (probeOnly) {
1034
1035 // No, just query an intersection and record the distance
1036 trace(cRay);
1037 rays->t += cRay->t*multiplier;
1038 } else {
1039 if (isExterior) {
1040 *cExteriorRays++ = cRay;
1041 cExteriorRay++;
1042
1043 if (--numExteriorRemaining == 0) {
1044 numReflectionRays += shootStep;
1045 exteriorBundle.numRays = shootStep;
1046 exteriorBundle.rays = (CRay **) exteriorRaysBase;
1047 exteriorBundle.depth = 0;
1048 exteriorBundle.last = 0;
1049 exteriorBundle.postShader = exteriorShader;
1050 traceEx(&exteriorBundle);
1051 cExteriorRay = exteriorRayBase;
1052 cExteriorRays = exteriorRaysBase;
1053 numExteriorRemaining = shootStep;
1054 }
1055 } else {
1056 *cInteriorRays++ = cRay;
1057 cInteriorRay++;
1058
1059 if (--numInteriorRemaining == 0) {
1060 numReflectionRays += shootStep;
1061 interiorBundle.numRays = shootStep;
1062 interiorBundle.rays = (CRay **) interiorRaysBase;
1063 interiorBundle.depth = 0;
1064 interiorBundle.last = 0;
1065 interiorBundle.postShader = interiorShader;
1066 traceEx(&interiorBundle);
1067 cInteriorRay = interiorRayBase;
1068 cInteriorRays = interiorRaysBase;
1069 numInteriorRemaining = shootStep;
1070 }
1071 }
1072 }
1073 }
1074 }
1075 }
1076
1077 // Finish the bundles
1078 if (numExteriorRemaining != shootStep) {
1079 numReflectionRays += shootStep-numExteriorRemaining;
1080 exteriorBundle.numRays = shootStep-numExteriorRemaining;
1081 exteriorBundle.rays = (CRay **) exteriorRaysBase;
1082 exteriorBundle.depth = 0;
1083 exteriorBundle.last = 0;
1084 exteriorBundle.postShader = exteriorShader;
1085 traceEx(&exteriorBundle);
1086 }
1087 if (numInteriorRemaining != shootStep) {
1088 numReflectionRays += shootStep-numInteriorRemaining;
1089 interiorBundle.numRays = shootStep-numInteriorRemaining;
1090 interiorBundle.rays = (CRay **) interiorRaysBase;
1091 interiorBundle.depth = 0;
1092 interiorBundle.last = 0;
1093 interiorBundle.postShader = interiorShader;
1094 traceEx(&interiorBundle);
1095 }
1096 }
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107 ///////////////////////////////////////////////////////////////////////
1108 // Class : CShadingContext
1109 // Method : rayDiff
1110 // Description : Compute the ray differentials
1111 // Return Value : -
1112 // Comments :
rayDiff(const float * from,const float * dir,const float * to)1113 float *CShadingContext::rayDiff(const float *from,const float *dir,const float *to) {
1114
1115 // Allocate the return value
1116 const int numVertices = currentShadingState->numVertices;
1117 float *ab = (float *) ralloc(numVertices*2*sizeof(float),threadMemory);
1118
1119 // Compute the direction vector if not already computed
1120 if (dir == NULL) {
1121 int i;
1122
1123 float *D = (float *) ralloc(numVertices*3*sizeof(float),threadMemory);
1124 for (i=numVertices;i>0;i--,D+=3,from+=3,to+=3) subvv(D,to,from);
1125
1126 D -= numVertices*3;
1127 from -= numVertices*3;
1128 to -= numVertices*3;
1129 dir = D;
1130 }
1131
1132
1133 switch(currentShadingState->shadingDim) {
1134
1135
1136
1137
1138
1139 // Dv executing on Points
1140 case SHADING_0D:
1141 {
1142
1143 // Set anyway
1144 for (int i=numVertices;i>0;i--) {
1145 *ab++ = DEFAULT_RAY_DA;
1146 *ab++ = DEFAULT_RAY_DB;
1147 }
1148
1149 return ab - numVertices*2;
1150 }
1151 break;
1152
1153
1154
1155
1156
1157
1158
1159
1160 // Dv executing on a 2D grid
1161 case SHADING_2D_GRID:
1162 {
1163 const int uVertices = currentShadingState->numUvertices;
1164 const int vVertices = currentShadingState->numVvertices;
1165 int i,j;
1166
1167 for (j=0;j<vVertices;j++) {
1168 for (i=0;i<uVertices;i++) {
1169
1170 const int ii = min(i,uVertices-2);
1171 const int jj = min(j,vVertices-2);
1172
1173 // The 4 corners of the current quad
1174 const float *cFrom0 = from + jj*uVertices*3 + ii*3;
1175 const float *cFrom1 = cFrom0 + 3;
1176 const float *cFrom2 = cFrom0 + uVertices*3;
1177 const float *cFrom3 = cFrom2 + 3;
1178
1179 ab[0] = 0;
1180 ab[1] = 0;
1181
1182 vector tmp;
1183 subvv(tmp,cFrom1,cFrom0);
1184 ab[1] += lengthv(tmp);
1185 subvv(tmp,cFrom2,cFrom0);
1186 ab[1] += lengthv(tmp);
1187 subvv(tmp,cFrom1,cFrom3);
1188 ab[1] += lengthv(tmp);
1189 subvv(tmp,cFrom2,cFrom3);
1190 ab[1] += lengthv(tmp);
1191
1192 // The directions at 4 corners of the quad
1193 const float *cDir0 = dir + jj*uVertices*3 + ii*3;
1194 const float *cDir1 = cDir0 + 3;
1195 const float *cDir2 = cDir0 + uVertices*3;
1196 const float *cDir3 = cDir2 + 3;
1197
1198 float a = dotvv(cDir1,cDir0);
1199 ab[0] += acosf(sqrtf(a*a / (dotvv(cDir0,cDir0)*dotvv(cDir1,cDir1) + C_EPSILON)));
1200
1201 a = dotvv(cDir2,cDir0);
1202 ab[0] += acosf(sqrtf(a*a / (dotvv(cDir0,cDir0)*dotvv(cDir2,cDir2) + C_EPSILON)));
1203
1204 a = dotvv(cDir3,cDir1);
1205 ab[0] += acosf(sqrtf(a*a / (dotvv(cDir3,cDir3)*dotvv(cDir1,cDir1) + C_EPSILON)));
1206
1207 a = dotvv(cDir2,cDir3);
1208 ab[0] += acosf(sqrtf(a*a / (dotvv(cDir2,cDir2)*dotvv(cDir3,cDir3) + C_EPSILON)));
1209
1210 ab[0] *= 0.25f;
1211 ab[1] *= 0.25f;
1212
1213 ab[0] = tanf(min(ab[0],((float) C_PI)*0.5f - C_EPSILON));
1214 ab[0] = min(ab[0],DEFAULT_RAY_DA);
1215
1216 // guard against bad differentials
1217
1218 if(ab[0] != ab[0]) ab[0] = DEFAULT_RAY_DA;
1219
1220 assert(ab[0] >= 0);
1221 assert(ab[1] >= 0);
1222
1223 ab += 2;
1224 }
1225 }
1226
1227 return ab - uVertices*vVertices*2;
1228 }
1229 break;
1230
1231
1232
1233
1234
1235
1236
1237 // Dv executing on a 2D raytraced surface
1238 case SHADING_2D:
1239 {
1240 const int numRealVertices = currentShadingState->numRealVertices;
1241 const float *dfrom = from + numRealVertices*3;
1242 const float *ddir = dir + numRealVertices*3;
1243 int i;
1244
1245 assert(numVertices == numRealVertices*3);
1246
1247 for (i=numRealVertices;i>0;i--) {
1248 vector tmp;
1249
1250 ab[0] = 0;
1251 ab[1] = 0;
1252
1253 subvv(tmp,dfrom,from);
1254 ab[1] += lengthv(tmp);
1255 subvv(tmp,dfrom + 3,from);
1256 ab[1] += lengthv(tmp);
1257
1258 float a;
1259 a = dotvv(dir,ddir);
1260 ab[0] += acosf(sqrtf(a*a / (dotvv(dir,dir)*dotvv(ddir,ddir) + C_EPSILON)));
1261 a = dotvv(dir,ddir+3);
1262 ab[0] += acosf(sqrtf(a*a / (dotvv(dir,dir)*dotvv(ddir+3,ddir+3) + C_EPSILON)));
1263
1264 ab[0] *= 0.5f;
1265 ab[1] *= 0.5f;
1266 ab[0] = tanf(min(ab[0],((float) C_PI)*0.5f - C_EPSILON));
1267 ab[0] = min(ab[0],DEFAULT_RAY_DA);
1268
1269 // guard against bad differentials
1270
1271 if(ab[0] != ab[0]) ab[0] = DEFAULT_RAY_DA;
1272
1273 assert(ab[0] >= 0);
1274 assert(ab[1] >= 0);
1275
1276 ab += 2;
1277 from += 3;
1278 dir += 3;
1279 dfrom += 6;
1280 ddir += 6;
1281 }
1282
1283 return ab - numRealVertices*2;
1284 }
1285 break;
1286 }
1287
1288 assert(FALSE);
1289 return NULL;
1290 }
1291
1292
1293
1294 ///////////////////////////////////////////////////////////////////////
1295 // Class : CShadingContext
1296 // Method : rayDiff
1297 // Description : Compute the ray differentials
1298 // Return Value : -
1299 // Comments :
rayDiff(const float * from)1300 float *CShadingContext::rayDiff(const float *from) {
1301
1302 // Allocate the return value
1303 const int numVertices = currentShadingState->numVertices;
1304 float *b = (float *) ralloc(numVertices*sizeof(float),threadMemory);
1305
1306
1307 switch(currentShadingState->shadingDim) {
1308
1309
1310
1311
1312
1313 // Dv executing on Points
1314 case SHADING_0D:
1315 {
1316 // Set anyway
1317 for (int i=numVertices;i>0;i--) {
1318 *b++ = DEFAULT_RAY_DB;
1319 }
1320
1321 return b - numVertices;
1322 }
1323 break;
1324
1325
1326
1327
1328
1329
1330
1331
1332 // Dv executing on a 2D grid
1333 case SHADING_2D_GRID:
1334 {
1335 const int uVertices = currentShadingState->numUvertices;
1336 const int vVertices = currentShadingState->numVvertices;
1337 int i,j;
1338
1339 for (j=0;j<vVertices;j++) {
1340 for (i=0;i<uVertices;i++) {
1341
1342 const int ii = min(i,uVertices-2);
1343 const int jj = min(j,vVertices-2);
1344
1345 // The 4 corners of the current quad
1346 const float *cFrom0 = from + jj*uVertices*3 + ii*3;
1347 const float *cFrom1 = cFrom0 + 3;
1348 const float *cFrom2 = cFrom0 + uVertices*3;
1349 const float *cFrom3 = cFrom2 + 3;
1350
1351 b[0] = 0;
1352
1353 vector tmp;
1354 subvv(tmp,cFrom1,cFrom0);
1355 b[0] += lengthv(tmp);
1356 subvv(tmp,cFrom2,cFrom0);
1357 b[0] += lengthv(tmp);
1358 subvv(tmp,cFrom1,cFrom3);
1359 b[0] += lengthv(tmp);
1360 subvv(tmp,cFrom2,cFrom3);
1361 b[0] += lengthv(tmp);
1362
1363 b[0] *= 0.25f;
1364 b++;
1365 }
1366 }
1367
1368 return b - uVertices*vVertices;
1369 }
1370 break;
1371
1372
1373
1374
1375
1376
1377
1378 // Dv executing on a 2D raytraced surface
1379 case SHADING_2D:
1380 {
1381 const int numRealVertices = currentShadingState->numRealVertices;
1382 const float *dfrom = from + numRealVertices*3;
1383 int i;
1384
1385 assert(numVertices == numRealVertices*3);
1386
1387 for (i=numRealVertices;i>0;i--) {
1388 vector tmp;
1389
1390 b[0] = 0;
1391
1392 subvv(tmp,dfrom,from);
1393 b[0] += lengthv(tmp);
1394 subvv(tmp,dfrom + 3,from);
1395 b[0] += lengthv(tmp);
1396 b[0] *= 0.5f;
1397
1398 b++;
1399 from += 3;
1400 dfrom += 6;
1401 }
1402
1403 return b - numRealVertices;
1404 }
1405 break;
1406 }
1407
1408 assert(FALSE);
1409 return NULL;
1410 }
1411