Fix for #1449 (blocky shadows)

This problem appeared to be a famous one, with some fun read to be found
on the web. The solution as I commit here is described on the site:
http://www.blender3d.org/cms/Misc_improvements.355.0.html

As extra (I needed it quite some!) added requested feature to have the
renderwindow display in titlebar whether the spare page is shown (JKEY)
This commit is contained in:
2004-07-26 17:12:04 +00:00
parent 8a52016501
commit 653abbae6c
7 changed files with 122 additions and 39 deletions

View File

@@ -140,6 +140,7 @@ typedef struct Material {
#define MA_SHADOW_TRA 0x80000 #define MA_SHADOW_TRA 0x80000
#define MA_RAMP_COL 0x100000 #define MA_RAMP_COL 0x100000
#define MA_RAMP_SPEC 0x200000 #define MA_RAMP_SPEC 0x200000
#define MA_RAYBIAS 0x400000
/* diff_shader */ /* diff_shader */
#define MA_DIFF_LAMBERT 0 #define MA_DIFF_LAMBERT 0

View File

@@ -198,7 +198,7 @@ typedef struct Object {
LBuf lbuf; LBuf lbuf;
LBuf port; LBuf port;
float toonedge, pad2; float toonedge, smoothresh; /* smoothresh is phong interpolation ray_shadow correction in render */
} Object; } Object;
/* this work object is defined in object.c */ /* this work object is defined in object.c */

View File

@@ -2062,7 +2062,7 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac)
VECCOPY(lampco, lar->co); VECCOPY(lampco, lar->co);
} }
/* shadow and soft not implemented yet */ /* transp-shadow and soft not implemented yet */
if(lar->ray_totsamp<2 || isec.mode == DDA_SHADOW_TRA) { if(lar->ray_totsamp<2 || isec.mode == DDA_SHADOW_TRA) {
/* set up isec */ /* set up isec */
VECCOPY(isec.start, shi->co); VECCOPY(isec.start, shi->co);

View File

@@ -1899,14 +1899,14 @@ static void ambient_occlusion(World *wrld, ShadeInput *shi, ShadeResult *shr)
void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr) void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
{ {
LampRen *lar; LampRen *lar;
Material *ma; Material *ma= shi->matren;
VlakRen *vlr= shi->vlr;
float i, inp, inpr, is, t, lv[3], lampdist, ld = 0; float i, inp, inpr, is, t, lv[3], lampdist, ld = 0;
float lvrot[3], *vn, *view, shadfac[4], soft; // shadfac = rgba float lvrot[3], *vn, *view, shadfac[4], soft, phongcorr; // shadfac = rgba
int a; int a;
vn= shi->vn; vn= shi->vn;
view= shi->view; view= shi->view;
ma= shi->matren;
memset(shr, 0, sizeof(ShadeResult)); memset(shr, 0, sizeof(ShadeResult));
@@ -1918,7 +1918,7 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
for(a=0; a<R.totlamp; a++) { for(a=0; a<R.totlamp; a++) {
lar= R.la[a]; lar= R.la[a];
if(lar->mode & LA_LAYER) if((lar->lay & shi->vlr->lay)==0) continue; if(lar->mode & LA_LAYER) if((lar->lay & vlr->lay)==0) continue;
lv[0]= shi->co[0]-lar->co[0]; lv[0]= shi->co[0]-lar->co[0];
lv[1]= shi->co[1]-lar->co[1]; lv[1]= shi->co[1]-lar->co[1];
@@ -1953,7 +1953,7 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
float shad[4]; float shad[4];
/* single sided? */ /* single sided? */
if( shi->vlr->n[0]*lv[0] + shi->vlr->n[1]*lv[1] + shi->vlr->n[2]*lv[2] > -0.01) { if( vlr->n[0]*lv[0] + vlr->n[1]*lv[1] + vlr->n[2]*lv[2] > -0.01) {
ray_shadow(shi, lar, shad); ray_shadow(shi, lar, shad);
shadfac[3]+= shad[3]; shadfac[3]+= shad[3];
ir+= 1.0; ir+= 1.0;
@@ -2014,7 +2014,7 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
lar= R.la[a]; lar= R.la[a];
/* test for lamp layer */ /* test for lamp layer */
if(lar->mode & LA_LAYER) if((lar->lay & shi->vlr->lay)==0) continue; if(lar->mode & LA_LAYER) if((lar->lay & vlr->lay)==0) continue;
/* lampdist calculation */ /* lampdist calculation */
if(lar->type==LA_SUN || lar->type==LA_HEMI) { if(lar->type==LA_SUN || lar->type==LA_HEMI) {
@@ -2119,7 +2119,18 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
/* inp = dotproduct, is = shader result, i = lamp energy (with shadow) */ /* inp = dotproduct, is = shader result, i = lamp energy (with shadow) */
inp= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2]; inp= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2];
/* phong threshold to prevent backfacing faces having artefacts on ray shadow (terminator problem) */
if((ma->mode & MA_RAYBIAS) && (lar->mode & LA_SHAD_RAY) && (vlr->flag & R_SMOOTH)) {
float thresh= vlr->ob->smoothresh;
if(inp>thresh)
phongcorr= (inp-thresh)/(inp*(1.0-thresh));
else
phongcorr= 0.0;
}
else phongcorr= 1.0;
/* diffuse shaders */
if(lar->mode & LA_NO_DIFF) { if(lar->mode & LA_NO_DIFF) {
is= 0.0; // skip shaders is= 0.0; // skip shaders
} }
@@ -2141,7 +2152,8 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
else is= inp; // Lambert else is= inp; // Lambert
} }
i= is; i= is*phongcorr;
if(i>0.0) { if(i>0.0) {
i*= lampdist*ma->ref; i*= lampdist*ma->ref;
} }
@@ -2157,10 +2169,7 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
shadfac[3] = testshadowbuf(lar->shb, shi->co, inp); shadfac[3] = testshadowbuf(lar->shb, shi->co, inp);
} }
else if(lar->mode & LA_SHAD_RAY) { else if(lar->mode & LA_SHAD_RAY) {
// this extra 0.001 prevents boundary cases (shadow on smooth sphere) ray_shadow(shi, lar, shadfac);
if((shi->vlr->n[0]*lv[0] + shi->vlr->n[1]*lv[1] + shi->vlr->n[2]*lv[2]) > -0.001)
ray_shadow(shi, lar, shadfac);
else shadfac[3]= 0.0;
} }
/* warning, here it skips the loop */ /* warning, here it skips the loop */
@@ -2773,7 +2782,7 @@ void *shadepixel(float x, float y, int vlaknr, int mask, float *col)
if(shi.mat->mode & MA_RAYTRANSP) shr.alpha= 1.0; if(shi.mat->mode & MA_RAYTRANSP) shr.alpha= 1.0;
} }
VecAddf(col, shr.diff, shr.spec); VECADD(col, shr.diff, shr.spec);
/* exposure correction */ /* exposure correction */
if(R.wrld.exp!=0.0 || R.wrld.range!=1.0) { if(R.wrld.exp!=0.0 || R.wrld.range!=1.0) {

View File

@@ -145,10 +145,10 @@ static void init_render_object(Object *ob);
static HaloRen *initstar(float *vec, float hasize); static HaloRen *initstar(float *vec, float hasize);
/* Displacement Texture */ /* Displacement Texture */
void displace_render_face(VlakRen *vlr, float *scale); static void displace_render_face(VlakRen *vlr, float *scale);
void do_displacement(Object *ob, int startface, int numface, int startvert, int numvert); static void do_displacement(Object *ob, int startface, int numface, int startvert, int numvert);
short test_for_displace(Object *ob); static short test_for_displace(Object *ob);
void displace_render_vert(ShadeInput *shi, VertRen *vr, float *scale); static void displace_render_vert(ShadeInput *shi, VertRen *vr, float *scale);
/* more prototypes for autosmoothing below */ /* more prototypes for autosmoothing below */
@@ -2493,6 +2493,54 @@ static void init_render_curve(Object *ob)
} }
} }
/* prevent phong interpolation for giving ray shadow errors (terminator problem) */
static void set_phong_threshold(Object *ob, int startface, int numface, int startvert, int numvert )
{
VertRen *ver;
VlakRen *vlr;
float thresh= 0.0, dot;
int tot=0, i;
/* Added check for 'pointy' situations, only dotproducts of 0.9 and larger
are taken into account. This threshold is meant to work on smooth geometry, not
for extreme cases (ton) */
for(i=startface; i<startface+numface; i++) {
vlr= RE_findOrAddVlak(i);
if(vlr->flag & R_SMOOTH) {
dot= INPR(vlr->n, vlr->v1->n);
dot= ABS(dot);
if(dot>0.9) {
thresh+= dot; tot++;
}
dot= INPR(vlr->n, vlr->v2->n);
dot= ABS(dot);
if(dot>0.9) {
thresh+= dot; tot++;
}
dot= INPR(vlr->n, vlr->v3->n);
dot= ABS(dot);
if(dot>0.9) {
thresh+= dot; tot++;
}
if(vlr->v4) {
dot= INPR(vlr->n, vlr->v4->n);
dot= ABS(dot);
if(dot>0.9) {
thresh+= dot; tot++;
}
}
}
}
if(tot) {
thresh/= (float)tot;
ob->smoothresh= cos(0.5*M_PI-acos(thresh));
}
}
static void init_render_object(Object *ob) static void init_render_object(Object *ob)
{ {
float mat[4][4]; float mat[4][4];
@@ -2518,11 +2566,20 @@ static void init_render_object(Object *ob)
MTC_Mat4Invert(ob->imat, mat); MTC_Mat4Invert(ob->imat, mat);
} }
/* the exception below is because displace code now is in init_render_mesh call, /* generic post process here */
I will look at means to have autosmooth enabled for all object types if(startvert!=R.totvert) {
and have it as general postprocess, like displace */
if (ob->type!=OB_MESH && test_for_displace( ob ) ) /* the exception below is because displace code now is in init_render_mesh call,
do_displacement(ob, startface, R.totvlak-startface, startvert, R.totvert-startvert); I will look at means to have autosmooth enabled for all object types
and have it as general postprocess, like displace */
if (ob->type!=OB_MESH && test_for_displace( ob ) )
do_displacement(ob, startface, R.totvlak-startface, startvert, R.totvert-startvert);
/* phong normal interpolation can cause error in tracing (terminator prob) */
ob->smoothresh= 0.0;
if( (R.r.mode & R_RAYTRACE) && (R.r.mode & R_SHADOW) )
set_phong_threshold(ob, startface, R.totvlak-startface, startvert, R.totvert-startvert);
}
} }
void RE_freeRotateBlenderScene(void) void RE_freeRotateBlenderScene(void)
@@ -2927,7 +2984,7 @@ void RE_rotateBlenderScene(void)
/* **************************************************************** */ /* **************************************************************** */
/* Displacement mapping */ /* Displacement mapping */
/* **************************************************************** */ /* **************************************************************** */
short test_for_displace(Object *ob) static short test_for_displace(Object *ob)
{ {
/* return 1 when this object uses displacement textures. */ /* return 1 when this object uses displacement textures. */
Material *ma; Material *ma;
@@ -2942,7 +2999,7 @@ short test_for_displace(Object *ob)
} }
void do_displacement(Object *ob, int startface, int numface, int startvert, int numvert ) static void do_displacement(Object *ob, int startface, int numface, int startvert, int numvert )
{ {
VertRen *vr; VertRen *vr;
VlakRen *vlr; VlakRen *vlr;
@@ -2974,7 +3031,7 @@ void do_displacement(Object *ob, int startface, int numface, int startvert, int
normalenrender(startvert, startface); normalenrender(startvert, startface);
} }
void displace_render_face(VlakRen *vlr, float *scale) static void displace_render_face(VlakRen *vlr, float *scale)
{ {
ShadeInput shi; ShadeInput shi;
VertRen vr; VertRen vr;
@@ -3042,7 +3099,7 @@ void displace_render_face(VlakRen *vlr, float *scale)
} }
void displace_render_vert(ShadeInput *shi, VertRen *vr, float *scale) static void displace_render_vert(ShadeInput *shi, VertRen *vr, float *scale)
{ {
short texco= shi->matren->texco; short texco= shi->matren->texco;
float sample=0; float sample=0;

View File

@@ -2707,14 +2707,15 @@ static void material_panel_shading(Material *ma)
uiBlockEndAlign(block); uiBlockEndAlign(block);
uiBlockSetCol(block, TH_BUT_SETTING1); uiBlockSetCol(block, TH_BUT_SETTING1);
uiDefButI(block, TOG|BIT|0, 0, "Traceable", 245,140,65,19, &(ma->mode), 0, 0, 0, 0, "Makes material to cast shadows or being detected by ray tracing"); uiDefButI(block, TOG|BIT|0, 0, "Traceable", 245,150,65,19, &(ma->mode), 0, 0, 0, 0, "Makes material to cast shadows or being detected by ray tracing");
uiBlockBeginAlign(block); uiBlockBeginAlign(block);
uiDefButI(block, TOG|BIT|1, 0, "Shadow", 245,110,65,19, &(ma->mode), 0, 0, 0, 0, "Makes material receive shadows"); uiDefButI(block, TOG|BIT|1, 0, "Shadow", 245,120,65,19, &(ma->mode), 0, 0, 0, 0, "Makes material receive shadows");
uiDefButI(block, TOG|BIT|19, 0, "TraShadow", 245,90,65,19, &(ma->mode), 0, 0, 0, 0, "Recieves transparent shadows based at material color and alpha"); uiDefButI(block, TOG|BIT|19, 0, "TraShadow", 245,100,65,19, &(ma->mode), 0, 0, 0, 0, "Recieves transparent shadows based at material color and alpha");
uiDefButI(block, TOG|BIT|22, 0, "Bias", 245,80,65,19, &(ma->mode), 0, 0, 0, 0, "Prevents ray traced shadow errors with phong interpolated normals (terminator problem)");
uiBlockEndAlign(block); uiBlockEndAlign(block);
uiDefButI(block, TOG|BIT|16, 0, "Radio", 245,60,65,19, &(ma->mode), 0, 0, 0, 0, "Enables material for radiosty rendering"); uiDefButI(block, TOG|BIT|16, 0, "Radio", 245,55,65,19, &(ma->mode), 0, 0, 0, 0, "Enables material for radiosty rendering");
} }

View File

@@ -445,18 +445,32 @@ static void renderwin_handler(Window *win, void *user_data, short evt, short val
} }
} }
static char *renderwin_get_title(int doswap)
{
static int swap= 0;
char *title="";
swap+= doswap;
if(swap & 1) {
if (G.scene->r.renderer==R_YAFRAY) title = "YafRay:Render (spare)";
else title = "Blender:Render (spare)";
}
else {
if (G.scene->r.renderer==R_YAFRAY) title = "YafRay:Render";
else title = "Blender:Render";
}
return title;
}
/* opens window and allocs struct */ /* opens window and allocs struct */
static void open_renderwin(int winpos[2], int winsize[2]) static void open_renderwin(int winpos[2], int winsize[2])
{ {
Window *win; Window *win;
/* yafray: Window title change for yafray, totally unnecessary of course, but... */ char *title;
char* title;
if (G.scene->r.renderer==R_YAFRAY) title= renderwin_get_title(0); /* 0 = no swap */
title = "YafRay:Render";
else
title = "Blender:Render";
win= window_open(title, winpos[0], winpos[1], winsize[0], winsize[1], 0); win= window_open(title, winpos[0], winpos[1], winsize[0], winsize[1], 0);
render_win= renderwin_alloc(win); render_win= renderwin_alloc(win);
@@ -941,6 +955,7 @@ void BIF_swap_render_rects(void)
// don't open render_win if rendering has been // don't open render_win if rendering has been
// canceled or the render_win has been actively closed // canceled or the render_win has been actively closed
if (render_win) { if (render_win) {
window_set_title(render_win->win, renderwin_get_title(1));
renderwin_queue_redraw(render_win); renderwin_queue_redraw(render_win);
} }
} else { } else {