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_RAMP_COL 0x100000
|
||||
#define MA_RAMP_SPEC 0x200000
|
||||
#define MA_RAYBIAS 0x400000
|
||||
|
||||
/* diff_shader */
|
||||
#define MA_DIFF_LAMBERT 0
|
||||
|
||||
@@ -198,7 +198,7 @@ typedef struct Object {
|
||||
LBuf lbuf;
|
||||
LBuf port;
|
||||
|
||||
float toonedge, pad2;
|
||||
float toonedge, smoothresh; /* smoothresh is phong interpolation ray_shadow correction in render */
|
||||
} Object;
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* shadow and soft not implemented yet */
|
||||
/* transp-shadow and soft not implemented yet */
|
||||
if(lar->ray_totsamp<2 || isec.mode == DDA_SHADOW_TRA) {
|
||||
/* set up isec */
|
||||
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)
|
||||
{
|
||||
LampRen *lar;
|
||||
Material *ma;
|
||||
Material *ma= shi->matren;
|
||||
VlakRen *vlr= shi->vlr;
|
||||
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;
|
||||
|
||||
vn= shi->vn;
|
||||
view= shi->view;
|
||||
ma= shi->matren;
|
||||
|
||||
memset(shr, 0, sizeof(ShadeResult));
|
||||
|
||||
@@ -1918,7 +1918,7 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
|
||||
for(a=0; a<R.totlamp; 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[1]= shi->co[1]-lar->co[1];
|
||||
@@ -1953,7 +1953,7 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
|
||||
float shad[4];
|
||||
|
||||
/* 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);
|
||||
shadfac[3]+= shad[3];
|
||||
ir+= 1.0;
|
||||
@@ -2014,7 +2014,7 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
|
||||
lar= R.la[a];
|
||||
|
||||
/* 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 */
|
||||
if(lar->type==LA_SUN || lar->type==LA_HEMI) {
|
||||
@@ -2120,6 +2120,17 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
|
||||
|
||||
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) {
|
||||
is= 0.0; // skip shaders
|
||||
}
|
||||
@@ -2141,7 +2152,8 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
|
||||
else is= inp; // Lambert
|
||||
}
|
||||
|
||||
i= is;
|
||||
i= is*phongcorr;
|
||||
|
||||
if(i>0.0) {
|
||||
i*= lampdist*ma->ref;
|
||||
}
|
||||
@@ -2157,10 +2169,7 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
|
||||
shadfac[3] = testshadowbuf(lar->shb, shi->co, inp);
|
||||
}
|
||||
else if(lar->mode & LA_SHAD_RAY) {
|
||||
// this extra 0.001 prevents boundary cases (shadow on smooth sphere)
|
||||
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 */
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
VecAddf(col, shr.diff, shr.spec);
|
||||
VECADD(col, shr.diff, shr.spec);
|
||||
|
||||
/* exposure correction */
|
||||
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);
|
||||
|
||||
/* Displacement Texture */
|
||||
void displace_render_face(VlakRen *vlr, float *scale);
|
||||
void do_displacement(Object *ob, int startface, int numface, int startvert, int numvert);
|
||||
short test_for_displace(Object *ob);
|
||||
void displace_render_vert(ShadeInput *shi, VertRen *vr, float *scale);
|
||||
static void displace_render_face(VlakRen *vlr, float *scale);
|
||||
static void do_displacement(Object *ob, int startface, int numface, int startvert, int numvert);
|
||||
static short test_for_displace(Object *ob);
|
||||
static void displace_render_vert(ShadeInput *shi, VertRen *vr, float *scale);
|
||||
|
||||
/* 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)
|
||||
{
|
||||
float mat[4][4];
|
||||
@@ -2518,11 +2566,20 @@ static void init_render_object(Object *ob)
|
||||
MTC_Mat4Invert(ob->imat, mat);
|
||||
}
|
||||
|
||||
/* generic post process here */
|
||||
if(startvert!=R.totvert) {
|
||||
|
||||
/* the exception below is because displace code now is in init_render_mesh call,
|
||||
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)
|
||||
@@ -2927,7 +2984,7 @@ void RE_rotateBlenderScene(void)
|
||||
/* **************************************************************** */
|
||||
/* Displacement mapping */
|
||||
/* **************************************************************** */
|
||||
short test_for_displace(Object *ob)
|
||||
static short test_for_displace(Object *ob)
|
||||
{
|
||||
/* return 1 when this object uses displacement textures. */
|
||||
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;
|
||||
VlakRen *vlr;
|
||||
@@ -2974,7 +3031,7 @@ void do_displacement(Object *ob, int startface, int numface, int startvert, int
|
||||
normalenrender(startvert, startface);
|
||||
}
|
||||
|
||||
void displace_render_face(VlakRen *vlr, float *scale)
|
||||
static void displace_render_face(VlakRen *vlr, float *scale)
|
||||
{
|
||||
ShadeInput shi;
|
||||
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;
|
||||
float sample=0;
|
||||
|
||||
@@ -2707,14 +2707,15 @@ static void material_panel_shading(Material *ma)
|
||||
uiBlockEndAlign(block);
|
||||
|
||||
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);
|
||||
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|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|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,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);
|
||||
|
||||
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 */
|
||||
static void open_renderwin(int winpos[2], int winsize[2])
|
||||
{
|
||||
Window *win;
|
||||
/* yafray: Window title change for yafray, totally unnecessary of course, but... */
|
||||
char* title;
|
||||
if (G.scene->r.renderer==R_YAFRAY)
|
||||
title = "YafRay:Render";
|
||||
else
|
||||
title = "Blender:Render";
|
||||
char *title;
|
||||
|
||||
title= renderwin_get_title(0); /* 0 = no swap */
|
||||
win= window_open(title, winpos[0], winpos[1], winsize[0], winsize[1], 0);
|
||||
|
||||
render_win= renderwin_alloc(win);
|
||||
@@ -941,6 +955,7 @@ void BIF_swap_render_rects(void)
|
||||
// don't open render_win if rendering has been
|
||||
// canceled or the render_win has been actively closed
|
||||
if (render_win) {
|
||||
window_set_title(render_win->win, renderwin_get_title(1));
|
||||
renderwin_queue_redraw(render_win);
|
||||
}
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user