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