Patch #8034: "soft" option for halos, which avoids ugly intersections
with geometry, and makes halos look more volumetric. Patch contributed by Markus Ilmola, thanks!
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#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);
|
||||
@@ -367,20 +424,9 @@ void shadeHaloFloat(HaloRen *har, float *col, int zz,
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
@@ -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,10 +182,8 @@ 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);
|
||||
if((zz> har->zs) || (har->mat->mode & MA_HALO_SOFT)) {
|
||||
if(shadeHaloFloat(har, col, zz, dist, xn, yn, flarec)) {
|
||||
flarec= 0;
|
||||
|
||||
if(fullsample) {
|
||||
@@ -199,6 +199,7 @@ static void halo_pixelstruct(HaloRen *har, RenderLayer **rlpp, int totsample, in
|
||||
accol[3]+= fac*col[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mask |= ps->mask;
|
||||
ps= ps->next;
|
||||
@@ -207,10 +208,7 @@ 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(shadeHaloFloat(har, col, 0x7FFFFF, dist, xn, yn, flarec)) {
|
||||
if(!fullsample) {
|
||||
fac= ((float)amount)/(float)R.osa;
|
||||
accol[0]+= fac*col[0];
|
||||
@@ -219,6 +217,7 @@ static void halo_pixelstruct(HaloRen *har, RenderLayer **rlpp, int totsample, in
|
||||
accol[3]+= fac*col[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(fullsample) {
|
||||
for(sample=0; sample<totsample; sample++)
|
||||
@@ -301,14 +300,14 @@ 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);
|
||||
|
||||
if((zz> har->zs) || (har->mat->mode & MA_HALO_SOFT)) {
|
||||
if(shadeHaloFloat(har, col, zz, dist, xn, yn, har->flarec)) {
|
||||
for(sample=0; sample<totsample; sample++)
|
||||
addalphaAddfacFloat(rlpp[sample]->rectf + od*4, col, har->add);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(rd) rd++;
|
||||
}
|
||||
}
|
||||
@@ -1634,7 +1633,7 @@ static void renderhalo_post(RenderResult *rr, float *rectf, HaloRen *har) /* pos
|
||||
dist= xsq+ysq;
|
||||
if(dist<har->radsq) {
|
||||
|
||||
shadeHaloFloat(har, colf, 0x7FFFFF, dist, xn, yn, har->flarec);
|
||||
if(shadeHaloFloat(har, colf, 0x7FFFFF, dist, xn, yn, har->flarec))
|
||||
addalphaAddfacFloat(rtf, colf, har->add);
|
||||
}
|
||||
rtf+=4;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user