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