|
Blender
V2.59
|
00001 /* 00002 * 00003 * ***** BEGIN GPL LICENSE BLOCK ***** 00004 * 00005 * This program is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU General Public License 00007 * as published by the Free Software Foundation; either version 2 00008 * of the License, or (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, write to the Free Software Foundation, 00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00018 * 00019 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00020 * All rights reserved. 00021 * 00022 * Contributor(s): 2004-2006, Blender Foundation, full recode 00023 * 00024 * ***** END GPL LICENSE BLOCK ***** 00025 */ 00026 00032 #include <float.h> 00033 #include <math.h> 00034 #include <string.h> 00035 00036 #include "BLI_math.h" 00037 #include "BLI_utildefines.h" 00038 00039 /* External modules: */ 00040 #include "IMB_imbuf_types.h" 00041 #include "IMB_imbuf.h" 00042 00043 #include "DNA_camera_types.h" 00044 #include "DNA_group_types.h" 00045 #include "DNA_material_types.h" 00046 #include "DNA_object_types.h" 00047 #include "DNA_image_types.h" 00048 #include "DNA_texture_types.h" 00049 #include "DNA_lamp_types.h" 00050 00051 #include "BKE_colortools.h" 00052 #include "BKE_image.h" 00053 #include "BKE_global.h" 00054 #include "BKE_material.h" 00055 #include "BKE_texture.h" 00056 00057 00058 /* own module */ 00059 #include "render_types.h" 00060 #include "renderpipeline.h" 00061 #include "renderdatabase.h" 00062 #include "texture.h" 00063 #include "pixelblending.h" 00064 #include "rendercore.h" 00065 #include "shadbuf.h" 00066 #include "pixelshading.h" 00067 #include "shading.h" 00068 #include "sunsky.h" 00069 00070 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 00071 /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */ 00072 /* only to be used here in this file, it's for speed */ 00073 extern struct Render R; 00074 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 00075 00076 00077 extern float hashvectf[]; 00078 00079 static void render_lighting_halo(HaloRen *har, float *colf) 00080 { 00081 GroupObject *go; 00082 LampRen *lar; 00083 float i, inp, inpr, rco[3], dco[3], lv[3], lampdist, ld, t, *vn; 00084 float ir, ig, ib, shadfac, soft, lacol[3]; 00085 00086 ir= ig= ib= 0.0; 00087 00088 VECCOPY(rco, har->co); 00089 dco[0]=dco[1]=dco[2]= 1.0/har->rad; 00090 00091 vn= har->no; 00092 00093 for(go=R.lights.first; go; go= go->next) { 00094 lar= go->lampren; 00095 00096 /* test for lamplayer */ 00097 if(lar->mode & LA_LAYER) if((lar->lay & har->lay)==0) continue; 00098 00099 /* lampdist cacluation */ 00100 if(lar->type==LA_SUN || lar->type==LA_HEMI) { 00101 VECCOPY(lv, lar->vec); 00102 lampdist= 1.0; 00103 } 00104 else { 00105 lv[0]= rco[0]-lar->co[0]; 00106 lv[1]= rco[1]-lar->co[1]; 00107 lv[2]= rco[2]-lar->co[2]; 00108 ld= sqrt(lv[0]*lv[0]+lv[1]*lv[1]+lv[2]*lv[2]); 00109 lv[0]/= ld; 00110 lv[1]/= ld; 00111 lv[2]/= ld; 00112 00113 /* ld is re-used further on (texco's) */ 00114 00115 if(lar->mode & LA_QUAD) { 00116 t= 1.0; 00117 if(lar->ld1>0.0) 00118 t= lar->dist/(lar->dist+lar->ld1*ld); 00119 if(lar->ld2>0.0) 00120 t*= lar->distkw/(lar->distkw+lar->ld2*ld*ld); 00121 00122 lampdist= t; 00123 } 00124 else { 00125 lampdist= (lar->dist/(lar->dist+ld)); 00126 } 00127 00128 if(lar->mode & LA_SPHERE) { 00129 t= lar->dist - ld; 00130 if(t<0.0) continue; 00131 00132 t/= lar->dist; 00133 lampdist*= (t); 00134 } 00135 00136 } 00137 00138 lacol[0]= lar->r; 00139 lacol[1]= lar->g; 00140 lacol[2]= lar->b; 00141 00142 if(lar->mode & LA_TEXTURE) { 00143 ShadeInput shi; 00144 00145 /* Warning, This is not that nice, and possibly a bit slow, 00146 however some variables were not initialized properly in, unless using shade_input_initialize(...), we need to do a memset */ 00147 memset(&shi, 0, sizeof(ShadeInput)); 00148 /* end warning! - Campbell */ 00149 00150 VECCOPY(shi.co, rco); 00151 shi.osatex= 0; 00152 do_lamp_tex(lar, lv, &shi, lacol, LA_TEXTURE); 00153 } 00154 00155 if(lar->type==LA_SPOT) { 00156 00157 if(lar->mode & LA_SQUARE) { 00158 if(lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2]>0.0) { 00159 float x, lvrot[3]; 00160 00161 /* rotate view to lampspace */ 00162 VECCOPY(lvrot, lv); 00163 mul_m3_v3(lar->imat, lvrot); 00164 00165 x= MAX2(fabs(lvrot[0]/lvrot[2]) , fabs(lvrot[1]/lvrot[2])); 00166 /* 1.0/(sqrt(1+x*x)) is equivalent to cos(atan(x)) */ 00167 00168 inpr= 1.0/(sqrt(1.0+x*x)); 00169 } 00170 else inpr= 0.0; 00171 } 00172 else { 00173 inpr= lv[0]*lar->vec[0]+lv[1]*lar->vec[1]+lv[2]*lar->vec[2]; 00174 } 00175 00176 t= lar->spotsi; 00177 if(inpr<t) continue; 00178 else { 00179 t= inpr-t; 00180 i= 1.0; 00181 soft= 1.0; 00182 if(t<lar->spotbl && lar->spotbl!=0.0) { 00183 /* soft area */ 00184 i= t/lar->spotbl; 00185 t= i*i; 00186 soft= (3.0*t-2.0*t*i); 00187 inpr*= soft; 00188 } 00189 if(lar->mode & LA_ONLYSHADOW) { 00190 /* if(ma->mode & MA_SHADOW) { */ 00191 /* dot product positive: front side face! */ 00192 inp= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2]; 00193 if(inp>0.0) { 00194 /* testshadowbuf==0.0 : 100% shadow */ 00195 shadfac = testshadowbuf(&R, lar->shb, rco, dco, dco, inp, 0.0f); 00196 if( shadfac>0.0 ) { 00197 shadfac*= inp*soft*lar->energy; 00198 ir -= shadfac; 00199 ig -= shadfac; 00200 ib -= shadfac; 00201 00202 continue; 00203 } 00204 } 00205 /* } */ 00206 } 00207 lampdist*=inpr; 00208 } 00209 if(lar->mode & LA_ONLYSHADOW) continue; 00210 00211 } 00212 00213 /* dot product and reflectivity*/ 00214 00215 inp= 1.0-fabs(vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2]); 00216 00217 /* inp= cos(0.5*M_PI-acos(inp)); */ 00218 00219 i= inp; 00220 00221 if(lar->type==LA_HEMI) { 00222 i= 0.5*i+0.5; 00223 } 00224 if(i>0.0) { 00225 i*= lampdist; 00226 } 00227 00228 /* shadow */ 00229 if(i> -0.41) { /* heuristic valua! */ 00230 shadfac= 1.0; 00231 if(lar->shb) { 00232 shadfac = testshadowbuf(&R, lar->shb, rco, dco, dco, inp, 0.0f); 00233 if(shadfac==0.0) continue; 00234 i*= shadfac; 00235 } 00236 } 00237 00238 if(i>0.0) { 00239 ir+= i*lacol[0]; 00240 ig+= i*lacol[1]; 00241 ib+= i*lacol[2]; 00242 } 00243 } 00244 00245 if(ir<0.0) ir= 0.0; 00246 if(ig<0.0) ig= 0.0; 00247 if(ib<0.0) ib= 0.0; 00248 00249 colf[0]*= ir; 00250 colf[1]*= ig; 00251 colf[2]*= ib; 00252 00253 } 00254 00255 00261 static float haloZtoDist(int z) 00262 { 00263 float zco = 0; 00264 00265 if(z >= 0x7FFFFF) 00266 return 10e10; 00267 else { 00268 zco = (float)z/(float)0x7FFFFF; 00269 if(R.r.mode & R_ORTHO) 00270 return (R.winmat[3][2] - zco*R.winmat[3][3])/(R.winmat[2][2]); 00271 else 00272 return (R.winmat[3][2])/(R.winmat[2][2] - R.winmat[2][3]*zco); 00273 } 00274 } 00275 00285 int shadeHaloFloat(HaloRen *har, float *col, int zz, 00286 float dist, float xn, float yn, short flarec) 00287 { 00288 /* fill in col */ 00289 float t, zn, radist, ringf=0.0f, linef=0.0f, alpha, si, co; 00290 int a; 00291 00292 if(R.wrld.mode & WO_MIST) { 00293 if(har->type & HA_ONLYSKY) { 00294 /* stars but no mist */ 00295 alpha= har->alfa; 00296 } 00297 else { 00298 /* a bit patchy... */ 00299 alpha= mistfactor(-har->co[2], har->co)*har->alfa; 00300 } 00301 } 00302 else alpha= har->alfa; 00303 00304 if(alpha==0.0) 00305 return 0; 00306 00307 /* soften the halo if it intersects geometry */ 00308 if(har->mat && har->mat->mode & MA_HALO_SOFT) { 00309 float segment_length, halo_depth, distance_from_z, visible_depth, soften; 00310 00311 /* calculate halo depth */ 00312 segment_length= har->hasize*sasqrt(1.0f - dist/(har->rad*har->rad)); 00313 halo_depth= 2.0f*segment_length; 00314 00315 if(halo_depth < FLT_EPSILON) 00316 return 0; 00317 00318 /* calculate how much of this depth is visible */ 00319 distance_from_z = haloZtoDist(zz) - haloZtoDist(har->zs); 00320 visible_depth = halo_depth; 00321 if(distance_from_z < segment_length) { 00322 soften= (segment_length + distance_from_z)/halo_depth; 00323 00324 /* apply softening to alpha */ 00325 if(soften < 1.0f) 00326 alpha *= soften; 00327 if(alpha <= 0.0f) 00328 return 0; 00329 } 00330 } 00331 else { 00332 /* not a soft halo. use the old softening code */ 00333 /* halo being intersected? */ 00334 if(har->zs> zz-har->zd) { 00335 t= ((float)(zz-har->zs))/(float)har->zd; 00336 alpha*= sqrt(sqrt(t)); 00337 } 00338 } 00339 00340 radist= sqrt(dist); 00341 00342 /* watch it: not used nicely: flarec is set at zero in pixstruct */ 00343 if(flarec) har->pixels+= (int)(har->rad-radist); 00344 00345 if(har->ringc) { 00346 float *rc, fac; 00347 int ofs; 00348 00349 /* per ring an antialised circle */ 00350 ofs= har->seed; 00351 00352 for(a= har->ringc; a>0; a--, ofs+=2) { 00353 00354 rc= hashvectf + (ofs % 768); 00355 00356 fac= fabs( rc[1]*(har->rad*fabs(rc[0]) - radist) ); 00357 00358 if(fac< 1.0) { 00359 ringf+= (1.0-fac); 00360 } 00361 } 00362 } 00363 00364 if(har->type & HA_VECT) { 00365 dist= fabs( har->cos*(yn) - har->sin*(xn) )/har->rad; 00366 if(dist>1.0) dist= 1.0; 00367 if(har->tex) { 00368 zn= har->sin*xn - har->cos*yn; 00369 yn= har->cos*xn + har->sin*yn; 00370 xn= zn; 00371 } 00372 } 00373 else dist= dist/har->radsq; 00374 00375 if(har->type & HA_FLARECIRC) { 00376 00377 dist= 0.5+fabs(dist-0.5); 00378 00379 } 00380 00381 if(har->hard>=30) { 00382 dist= sqrt(dist); 00383 if(har->hard>=40) { 00384 dist= sin(dist*M_PI_2); 00385 if(har->hard>=50) { 00386 dist= sqrt(dist); 00387 } 00388 } 00389 } 00390 else if(har->hard<20) dist*=dist; 00391 00392 if(dist < 1.0f) 00393 dist= (1.0f-dist); 00394 else 00395 dist= 0.0f; 00396 00397 if(har->linec) { 00398 float *rc, fac; 00399 int ofs; 00400 00401 /* per starpoint an antialiased line */ 00402 ofs= har->seed; 00403 00404 for(a= har->linec; a>0; a--, ofs+=3) { 00405 00406 rc= hashvectf + (ofs % 768); 00407 00408 fac= fabs( (xn)*rc[0]+(yn)*rc[1]); 00409 00410 if(fac< 1.0f ) 00411 linef+= (1.0f-fac); 00412 } 00413 00414 linef*= dist; 00415 } 00416 00417 if(har->starpoints) { 00418 float ster, angle; 00419 /* rotation */ 00420 angle= atan2(yn, xn); 00421 angle*= (1.0+0.25*har->starpoints); 00422 00423 co= cos(angle); 00424 si= sin(angle); 00425 00426 angle= (co*xn+si*yn)*(co*yn-si*xn); 00427 00428 ster= fabs(angle); 00429 if(ster>1.0) { 00430 ster= (har->rad)/(ster); 00431 00432 if(ster<1.0) dist*= sqrt(ster); 00433 } 00434 } 00435 00436 /* disputable optimize... (ton) */ 00437 if(dist<=0.00001) 00438 return 0; 00439 00440 dist*= alpha; 00441 ringf*= dist; 00442 linef*= alpha; 00443 00444 /* The color is either the rgb spec-ed by the user, or extracted from */ 00445 /* the texture */ 00446 if(har->tex) { 00447 col[0]= har->r; 00448 col[1]= har->g; 00449 col[2]= har->b; 00450 col[3]= dist; 00451 00452 do_halo_tex(har, xn, yn, col); 00453 00454 col[0]*= col[3]; 00455 col[1]*= col[3]; 00456 col[2]*= col[3]; 00457 00458 } 00459 else { 00460 col[0]= dist*har->r; 00461 col[1]= dist*har->g; 00462 col[2]= dist*har->b; 00463 if(har->type & HA_XALPHA) col[3]= dist*dist; 00464 else col[3]= dist; 00465 } 00466 00467 if(har->mat) { 00468 if(har->mat->mode & MA_HALO_SHADE) { 00469 /* we test for lights because of preview... */ 00470 if(R.lights.first) render_lighting_halo(har, col); 00471 } 00472 00473 /* Next, we do the line and ring factor modifications. */ 00474 if(linef!=0.0) { 00475 Material *ma= har->mat; 00476 00477 col[0]+= linef * ma->specr; 00478 col[1]+= linef * ma->specg; 00479 col[2]+= linef * ma->specb; 00480 00481 if(har->type & HA_XALPHA) col[3]+= linef*linef; 00482 else col[3]+= linef; 00483 } 00484 if(ringf!=0.0) { 00485 Material *ma= har->mat; 00486 00487 col[0]+= ringf * ma->mirr; 00488 col[1]+= ringf * ma->mirg; 00489 col[2]+= ringf * ma->mirb; 00490 00491 if(har->type & HA_XALPHA) col[3]+= ringf*ringf; 00492 else col[3]+= ringf; 00493 } 00494 } 00495 00496 /* alpha requires clip, gives black dots */ 00497 if(col[3] > 1.0f) 00498 col[3]= 1.0f; 00499 00500 return 1; 00501 } 00502 00503 /* ------------------------------------------------------------------------- */ 00504 00505 /* Only view vector is important here. Result goes to colf[3] */ 00506 void shadeSkyView(float *colf, float *rco, float *view, float *dxyview, short thread) 00507 { 00508 float lo[3], zen[3], hor[3], blend, blendm; 00509 int skyflag; 00510 00511 /* flag indicating if we render the top hemisphere */ 00512 skyflag = WO_ZENUP; 00513 00514 /* Some view vector stuff. */ 00515 if(R.wrld.skytype & WO_SKYREAL) { 00516 00517 blend= view[0]*R.grvec[0]+ view[1]*R.grvec[1]+ view[2]*R.grvec[2]; 00518 00519 if(blend<0.0) skyflag= 0; 00520 00521 blend= fabs(blend); 00522 } 00523 else if(R.wrld.skytype & WO_SKYPAPER) { 00524 blend= 0.5+ 0.5*view[1]; 00525 } 00526 else { 00527 /* the fraction of how far we are above the bottom of the screen */ 00528 blend= fabs(0.5+ view[1]); 00529 } 00530 00531 VECCOPY(hor, &R.wrld.horr); 00532 VECCOPY(zen, &R.wrld.zenr); 00533 00534 /* Careful: SKYTEX and SKYBLEND are NOT mutually exclusive! If */ 00535 /* SKYBLEND is active, the texture and color blend are added. */ 00536 if(R.wrld.skytype & WO_SKYTEX) { 00537 VECCOPY(lo, view); 00538 if(R.wrld.skytype & WO_SKYREAL) { 00539 00540 mul_m3_v3(R.imat, lo); 00541 00542 SWAP(float, lo[1], lo[2]); 00543 00544 } 00545 do_sky_tex(rco, lo, dxyview, hor, zen, &blend, skyflag, thread); 00546 } 00547 00548 if(blend>1.0) blend= 1.0; 00549 blendm= 1.0-blend; 00550 00551 /* No clipping, no conversion! */ 00552 if(R.wrld.skytype & WO_SKYBLEND) { 00553 colf[0] = (blendm*hor[0] + blend*zen[0]); 00554 colf[1] = (blendm*hor[1] + blend*zen[1]); 00555 colf[2] = (blendm*hor[2] + blend*zen[2]); 00556 } else { 00557 /* Done when a texture was grabbed. */ 00558 colf[0]= hor[0]; 00559 colf[1]= hor[1]; 00560 colf[2]= hor[2]; 00561 } 00562 } 00563 00564 /* shade sky according to sun lamps, all parameters are like shadeSkyView except sunsky*/ 00565 void shadeSunView(float *colf, float *view) 00566 { 00567 GroupObject *go; 00568 LampRen *lar; 00569 float sview[3]; 00570 int do_init= 1; 00571 00572 for(go=R.lights.first; go; go= go->next) { 00573 lar= go->lampren; 00574 if(lar->type==LA_SUN && lar->sunsky && (lar->sunsky->effect_type & LA_SUN_EFFECT_SKY)){ 00575 float sun_collector[3]; 00576 float colorxyz[3]; 00577 00578 if(do_init) { 00579 00580 VECCOPY(sview, view); 00581 normalize_v3(sview); 00582 mul_m3_v3(R.imat, sview); 00583 if (sview[2] < 0.0) 00584 sview[2] = 0.0; 00585 normalize_v3(sview); 00586 do_init= 0; 00587 } 00588 00589 GetSkyXYZRadiancef(lar->sunsky, sview, colorxyz); 00590 xyz_to_rgb(colorxyz[0], colorxyz[1], colorxyz[2], &sun_collector[0], &sun_collector[1], &sun_collector[2], 00591 lar->sunsky->sky_colorspace); 00592 00593 ramp_blend(lar->sunsky->skyblendtype, colf, colf+1, colf+2, lar->sunsky->skyblendfac, sun_collector); 00594 } 00595 } 00596 } 00597 00598 00599 /* 00600 Stuff the sky color into the collector. 00601 */ 00602 void shadeSkyPixel(float *collector, float fx, float fy, short thread) 00603 { 00604 float view[3], dxyview[2]; 00605 00606 /* 00607 The rules for sky: 00608 1. Draw an image, if a background image was provided. Stop 00609 2. get texture and color blend, and combine these. 00610 */ 00611 00612 float fac; 00613 00614 if((R.wrld.skytype & (WO_SKYBLEND+WO_SKYTEX))==0) { 00615 /* 1. solid color */ 00616 VECCOPY(collector, &R.wrld.horr); 00617 00618 collector[3] = 0.0f; 00619 } 00620 else { 00621 /* 2. */ 00622 00623 /* This one true because of the context of this routine */ 00624 if(R.wrld.skytype & WO_SKYPAPER) { 00625 view[0]= -1.0f + 2.0f*(fx/(float)R.winx); 00626 view[1]= -1.0f + 2.0f*(fy/(float)R.winy); 00627 view[2]= 0.0; 00628 00629 dxyview[0]= 1.0f/(float)R.winx; 00630 dxyview[1]= 1.0f/(float)R.winy; 00631 } 00632 else { 00633 calc_view_vector(view, fx, fy); 00634 fac= normalize_v3(view); 00635 00636 if(R.wrld.skytype & WO_SKYTEX) { 00637 dxyview[0]= -R.viewdx/fac; 00638 dxyview[1]= -R.viewdy/fac; 00639 } 00640 } 00641 00642 /* get sky color in the collector */ 00643 shadeSkyView(collector, NULL, view, dxyview, thread); 00644 collector[3] = 0.0f; 00645 } 00646 00647 calc_view_vector(view, fx, fy); 00648 shadeSunView(collector, view); 00649 } 00650 00651 /* aerial perspective */ 00652 void shadeAtmPixel(struct SunSky *sunsky, float *collector, float fx, float fy, float distance) 00653 { 00654 float view[3]; 00655 00656 calc_view_vector(view, fx, fy); 00657 normalize_v3(view); 00658 /*mul_m3_v3(R.imat, view);*/ 00659 AtmospherePixleShader(sunsky, view, distance, collector); 00660 } 00661 00662 /* eof */