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 : shading.cpp
27 // Classes : CShadingContext
28 // Description :
29 //
30 ////////////////////////////////////////////////////////////////////////
31 #include <stdarg.h>
32 #include <math.h>
33 #include <string.h>
34
35 #include "shading.h"
36 #include "object.h"
37 #include "raytracer.h"
38 #include "brickmap.h"
39 #include "photonMap.h"
40 #include "pointCloud.h"
41 #include "texture3d.h"
42 #include "irradiance.h"
43 #include "stats.h"
44 #include "memory.h"
45 #include "random.h"
46 #include "points.h"
47 #include "error.h"
48 #include "remoteChannel.h"
49 #include "renderer.h"
50 #include "shaderPl.h"
51 #include "ri_config.h"
52
53 // George's extrapolated derivative extensions
54 #define USE_EXTRAPOLATED_DERIV
55
56 // Options that are defined and responded
57 const char *optionsFormat = "Format";
58 const char *optionsDeviceFrame = "Frame";
59 const char *optionsDeviceResolution = "DeviceResolution";
60 const char *optionsFrameAspectRatio = "FrameAspectRatio";
61 const char *optionsCropWindow = "CropWindow";
62 const char *optionsDepthOfField = "DepthOfField";
63 const char *optionsShutter = "Shutter";
64 const char *optionsClipping = "Clipping";
65 const char *optionsBucketSize = "BucketSize";
66 const char *optionsColorQuantizer = "ColorQuantizer";
67 const char *optionsDepthQuantizer = "DepthQuantizer";
68 const char *optionsPixelFilter = "PixelFilter";
69 const char *optionsGamma = "Gamma";
70 const char *optionsMaxRayDepth = "MaxRayDepth";
71 const char *optionsRelativeDetail = "RelativeDetail";
72 const char *optionsPixelSamples = "PixelSamples";
73
74 // Attributes that are defined and responded
75 const char *attributesShadingRate = "ShadingRate";
76 const char *attributesSides = "Sides";
77 const char *attributesMatte = "matte";
78 const char *attributesMotionfactor = "GeometricApproximation:motionfactor";
79 const char *attributesDisplacementBnd = "displacementbound:sphere";
80 const char *attributesDisplacementSys = "displacementbound:coordinatesystem";
81 const char *attributesName = "identifier:name";
82
83 const char *attributesTraceBias = "trace:bias";
84 const char *attributesTraceMaxDiffuse = "trace:maxdiffusedepth";
85 const char *attributesTraceMaxSpecular = "trace:maxspeculardepth";
86
87 const char *attributesUser = "user:";
88
89 // Rendererinfo requests
90 const char *rendererinfoRenderer = "renderer";
91 const char *rendererinfoVersion = "version";
92 const char *rendererinfoVersionStr = "versionstring";
93
94 // Predefined ray labels used during raytracing
95 const char *rayLabelPrimary = "camera";
96 const char *rayLabelTrace = "trace";
97 const char *rayLabelTransmission = "transmission";
98 const char *rayLabelGather = "gather";
99
100
101 ///////////////////////////////////////////////////////////////////////
102 // Function : complete
103 // Description : This function fills in the missing data (not filled by the object) from attributes
104 // Return Value :
105 // Comments : Thread safe
complete(int num,float ** varying,unsigned int usedParameters,const CAttributes * attributes1,const CAttributes * attributes2)106 inline void complete(int num,float **varying,unsigned int usedParameters,const CAttributes *attributes1,const CAttributes *attributes2) {
107 int i;
108
109 if (usedParameters & PARAMETER_ALPHA) {
110 float *dest = varying[VARIABLE_ALPHA];
111
112 for (i=num;i>0;i--)
113 *dest++ = 1;
114 }
115
116 if (usedParameters & PARAMETER_S) {
117 const float *u = varying[VARIABLE_U];
118 float *s = varying[VARIABLE_S];
119
120 if (attributes1->flags & ATTRIBUTES_FLAGS_CUSTOM_ST) {
121 const float *v = varying[VARIABLE_V];
122 const float *time = varying[VARIABLE_TIME];
123 const float *s1 = attributes1->s;
124 const float *s2 = attributes2->s;
125
126 for (i=num;i>0;i--) {
127 const double ctime = *time++;
128 const double cu = *u++;
129 const double cv = *v++;
130
131 *s++ = (float) (((s1[0]*(1.0-ctime) + s2[0]*ctime)*(1.0-cu) +
132 (s1[1]*(1.0-ctime) + s2[1]*ctime)*cu)*(1.0-cv) +
133 ((s1[2]*(1.0-ctime) + s2[2]*ctime)*(1.0-cu) +
134 (s1[3]*(1.0-ctime) + s2[3]*ctime)*cu)*cv);
135 }
136 } else {
137 memcpy(s,u,num*sizeof(float));
138 }
139 }
140
141 if (usedParameters & PARAMETER_T) {
142 const float *v = varying[VARIABLE_V];
143 float *t = varying[VARIABLE_T];
144
145 if (attributes1->flags & ATTRIBUTES_FLAGS_CUSTOM_ST) {
146 const float *u = varying[VARIABLE_U];
147 const float *time = varying[VARIABLE_TIME];
148 const float *t1 = attributes1->t;
149 const float *t2 = attributes2->t;
150
151 for (i=num;i>0;i--) {
152 const double ctime = *time++;
153 const double cu = *u++;
154 const double cv = *v++;
155
156 *t++ = (float) (((t1[0]*(1.0-ctime) + t2[0]*ctime)*(1.0-cu) +
157 (t1[1]*(1.0-ctime) + t2[1]*ctime)*cu)*(1.0-cv) +
158 ((t1[2]*(1.0-ctime) + t2[2]*ctime)*(1.0-cu) +
159 (t1[3]*(1.0-ctime) + t2[3]*ctime)*cu)*cv);
160 u++;
161 v++;
162 time++;
163 }
164 } else {
165 memcpy(t,v,num*sizeof(float));
166 }
167 }
168
169 if (usedParameters & PARAMETER_CS) {
170 float *dest = varying[VARIABLE_CS];
171 const float *time = varying[VARIABLE_TIME];
172 const float *c1 = attributes1->surfaceColor;
173 const float *c2 = attributes2->surfaceColor;
174
175
176 for (i=num;i>0;i--) {
177 interpolatev(dest,c1,c2,*time++);
178 dest += 3;
179 }
180 }
181
182 if (usedParameters & PARAMETER_OS) {
183 float *dest = varying[VARIABLE_OS];
184 const float *time = varying[VARIABLE_TIME];
185 const float *c1 = attributes1->surfaceOpacity;
186 const float *c2 = attributes2->surfaceOpacity;
187
188 for (i=num;i>0;i--) {
189 interpolatev(dest,c1,c2,*time++);
190 dest += 3;
191 }
192 }
193
194 // If the coordinate system is right handed, flip the normal vector
195 if (attributes1->flags & ATTRIBUTES_FLAGS_INSIDE) {
196 float *src = varying[VARIABLE_NG];
197 float *src2 = varying[VARIABLE_N];
198
199 for (i=num;i>0;i--) {
200 mulvf(src,-1);
201 mulvf(src2,-1);
202 src += 3;
203 src2 += 3;
204 }
205 }
206
207 // Copy the normal vector
208 if (usedParameters & PARAMETER_N) {
209 memcpy(varying[VARIABLE_N],varying[VARIABLE_NG],3*num*sizeof(float));
210 }
211
212 // ensure Oi and Ci are always filled in
213 if (!(usedParameters & PARAMETER_CI)) {
214 float *dest = varying[VARIABLE_CI];
215 const float *time = varying[VARIABLE_TIME];
216 const float *c1 = attributes1->surfaceColor;
217 const float *c2 = attributes2->surfaceColor;
218
219
220 for (i=num;i>0;i--) {
221 interpolatev(dest,c1,c2,*time);
222 dest += 3;
223 time ++;
224 }
225 }
226
227 if (!(usedParameters & PARAMETER_OI)) {
228 float *dest = varying[VARIABLE_OI];
229 const float *time = varying[VARIABLE_TIME];
230 const float *c1 = attributes1->surfaceOpacity;
231 const float *c2 = attributes2->surfaceOpacity;
232
233 for (i=num;i>0;i--) {
234 interpolatev(dest,c1,c2,*time);
235 dest += 3;
236 time ++;
237 }
238 }
239
240 // Finally, range-correct time
241 // Note: It is important this is last, as before this we assume a 0-1
242 // range for time. After this we must never use time assuing 0-1 range
243 if (usedParameters & (PARAMETER_TIME | PARAMETER_DTIME)) {
244
245 varying[VARIABLE_DTIME][0] = CRenderer::shutterClose - CRenderer::shutterOpen;
246
247 float *time = varying[VARIABLE_TIME];
248 const float idtime = CRenderer::invShutterTime;
249 const float t0 = CRenderer::shutterOpen;
250
251 for (i=num;i>0;i--) {
252 time[0] = (time[0]*idtime + t0);
253 time++;
254 }
255 }
256
257 }
258
259 ///////////////////////////////////////////////////////////////////////
260 // Function : complete
261 // Description : This function fills in the missing data (not filled by the object) from attributes
262 // Return Value :
263 // Comments : Thread safe
complete(int num,float ** varying,unsigned int usedParameters,const CAttributes * attributes)264 inline void complete(int num,float **varying,unsigned int usedParameters,const CAttributes *attributes) {
265 int i;
266
267 if (usedParameters & PARAMETER_ALPHA) {
268 float *dest = varying[VARIABLE_ALPHA];
269
270 for (i=num;i>0;i--)
271 *dest++ = 1;
272 }
273
274 if (usedParameters & PARAMETER_S) {
275 const float *u = varying[VARIABLE_U];
276 float *s = varying[VARIABLE_S];
277
278 if (attributes->flags & ATTRIBUTES_FLAGS_CUSTOM_ST) {
279 const float *v = varying[VARIABLE_V];
280 const float *sCoord = attributes->s;
281
282 for (i=num;i>0;i--) {
283 const double uu = *u;
284 const double vv = *v;
285 *s++ = (float) ((sCoord[0]*(1.0-uu) + sCoord[1]*uu)*(1.0-vv) + (sCoord[2]*(1.0-uu) + sCoord[3]*uu)*vv);
286 u++;
287 v++;
288 }
289 } else {
290 memcpy(s,u,num*sizeof(float));
291 }
292 }
293
294 if (usedParameters & PARAMETER_T) {
295 const float *v = varying[VARIABLE_V];
296 float *t = varying[VARIABLE_T];
297
298 if (attributes->flags & ATTRIBUTES_FLAGS_CUSTOM_ST) {
299 const float *u = varying[VARIABLE_U];
300 const float *tCoord = attributes->t;
301
302 for (i=num;i>0;i--) {
303 const double uu = *u;
304 const double vv = *v;
305 *t++ = (float) ((tCoord[0]*(1.0-uu) + tCoord[1]*uu)*(1.0-vv) + (tCoord[2]*(1.0-uu) + tCoord[3]*uu)*vv);
306 u++;
307 v++;
308 }
309 } else {
310 memcpy(t,v,num*sizeof(float));
311 }
312 }
313
314 if (usedParameters & PARAMETER_CS) {
315 float *dest = varying[VARIABLE_CS];
316 const float *src = attributes->surfaceColor;
317
318 for (i=num;i>0;i--) {
319 movvv(dest,src);
320 dest += 3;
321 }
322 }
323
324 if (usedParameters & PARAMETER_OS) {
325 float *dest = varying[VARIABLE_OS];
326 const float *src = attributes->surfaceOpacity;
327
328 for (i=num;i>0;i--) {
329 movvv(dest,src);
330 dest += 3;
331 }
332 }
333
334 if (attributes->flags & ATTRIBUTES_FLAGS_INSIDE) {
335 float *src = varying[VARIABLE_NG];
336
337 for (i=num;i>0;i--) {
338 mulvf(src,-1);
339 src += 3;
340 }
341 }
342
343 if (usedParameters & PARAMETER_N) {
344 memcpy(varying[VARIABLE_N],varying[VARIABLE_NG],3*num*sizeof(float));
345 }
346
347 // ensure Oi and Ci are always filled in
348 if (!(usedParameters & PARAMETER_CI)) {
349 float *dest = varying[VARIABLE_CI];
350 const float *src = attributes->surfaceColor;
351
352 for (i=num;i>0;i--) {
353 movvv(dest,src);
354 dest += 3;
355 }
356 }
357
358 if (!(usedParameters & PARAMETER_OI)) {
359 float *dest = varying[VARIABLE_OI];
360 const float *src = attributes->surfaceOpacity;
361
362 for (i=num;i>0;i--) {
363 movvv(dest,src);
364 dest += 3;
365 }
366 }
367
368 // Finally, range-correct time
369 // Note: It is important this is last, as before this we assume a 0-1
370 // range for time. After this we must never use time assuing 0-1 range
371 if (usedParameters & (PARAMETER_TIME | PARAMETER_DTIME)) {
372
373 varying[VARIABLE_DTIME][0] = CRenderer::shutterClose - CRenderer::shutterOpen;
374
375 float *time = varying[VARIABLE_TIME];
376 const float idtime = CRenderer::invShutterTime;
377 const float t0 = CRenderer::shutterOpen;
378
379 for (i=num;i>0;i--) {
380 time[0] = (time[0]*idtime + t0);
381 time++;
382 }
383 }
384 }
385
386
387 ///////////////////////////////////////////////////////////////////////
388 // Class : CShadingContext
389 // Method : CShadingContext
390 // Description : Ctor
391 // Return Value : -
392 // Comments :
CShadingContext(int t)393 CShadingContext::CShadingContext(int t) : thread(t) {
394 // Initialize the shading state
395 currentShadingState = NULL;
396
397 // Initialize the shader state memory stack
398 memoryInit(shaderStateMemory);
399
400 // Initialize the thread memory stack
401 memoryInit(threadMemory);
402
403 // Init the bucket we're rendering
404 currentXBucket = 0;
405 currentYBucket = 0;
406
407 // Init the conditionals
408 conditionals = NULL;
409 currentRayDepth = 0;
410 currentRayLabel = rayLabelPrimary;
411 freeStates = NULL;
412 inShadow = FALSE;
413
414 // (globalMemory is checkpointed)
415 traceObjectHash = (TObjectHash *) ralloc(sizeof(TObjectHash)*SHADING_OBJECT_CACHE_SIZE,CRenderer::globalMemory);
416
417 // Fill the object pointers with impossible data
418 for (int i=0;i<SHADING_OBJECT_CACHE_SIZE;i++) traceObjectHash[i].object = (CSurface *) this;
419
420 // Init the PL hash
421 for (int i=0;i<PL_HASH_SIZE;i++) plHash[i] = NULL;
422
423 // Init the random number generator
424 randomInit(5489*(thread+1));
425
426 // Init the stats
427 numIndirectDiffuseRays = 0;
428 numIndirectDiffuseSamples = 0;
429 numOcclusionRays = 0;
430 numOcclusionSamples = 0;
431 numIndirectDiffusePhotonmapLookups = 0;
432 numShade = 0;
433 numSampled = 0;
434 numShaded = 0;
435 vertexMemory = 0;
436 peakVertexMemory = 0;
437 numTracedRays = 0;
438 numReflectionRays = 0;
439 numTransmissionRays = 0;
440 numGatherRays = 0;
441 }
442
443 ///////////////////////////////////////////////////////////////////////
444 // Class : CShadingContext
445 // Method : ~CShadingContext
446 // Description : Dtor
447 // Return Value : -
448 // Comments :
~CShadingContext()449 CShadingContext::~CShadingContext() {
450
451 // Delete the conditionals we allocated
452 CConditional *cConditional;
453 while((cConditional = conditionals) != NULL) {
454 conditionals = conditionals->next;
455 delete cConditional;
456 }
457
458 // Shutdown the random number generator
459 randomShutdown();
460
461 // Ditch the PL hash
462 for (int i=0;i<PL_HASH_SIZE;i++) {
463 CPLLookup *cLookup;
464 while((cLookup=plHash[i]) != NULL) {
465 plHash[i] = cLookup->next;
466 delete cLookup;
467 }
468 }
469
470 // Ditch the shading states that have been allocated
471 assert(currentShadingState != NULL);
472 freeState(currentShadingState);
473 CShadingState *cState;
474 while ((cState=freeStates) != NULL) {
475 freeStates = cState->next;
476
477 freeState(cState);
478 }
479 currentShadingState = NULL;
480
481 // Ditch the thread memory stack
482 memoryTini(threadMemory);
483
484 // Ditch the shader state memory stack
485 memoryTini(shaderStateMemory);
486
487 // The frame assertions
488 assert(vertexMemory == 0);
489
490 // Update the global statistics
491 stats.numIndirectDiffuseRays += numIndirectDiffuseRays;
492 stats.numIndirectDiffuseSamples += numIndirectDiffuseSamples;
493 stats.numOcclusionRays += numOcclusionRays;
494 stats.numOcclusionSamples += numOcclusionSamples;
495 stats.numIndirectDiffusePhotonmapLookups += numIndirectDiffusePhotonmapLookups;
496 stats.numShade += numShade;
497 stats.numSampled += numSampled;
498 stats.numShaded += numShaded;
499 stats.numTracedRays += numTracedRays;
500 stats.numReflectionRays += numReflectionRays;
501 stats.numTransmissionRays += numTransmissionRays;
502 stats.numGatherRays += numGatherRays;
503 }
504
505
506
507
508 ///////////////////////////////////////////////////////////////////////
509 // Class : CShadingContext
510 // Method : renderPrimitive
511 // Description : Add an object into the scene
512 // Return Value :
513 // Comments :
drawObject(CObject * cObject)514 void CShadingContext::drawObject(CObject *cObject) {
515 // This function must be overriden
516 }
517
518
519
520
521
522
523 ///////////////////////////////////////////////////////////////////////
524 // Class : CShadingContext
525 // Method : shade2D
526 // Description : Sample/Shade bunch of points
527 // Return Value : -
528 // Comments : Thread safe
529 //
530 //
531 //
532 // Preconditions:
533 // !!! -> u,v,time,I fields of varying must be set
shade(CSurface * object,int uVertices,int vVertices,EShadingDim dim,unsigned int usedParameters,int displaceOnly)534 void CShadingContext::shade(CSurface *object,int uVertices,int vVertices,EShadingDim dim,unsigned int usedParameters,int displaceOnly) {
535 const CAttributes *currentAttributes = object->attributes;
536 float **varying = currentShadingState->varying;
537 float ***locals = currentShadingState->locals;
538 CShaderInstance *displacement;
539 CShaderInstance *surface;
540 CShaderInstance *atmosphere;
541 int i;
542 CSurface *savedObject;
543
544 assert(uVertices > 0);
545 assert(vVertices > 0);
546
547 // This is the number of vertices we will be sampling/shading
548 int numVertices = uVertices*vVertices;
549 assert(numVertices <= CRenderer::maxGridSize);
550 assert(numVertices > 0);
551
552 // Update the stats
553 numShade++;
554 numSampled += numVertices;
555
556 // Are we just displacing the surface ?
557 if (displaceOnly == FALSE) {
558
559 // Are we in a shadow ray ?
560 if (inShadow == TRUE) {
561
562 // Yes, are we supposed to shade the objects in the shadow ?
563 if (currentAttributes->transmissionHitMode == 'p') {
564
565 // No, just copy the color/opacity from the attributes field
566 float *opacity = varying[VARIABLE_OI];
567 int i;
568 const float *so = currentAttributes->surfaceOpacity;
569
570 for (i=numVertices;i>0;i--,opacity+=3) movvv(opacity,so);
571
572 // Nothing more to do here, just return
573 return;
574 }
575
576 // The transmission must be shade at this point
577 assert(currentAttributes->transmissionHitMode == 's');
578
579 // We need to execute the shaders
580 displacement = NULL; //currentAttributes->displacement; // We probably don't need to execute the displacement shader
581 surface = currentAttributes->surface;
582 atmosphere = NULL;
583
584 } else {
585 // check the hit mode
586
587 // If we're raytracing, are we supposed to shade hit rays?
588 if ((dim == SHADING_2D) && (currentAttributes->specularHitMode == 'p')) {
589 // No, just copy the color/opacity from the attributes field
590 float *opacity = varying[VARIABLE_OI];
591 float *color = varying[VARIABLE_CI];
592 int i;
593 const float *so = currentAttributes->surfaceOpacity;
594 const float *sc = currentAttributes->surfaceColor;
595
596 for (i=numVertices;i>0;i--,opacity+=3,color+=3) {
597 movvv(opacity,so);
598 movvv(color,sc);
599 }
600
601 // Nothing more to do here, just return
602 return;
603 }
604
605 // We need to execute the shaders
606 if (currentAttributes->flags & ATTRIBUTES_FLAGS_MATTE) {
607 displacement = currentAttributes->displacement;
608 surface = currentAttributes->surface; // execute the surface shader for the output opacity
609 atmosphere = NULL;
610 } else {
611 displacement = currentAttributes->displacement;
612 surface = currentAttributes->surface;
613 atmosphere = currentAttributes->atmosphere;
614 }
615 }
616
617 // Prepare the used parameters by the shaders
618 usedParameters |= currentAttributes->usedParameters | CRenderer::additionalParameters;
619
620 // Prepare the locals
621 for (int a=0;a<NUM_ACCESSORS;a++) locals[a] = NULL;
622 } else {
623
624 // We are only interested in the surface position, not the color
625 #ifdef IGNORE_DISPLACEMENTS_FOR_DICING
626 if ( (currentAttributes->displacement == NULL) ||
627 ( (usedParameters & PARAMETER_RAYTRACE) && (!(currentAttributes->flags & ATTRIBUTES_FLAGS_DISPLACEMENTS))) ||
628 (displaceOnly & 2)
629 ) {
630 #else
631 if ( (currentAttributes->displacement == NULL) ||
632 ( (usedParameters & PARAMETER_RAYTRACE) && (!(currentAttributes->flags & ATTRIBUTES_FLAGS_DISPLACEMENTS)))) {
633 #endif
634 const int savedParameters = usedParameters;
635
636 // No, just sample the geometry
637 // Note: we pass NULL for each of the locals here because we do not wish
638 // to expand them (we're not running shaders) yet. This causes the
639 // interpolation to local shader vars from the pl not to occur
640 for (int a=0;a<NUM_ACCESSORS;a++) locals[a] = NULL;
641
642 object->sample(0,numVertices,varying,locals,usedParameters);
643 object->interpolate(numVertices,varying,locals);
644
645 // We're not shading just sampling
646 if (usedParameters & PARAMETER_N) {
647 assert(savedParameters & PARAMETER_NG);
648
649 // Flip the normal vector ?
650 if (currentAttributes->flags & ATTRIBUTES_FLAGS_INSIDE) {
651 int i = numVertices;
652 float *N = varying[VARIABLE_NG];
653
654 for (;i>0;i--) {
655 *N++ *= -1;
656 *N++ *= -1;
657 *N++ *= -1;
658 }
659 }
660
661 memcpy(varying[VARIABLE_N],varying[VARIABLE_NG],numVertices*3*sizeof(float));
662 }
663
664 // We're done here
665 return;
666 }
667
668 // Prepare the locals
669 for (int a=0;a<NUM_ACCESSORS;a++) locals[a] = NULL;
670
671 // We need to execute the displacement shader, so get ready
672 displacement = currentAttributes->displacement;
673 surface = NULL;
674 atmosphere = NULL;
675
676 // Note: we check for message passing with displacement and prepare appopriately below
677 }
678
679
680 // We're shading
681 savedObject = currentShadingState->currentObject;
682 currentShadingState->currentObject = object;
683 currentShadingState->numUvertices = uVertices;
684 currentShadingState->numVvertices = vVertices;
685 currentShadingState->numVertices = numVertices;
686
687 // Checkpoint the shader state stack
688 memBegin(shaderStateMemory);
689
690 // Allocate the caches for the shaders being executed
691 if (surface != NULL) locals[ACCESSOR_SURFACE] = surface->prepare(shaderStateMemory,varying,numVertices);
692 if (displacement != NULL) locals[ACCESSOR_DISPLACEMENT] = displacement->prepare(shaderStateMemory,varying,numVertices);
693 if (atmosphere != NULL) locals[ACCESSOR_ATMOSPHERE] = atmosphere->prepare(shaderStateMemory,varying,numVertices);
694
695 if (displaceOnly == TRUE) {
696 // Verify if we have to prepare other shaders, even though displacing
697 // due to message passing this _has_ to be after the shaderStateMemory checkPoint
698 usedParameters = displacement->requiredParameters() | PARAMETER_P | PARAMETER_N;
699
700 if (usedParameters & PARAMETER_MESSAGEPASSING) {
701 // displacement shader uses messsage passing, must prepare but not execute
702 // the surface and atmosphere shaders
703 if (currentAttributes->surface != NULL) locals[ACCESSOR_SURFACE] = currentAttributes->surface->prepare(shaderStateMemory,varying,numVertices);
704 if (currentAttributes->atmosphere != NULL) locals[ACCESSOR_ATMOSPHERE] = currentAttributes->atmosphere->prepare(shaderStateMemory,varying,numVertices);
705 }
706 }
707
708
709 // We do not prepare interior or exterior as these are limited to passing default values (no outputs, they don't recieve pl variables)
710
711 // If we need derivative information, treat differently
712 if ((usedParameters & PARAMETER_DERIVATIVE) && (dim != SHADING_0D)) { // Notice: we can not differentiate a 0 dimentional point set
713
714 if (dim == SHADING_2D) { // We're raytracing, so the derivative computation is different
715 const int numRealVertices = numVertices;
716 numVertices *= 3; // For the extra derivative vertices
717 currentShadingState->numVertices = numVertices;
718 currentShadingState->numRealVertices = numRealVertices;
719 currentShadingState->shadingDim = SHADING_2D;
720 currentShadingState->numActive = numVertices;
721 currentShadingState->numPassive = 0;
722
723 // Sample the object at the main intersection points
724 usedParameters |= PARAMETER_DPDU | PARAMETER_DPDV | PARAMETER_P;
725 const unsigned int shadingParameters = usedParameters;
726 object->sample(0,numRealVertices,varying,locals,usedParameters);
727 usedParameters = shadingParameters; // Restore the required parameters for the second round of shading
728
729 float *dPdu = varying[VARIABLE_DPDU];
730 float *dPdv = varying[VARIABLE_DPDV];
731 float *du = varying[VARIABLE_DU];
732 float *dv = varying[VARIABLE_DV];
733 float *u = varying[VARIABLE_U];
734 float *v = varying[VARIABLE_V];
735 float *time = varying[VARIABLE_TIME];
736 float *I = varying[VARIABLE_I];
737 int j;
738
739 // Compute du/dv
740 for (i=0,j=numRealVertices;i<numRealVertices;i++,I+=3,dPdu+=3,dPdv+=3) {
741 const float lengthu = dotvv(dPdu,dPdu);
742 const float lengthv = dotvv(dPdv,dPdv);
743 const float lengthi = dotvv(I,I);
744
745 float ku = dotvv(I,dPdu); ku = isqrtf((lengthu*lengthi - (ku*ku)) / (lengthu*lengthi + C_EPSILON));
746 float kv = dotvv(I,dPdv); kv = isqrtf((lengthv*lengthi - (kv*kv)) / (lengthv*lengthi + C_EPSILON));
747
748 const float dest = du[i]; // The ray crosssection at the intersection
749 // Note: we are clamping the maximal du dv because otherwise the surface
750 // sampling becomes grossly inaccurate, and in recursive raytracing, db
751 // grows unboundedly, causing inf and nan, and messing up filtering
752 // These are the 0-1 patch uvs, not the expanded range uvs, so this is OK.
753 const float dud = min(ku * dest * isqrtf(lengthu) + C_EPSILON,1.0f);
754 const float dvd = min(kv * dest * isqrtf(lengthv) + C_EPSILON,1.0f);
755
756 // Create one more shading point at (u + du,v)
757 u[j] = u[i] + dud;
758 v[j] = v[i];
759 time[j] = time[i];
760 movvv(varying[VARIABLE_I] + j*3,I);
761 du[i] = dud;
762 du[j] = dud;
763 dv[j] = dvd;
764 j++;
765
766 // Create one more shading point at (u,v + dv)
767 u[j] = u[i];
768 v[j] = v[i] + dvd;
769 time[j] = time[i];
770 movvv(varying[VARIABLE_I] + j*3,I);
771 dv[i] = dvd;
772 du[j] = dud;
773 dv[j] = dvd;
774 j++;
775 }
776
777 // Sample the object again, this time at the extra shading points
778 object->sample(numRealVertices,2*numRealVertices,varying,locals,usedParameters);
779
780 // Interpolate the various variables defined on the object
781 object->interpolate(numVertices,varying,locals);
782
783 } else {
784 // We're shading a regular grid, so take the shortcut while computing the surface derivatives
785 int i,j;
786 const float shadingRate = currentAttributes->shadingRate;
787
788 assert(dim == SHADING_2D_GRID);
789
790 currentShadingState->numRealVertices = numVertices;
791 currentShadingState->shadingDim = SHADING_2D_GRID;
792 currentShadingState->numActive = numVertices;
793 currentShadingState->numPassive = 0;
794
795 // First sample the object at the grid vertices
796 usedParameters |= PARAMETER_P;
797
798 // Sample the object
799 object->sample(0,numVertices,varying,locals,usedParameters);
800
801 // Interpolate the various variables defined on the object
802 object->interpolate(numVertices,varying,locals);
803
804 // We're rasterizing, so the derivative information is already available
805 memBegin(threadMemory);
806
807 // This array holds the projected xy pixel positions for the vertices
808 float *xy = (float *) ralloc(numVertices*2*sizeof(float),threadMemory);
809 const float *P = varying[VARIABLE_P];
810
811 // Project the grid vertices first
812 // PS: The offset is not important, so do not compute it
813 const float maxdPixeldxy = max(CRenderer::dPixeldx,CRenderer::dPixeldy);
814 const float dPixeldx = (currentAttributes->flags & ATTRIBUTES_FLAGS_NONRASTERORIENT_DICE) ? 1.0f : CRenderer::dPixeldx;
815 const float dPixeldy = (currentAttributes->flags & ATTRIBUTES_FLAGS_NONRASTERORIENT_DICE) ? 1.0f : CRenderer::dPixeldy;
816 if (CRenderer::projection == OPTIONS_PROJECTION_PERSPECTIVE) {
817 float *cXy = xy;
818
819 for (i=numVertices;i>0;i--) {
820 cXy[0] = (P[COMP_X] * CRenderer::imagePlane / P[COMP_Z])*dPixeldx;
821 cXy[1] = (P[COMP_Y] * CRenderer::imagePlane / P[COMP_Z])*dPixeldy;
822 cXy += 2;
823 P += 3;
824 }
825
826 // Compute the I
827 memcpy(varying[VARIABLE_I],varying[VARIABLE_P],numVertices*3*sizeof(float));
828 } else {
829 float *cXy = xy;
830
831 for (i=numVertices;i>0;i--) {
832 cXy[0] = P[COMP_X]*dPixeldx;
833 cXy[1] = P[COMP_Y]*dPixeldy;
834 cXy += 2;
835 P += 3;
836 }
837
838 // Compute the I
839 float *I = varying[VARIABLE_I];
840 P = varying[VARIABLE_P];
841 for (i=numVertices;i>0;i--,I+=3,P+=3) initv(I,0,0,P[COMP_Z]);
842 }
843
844 float *du = varying[VARIABLE_DU];
845 float *dv = varying[VARIABLE_DV];
846 const float *u = varying[VARIABLE_U];
847 const float *v = varying[VARIABLE_V];
848
849 #ifdef USE_EXTRAPOLATED_DERIV
850 #define extrapolateDerivU() \
851 if (uVertices > 3) { \
852 const float A = (cDU[-3] - cDU[-2])/((cU[-3]-cU[-2])*(cU[-3]-cU[-1])) - \
853 (cDU[-1] - cDU[-2])/((cU[-1]-cU[-2])*(cU[-3]-cU[-1])); \
854 const float B = (cDU[-1] - cDU[-2] + A*(cU[-2]*cU[-2] - cU[-1]*cU[-1])) / \
855 (cU[-1] - cU[-2]); \
856 const float C = (cDU[-1] - A*cU[-1]*cU[-1] - B*cU[-1]); \
857 d = A*cU[0]*cU[0] + B*cU[0] + C; \
858 }
859
860 #define extrapolateDerivV() \
861 if (vVertices > 3) { \
862 const float A = (cDV[-uVertices*3] - cDV[-uVertices*2])/((cV[-uVertices*3]-cV[-uVertices*2])*(cV[-uVertices*3]-cV[-uVertices*1])) - \
863 (cDV[-uVertices*1] - cDV[-uVertices*2])/((cV[-uVertices*1]-cV[-uVertices*2])*(cV[-uVertices*3]-cV[-uVertices*1])); \
864 const float B = (cDV[-uVertices*1] - cDV[-uVertices*2] + A*(cV[-uVertices*2]*cV[-uVertices*2] - cV[-uVertices*1]*cV[-uVertices*1])) / \
865 (cV[-uVertices*1] - cV[-uVertices*2]); \
866 const float C = (cDV[-uVertices*1] - A*cV[-uVertices*1]*cV[-uVertices*1] - B*cV[-uVertices*1]); \
867 d = A*cV[0]*cV[0] + B*cV[0] + C; \
868 }
869
870 #else
871 #define extrapolateDerivU()
872 #define extrapolateDerivV()
873 #endif
874
875 #define MAX_DIFFERENTIAL_DISCREPANCY 4*shadingRate
876
877 if (!(currentAttributes->flags & ATTRIBUTES_FLAGS_NONRASTERORIENT_DICE)) {
878 // Compute the du
879 for (i=0;i<vVertices;i++) {
880 const int tmp = i*uVertices;
881 float *cDU = du + tmp;
882 const float *cU = u + tmp;
883 float *cXy = xy + tmp*2;
884 float d = 0;
885
886 for (j=uVertices-1;j>0;j--) {
887 const float dx = cXy[2] - cXy[0];
888 const float dy = cXy[3] - cXy[1];
889 float cSr = shadingRate*isqrtf(dx*dx + dy*dy);
890 if (cSr > MAX_DIFFERENTIAL_DISCREPANCY) cSr = MAX_DIFFERENTIAL_DISCREPANCY;
891 d = cSr*(cU[1] - cU[0]);
892 d = min(d,1);
893 d = max(d,C_EPSILON);
894 assert(d > 0);
895 assert(d <= 1);
896 cDU[0] = d;
897 cDU += 1;
898 cU += 1;
899 cXy += 2;
900 }
901
902 extrapolateDerivU();
903
904 cDU[0] = d;
905 }
906
907 // Compute the dv,dPdv
908 for (i=0;i<uVertices;i++) {
909 float *cDV = dv + i;
910 const float *cV = v + i;
911 float *cXy = xy + i*2;
912 float d = 0;
913
914 for (j=0;j<vVertices-1;j++) {
915 const float dx = cXy[uVertices*2] - cXy[0];
916 const float dy = cXy[uVertices*2+1] - cXy[1];
917 float cSr = shadingRate*isqrtf(dx*dx + dy*dy);
918 if (cSr > MAX_DIFFERENTIAL_DISCREPANCY) cSr = MAX_DIFFERENTIAL_DISCREPANCY;
919 d = cSr*(cV[uVertices] - cV[0]);
920 d = max(d,C_EPSILON);
921 d = min(d,1);
922 assert(d > 0);
923 assert(d <= 1);
924 cDV[0] = d;
925 cDV += uVertices;
926 cV += uVertices;
927 cXy += uVertices*2;
928 }
929
930 extrapolateDerivV();
931
932 cDV[0] = d;
933 }
934
935 } else {
936 // Non raster orient
937 vector tmp1,tmp2;
938
939 // Compute the du
940 for (i=0;i<vVertices;i++) {
941 const int tmp = i*uVertices;
942 float *cDU = du + tmp;
943 const float *cU = u + tmp;
944 float *cXy = xy + tmp*2;
945 float d = 0;
946
947 P = varying[VARIABLE_P] + tmp*3;
948 for (j=uVertices-1;j>0;j--) {
949 initv(tmp1,cXy[2]-P[3],cXy[3]-P[4],P[5]-1);
950 initv(tmp2,cXy[0]-P[0],cXy[1]-P[1],P[2]-1);
951 const float dx = maxdPixeldxy*(cXy[2] - cXy[0]);
952 const float dy = maxdPixeldxy*(cXy[3] - cXy[1]);
953 const float dz = maxdPixeldxy*(lengthv(tmp1) - lengthv(tmp2));
954
955 float cSr = shadingRate*isqrtf(dx*dx + dy*dy + dz*dz);
956 if (cSr > MAX_DIFFERENTIAL_DISCREPANCY) cSr = MAX_DIFFERENTIAL_DISCREPANCY;
957 d = cSr*(cU[1] - cU[0]);
958 d = min(d,1);
959 d = max(d,C_EPSILON);
960 assert(d > 0);
961 assert(d <= 1);
962 cDU[0] = d;
963 cDU += 1;
964 cU += 1;
965 P += 3;
966 cXy += 2;
967 }
968
969 extrapolateDerivU();
970
971 cDU[0] = d;
972 }
973
974 // Compute the dv,dPdv
975 for (i=0;i<uVertices;i++) {
976 float *cDV = dv + i;
977 const float *cV = v + i;
978 float *cXy = xy + i*2;
979 float d = 0;
980
981 P = varying[VARIABLE_P] + i*3;
982 for (j=0;j<vVertices-1;j++) {
983 initv(tmp1,cXy[uVertices*2]-P[uVertices*3+0],cXy[uVertices*2+1]-P[uVertices*3+1],P[uVertices*3+2]-1);
984 initv(tmp2,cXy[0]-P[0],cXy[1]-P[1],P[2]-1);
985
986 const float dx = maxdPixeldxy*(cXy[uVertices*2] - cXy[0]);
987 const float dy = maxdPixeldxy*(cXy[uVertices*2+1] - cXy[1]);
988 const float dz = maxdPixeldxy*(lengthv(tmp1) - lengthv(tmp2));
989
990 float cSr = shadingRate*isqrtf(dx*dx + dy*dy + dz*dz);
991 if (cSr > MAX_DIFFERENTIAL_DISCREPANCY) cSr = MAX_DIFFERENTIAL_DISCREPANCY;
992 d = cSr*(cV[uVertices] - cV[0]);
993 d = max(d,C_EPSILON);
994 d = min(d,1);
995 assert(d > 0);
996 assert(d <= 1);
997 cDV[0] = d;
998 cDV += uVertices;
999 cV += uVertices;
1000 P += uVertices*3;
1001 cXy += uVertices*2;
1002 }
1003
1004 extrapolateDerivV();
1005
1006 cDV[0] = d;
1007 }
1008 }
1009
1010 #undef MAX_DIFFERENTIAL_DISCREPANCY
1011 #undef extrapolateDerivU
1012 #undef extrapolateDerivV
1013
1014 // Done and done
1015 memEnd(threadMemory);
1016 }
1017 } else {
1018 // No derivative information is needed
1019 currentShadingState->shadingDim = dim;
1020 currentShadingState->numRealVertices = numVertices;
1021 currentShadingState->numActive = numVertices;
1022 currentShadingState->numPassive = 0;
1023
1024 // Sample the object
1025 object->sample(0,numVertices,varying,locals,usedParameters);
1026
1027 // Interpolate the various variables defined on the object
1028 object->interpolate(numVertices,varying,locals);
1029
1030 // Compute the I
1031 if (currentRayDepth == 0) {
1032 if (CRenderer::projection == OPTIONS_PROJECTION_PERSPECTIVE) {
1033 memcpy(varying[VARIABLE_I],varying[VARIABLE_P],numVertices*3*sizeof(float));
1034 } else {
1035 float *I = varying[VARIABLE_I];
1036 const float *P = varying[VARIABLE_P];
1037 for (i=numVertices;i>0;i--,I+=3,P+=3) initv(I,0,0,P[COMP_Z]);
1038 }
1039 }
1040 }
1041
1042 // Clear the tags for shader execution
1043 memset(currentShadingState->tags,0,numVertices*sizeof(int));
1044
1045 // Fill in the uninitialized variables from the attributes
1046 if (currentAttributes->next != NULL) {
1047 complete(numVertices,varying,usedParameters,currentAttributes,currentAttributes->next);
1048 } else {
1049 complete(numVertices,varying,usedParameters,currentAttributes);
1050 }
1051
1052 // Save the memory here
1053 memBegin(threadMemory);
1054
1055 // Set up lighting here incase displacement shader uses lighting
1056
1057 // No lights are executed yet
1058 currentShadingState->lightsExecuted = FALSE;
1059 currentShadingState->ambientLightsExecuted = FALSE;
1060 currentShadingState->lightCategory = 0;
1061
1062 // Clear out previous lights etc
1063 currentShadingState->lights = NULL;
1064 currentShadingState->alights = NULL;
1065 currentShadingState->currentLight = NULL;
1066 currentShadingState->freeLights = NULL;
1067
1068 // Run the displacement shader here
1069 if (displacement != NULL) {
1070 displacement->execute(this,locals[ACCESSOR_DISPLACEMENT]);
1071 }
1072
1073 // Do we need to run the surface shader?
1074 if (displaceOnly == FALSE) {
1075
1076 // Is there a surface shader ?
1077 if (surface != NULL) {
1078 numShaded += numVertices;
1079 surface->execute(this,locals[ACCESSOR_SURFACE]);
1080 } else {
1081 // No surface shader eh, make up a color
1082
1083
1084 // Overwrite the colors if not specified by the primitives
1085 if (usedParameters & PARAMETER_CS) {
1086 const float *Cs = currentAttributes->surfaceColor;
1087 float *C = varying[VARIABLE_CI];
1088 for (i=numVertices;i>0;i--,C+=3) movvv(C,Cs);
1089 }
1090
1091 // Overwrite the opacity if not specified by the primitive
1092 if (usedParameters & PARAMETER_OS) {
1093 const float *Os = currentAttributes->surfaceOpacity;
1094 float *O = varying[VARIABLE_OI];
1095 for (i=numVertices;i>0;i--,O+=3) movvv(O,Os);
1096 }
1097
1098 // Get the variables
1099 float *C = varying[VARIABLE_CI];
1100 float *N = varying[VARIABLE_N];
1101 float *I = varying[VARIABLE_I];
1102
1103 // Do a simple dot product shading here
1104 for (i=numVertices;i>0;i--) {
1105 normalizevf(N);
1106 normalizevf(I);
1107
1108 mulvf(C,absf(dotvv(I,N)));
1109 C += 3;
1110 N += 3;
1111 I += 3;
1112 }
1113 }
1114
1115 // Is there an atmosphere shader ?
1116 if (atmosphere != NULL) {
1117
1118 // Do not execute atmosphere for non-camera rays
1119 if (currentRayDepth == 0) {
1120 atmosphere->execute(this,locals[ACCESSOR_ATMOSPHERE]);
1121 }
1122 }
1123
1124 // Is there an interior/exterior shader waiting to be executed?
1125 if (currentShadingState->postShader != NULL) {
1126 locals[ACCESSOR_POSTSHADER] = currentShadingState->postShader->prepare(shaderStateMemory,varying,numVertices);
1127 currentShadingState->postShader->execute(this,locals[ACCESSOR_POSTSHADER]);
1128 }
1129 }
1130
1131
1132 // Check if we should are a camera ray, and have primitive hit mode
1133 if ((dim == SHADING_2D_GRID) && (currentAttributes->cameraHitMode == 'p')) {
1134 // Yes, force opacity 1
1135 float *opacity = varying[VARIABLE_OI];
1136 const float *so = currentAttributes->surfaceOpacity;
1137 int i;
1138
1139 for (i=numVertices;i>0;i--,opacity+=3) movvv(opacity,so);
1140 }
1141
1142 // Restore the thread memory
1143 memEnd(threadMemory);
1144
1145 // Unwind the stack of shader states
1146 memEnd(shaderStateMemory);
1147
1148 // Restore the shaded object
1149 currentShadingState->currentObject = savedObject;
1150 }
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162 ///////////////////////////////////////////////////////////////////////
1163 // Class : CShadingContext
1164 // Method : newState
1165 // Description : Allocate a new shading state
1166 // Return Value : -
1167 // Comments :
1168 CShadingState *CShadingContext::newState() {
1169
1170 if (freeStates == NULL) {
1171 CShadingState *newState = new CShadingState;
1172 int j;
1173 float *E;
1174 const int numGlobalVariables = CRenderer::globalVariables->numItems;
1175 CVariable **globalVariables = CRenderer::globalVariables->array;
1176
1177 newState->varying = new float*[numGlobalVariables]; vertexMemory += numGlobalVariables*sizeof(float *);
1178 newState->tags = new int[CRenderer::maxGridSize*3]; vertexMemory += CRenderer::maxGridSize*3*sizeof(int);
1179 newState->lightingTags = new int[CRenderer::maxGridSize*3]; vertexMemory += CRenderer::maxGridSize*3*sizeof(int);
1180 newState->Ns = new float[CRenderer::maxGridSize*9]; vertexMemory += CRenderer::maxGridSize*9*sizeof(float);
1181 newState->alights = NULL;
1182 newState->freeLights = NULL;
1183 newState->postShader = NULL;
1184 newState->currentObject = NULL;
1185
1186 for (j=0;j<numGlobalVariables;j++) {
1187 const CVariable *var = globalVariables[j];
1188
1189 assert(var != NULL);
1190
1191 if ( (var->container == CONTAINER_UNIFORM) || (var->container == CONTAINER_CONSTANT) ) {
1192 if (var->type == TYPE_STRING) {
1193 newState->varying[j] = (float*) new char*[var->numFloats];
1194 vertexMemory += var->numFloats*sizeof(char*);
1195 } else {
1196 newState->varying[j] = new float[var->numFloats];
1197 vertexMemory += var->numFloats*sizeof(float);
1198 }
1199 } else {
1200 if (var->type == TYPE_STRING) {
1201 newState->varying[j] = (float*) new char*[var->numFloats*CRenderer::maxGridSize*3];
1202 vertexMemory += var->numFloats*CRenderer::maxGridSize*3*sizeof(char*);
1203 } else {
1204 newState->varying[j] = new float[var->numFloats*CRenderer::maxGridSize*3];
1205 vertexMemory += var->numFloats*CRenderer::maxGridSize*3*sizeof(float);
1206 }
1207 }
1208 }
1209
1210 // E is always (0,0,0)
1211 E = newState->varying[VARIABLE_E];
1212 for (j=CRenderer::maxGridSize*3;j>0;j--,E+=3) initv(E,0,0,0);
1213
1214 if (vertexMemory > peakVertexMemory) peakVertexMemory= vertexMemory;
1215
1216 newState->next = NULL;
1217 return newState;
1218 } else {
1219 CShadingState *newState = freeStates;
1220 freeStates = newState->next;
1221
1222 return newState;
1223 }
1224 }
1225
1226 ///////////////////////////////////////////////////////////////////////
1227 // Class : CShadingContext
1228 // Method : newState
1229 // Description : Allocate a new shading state
1230 // Return Value : -
1231 // Comments :
1232 void CShadingContext::deleteState(CShadingState *cState) {
1233 cState->next = freeStates;
1234 freeStates = cState;
1235 }
1236
1237
1238 ///////////////////////////////////////////////////////////////////////
1239 // Class : CShadingContext
1240 // Method : freeState
1241 // Description : Ditch a shading state
1242 // Return Value : -
1243 // Comments :
1244 void CShadingContext::freeState(CShadingState *cState) {
1245 int j;
1246 const int numGlobalVariables = CRenderer::globalVariables->numItems;
1247 CVariable **globalVariables = CRenderer::globalVariables->array;
1248
1249 for (j=0;j<numGlobalVariables;j++) {
1250 const CVariable *var = globalVariables[j];
1251
1252 if ( (var->container == CONTAINER_UNIFORM) || (var->container == CONTAINER_CONSTANT) ) {
1253 delete [] cState->varying[j];
1254 vertexMemory -= var->numFloats*sizeof(float);
1255 } else {
1256 delete [] cState->varying[j];
1257 vertexMemory -= var->numFloats*CRenderer::maxGridSize*3*sizeof(float);
1258 }
1259 }
1260
1261 delete [] cState->varying; vertexMemory -= numGlobalVariables*sizeof(float *);
1262 delete [] cState->tags; vertexMemory -= CRenderer::maxGridSize*3*sizeof(int);
1263 delete [] cState->lightingTags; vertexMemory -= CRenderer::maxGridSize*3*sizeof(int);
1264 delete [] cState->Ns; vertexMemory -= CRenderer::maxGridSize*9*sizeof(float);
1265
1266 delete cState;
1267 }
1268
1269
1270
1271
1272
1273
1274
1275 ///////////////////////////////////////////////////////////////////////
1276 // Class : CShadingContext
1277 // Method : variableUpdate
1278 // Description : This function is called to signal that there has been
1279 // a modification on the set of active variables
1280 // Return Value : -
1281 // Comments :
1282 void CShadingContext::updateState() {
1283 CShadingState *cState;
1284
1285 // Ditch the shading states that have been allocated
1286 while ((cState=freeStates) != NULL) {
1287 freeStates = cState->next;
1288 freeState(cState);
1289 }
1290
1291 // Recreate
1292 if (currentShadingState != NULL) freeState(currentShadingState);
1293
1294 currentShadingState = NULL;
1295 currentShadingState = newState();
1296 }
1297
1298 ///////////////////////////////////////////////////////////////////////
1299 // Class : CShadingContext
1300 // Method : saveState
1301 // Description : Save the shading state so a nested tesselation
1302 // doesn't trash our variables
1303 // Return Value : an opaque shading state reference
1304 // Comments :
1305 void *CShadingContext::saveState() {
1306 CShadingState *savedState = currentShadingState;
1307 if (freeStates == NULL) freeStates = newState();
1308
1309 currentShadingState = freeStates;
1310 freeStates = currentShadingState->next;
1311
1312 return (void*) savedState;
1313 }
1314
1315 ///////////////////////////////////////////////////////////////////////
1316 // Class : CShadingContext
1317 // Method : restoreState
1318 // Description : Restore the shading state from a previous save
1319 // Return Value : -
1320 // Comments :
1321 void CShadingContext::restoreState(void *state) {
1322 CShadingState *savedState = (CShadingState*) state;
1323
1324 currentShadingState->next = freeStates;
1325 freeStates = currentShadingState;
1326
1327 currentShadingState = savedState;
1328 }
1329
1330
1331 ///////////////////////////////////////////////////////////////////////
1332 // Class : CShadingContext
1333 // Method : surfaceParameter
1334 // Description : Execute light sources
1335 // Return Value : -
1336 // Comments :
1337 int CShadingContext::surfaceParameter(void *dest,const char *name,CVariable **var,int *globalIndex) {
1338 const CAttributes *currentAttributes = currentShadingState->currentObject->attributes;
1339
1340 if (currentAttributes->surface != NULL)
1341 return currentAttributes->surface->getParameter(name,dest,var,globalIndex);
1342 return FALSE;
1343 }
1344
1345 ///////////////////////////////////////////////////////////////////////
1346 // Class : CShadingContext
1347 // Method : displacementParameter
1348 // Description : Execute light sources
1349 // Return Value : -
1350 // Comments :
1351 int CShadingContext::displacementParameter(void *dest,const char *name,CVariable **var,int *globalIndex) {
1352 const CAttributes *currentAttributes = currentShadingState->currentObject->attributes;
1353
1354 if (currentAttributes->displacement != NULL)
1355 return currentAttributes->displacement->getParameter(name,dest,var,globalIndex);
1356 return FALSE;
1357 }
1358
1359
1360 ///////////////////////////////////////////////////////////////////////
1361 // Class : CShadingContext
1362 // Method : atmosphereParameter
1363 // Description : Execute light sources
1364 // Return Value : -
1365 // Comments :
1366 int CShadingContext::atmosphereParameter(void *dest,const char *name,CVariable **var,int *globalIndex) {
1367 const CAttributes *currentAttributes = currentShadingState->currentObject->attributes;
1368
1369 if (currentAttributes->atmosphere != NULL)
1370 return currentAttributes->atmosphere->getParameter(name,dest,var,globalIndex);
1371 return FALSE;
1372 }
1373
1374 ///////////////////////////////////////////////////////////////////////
1375 // Class : CShadingContext
1376 // Method : incidentParameter
1377 // Description : Execute light sources
1378 // Return Value : -
1379 // Comments :
1380 int CShadingContext::incidentParameter(void *dest,const char *name,CVariable **var,int *globalIndex) {
1381 const CAttributes *currentAttributes = currentShadingState->currentObject->attributes;
1382
1383 if (currentAttributes->interior != NULL)
1384 return currentAttributes->interior->getParameter(name,dest,NULL,NULL); // skip mutable parameters
1385 return FALSE;
1386 }
1387
1388 ///////////////////////////////////////////////////////////////////////
1389 // Class : CShadingContext
1390 // Method : oppositeParameter
1391 // Description : Execute light sources
1392 // Return Value : -
1393 // Comments :
1394 int CShadingContext::oppositeParameter(void *dest,const char *name,CVariable **var,int *globalIndex) {
1395 const CAttributes *currentAttributes = currentShadingState->currentObject->attributes;
1396
1397 if (currentAttributes->exterior != NULL)
1398 return currentAttributes->exterior->getParameter(name,dest,NULL,NULL); // skip mutable parameters
1399 return FALSE;
1400 }
1401
1402 ///////////////////////////////////////////////////////////////////////
1403 // Class : CShadingContext
1404 // Method : options
1405 // Description : Execute light sources
1406 // Return Value : -
1407 // Comments :
1408 int CShadingContext::options(void *dest,const char *name,CVariable **,int *) {
1409 if (strcmp(name,optionsFormat) == 0) {
1410 float *d = (float *) dest;
1411 d[0] = (float) CRenderer::xres;
1412 d[1] = (float) CRenderer::yres;
1413 d[2] = (float) 1;
1414 return TRUE;
1415 } else if (strcmp(name,optionsDeviceFrame) == 0) {
1416 float *d = (float *) dest;
1417 d[0] = (float) CRenderer::frame;
1418 return TRUE;
1419 } else if (strcmp(name,optionsDeviceResolution) == 0) {
1420 float *d = (float *) dest;
1421 d[0] = (float) CRenderer::xres;
1422 d[1] = (float) CRenderer::yres;
1423 d[2] = (float) 1;
1424 return TRUE;
1425 } else if (strcmp(name,optionsFrameAspectRatio) == 0) {
1426 float *d = (float *) dest;
1427 d[0] = (float) CRenderer::frameAR;
1428 return TRUE;
1429 } else if (strcmp(name,optionsCropWindow) == 0) {
1430 float *d = (float *) dest;
1431 d[0] = (float) CRenderer::cropLeft;
1432 d[1] = (float) CRenderer::cropTop;
1433 d[2] = (float) CRenderer::cropRight;
1434 d[3] = (float) CRenderer::cropBottom;
1435 return TRUE;
1436 } else if (strcmp(name,optionsDepthOfField) == 0) {
1437 float *d = (float *) dest;
1438 d[0] = (float) CRenderer::fstop;
1439 d[1] = (float) CRenderer::focallength;
1440 d[2] = (float) CRenderer::focaldistance;
1441 return TRUE;
1442 } else if (strcmp(name,optionsShutter) == 0) {
1443 float *d = (float *) dest;
1444 d[0] = (float) CRenderer::shutterOpen;
1445 d[1] = (float) CRenderer::shutterClose;
1446 return TRUE;
1447 } else if (strcmp(name,optionsClipping) == 0) {
1448 float *d = (float *) dest;
1449 d[0] = (float) CRenderer::clipMin;
1450 d[1] = (float) CRenderer::clipMax;
1451 return TRUE;
1452 } else if (strcmp(name,optionsBucketSize) == 0) {
1453 float *d = (float *) dest;
1454 d[0] = (float) CRenderer::bucketWidth;
1455 d[1] = (float) CRenderer::bucketHeight;
1456 return TRUE;
1457 } else if (strcmp(name,optionsColorQuantizer) == 0) {
1458 float *d = (float *) dest;
1459 d[0] = (float) CRenderer::colorQuantizer[0];
1460 d[1] = (float) CRenderer::colorQuantizer[1];
1461 d[2] = (float) CRenderer::colorQuantizer[2];
1462 d[3] = (float) CRenderer::colorQuantizer[3];
1463 return TRUE;
1464 } else if (strcmp(name,optionsDepthQuantizer) == 0) {
1465 float *d = (float *) dest;
1466 d[0] = (float) CRenderer::depthQuantizer[0];
1467 d[1] = (float) CRenderer::depthQuantizer[1];
1468 d[2] = (float) CRenderer::depthQuantizer[2];
1469 d[3] = (float) CRenderer::depthQuantizer[3];
1470 return TRUE;
1471 } else if (strcmp(name,optionsPixelFilter) == 0) {
1472 float *d = (float *) dest;
1473 d[0] = (float) CRenderer::pixelFilterWidth;
1474 d[1] = (float) CRenderer::pixelFilterHeight;
1475 return TRUE;
1476 } else if (strcmp(name,optionsGamma) == 0) {
1477 float *d = (float *) dest;
1478 d[0] = (float) CRenderer::gamma;
1479 d[1] = (float) CRenderer::gain;
1480 return TRUE;
1481 } else if (strcmp(name,optionsMaxRayDepth) == 0) {
1482 float *d = (float *) dest;
1483 d[0] = (float) CRenderer::maxRayDepth;
1484 return TRUE;
1485 } else if (strcmp(name,optionsRelativeDetail) == 0) {
1486 float *d = (float *) dest;
1487 d[0] = (float) CRenderer::relativeDetail;
1488 return TRUE;
1489 } else if (strcmp(name,optionsPixelSamples) == 0) {
1490 float *d = (float *) dest;
1491 d[0] = (float) CRenderer::pixelXsamples;
1492 d[1] = (float) CRenderer::pixelYsamples;
1493 return TRUE;
1494 }
1495 // User options
1496 else if (strncmp(name,attributesUser,strlen(attributesUser)) == 0) {
1497 CVariable *var;
1498
1499 if (CRenderer::userOptions->lookup(name+strlen(attributesUser),var) == TRUE) {
1500 if (var->type == TYPE_STRING) {
1501 char **d = (char **) dest;
1502 char **s = (char **) var->defaultValue;
1503 for (int i=0;i<var->numFloats;i++) {
1504 d[i] = s[i];
1505 }
1506 } else {
1507 float *d = (float *) dest;
1508 memcpy(d,var->defaultValue,sizeof(float)*var->numFloats);
1509 }
1510 return TRUE;
1511 }
1512 }
1513
1514 return FALSE;
1515 }
1516
1517 ///////////////////////////////////////////////////////////////////////
1518 // Class : CShadingContext
1519 // Method : attributes
1520 // Description : Execute light sources
1521 // Return Value : -
1522 // Comments :
1523 int CShadingContext::attributes(void *dest,const char *name,CVariable **,int *) {
1524 const CAttributes *currentAttributes = currentShadingState->currentObject->attributes;
1525
1526 if (strcmp(name,attributesShadingRate) == 0) {
1527 float *d = (float *) dest;
1528 d[0] = (float) currentAttributes->shadingRate;
1529 return TRUE;
1530 } else if (strcmp(name,attributesSides) == 0) {
1531 float *d = (float *) dest;
1532 d[0] = (float) (currentAttributes->flags & ATTRIBUTES_FLAGS_DOUBLE_SIDED ? 2 : 1);
1533 return TRUE;
1534 } else if (strcmp(name,attributesMatte) == 0) {
1535 float *d = (float *) dest;
1536 d[0] = (float) ((currentAttributes->flags & ATTRIBUTES_FLAGS_MATTE) != 0);
1537 return TRUE;
1538 } else if (strcmp(name,attributesMotionfactor) == 0) {
1539 float *d = (float *) dest;
1540 d[0] = (float) currentAttributes->motionFactor;
1541 return TRUE;
1542 } else if (strcmp(name,attributesDisplacementBnd) == 0) {
1543 float *d = (float *) dest;
1544 d[0] = (float) currentAttributes->maxDisplacement;
1545 return TRUE;
1546 } else if (strcmp(name,attributesDisplacementSys) == 0) {
1547 char **d = (char **) dest;
1548 d[0] = currentAttributes->maxDisplacementSpace;
1549 return TRUE;
1550 } else if (strcmp(name,attributesName) == 0) {
1551 char **d = (char **) dest;
1552 d[0] = currentAttributes->name;
1553 return TRUE;
1554 }
1555 // Additional attributes
1556 else if (strcmp(name,attributesTraceBias) == 0) {
1557 float *d = (float *) dest;
1558 d[0] = (float) currentAttributes->bias;
1559 return TRUE;
1560 } else if (strcmp(name,attributesTraceMaxDiffuse) == 0) {
1561 float *d = (float *) dest;
1562 d[0] = (float) currentAttributes->maxDiffuseDepth;
1563 return TRUE;
1564 } else if (strcmp(name,attributesTraceMaxSpecular) == 0) {
1565 float *d = (float *) dest;
1566 d[0] = (float) currentAttributes->maxSpecularDepth;
1567 return TRUE;
1568 }
1569 // User attributes
1570 else if (strncmp(name,attributesUser,strlen(attributesUser)) == 0) {
1571 CVariable *var;
1572
1573 if (currentAttributes->userAttributes.lookup(name+strlen(attributesUser),var) == TRUE) {
1574 if (var->type == TYPE_STRING) {
1575 char **d = (char **) dest;
1576 char **s = (char **) var->defaultValue;
1577 for (int i=0;i<var->numFloats;i++) {
1578 d[i] = s[i];
1579 }
1580 } else {
1581 float *d = (float *) dest;
1582 memcpy(d,var->defaultValue,sizeof(float)*var->numFloats);
1583 }
1584 return TRUE;
1585 }
1586 }
1587
1588 return FALSE;
1589 }
1590
1591
1592 ///////////////////////////////////////////////////////////////////////
1593 // Class : CShadingContext
1594 // Method : rendererInfo
1595 // Description : Execute light sources
1596 // Return Value : -
1597 // Comments :
1598 int CShadingContext::rendererInfo(void *dest,const char *name,CVariable **,int *) {
1599
1600 if (strcmp(name,rendererinfoRenderer) == 0) {
1601 char **d = (char **) dest;
1602 d[0] = (char *) "Pixie";
1603 return TRUE;
1604 } else if (strcmp(name,rendererinfoVersion) == 0) {
1605 float *d = (float *) dest;
1606 d[0] = (float) VERSION_RELEASE;
1607 d[1] = (float) VERSION_BETA;
1608 d[2] = (float) VERSION_ALPHA;
1609 d[3] = (float) 0;
1610 return TRUE;
1611 }
1612
1613 return FALSE;
1614 }
1615
1616 ///////////////////////////////////////////////////////////////////////
1617 // Class : CShadingContext
1618 // Method : shaderName
1619 // Description : Get the name of the shader
1620 // Return Value : -
1621 // Comments :
1622 const char *CShadingContext::shaderName() {
1623 assert(currentShadingState->currentShaderInstance != NULL);
1624
1625 return currentShadingState->currentShaderInstance->getName();
1626 }
1627
1628 ///////////////////////////////////////////////////////////////////////
1629 // Class : CShadingContext
1630 // Method : shaderName
1631 // Description : Get the name of a particular shader
1632 // Return Value : -
1633 // Comments :
1634 const char *CShadingContext::shaderName(const char *type) {
1635 CAttributes *currentAttributes = currentShadingState->currentObject->attributes;
1636
1637 if (strcmp(type,"surface") == 0) {
1638 if (currentAttributes->surface != NULL)
1639 return currentAttributes->surface->getName();
1640 } else if (strcmp(type,"displacement") == 0) {
1641 if (currentAttributes->displacement != NULL)
1642 return currentAttributes->displacement->getName();
1643 } else if (strcmp(type,"atmosphere") == 0) {
1644 if (currentAttributes->atmosphere != NULL)
1645 return currentAttributes->atmosphere->getName();
1646 } else if (strcmp(type,"interior") == 0) {
1647 if (currentAttributes->interior != NULL)
1648 return currentAttributes->interior->getName();
1649 } else if (strcmp(type,"exterior") == 0) {
1650 if (currentAttributes->exterior != NULL)
1651 return currentAttributes->exterior->getName();
1652 } else if (strcmp(type,"lightsource") == 0) {
1653 if (currentShadingState->currentLight != NULL)
1654 return currentShadingState->currentLight->instance->getName();
1655 }
1656 return "";
1657 }
1658
1659
1660 ///////////////////////////////////////////////////////////////////////
1661 // Class : CShadingContext
1662 // Method : findCoordinateSystem
1663 // Description : Locate a coordinate system
1664 // Return Value : -
1665 // Comments : Sometimes we just don't care about what system it is
1666 void CShadingContext::findCoordinateSystem(const char *name,const float *&from,const float *&to) {
1667 ECoordinateSystem dummy;
1668
1669 findCoordinateSystem(name,from,to,dummy);
1670 }
1671
1672 ///////////////////////////////////////////////////////////////////////
1673 // Class : CShadingContext
1674 // Method : findCoordinateSystem
1675 // Description : Locate a coordinate system
1676 // Return Value : -
1677 // Comments :
1678 void CShadingContext::findCoordinateSystem(const char *name,const float *&from,const float *&to,ECoordinateSystem &cSystem) {
1679 CNamedCoordinateSystem *currentSystem;
1680
1681 if(CRenderer::definedCoordinateSystems->find(name,currentSystem)) {
1682 from = currentSystem->from;
1683 to = currentSystem->to;
1684 cSystem = currentSystem->systemType;
1685
1686 switch(currentSystem->systemType) {
1687 case COORDINATE_OBJECT:
1688 if (currentShadingState->currentObject == NULL) {
1689 error(CODE_SYSTEM,"Object system reference without an object\n");
1690 from = identityMatrix;
1691 to = identityMatrix;
1692 } else {
1693 from = currentShadingState->currentObject->xform->from;
1694 to = currentShadingState->currentObject->xform->to;
1695 }
1696 break;
1697 case COORDINATE_CAMERA:
1698 from = identityMatrix;
1699 to = identityMatrix;
1700 break;
1701 case COORDINATE_WORLD:
1702 from = CRenderer::fromWorld;
1703 to = CRenderer::toWorld;
1704 break;
1705 case COORDINATE_SHADER:
1706 assert(currentShadingState->currentShaderInstance != NULL);
1707
1708 from = currentShadingState->currentShaderInstance->xform->from;
1709 to = currentShadingState->currentShaderInstance->xform->to;
1710 break;
1711 case COORDINATE_LIGHT:
1712 assert(currentShadingState->currentLightInstance != NULL);
1713
1714 from = currentShadingState->currentLightInstance->xform->from;
1715 to = currentShadingState->currentLightInstance->xform->to;
1716 break;
1717 case COORDINATE_NDC:
1718 from = CRenderer::fromNDC;
1719 to = CRenderer::toNDC;
1720 break;
1721 case COORDINATE_RASTER:
1722 from = CRenderer::fromRaster;
1723 to = CRenderer::toRaster;
1724 break;
1725 case COORDINATE_SCREEN:
1726 from = CRenderer::fromScreen;
1727 to = CRenderer::toScreen;
1728 break;
1729 case COORDINATE_CURRENT:
1730 from = identityMatrix;
1731 to = identityMatrix;
1732 break;
1733 case COLOR_RGB:
1734 case COLOR_HSL:
1735 case COLOR_HSV:
1736 case COLOR_XYZ:
1737 case COLOR_CIE:
1738 case COLOR_YIQ:
1739 case COLOR_XYY:
1740 // Don't handle color, the custom must have been handled
1741 break;
1742 case COORDINATE_CUSTOM:
1743 // Don't handle color, the custom must have been handled
1744 from = currentSystem->from;
1745 to = currentSystem->to;
1746 break;
1747 default:
1748 warning(CODE_BUG,"Unknown coordinate system: %s\n",name);
1749 from = identityMatrix;
1750 to = identityMatrix;
1751 break;
1752 }
1753 } else {
1754 warning(CODE_BUG,"Unknown coordinate system: %s\n",name);
1755 from = identityMatrix;
1756 to = identityMatrix;
1757 }
1758 }
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769 //Period parameters
1770 #define N 624
1771 #define M 397
1772 #define MATRIX_A 0x9908b0dfUL //constant vector a
1773 #define UMASK 0x80000000UL //most significant w-r bits
1774 #define LMASK 0x7fffffffUL //least significant r bits
1775 #define MIXBITS(u,v) ( ((u) & UMASK) | ((v) & LMASK) )
1776 #define TWIST(u,v) ((MIXBITS(u,v) >> 1) ^ (_uTable[v & 1UL] ))
1777
1778
1779 ///////////////////////////////////////////////////////////////////////
1780 // Class : CShadingContext
1781 // Method : randomInit
1782 // Description : Init the random number generator
1783 // Return Value : -
1784 // Comments :
1785 void CShadingContext::randomInit(uint32_t s) {
1786 int j;
1787 state[0]= s & 0xffffffffUL;
1788 for (j=1; j<N; j++) {
1789 state[j] = (1812433253UL * (state[j-1] ^ (state[j-1] >> 30)) + j);
1790 state[j] &= 0xffffffffUL; /* for >32 bit machines */
1791 }
1792 next = state;
1793 return;
1794 }
1795
1796 ///////////////////////////////////////////////////////////////////////
1797 // Class : CShadingContext
1798 // Method : randomShutdown
1799 // Description : Shutdown the random number generator
1800 // Return Value : -
1801 // Comments :
1802 void CShadingContext::randomShutdown() {
1803 }
1804
1805 ///////////////////////////////////////////////////////////////////////
1806 // Class : CShadingContext
1807 // Method : next_state
1808 // Description : Get the next stage for the random number generator
1809 // Return Value : -
1810 // Comments :
1811 void CShadingContext::next_state() {
1812 static const uint32_t _uTable[2] = { 0UL, MATRIX_A };
1813 register signed int j;
1814
1815 register uint32_t *p0;
1816 register uint32_t *p1;
1817
1818 j = ( N-M ) >> 1;
1819 p0 = state;
1820 p1 = p0 + 1;
1821 while(j) {
1822 --j;
1823 *p0 = TWIST( *p0, *p1 );
1824 *p0 ^= p0[M];
1825 ++p1;
1826 ++p0;
1827
1828 *p0 = TWIST( *p0, *p1 );
1829 *p0 ^= p0[M];
1830 ++p1;
1831 ++p0;
1832 }
1833
1834 *p0 = TWIST( *p0, *p1);
1835 *p0 ^= p0[M];
1836 ++p1;
1837 ++p0;
1838
1839 j = (M-1) >> 1;
1840 while( j ) {
1841 --j;
1842 *p0 = TWIST( *p0, *p1 );
1843 *p0 ^= p0[M-N];
1844 ++p1;
1845 ++p0;
1846
1847 *p0 = TWIST( *p0, *p1 );
1848 *p0 ^= p0[M-N];
1849 ++p1;
1850 ++p0;
1851 }
1852 *p0 = TWIST( *p0, *state );
1853 *p0 ^= p0[M-N];
1854
1855 next = state + N;
1856 return;
1857 }
1858
1859