diff options
Diffstat (limited to 'source/blender/render/intern/source/pixelshading.c')
-rw-r--r-- | source/blender/render/intern/source/pixelshading.c | 154 |
1 files changed, 129 insertions, 25 deletions
diff --git a/source/blender/render/intern/source/pixelshading.c b/source/blender/render/intern/source/pixelshading.c index cffed99c738..60723963af9 100644 --- a/source/blender/render/intern/source/pixelshading.c +++ b/source/blender/render/intern/source/pixelshading.c @@ -24,7 +24,9 @@ * ***** END GPL LICENSE BLOCK ***** */ +#include <float.h> #include <math.h> +#include <string.h> #include "BLI_arithb.h" /* External modules: */ @@ -43,6 +45,7 @@ #include "BKE_image.h" #include "BKE_global.h" +#include "BKE_material.h" #include "BKE_texture.h" #include "BKE_utildefines.h" @@ -55,6 +58,7 @@ #include "rendercore.h" #include "shadbuf.h" #include "pixelshading.h" +#include "sunsky.h" /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */ @@ -130,9 +134,15 @@ static void render_lighting_halo(HaloRen *har, float *colf) if(lar->mode & LA_TEXTURE) { ShadeInput shi; + + /* Warning, This is not that nice, and possibly a bit slow, + however some variables were not initialized properly in, unless using shade_input_initialize(...), we need to do a memset */ + memset(&shi, 0, sizeof(ShadeInput)); + /* end warning! - Campbell */ + VECCOPY(shi.co, rco); shi.osatex= 0; - do_lamp_tex(lar, lv, &shi, lacol); + do_lamp_tex(lar, lv, &shi, lacol, LA_TEXTURE); } if(lar->type==LA_SPOT) { @@ -175,7 +185,7 @@ static void render_lighting_halo(HaloRen *har, float *colf) inp= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2]; if(inp>0.0) { /* testshadowbuf==0.0 : 100% shadow */ - shadfac = testshadowbuf(lar->shb, rco, dco, dco, inp); + shadfac = testshadowbuf(&R, lar->shb, rco, dco, dco, inp, 0.0f); if( shadfac>0.0 ) { shadfac*= inp*soft*lar->energy; ir -= shadfac; @@ -212,7 +222,7 @@ static void render_lighting_halo(HaloRen *har, float *colf) if(i> -0.41) { /* heuristic valua! */ shadfac= 1.0; if(lar->shb) { - shadfac = testshadowbuf(lar->shb, rco, dco, dco, inp); + shadfac = testshadowbuf(&R, lar->shb, rco, dco, dco, inp, 0.0f); if(shadfac==0.0) continue; i*= shadfac; } @@ -236,8 +246,36 @@ static void render_lighting_halo(HaloRen *har, float *colf) } +/** + * Converts a halo z-buffer value to distance from the camera's near plane + * @param z The z-buffer value to convert + * @return a distance from the camera's near plane in blender units + */ +static float haloZtoDist(int z) +{ + float zco = 0; -void shadeHaloFloat(HaloRen *har, float *col, int zz, + if(z >= 0x7FFFFF) + return 10e10; + else { + zco = (float)z/(float)0x7FFFFF; + if(R.r.mode & R_ORTHO) + return (R.winmat[3][2] - zco*R.winmat[3][3])/(R.winmat[2][2]); + else + return (R.winmat[3][2])/(R.winmat[2][2] - R.winmat[2][3]*zco); + } +} + +/** + * @param col (float[4]) Store the rgb color here (with alpha) + * The alpha is used to blend the color to the background + * color_new = (1-alpha)*color_background + color + * @param zz The current zbuffer value at the place of this pixel + * @param dist Distance of the pixel from the center of the halo squared. Given in pixels + * @param xn The x coordinate of the pixel relaticve to the center of the halo. given in pixels + * @param yn The y coordinate of the pixel relaticve to the center of the halo. given in pixels + */ +int shadeHaloFloat(HaloRen *har, float *col, int zz, float dist, float xn, float yn, short flarec) { /* fill in col */ @@ -256,12 +294,40 @@ void shadeHaloFloat(HaloRen *har, float *col, int zz, } else alpha= har->alfa; - if(alpha==0.0) { - col[0] = 0.0; - col[1] = 0.0; - col[2] = 0.0; - col[3] = 0.0; - return; + if(alpha==0.0) + return 0; + + /* soften the halo if it intersects geometry */ + if(har->mat && har->mat->mode & MA_HALO_SOFT) { + float segment_length, halo_depth, distance_from_z, visible_depth, soften; + + /* calculate halo depth */ + segment_length= har->hasize*sasqrt(1.0f - dist/(har->rad*har->rad)); + halo_depth= 2.0f*segment_length; + + if(halo_depth < FLT_EPSILON) + return 0; + + /* calculate how much of this depth is visible */ + distance_from_z = haloZtoDist(zz) - haloZtoDist(har->zs); + visible_depth = halo_depth; + if(distance_from_z < segment_length) { + soften= (segment_length + distance_from_z)/halo_depth; + + /* apply softening to alpha */ + if(soften < 1.0f) + alpha *= soften; + if(alpha <= 0.0f) + return 0; + } + } + else { + /* not a soft halo. use the old softening code */ + /* halo being intersected? */ + if(har->zs> zz-har->zd) { + t= ((float)(zz-har->zs))/(float)har->zd; + alpha*= sqrt(sqrt(t)); + } } radist= sqrt(dist); @@ -359,21 +425,10 @@ void shadeHaloFloat(HaloRen *har, float *col, int zz, if(ster<1.0) dist*= sqrt(ster); } } - - /* halo being intersected? */ - if(har->zs> zz-har->zd) { - t= ((float)(zz-har->zs))/(float)har->zd; - alpha*= sqrt(sqrt(t)); - } /* disputable optimize... (ton) */ - if(dist<=0.00001) { - col[0] = 0.0; - col[1] = 0.0; - col[2] = 0.0; - col[3] = 0.0; - return; - } + if(dist<=0.00001) + return 0; dist*= alpha; ringf*= dist; @@ -434,6 +489,8 @@ void shadeHaloFloat(HaloRen *har, float *col, int zz, /* alpha requires clip, gives black dots */ if(col[3] > 1.0f) col[3]= 1.0f; + + return 1; } /* ------------------------------------------------------------------------- */ @@ -512,13 +569,48 @@ void shadeSkyView(float *colf, float *rco, float *view, float *dxyview) } } +/* shade sky according to sun lamps, all parameters are like shadeSkyView except sunsky*/ +void shadeSunView(float *colf, float *view) +{ + GroupObject *go; + LampRen *lar; + float sview[3]; + int do_init= 1; + + for(go=R.lights.first; go; go= go->next) { + lar= go->lampren; + if(lar->type==LA_SUN && lar->sunsky && (lar->sunsky->effect_type & LA_SUN_EFFECT_SKY)){ + float sun_collector[3]; + float colorxyz[3]; + + if(do_init) { + + VECCOPY(sview, view); + Normalize(sview); + MTC_Mat3MulVecfl(R.imat, sview); + if (sview[2] < 0.0) + sview[2] = 0.0; + Normalize(sview); + do_init= 0; + } + + GetSkyXYZRadiancef(lar->sunsky, sview, colorxyz); + xyz_to_rgb(colorxyz[0], colorxyz[1], colorxyz[2], &sun_collector[0], &sun_collector[1], &sun_collector[2], + lar->sunsky->sky_colorspace); + + ramp_blend(lar->sunsky->skyblendtype, colf, colf+1, colf+2, lar->sunsky->skyblendfac, sun_collector); + } + } +} + + /* Stuff the sky color into the collector. */ void shadeSkyPixel(float *collector, float fx, float fy) { float view[3], dxyview[2]; - + /* The rules for sky: 1. Draw an image, if a background image was provided. Stop @@ -530,7 +622,6 @@ void shadeSkyPixel(float *collector, float fx, float fy) /* 1. Do a backbuffer image: */ if(R.r.bufflag & 1) { fillBackgroundImage(collector, fx, fy); - return; } else if((R.wrld.skytype & (WO_SKYBLEND+WO_SKYTEX))==0) { /* 2. solid color */ @@ -565,7 +656,20 @@ void shadeSkyPixel(float *collector, float fx, float fy) shadeSkyView(collector, NULL, view, dxyview); collector[3] = 0.0f; } + + calc_view_vector(view, fx, fy); + shadeSunView(collector, view); } +/* aerial perspective */ +void shadeAtmPixel(struct SunSky *sunsky, float *collector, float fx, float fy, float distance) +{ + float view[3]; + + calc_view_vector(view, fx, fy); + Normalize(view); + /*MTC_Mat3MulVecfl(R.imat, view);*/ + AtmospherePixleShader(sunsky, view, distance, collector); +} /* eof */ |