diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h index 1ae6599e23a..6f6af6d5f22 100644 --- a/source/blender/makesdna/DNA_material_types.h +++ b/source/blender/makesdna/DNA_material_types.h @@ -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 diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 2528149e89a..ac6e75f03e5 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -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 */ diff --git a/source/blender/render/intern/source/ray.c b/source/blender/render/intern/source/ray.c index 9efe1c56af3..36f2b38d5f8 100644 --- a/source/blender/render/intern/source/ray.c +++ b/source/blender/render/intern/source/ray.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); diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index 55c19d53a0d..37add270d47 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -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; amode & 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) { @@ -2119,7 +2119,18 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr) /* inp = dotproduct, is = shader result, i = lamp energy (with shadow) */ 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; + ray_shadow(shi, lar, shadfac); } /* 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) { diff --git a/source/blender/renderconverter/intern/convertBlenderScene.c b/source/blender/renderconverter/intern/convertBlenderScene.c index e85661b848c..712cbf5c35b 100644 --- a/source/blender/renderconverter/intern/convertBlenderScene.c +++ b/source/blender/renderconverter/intern/convertBlenderScene.c @@ -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; iflag & 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); } - /* 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); + /* 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; diff --git a/source/blender/src/buttons_shading.c b/source/blender/src/buttons_shading.c index 2368af026c6..cdc0290254e 100644 --- a/source/blender/src/buttons_shading.c +++ b/source/blender/src/buttons_shading.c @@ -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"); } diff --git a/source/blender/src/renderwin.c b/source/blender/src/renderwin.c index dbe44022e89..9266846029f 100644 --- a/source/blender/src/renderwin.c +++ b/source/blender/src/renderwin.c @@ -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 {