Index: source/blender/render/intern/source/pixelshading.c =================================================================== --- source/blender/render/intern/source/pixelshading.c (revision 14384) +++ source/blender/render/intern/source/pixelshading.c (working copy) @@ -243,13 +243,49 @@ } +/** + * Converts a z-buffer value to absolute 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 ZtoD(int z) +{ + int ortho = R.r.mode & R_ORTHO; + float zco = 0; + if(z >= 8388607) + return 10e10; + else { + zco = ((float)z)/8388607.0f; + if(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); + } + return 10e10; +} + + +/** + * @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 + */ void shadeHaloFloat(HaloRen *har, float *col, int zz, float dist, float xn, float yn, short flarec) { /* fill in col */ float t, zn, radist, ringf=0.0f, linef=0.0f, alpha, si, co; int a; + // for soft halos + float segment_length, halo_depth, distance_from_z, visible_depth, softening_factor; + float normalized_distance = sqrt(dist)/har->rad; + if (normalized_distance>1.0f) normalized_distance = 1.0f; + if(R.wrld.mode & WO_MIST) { if(har->type & HA_ONLYSKY) { @@ -367,11 +403,28 @@ } } - /* halo being intersected? */ - if(har->zs> zz-har->zd) { - t= ((float)(zz-har->zs))/(float)har->zd; - alpha*= sqrt(sqrt(t)); + // Soften the halo if it intersects geometry + if (har->mat->mode & MA_HALO_SOFT) { + // Calculate halo sphere depth at this pixel + segment_length = har->hasize * sqrt(1.0f-normalized_distance*normalized_distance); + halo_depth = 2.0f * segment_length; + // Calculate how much of this depth is visible + distance_from_z = ZtoD(zz) - ZtoD(har->zs); + visible_depth = halo_depth; + if (distance_from_zzs> zz-har->zd) { + t= ((float)(zz-har->zs))/(float)har->zd; + alpha*= sqrt(sqrt(t)); + } + } /* disputable optimize... (ton) */ if(dist<=0.00001) { @@ -441,6 +494,7 @@ /* alpha requires clip, gives black dots */ if(col[3] > 1.0f) col[3]= 1.0f; + } /* ------------------------------------------------------------------------- */ Index: source/blender/render/intern/source/rendercore.c =================================================================== --- source/blender/render/intern/source/rendercore.c (revision 14384) +++ source/blender/render/intern/source/rendercore.c (working copy) @@ -165,6 +165,8 @@ 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]; @@ -179,15 +181,14 @@ amount+= amountm; zz= calchalo_z(har, ps->z); - if(zz> har->zs) { + if(zz> har->zs || (har->mat->mode & MA_HALO_SOFT)) { // No depth test for soft halos float fac; - - shadeHaloFloat(har, col, zz, dist, xn, yn, flarec); + shadeHaloFloat(har, col, zz, dist, xn, yn, flarec); 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]; + accol[0] += fac*col[0]; + accol[1] += fac*col[1]; + accol[2] += fac*col[2]; + accol[3] += fac*col[3]; flarec= 0; } @@ -279,7 +280,7 @@ } else { zz= calchalo_z(har, *rz); - if(zz> har->zs) { + if(zz> har->zs || (har->mat->mode & MA_HALO_SOFT)) { // No depth test for soft halos shadeHaloFloat(har, col, zz, dist, xn, yn, har->flarec); for(sample=0; samplemode), 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 {