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 // This is the portion of Pixie that draws a quad into the stochastic
26 
27 ///////////////////////////////////////////////////////////////////////////////////////////
28 //
29 //   Here're some macros that make the rasterization job easier for us
30 //
31 ///////////////////////////////////////////////////////////////////////////////////////////
32 
33 
34 // Shade _very_ early if we know we are guaranteed to have to anyway
35 // This also solves issues with grids viewed exactly side-on never
36 // being shaded when baking
37 // Note: we retain the pre-rasterization method for the case where RASTER_SHADE_HIDDEN
38 // is not set, and for the cases where 1 sidedness must be respected
39 
40 #ifdef STOCHASTIC_UNSHADED
41 #ifdef STOCHASTIC_UNDERCULL
42 	const	int	_flags = grid->flags;
43 	if ((_flags & RASTER_SHADE_HIDDEN) &&
44 		(_flags & (RASTER_DRAW_FRONT | RASTER_SHADE_BACKFACE)) &&
45 		(_flags & (RASTER_DRAW_BACK | RASTER_SHADE_BACKFACE))) {
46 
47 		shadeGrid(grid,FALSE);
48 		rasterDrawPrimitives(grid);
49 		return;
50 	}
51 #endif
52 #endif
53 
54 #ifdef STOCHASTIC_EXTRA_SAMPLES
55 	const int displacement	=	10 + CRenderer::numExtraSamples;
56 #else
57 	#define	displacement	10
58 #endif
59 
60 ///////////////////////////////////////////////////////////////////////////////////////////
61 //  This macro checks the pixel LOD against the object LOD level
62 #ifdef STOCHASTIC_LOD
63 	const float importance = grid->object->attributes->lodImportance;
64 
65 	#define lodCheck()																			\
66 		if (importance >= 0) {																	\
67 			if (pixel->jimp > importance)		continue;										\
68 		} else {																				\
69 			if ((1-pixel->jimp) >= -importance)	continue;										\
70 		}
71 
72 #else
73 	#define lodCheck()
74 #endif
75 
76 
77 
78 
79 //////////////////////////////////////////////////////////////////////////////////////////
80 // The following macro is used to draw extra samples for each pixels if any
81 #ifdef STOCHASTIC_EXTRA_SAMPLES
82 #ifdef STOCHASTIC_MOVING
83 
84 // We have motion blur, interpolate in time as well as space
85 #define	drawExtraSamples()	{																\
86 	int				currentSample;															\
87 	const	float	*s0	=	v0+10;															\
88 	const	float	*s1	=	v1+10;															\
89 	const	float	*s2	=	v2+10;															\
90 	const	float	*s3	=	v3+10;															\
91 	float			*dest;																	\
92 																							\
93 	for (dest=nSample->extraSamples,currentSample=CRenderer::numExtraSamples;currentSample>0;currentSample--,s0++,s1++,s2++,s3++) {		\
94 		*dest++	=	((s0[0]*(1-jt)+s0[displacement]*jt)*(1-u) + (s1[0]*(1-jt)+s1[displacement]*jt)*u)*(1-v)	+	\
95 					((s2[0]*(1-jt)+s2[displacement]*jt)*(1-u) + (s3[0]*(1-jt)+s3[displacement]*jt)*u)*v;		\
96 	}																						\
97 }
98 
99 #else
100 
101 // No motion blur, interpolate in space only
102 #define	drawExtraSamples()	{																\
103 	int				currentSample;															\
104 	const	float	*s0	=	v0+10;															\
105 	const	float	*s1	=	v1+10;															\
106 	const	float	*s2	=	v2+10;															\
107 	const	float	*s3	=	v2+10;															\
108 	float			*dest;																	\
109 																							\
110 	for (dest=nSample->extraSamples,currentSample=CRenderer::numExtraSamples;currentSample>0;currentSample--) {	\
111 		*dest++	=	((*s0++)*(1-u) + (*s1++)*u)*(1-v) + ((*s2++)*(1-u) + (*s3++)*u)*v;		\
112 	}																						\
113 }
114 
115 #endif
116 
117 #else
118 #define	drawExtraSamples()
119 #endif
120 
121 
122 
123 
124 
125 
126 //////////////////////////////////////////////////////////////////////////////////////////
127 // This big ass macro is for computing the final color/opacity of a pixel
128 #ifdef STOCHASTIC_MOVING
129 #ifdef STOCHASTIC_TRANSPARENT
130 
131 // M T
132 #ifndef STOCHASTIC_MATTE
133 
134 	#define colorOpacityUpdate()																\
135 		const float	*v0c		=	v0+3;														\
136 		const float	*v1c		=	v1+3;														\
137 		const float	*v2c		=	v2+3;														\
138 		const float	*v3c		=	v3+3;														\
139 		nSample->color[0]		=	((v0c[0]*(1-jt) + v0c[displacement+0]*jt)*(1-u) + (v1c[0]*(1-jt) + v1c[displacement+0]*jt)*u)*(1-v) + ((v2c[0]*(1-jt) + v2c[displacement+0]*jt)*(1-u) + (v3c[0]*(1-jt) + v3c[displacement+0]*jt)*u)*v;	\
140 		v0c++;	v1c++;	v2c++;	v3c++;															\
141 		nSample->color[1]		=	((v0c[0]*(1-jt) + v0c[displacement+0]*jt)*(1-u) + (v1c[0]*(1-jt) + v1c[displacement+0]*jt)*u)*(1-v) + ((v2c[0]*(1-jt) + v2c[displacement+0]*jt)*(1-u) + (v3c[0]*(1-jt) + v3c[displacement+0]*jt)*u)*v;	\
142 		v0c++;	v1c++;	v2c++;	v3c++;															\
143 		nSample->color[2]		=	((v0c[0]*(1-jt) + v0c[displacement+0]*jt)*(1-u) + (v1c[0]*(1-jt) + v1c[displacement+0]*jt)*u)*(1-v) + ((v2c[0]*(1-jt) + v2c[displacement+0]*jt)*(1-u) + (v3c[0]*(1-jt) + v3c[displacement+0]*jt)*u)*v;	\
144 		v0c++;	v1c++;	v2c++;	v3c++;															\
145 		nSample->opacity[0]		=	((v0c[0]*(1-jt) + v0c[displacement+0]*jt)*(1-u) + (v1c[0]*(1-jt) + v1c[displacement+0]*jt)*u)*(1-v) + ((v2c[0]*(1-jt) + v2c[displacement+0]*jt)*(1-u) + (v3c[0]*(1-jt) + v3c[displacement+0]*jt)*u)*v;	\
146 		v0c++;	v1c++;	v2c++;	v3c++;															\
147 		nSample->opacity[1]		=	((v0c[0]*(1-jt) + v0c[displacement+0]*jt)*(1-u) + (v1c[0]*(1-jt) + v1c[displacement+0]*jt)*u)*(1-v) + ((v2c[0]*(1-jt) + v2c[displacement+0]*jt)*(1-u) + (v3c[0]*(1-jt) + v3c[displacement+0]*jt)*u)*v;	\
148 		v0c++;	v1c++;	v2c++;	v3c++;															\
149 		nSample->opacity[2]		=	((v0c[0]*(1-jt) + v0c[displacement+0]*jt)*(1-u) + (v1c[0]*(1-jt) + v1c[displacement+0]*jt)*u)*(1-v) + ((v2c[0]*(1-jt) + v2c[displacement+0]*jt)*(1-u) + (v3c[0]*(1-jt) + v3c[displacement+0]*jt)*u)*v;
150 
151 #else
152 
153 	#define colorOpacityUpdate()																\
154 		initv(nSample->color,0);																\
155 		const float	*v0c		=	v0+6;														\
156 		const float	*v1c		=	v1+6;														\
157 		const float	*v2c		=	v2+6;														\
158 		const float	*v3c		=	v3+6;														\
159 		nSample->opacity[0]		=	-(((v0c[0]*(1-jt) + v0c[displacement+0]*jt)*(1-u) + (v1c[0]*(1-jt) + v1c[displacement+0]*jt)*u)*(1-v) + ((v2c[0]*(1-jt) + v2c[displacement+0]*jt)*(1-u) + (v3c[0]*(1-jt) + v3c[displacement+0]*jt)*u)*v);	\
160 		v0c++;	v1c++;	v2c++;	v3c++;															\
161 		nSample->opacity[1]		=	-(((v0c[0]*(1-jt) + v0c[displacement+0]*jt)*(1-u) + (v1c[0]*(1-jt) + v1c[displacement+0]*jt)*u)*(1-v) + ((v2c[0]*(1-jt) + v2c[displacement+0]*jt)*(1-u) + (v3c[0]*(1-jt) + v3c[displacement+0]*jt)*u)*v);	\
162 		v0c++;	v1c++;	v2c++;	v3c++;															\
163 		nSample->opacity[2]		=	-(((v0c[0]*(1-jt) + v0c[displacement+0]*jt)*(1-u) + (v1c[0]*(1-jt) + v1c[displacement+0]*jt)*u)*(1-v) + ((v2c[0]*(1-jt) + v2c[displacement+0]*jt)*(1-u) + (v3c[0]*(1-jt) + v3c[displacement+0]*jt)*u)*v);	\
164 		movvv(pixel->first.opacity,nSample->opacity);
165 
166 #endif
167 
168 #define	drawPixel() 																			\
169 	if (z < pixel->z) {																			\
170 		const	float	jt		=	pixel->jt;													\
171 		findSample(nSample,z);																	\
172 		nSample->z				=	z;															\
173 		colorOpacityUpdate();																	\
174 		drawExtraSamples();																		\
175 		updateTransparent(depthFilterIf,depthFilterElse);										\
176 	}
177 
178 #else
179 
180 // M, nT
181 #ifndef STOCHASTIC_MATTE
182 
183 	#define colorOpacityUpdate()																\
184 		const float	*v0c		=	v0+3;														\
185 		const float	*v1c		=	v1+3;														\
186 		const float	*v2c		=	v2+3;														\
187 		const float	*v3c		=	v3+3;														\
188 		nSample->color[0]		=	((v0c[0]*(1-jt) + v0c[displacement+0]*jt)*(1-u) + (v1c[0]*(1-jt) + v1c[displacement+0]*jt)*u)*(1-v) + ((v2c[0]*(1-jt) + v2c[displacement+0]*jt)*(1-u) + (v3c[0]*(1-jt) + v3c[displacement+0]*jt)*u)*v;	\
189 		v0c++;	v1c++;	v2c++;	v3c++;															\
190 		nSample->color[1]		=	((v0c[0]*(1-jt) + v0c[displacement+0]*jt)*(1-u) + (v1c[0]*(1-jt) + v1c[displacement+0]*jt)*u)*(1-v) + ((v2c[0]*(1-jt) + v2c[displacement+0]*jt)*(1-u) + (v3c[0]*(1-jt) + v3c[displacement+0]*jt)*u)*v;	\
191 		v0c++;	v1c++;	v2c++;	v3c++;															\
192 		nSample->color[2]		=	((v0c[0]*(1-jt) + v0c[displacement+0]*jt)*(1-u) + (v1c[0]*(1-jt) + v1c[displacement+0]*jt)*u)*(1-v) + ((v2c[0]*(1-jt) + v2c[displacement+0]*jt)*(1-u) + (v3c[0]*(1-jt) + v3c[displacement+0]*jt)*u)*v;	\
193 		nSample->opacity[0]		=	1;															\
194 		nSample->opacity[1]		=	1;															\
195 		nSample->opacity[2]		=	1;
196 
197 #else
198 
199 	#define colorOpacityUpdate()																\
200 		initv(nSample->color,0);																\
201 		initv(nSample->opacity,-1);																\
202 		movvv(pixel->first.opacity,nSample->opacity);
203 
204 #endif
205 
206 #define	drawPixel() 																			\
207 	if (z < pixel->z) {																			\
208 		const	float	jt		=	pixel->jt;													\
209 		updateOpaque();																			\
210 		nSample					=	&pixel->last;												\
211 		nSample->z				=	z;															\
212 		colorOpacityUpdate();																	\
213 		drawExtraSamples();																		\
214 		depthFilterIf();																		\
215 		pixel->z				=	z;															\
216 		depthFilterTouchNode();																	\
217 	} depthFilterElse();
218 
219 #endif
220 
221 #else
222 
223 #ifdef STOCHASTIC_TRANSPARENT
224 
225 
226 // nM, T
227 #ifndef STOCHASTIC_MATTE
228 
229 	#define colorOpacityUpdate()															\
230 		const float	*v0c		=	v0+3;													\
231 		const float	*v1c		=	v1+3;													\
232 		const float	*v2c		=	v2+3;													\
233 		const float	*v3c		=	v3+3;													\
234 		nSample->color[0]		=	(v0c[0]*(1-u) + v1c[0]*u)*(1-v) + (v2c[0]*(1-u) + v3c[0]*u)*v;	\
235 		nSample->color[1]		=	(v0c[1]*(1-u) + v1c[1]*u)*(1-v) + (v2c[1]*(1-u) + v3c[1]*u)*v;	\
236 		nSample->color[2]		=	(v0c[2]*(1-u) + v1c[2]*u)*(1-v) + (v2c[2]*(1-u) + v3c[2]*u)*v;	\
237 		nSample->opacity[0]		=	(v0c[3]*(1-u) + v1c[3]*u)*(1-v) + (v2c[3]*(1-u) + v3c[3]*u)*v;	\
238 		nSample->opacity[1]		=	(v0c[4]*(1-u) + v1c[4]*u)*(1-v) + (v2c[4]*(1-u) + v3c[4]*u)*v;	\
239 		nSample->opacity[2]		=	(v0c[5]*(1-u) + v1c[5]*u)*(1-v) + (v2c[5]*(1-u) + v3c[5]*u)*v;
240 
241 #else
242 
243 	#define colorOpacityUpdate()															\
244 		initv(nSample->color,0);															\
245 		const float	*v0c		=	v0+6;													\
246 		const float	*v1c		=	v1+6;													\
247 		const float	*v2c		=	v2+6;													\
248 		const float	*v3c		=	v3+6;													\
249 		nSample->opacity[0]		=	-((v0c[0]*(1-u) + v1c[0]*u)*(1-v) + (v2c[0]*(1-u) + v3c[0]*u)*v);	\
250 		nSample->opacity[1]		=	-((v0c[1]*(1-u) + v1c[1]*u)*(1-v) + (v2c[1]*(1-u) + v3c[1]*u)*v);	\
251 		nSample->opacity[2]		=	-((v0c[2]*(1-u) + v1c[2]*u)*(1-v) + (v2c[2]*(1-u) + v3c[2]*u)*v);	\
252 		movvv(pixel->first.opacity,nSample->opacity);
253 
254 #endif
255 
256 #define	drawPixel() 																		\
257 	if (z < pixel->z) {																		\
258 		findSample(nSample,z);																\
259 		nSample->z				=	z;														\
260 		colorOpacityUpdate();																\
261 		drawExtraSamples();																	\
262 		updateTransparent(depthFilterIf,depthFilterElse);									\
263 	}
264 
265 #else
266 
267 // nM, nT
268 #ifndef STOCHASTIC_MATTE
269 
270 	#define colorOpacityUpdate()															\
271 		const float	*v0c		=	v0+3;													\
272 		const float	*v1c		=	v1+3;													\
273 		const float	*v2c		=	v2+3;													\
274 		const float	*v3c		=	v3+3;													\
275 		nSample->color[0]		=	(v0c[0]*(1-u) + v1c[0]*u)*(1-v) + (v2c[0]*(1-u) + v3c[0]*u)*v;	\
276 		nSample->color[1]		=	(v0c[1]*(1-u) + v1c[1]*u)*(1-v) + (v2c[1]*(1-u) + v3c[1]*u)*v;	\
277 		nSample->color[2]		=	(v0c[2]*(1-u) + v1c[2]*u)*(1-v) + (v2c[2]*(1-u) + v3c[2]*u)*v;	\
278 		nSample->opacity[0]		=	1;														\
279 		nSample->opacity[1]		=	1;														\
280 		nSample->opacity[2]		=	1;
281 
282 #else
283 
284 	#define colorOpacityUpdate()															\
285 		initv(nSample->color,0);															\
286 		initv(nSample->opacity,-1);															\
287 		movvv(pixel->first.opacity,nSample->opacity);
288 
289 #endif
290 
291 #define	drawPixel()																			\
292 	if (z < pixel->z) {																		\
293 		updateOpaque();																		\
294 		nSample					=	&pixel->last;											\
295 		nSample->z				=	z;														\
296 		colorOpacityUpdate();																\
297 		drawExtraSamples();																	\
298 		depthFilterIf();																	\
299 		pixel->z				=	z;														\
300 		depthFilterTouchNode();																\
301 	} depthFilterElse();
302 
303 #endif
304 #endif
305 
306 
307 
308 
309 
310 //////////////////////////////////////////////////////////////////////////////////////////
311 // These macros decide whether we should draw a quad or not
312 #ifdef STOCHASTIC_UNDERCULL
313 #define shouldDrawFront()			(flags & (RASTER_DRAW_FRONT | RASTER_SHADE_BACKFACE))
314 #define shouldDrawBack()			(flags & (RASTER_DRAW_BACK  | RASTER_SHADE_BACKFACE))
315 #else
316 #define shouldDrawFront()			(flags & RASTER_DRAW_FRONT)
317 #define shouldDrawBack()			(flags & RASTER_DRAW_BACK)
318 #endif
319 
320 
321 
322 //////////////////////////////////////////////////////////////////////////////////////////
323 //This macro is the entry point that checks if the pixel passes a depth test and if we need
324 // to shade the grid or not
325 #ifdef STOCHASTIC_UNSHADED
326 // We're not shaded yet, so if we pass the depth test, we need to back and shade the grid
327 #ifdef STOCHASTIC_UNDERCULL
328 #define drawPixelCheck()															\
329 	if (z < pixel->z || (flags & RASTER_SHADE_HIDDEN)) {							\
330 		shadeGrid(grid,FALSE);														\
331 		rasterDrawPrimitives(grid);													\
332 		return;																		\
333 	} depthFilterElse();
334 #else
335 #define drawPixelCheck()															\
336 	if (z < pixel->z) {																\
337 		shadeGrid(grid,FALSE);														\
338 		rasterDrawPrimitives(grid);													\
339 		return;																		\
340 	} depthFilterElse();
341 
342 
343 #endif // undercull
344 #else
345 #define drawPixelCheck()															\
346 	CFragment *nSample;																\
347 	drawPixel();
348 #endif
349 
350 
351 
352 
353 //////////////////////////////////////////////////////////////////////////////////////////
354 // This macro is used to check whether the sample is inside the quad or not
355 #define	checkPixel(__op)																					\
356 	const float		xcent	=	pixel->xcent;																\
357 	const float		ycent	=	pixel->ycent;																\
358 	float			aleft,atop,aright,abottom;																\
359 																											\
360 	if ((atop		= area(xcent,ycent,v0[COMP_X],v0[COMP_Y],v1[COMP_X],v1[COMP_Y])) __op 0)	continue;	\
361 	if ((aright		= area(xcent,ycent,v1[COMP_X],v1[COMP_Y],v3[COMP_X],v3[COMP_Y])) __op 0)	continue;	\
362 	if ((abottom	= area(xcent,ycent,v3[COMP_X],v3[COMP_Y],v2[COMP_X],v2[COMP_Y])) __op 0)	continue;	\
363 	if ((aleft		= area(xcent,ycent,v2[COMP_X],v2[COMP_Y],v0[COMP_X],v0[COMP_Y])) __op 0)	continue;	\
364 																											\
365 	const float u	=	aleft / (aleft + aright);															\
366 	const float v	=	atop / (atop + abottom);															\
367 	const float	z	=	(v0[COMP_Z]*(1-u) + v1[COMP_Z]*u)*(1-v) + (v2[COMP_Z]*(1-u) + v3[COMP_Z]*u)*v;		\
368 	if (z < CRenderer::clipMin)	continue;
369 
370 
371 
372 ///////////////////////////////////////////////////////////////////////////////////////////
373 //
374 //   Here's the code that actually iterates over the quads and draws them
375 //
376 ///////////////////////////////////////////////////////////////////////////////////////////
377 
378 #ifdef STOCHASTIC_XTREME
379 
380 // Iterate over pixels, discarding quads
381 // --- Extreme motion blur/depth of field case
382 
383 
384 const int	xres		=	sampleWidth - 1;
385 const int	yres		=	sampleHeight - 1;
386 
387 int xmin				=	grid->xbound[0] - left;
388 int xmax				=	grid->xbound[1] - left;
389 int ymin				=	grid->ybound[0] - top;
390 int ymax				=	grid->ybound[1] - top;
391 
392 xmin					=	max(xmin,0);		// Clamp the bound in the current bucket
393 ymin					=	max(ymin,0);
394 xmax					=	min(xmax,xres);
395 ymax					=	min(ymax,yres);
396 
397 int	x,y;
398 for (y=ymin;y<=ymax;y++) for (x=xmin;x<=xmax;x++) {
399 	CPixel		*pixel		=	fb[y] + x;
400 	int			i,j;
401 
402 	const int	*bounds		=	grid->bounds;
403 
404 	const float	*vertices	=	grid->vertices;
405 	const	int	udiv		=	grid->udiv;
406 
407 	const	int	vdiv		=	grid->vdiv;
408 	const	int	flags		=	grid->flags;
409 
410 	for (j=0;j<vdiv;j++) {
411 		for (i=0;i<udiv;i++,bounds+=4,vertices+=numVertexSamples) {
412 
413 			if (x+left < bounds[0])		continue;
414 			if (x+left > bounds[1])		continue;
415 			if (y+top < bounds[2])		continue;
416 			if (y+top > bounds[3])		continue;
417 
418 			lodCheck();
419 
420 			const float	*v0	=	vertices;
421 			const float	*v1	=	vertices + numVertexSamples;
422 			const float	*v2	=	v1 + udiv*numVertexSamples;
423 			const float	*v3	=	v2 + numVertexSamples;
424 
425 #ifdef STOCHASTIC_FOCAL_BLUR
426 				const float v0d =	v0[9];
427 				const float v1d =	v1[9];
428 				const float v2d =	v2[9];
429 				const float v3d =	v3[9];
430 #endif
431 
432 #ifdef STOCHASTIC_MOVING
433 			vector	v0movTmp;
434 			vector	v1movTmp;
435 			vector	v2movTmp;
436 			vector	v3movTmp;
437 			interpolatev(v0movTmp,v0,v0+displacement,pixel->jt);
438 			interpolatev(v1movTmp,v1,v1+displacement,pixel->jt);
439 			interpolatev(v2movTmp,v2,v2+displacement,pixel->jt);
440 			interpolatev(v3movTmp,v3,v3+displacement,pixel->jt);
441 			v0		=	v0movTmp;
442 			v1		=	v1movTmp;
443 			v2		=	v2movTmp;
444 			v3		=	v3movTmp;
445 #endif
446 
447 
448 #ifdef STOCHASTIC_FOCAL_BLUR
449 			vector	v0focTmp;
450 			vector	v1focTmp;
451 			vector	v2focTmp;
452 			vector	v3focTmp;
453 			v0focTmp[COMP_X]	=	v0[COMP_X] + pixel->jdx*v0d;
454 			v1focTmp[COMP_X]	=	v1[COMP_X] + pixel->jdx*v1d;
455 			v2focTmp[COMP_X]	=	v2[COMP_X] + pixel->jdx*v2d;
456 			v3focTmp[COMP_X]	=	v3[COMP_X] + pixel->jdx*v3d;
457 
458 			v0focTmp[COMP_Y]	=	v0[COMP_Y] + pixel->jdy*v0d;
459 			v1focTmp[COMP_Y]	=	v1[COMP_Y] + pixel->jdy*v1d;
460 			v2focTmp[COMP_Y]	=	v2[COMP_Y] + pixel->jdy*v2d;
461 			v3focTmp[COMP_Y]	=	v3[COMP_Y] + pixel->jdy*v3d;
462 
463 			v0focTmp[COMP_Z]	=	v0[COMP_Z];
464 			v1focTmp[COMP_Z]	=	v1[COMP_Z];
465 			v2focTmp[COMP_Z]	=	v2[COMP_Z];
466 			v3focTmp[COMP_Z]	=	v3[COMP_Z];
467 
468 			v0					=	v0focTmp;
469 			v1					=	v1focTmp;
470 			v2					=	v2focTmp;
471 			v3					=	v3focTmp;
472 #endif
473 
474 			// Check the orientation of the quad
475 			float a	= area(v0[COMP_X],v0[COMP_Y],v1[COMP_X],v1[COMP_Y],v2[COMP_X],v2[COMP_Y]);
476 			if (fabsf(a) < C_EPSILON)  a = area(v1[COMP_X],v1[COMP_Y],v3[COMP_X],v3[COMP_Y],v2[COMP_X],v2[COMP_Y]);
477 			if (a > 0) {
478 
479 				// Back face culling
480 				if (!shouldDrawBack()) {
481 					continue;
482 				}
483 
484 				checkPixel(<);
485 
486 				v0	=	vertices;
487 				v1	=	v0 + numVertexSamples;
488 				v2	=	v1 + udiv*numVertexSamples;
489 				v3	=	v2 + numVertexSamples;
490 
491 				drawPixelCheck();
492 			} else {
493 
494 				// Back face culling
495 				if (!shouldDrawFront()) {
496 					continue;
497 				}
498 
499 				checkPixel(>);
500 
501 				v0	=	vertices;
502 				v1	=	v0 + numVertexSamples;
503 				v2	=	v1 + udiv*numVertexSamples;
504 				v3	=	v2 + numVertexSamples;
505 
506 				drawPixelCheck();
507 			}
508 		}
509 		vertices	+=	numVertexSamples;
510 	}
511 }
512 
513 #else
514 
515 // Iterate over quads, discarding pixels
516 // --- No (significant) motion blur/depth of field
517 
518 int			i,j;
519 const int	*bounds		=	grid->bounds;
520 const float	*vertices	=	grid->vertices;
521 const	int	xres		=	sampleWidth - 1;
522 const	int	yres		=	sampleHeight - 1;
523 const	int	udiv		=	grid->udiv;
524 const	int	vdiv		=	grid->vdiv;
525 const	int	flags		=	grid->flags;
526 
527 for (j=0;j<vdiv;j++) {
528 	for (i=0;i<udiv;i++,bounds+=4,vertices+=numVertexSamples) {
529 
530 		// Trivial rejects
531 		if (bounds[1] < left)		continue;
532 		if (bounds[3] < top)		continue;
533 		if (bounds[0] >= right)		continue;
534 		if (bounds[2] >= bottom)	continue;
535 
536 		// Extract the quad corners
537 		const float	*v0	=	vertices;
538 		const float	*v1	=	vertices + numVertexSamples;
539 		const float	*v2	=	v1 + udiv*numVertexSamples;
540 		const float	*v3	=	v2 + numVertexSamples;
541 
542 
543 		int	xmin	=	bounds[0] - left;	// Convert the bound into the current bucket
544 		int	ymin	=	bounds[2] - top;
545 		int	xmax	=	bounds[1] - left;
546 		int	ymax	=	bounds[3] - top;
547 
548 		xmin		=	max(xmin,0);		// Clamp the bound in the current bucket
549 		ymin		=	max(ymin,0);
550 		xmax		=	min(xmax,xres);
551 		ymax		=	min(ymax,yres);
552 
553 
554 		// Figure our if we have to do the slow rasterization
555 #ifdef STOCHASTIC_FOCAL_BLUR
556 	#define SLOW_RASTER
557 #endif
558 
559 #ifdef STOCHASTIC_MOVING
560 	#ifndef SLOW_RASTER
561 		#define SLOW_RASTER
562 	#endif
563 #endif
564 
565 
566 
567 
568 // SLOW_RENDER means the quad has motion blur or depth of field
569 // In such a case, we need to deform the quad individually for each
570 // sample which makes the rasterization slower
571 #ifndef SLOW_RASTER
572 
573 
574 		// Do the fast rasterization
575 
576 		// Check the orientation of the quad
577 		float a	= area(v0[COMP_X],v0[COMP_Y],v1[COMP_X],v1[COMP_Y],v2[COMP_X],v2[COMP_Y]);
578 		if (fabsf(a) < C_EPSILON)  a = area(v1[COMP_X],v1[COMP_Y],v3[COMP_X],v3[COMP_Y],v2[COMP_X],v2[COMP_Y]);
579 		if (a > 0) {
580 
581 			// Back face culling
582 			if (!shouldDrawBack()) {
583 				continue;
584 			}
585 
586 			// For each sample
587 			int		x,y;
588 			for (y=ymin;y<=ymax;y++) {
589 				CPixel	*pixel;
590 
591 				for (pixel=fb[y]+xmin,x=xmin;x<=xmax;x++,pixel++) {
592 
593 					lodCheck();
594 
595 					checkPixel(<);
596 
597 					drawPixelCheck();
598 				}
599 			}
600 		} else {
601 
602 			// Back face culling
603 			if (!shouldDrawFront()) {
604 				continue;
605 			}
606 
607 			int	x,y;
608 			for (y=ymin;y<=ymax;y++) {
609 				CPixel	*pixel;
610 
611 				for (pixel=fb[y]+xmin,x=xmin;x<=xmax;x++,pixel++) {
612 
613 					lodCheck();
614 
615 					checkPixel(>);
616 
617 					drawPixelCheck();
618 				}
619 			}
620 		}
621 
622 #else
623 
624 		// Do the slow rasterization
625 
626 		int	x,y;
627 		for (y=ymin;y<=ymax;y++) {
628 			CPixel		*pixel;
629 
630 			for (pixel=fb[y]+xmin,x=xmin;x<=xmax;x++,pixel++) {
631 
632 				lodCheck();
633 
634 				const float	*v0	=	vertices;
635 				const float	*v1	=	vertices + numVertexSamples;
636 				const float	*v2	=	v1 + udiv*numVertexSamples;
637 				const float	*v3	=	v2 + numVertexSamples;
638 
639 #ifdef STOCHASTIC_FOCAL_BLUR
640 				const float v0d =	v0[9];
641 				const float v1d =	v1[9];
642 				const float v2d =	v2[9];
643 				const float v3d =	v3[9];
644 #endif
645 
646 #ifdef STOCHASTIC_MOVING
647 				vector	v0movTmp;
648 				vector	v1movTmp;
649 				vector	v2movTmp;
650 				vector	v3movTmp;
651 				interpolatev(v0movTmp,v0,v0+displacement,pixel->jt);
652 				interpolatev(v1movTmp,v1,v1+displacement,pixel->jt);
653 				interpolatev(v2movTmp,v2,v2+displacement,pixel->jt);
654 				interpolatev(v3movTmp,v3,v3+displacement,pixel->jt);
655 				v0		=	v0movTmp;
656 				v1		=	v1movTmp;
657 				v2		=	v2movTmp;
658 				v3		=	v3movTmp;
659 #endif
660 
661 
662 #ifdef STOCHASTIC_FOCAL_BLUR
663 				vector	v0focTmp;
664 				vector	v1focTmp;
665 				vector	v2focTmp;
666 				vector	v3focTmp;
667 				v0focTmp[COMP_X]	=	v0[COMP_X] + pixel->jdx*v0d;
668 				v1focTmp[COMP_X]	=	v1[COMP_X] + pixel->jdx*v1d;
669 				v2focTmp[COMP_X]	=	v2[COMP_X] + pixel->jdx*v2d;
670 				v3focTmp[COMP_X]	=	v3[COMP_X] + pixel->jdx*v3d;
671 
672 				v0focTmp[COMP_Y]	=	v0[COMP_Y] + pixel->jdy*v0d;
673 				v1focTmp[COMP_Y]	=	v1[COMP_Y] + pixel->jdy*v1d;
674 				v2focTmp[COMP_Y]	=	v2[COMP_Y] + pixel->jdy*v2d;
675 				v3focTmp[COMP_Y]	=	v3[COMP_Y] + pixel->jdy*v3d;
676 
677 				v0focTmp[COMP_Z]	=	v0[COMP_Z];
678 				v1focTmp[COMP_Z]	=	v1[COMP_Z];
679 				v2focTmp[COMP_Z]	=	v2[COMP_Z];
680 				v3focTmp[COMP_Z]	=	v3[COMP_Z];
681 
682 				v0					=	v0focTmp;
683 				v1					=	v1focTmp;
684 				v2					=	v2focTmp;
685 				v3					=	v3focTmp;
686 #endif
687 
688 				// Check the orientation of the quad
689 				float a	= area(v0[COMP_X],v0[COMP_Y],v1[COMP_X],v1[COMP_Y],v2[COMP_X],v2[COMP_Y]);
690 				if (fabsf(a) < C_EPSILON)  a = area(v1[COMP_X],v1[COMP_Y],v3[COMP_X],v3[COMP_Y],v2[COMP_X],v2[COMP_Y]);
691 				if (a > 0) {
692 
693 
694 					// Back face culling
695 					if (!shouldDrawBack()) {
696 						continue;
697 					}
698 
699 					checkPixel(<);
700 
701 					v0	=	vertices;
702 					v1	=	v0 + numVertexSamples;
703 					v2	=	v1 + udiv*numVertexSamples;
704 					v3	=	v2 + numVertexSamples;
705 
706 					drawPixelCheck();
707 				} else {
708 
709 					// Back face culling
710 					if (!shouldDrawFront()) {
711 						continue;
712 					}
713 
714 					checkPixel(>);
715 
716 					v0	=	vertices;
717 					v1	=	v0 + numVertexSamples;
718 					v2	=	v1 + udiv*numVertexSamples;
719 					v3	=	v2 + numVertexSamples;
720 
721 					drawPixelCheck();
722 				}
723 			}
724 		}
725 
726 #endif
727 	}
728 
729 	vertices	+=	numVertexSamples;
730 }
731 
732 #endif
733 
734 
735 #undef SLOW_RASTER
736 #undef lodCheck
737 #undef drawPixelCheck
738 #undef drawPixel
739 #undef drawExtraSamples
740 #undef displacement
741 #undef colorOpacityUpdate
742 #undef shouldDrawFront
743 #undef shouldDrawBack
744 #undef checkPixel
745 
746 
747 
748 
749 
750 
751