From 0b8b4369c9dbfd9f0048b54a74bf3669919e7f0f Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 14 Apr 2008 19:48:14 +0000 Subject: Patch #8034: "soft" option for halos, which avoids ugly intersections with geometry, and makes halos look more volumetric. Patch contributed by Markus Ilmola, thanks! --- source/blender/makesdna/DNA_material_types.h | 1 + .../blender/render/intern/include/pixelshading.h | 2 +- source/blender/render/intern/source/pixelshading.c | 88 +++++++++++++++++----- source/blender/render/intern/source/rendercore.c | 69 +++++++++-------- source/blender/src/buttons_shading.c | 17 +++-- 5 files changed, 113 insertions(+), 64 deletions(-) (limited to 'source') diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h index a4c6120374a..361b240eabf 100644 --- a/source/blender/makesdna/DNA_material_types.h +++ b/source/blender/makesdna/DNA_material_types.h @@ -161,6 +161,7 @@ typedef struct Material { #define MA_SHLESS 4 #define MA_WIRE 8 #define MA_VERTEXCOL 16 +#define MA_HALO_SOFT 16 #define MA_HALO 32 #define MA_ZTRA 64 #define MA_VERTEXCOLP 128 diff --git a/source/blender/render/intern/include/pixelshading.h b/source/blender/render/intern/include/pixelshading.h index d2235784a59..ee7199a4295 100644 --- a/source/blender/render/intern/include/pixelshading.h +++ b/source/blender/render/intern/include/pixelshading.h @@ -45,7 +45,7 @@ * mask is pixel coverage in bits * @return pointer to the object */ -void shadeHaloFloat(HaloRen *har, +int shadeHaloFloat(HaloRen *har, float *col, int zz, float dist, float xn, float yn, short flarec); diff --git a/source/blender/render/intern/source/pixelshading.c b/source/blender/render/intern/source/pixelshading.c index 6871a066c4f..6128a4823a4 100644 --- a/source/blender/render/intern/source/pixelshading.c +++ b/source/blender/render/intern/source/pixelshading.c @@ -24,6 +24,7 @@ * ***** END GPL LICENSE BLOCK ***** */ +#include #include #include #include "BLI_arithb.h" @@ -243,8 +244,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 */ @@ -263,12 +292,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->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); @@ -366,21 +423,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; @@ -441,6 +487,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; } /* ------------------------------------------------------------------------- */ diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index e36d8649036..15d41d45d88 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -165,9 +165,11 @@ static int calchalo_z(HaloRen *har, int zz) return zz; } + + static void halo_pixelstruct(HaloRen *har, RenderLayer **rlpp, int totsample, int od, float dist, float xn, float yn, PixStr *ps) { - float col[4], accol[4]; + float col[4], accol[4], fac; int amount, amountm, zz, flarec, sample, fullsample, mask=0; fullsample= (totsample > 1); @@ -180,23 +182,22 @@ static void halo_pixelstruct(HaloRen *har, RenderLayer **rlpp, int totsample, in amount+= amountm; zz= calchalo_z(har, ps->z); - if(zz> har->zs) { - float fac; - - shadeHaloFloat(har, col, zz, dist, xn, yn, flarec); - flarec= 0; - - if(fullsample) { - for(sample=0; samplemask & (1 << sample)) - addalphaAddfacFloat(rlpp[sample]->rectf + od*4, col, har->add); - } - else { - fac= ((float)amountm)/(float)R.osa; - accol[0]+= fac*col[0]; - accol[1]+= fac*col[1]; - accol[2]+= fac*col[2]; - accol[3]+= fac*col[3]; + if((zz> har->zs) || (har->mat->mode & MA_HALO_SOFT)) { + if(shadeHaloFloat(har, col, zz, dist, xn, yn, flarec)) { + flarec= 0; + + if(fullsample) { + for(sample=0; samplemask & (1 << sample)) + addalphaAddfacFloat(rlpp[sample]->rectf + od*4, col, har->add); + } + else { + fac= ((float)amountm)/(float)R.osa; + accol[0]+= fac*col[0]; + accol[1]+= fac*col[1]; + accol[2]+= fac*col[2]; + accol[3]+= fac*col[3]; + } } } @@ -207,16 +208,14 @@ static void halo_pixelstruct(HaloRen *har, RenderLayer **rlpp, int totsample, in /* now do the sky sub-pixels */ amount= R.osa-amount; if(amount) { - float fac; - - shadeHaloFloat(har, col, 0x7FFFFF, dist, xn, yn, flarec); - - if(!fullsample) { - fac= ((float)amount)/(float)R.osa; - accol[0]+= fac*col[0]; - accol[1]+= fac*col[1]; - accol[2]+= fac*col[2]; - accol[3]+= fac*col[3]; + if(shadeHaloFloat(har, col, 0x7FFFFF, dist, xn, yn, flarec)) { + if(!fullsample) { + fac= ((float)amount)/(float)R.osa; + accol[0]+= fac*col[0]; + accol[1]+= fac*col[1]; + accol[2]+= fac*col[2]; + accol[3]+= fac*col[3]; + } } } @@ -301,11 +300,11 @@ static void halo_tile(RenderPart *pa, RenderLayer *rl) } else { zz= calchalo_z(har, *rz); - if(zz> har->zs) { - shadeHaloFloat(har, col, zz, dist, xn, yn, har->flarec); - - for(sample=0; samplerectf + od*4, col, har->add); + if((zz> har->zs) || (har->mat->mode & MA_HALO_SOFT)) { + if(shadeHaloFloat(har, col, zz, dist, xn, yn, har->flarec)) { + for(sample=0; samplerectf + od*4, col, har->add); + } } } } @@ -1634,8 +1633,8 @@ static void renderhalo_post(RenderResult *rr, float *rectf, HaloRen *har) /* pos dist= xsq+ysq; if(distradsq) { - shadeHaloFloat(har, colf, 0x7FFFFF, dist, xn, yn, har->flarec); - addalphaAddfacFloat(rtf, colf, har->add); + if(shadeHaloFloat(har, colf, 0x7FFFFF, dist, xn, yn, har->flarec)) + addalphaAddfacFloat(rtf, colf, har->add); } rtf+=4; } diff --git a/source/blender/src/buttons_shading.c b/source/blender/src/buttons_shading.c index 880076de162..db531c7e6e3 100644 --- a/source/blender/src/buttons_shading.c +++ b/source/blender/src/buttons_shading.c @@ -3843,14 +3843,15 @@ static void material_panel_shading(Material *ma) uiBlockSetCol(block, TH_BUT_SETTING1); uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, MA_HALO_FLARE, B_MATPRV, "Flare",245,142,65,28, &(ma->mode), 0, 0, 0, 0, "Renders halo as a lensflare"); - uiDefButBitI(block, TOG, MA_HALO_RINGS, B_MATPRV, "Rings", 245,123,65, 18, &(ma->mode), 0, 0, 0, 0, "Renders rings over halo"); - uiDefButBitI(block, TOG, MA_HALO_LINES, B_MATPRV, "Lines", 245,104,65, 18, &(ma->mode), 0, 0, 0, 0, "Renders star shaped lines over halo"); - uiDefButBitI(block, TOG, MA_STAR, B_MATPRV, "Star", 245,85,65, 18, &(ma->mode), 0, 0, 0, 0, "Renders halo as a star"); - uiDefButBitI(block, TOG, MA_HALOTEX, B_MATPRV, "HaloTex", 245,66,65, 18, &(ma->mode), 0, 0, 0, 0, "Gives halo a texture"); - uiDefButBitI(block, TOG, MA_HALOPUNO, B_MATPRV, "HaloPuno", 245,47,65, 18, &(ma->mode), 0, 0, 0, 0, "Uses the vertex normal to specify the dimension of the halo"); - uiDefButBitI(block, TOG, MA_HALO_XALPHA, B_MATPRV, "X Alpha", 245,28,65, 18, &(ma->mode), 0, 0, 0, 0, "Uses extreme alpha"); - uiDefButBitI(block, TOG, MA_HALO_SHADE, B_MATPRV, "Shaded", 245,9,65, 18, &(ma->mode), 0, 0, 0, 0, "Lets halo receive light and shadows"); + uiDefButBitI(block, TOG, MA_HALO_FLARE, B_MATPRV, "Flare", 245,161,65,28, &(ma->mode), 0, 0, 0, 0, "Renders halo as a lensflare"); + uiDefButBitI(block, TOG, MA_HALO_RINGS, B_MATPRV, "Rings", 245,142,65,18, &(ma->mode), 0, 0, 0, 0, "Renders rings over halo"); + uiDefButBitI(block, TOG, MA_HALO_LINES, B_MATPRV, "Lines", 245,123,65,18, &(ma->mode), 0, 0, 0, 0, "Renders star shaped lines over halo"); + uiDefButBitI(block, TOG, MA_STAR, B_MATPRV, "Star", 245,104,65, 18, &(ma->mode), 0, 0, 0, 0, "Renders halo as a star"); + uiDefButBitI(block, TOG, MA_HALOTEX, B_MATPRV, "HaloTex", 245,85,65, 18, &(ma->mode), 0, 0, 0, 0, "Gives halo a texture"); + uiDefButBitI(block, TOG, MA_HALOPUNO, B_MATPRV, "HaloPuno", 245,66,65, 18, &(ma->mode), 0, 0, 0, 0, "Uses the vertex normal to specify the dimension of the halo"); + uiDefButBitI(block, TOG, MA_HALO_XALPHA, B_MATPRV, "X Alpha", 245,47,65, 18, &(ma->mode), 0, 0, 0, 0, "Uses extreme alpha"); + uiDefButBitI(block, TOG, MA_HALO_SHADE, B_MATPRV, "Shaded", 245,28,65, 18, &(ma->mode), 0, 0, 0, 0, "Lets halo receive light and shadows"); + uiDefButBitI(block, TOG, MA_HALO_SOFT, B_MATPRV, "Soft", 245,9,65, 18, &(ma->mode), 0, 0, 0, 0, "Softens the halo"); uiBlockEndAlign(block); } else { -- cgit v1.2.3