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:
@@ -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
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user