From 902a69a7d3fad91d84bc109a6e6e5fd039a79e4b Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Fri, 8 Dec 2006 09:40:44 +0000 Subject: Numerous fixes in Render code: - Bug: material emit was ignored (showed in preview render backdrop) - Bug: world exposure was ignored - Bug: lamp halo was ignoring 'render layer light override'. Further reshuffled the way shadows are being pre-calculated, this to enable more advanced (and faster) usage of Material lightgroups. Now shadows are being cached in lamps, using a per-sample counter to check if a recalc is needed. Will also work (later) for Raytracing node shaders. - New: Material LightGroup option "Always", which always shades the lights in the group, independent of visibility layer. (so it allows to move such lights to hidden layer, not influencing anything). --- .../blender/render/intern/include/render_types.h | 10 +++- source/blender/render/intern/include/shading.h | 9 ++- .../blender/render/intern/source/convertblender.c | 52 ++++++++++------- source/blender/render/intern/source/rendercore.c | 16 +++--- source/blender/render/intern/source/shadeinput.c | 67 ++++++---------------- source/blender/render/intern/source/shadeoutput.c | 14 +++-- source/blender/render/intern/source/zbuf.c | 10 ++-- 7 files changed, 86 insertions(+), 92 deletions(-) (limited to 'source/blender/render/intern') diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index 77beb446c86..247f10bf7a0 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -290,8 +290,13 @@ struct MTex; * properties of a lightsource. */ +typedef struct LampShadowSubSample { + int samplenr; + float shadfac[4]; /* rgba shadow */ +} LampShadowSubSample; + typedef struct LampShadowSample { - float shadfac[16][4]; /* 16 = RE_MAX_OSA, 4 = rgba */ + LampShadowSubSample s[16]; /* MAX OSA */ } LampShadowSample; typedef struct LampRen { @@ -344,8 +349,7 @@ typedef struct LampRen { float area[8][3], areasize; /* passes & node shader support: all shadow info for a pixel */ - /* struct is currently 2k long... check on alloc? */ - LampShadowSample shadsamp[BLENDER_MAX_THREADS]; + LampShadowSample *shadsamp; /* yafray: photonlight params */ int YF_numphotons, YF_numsearch; diff --git a/source/blender/render/intern/include/shading.h b/source/blender/render/intern/include/shading.h index 38ed0f73e70..6c8f20673ed 100644 --- a/source/blender/render/intern/include/shading.h +++ b/source/blender/render/intern/include/shading.h @@ -28,6 +28,7 @@ struct ShadeResult; struct RenderPart; struct RenderLayer; struct PixStr; +struct LampRen; /* shadeinput.c */ @@ -35,8 +36,12 @@ struct PixStr; /* needed to calculate shadow and AO for an entire pixel */ typedef struct ShadeSample { int tot; /* amount of shi in use, can be 1 for not FULL_OSA */ + + /* could be malloced once */ ShadeInput shi[16]; /* RE_MAX_OSA */ ShadeResult shr[16]; /* RE_MAX_OSA */ + + int samplenr; /* counter, detect shadow-reuse for shaders */ } ShadeSample; @@ -52,8 +57,10 @@ void shade_input_set_normals(struct ShadeInput *shi); void shade_input_set_shade_texco(struct ShadeInput *shi); void shade_input_do_shade(struct ShadeInput *shi, struct ShadeResult *shr); +void shade_input_initialize(struct ShadeInput *shi, struct RenderPart *pa, struct RenderLayer *rl, int sample); + void shade_sample_initialize(struct ShadeSample *ssamp, struct RenderPart *pa, struct RenderLayer *rl); -void shade_samples_do_shadow(struct ShadeSample *ssamp); +void shade_samples_do_AO(struct ShadeSample *ssamp); int shade_samples(struct ShadeSample *ssamp, struct PixStr *ps, int x, int y); void vlr_set_uv_indices(struct VlakRen *vlr, int *i1, int *i2, int *i3); diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 0fba6916c36..c71bbaef7c8 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -2340,9 +2340,15 @@ static LampRen *add_render_lamp(Render *re, Object *ob) } } } - - /* yafray: shadowbuffers and jitter only needed for internal render */ + /* yafray: shadow flag should not be cleared, only used with internal renderer */ if (re->r.renderer==R_INTERN) { + /* to make sure we can check ray shadow easily in the render code */ + if(lar->mode & LA_SHAD_RAY) { + if( (re->r.mode & R_RAYTRACE)==0) + lar->mode &= ~LA_SHAD_RAY; + } + + if(re->r.mode & R_SHADOW) { if (la->type==LA_SPOT && (lar->mode & LA_SHAD_BUF) ) { /* Per lamp, one shadow buffer is made. */ @@ -2353,24 +2359,25 @@ static LampRen *add_render_lamp(Render *re, Object *ob) else if(la->type==LA_AREA && (lar->mode & LA_SHAD_RAY) ) { init_jitter_plane(lar); } + + /* this is the way used all over to check for shadow */ + if(lar->shb || (lar->mode & LA_SHAD_RAY)) { + LampShadowSubSample *lss; + int a, b, tot= re->r.threads*re->r.osa; + + lar->shadsamp= MEM_mallocN(re->r.threads*sizeof(LampShadowSample), "lamp shadow sample"); + lss= lar->shadsamp[0].s; + /* shadfacs actually mean light, let's put them to 1 to prevent unitialized accidents */ + for(a=0; asamplenr= -1; /* used to detect whether we store or read */ + lss->shadfac[b]= 1.0f; + } + } + } } } - /* yafray: shadow flag should not be cleared, only used with internal renderer */ - if (re->r.renderer==R_INTERN) { - int a, b; - - /* to make sure we can check ray shadow easily in the render code */ - if(lar->mode & LA_SHAD_RAY) { - if( (re->r.mode & R_RAYTRACE)==0) - lar->mode &= ~LA_SHAD_RAY; - } - /* shadfacs actually mean light, let's put them to 1 to prevent unitialized accidents */ - for(c=0; cr.threads; c++) - for(a=0; ar.osa; a++) - for(b=0; b<4; b++) - lar->shadsamp[c].shadfac[a][b]= 1.0f; - } return lar; } @@ -2928,8 +2935,10 @@ void RE_Database_Free(Render *re) for(go= re->lights.first; go; go= go->next) { struct LampRen *lar= go->lampren; + freeshadowbuf(lar); if(lar->jitter) MEM_freeN(lar->jitter); + if(lar->shadsamp) MEM_freeN(lar->shadsamp); MEM_freeN(lar); } @@ -3115,7 +3124,8 @@ static void check_non_flat_quads(Render *re) } } -static void add_lightgroup(Render *re, Group *group) +/* layflag: allows material group to ignore layerflag */ +static void add_lightgroup(Render *re, Group *group, int nolay) { GroupObject *go, *gol; @@ -3131,6 +3141,8 @@ static void add_lightgroup(Render *re, Group *group) } if(go->lampren==NULL) go->lampren= add_render_lamp(re, go->ob); + if(nolay) + ((LampRen *)go->lampren)->lay= 0xFFFFFFFF; } } } @@ -3143,7 +3155,7 @@ static void set_material_lightgroups(Render *re) /* hola! materials not in use...? */ for(ma= G.main->mat.first; ma; ma=ma->id.next) { if(ma->group) - add_lightgroup(re, ma->group); + add_lightgroup(re, ma->group, ma->mode & MA_GROUP_NOLAY); } } @@ -3153,7 +3165,7 @@ static void set_renderlayer_lightgroups(Render *re, Scene *sce) for(srl= sce->r.layers.first; srl; srl= srl->next) { if(srl->light_override) - add_lightgroup(re, srl->light_override); + add_lightgroup(re, srl->light_override, 0); } } diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index 20718941aad..e8e75b6f7fb 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -287,14 +287,15 @@ static void halo_tile(RenderPart *pa, float *pass, unsigned int lay) } } -static void lamphalo_tile(RenderPart *pa, float *pass, unsigned int lay) +static void lamphalo_tile(RenderPart *pa, RenderLayer *rl) { ShadeInput shi; + float *pass= rl->rectf; float fac; long *rd= pa->rectdaps; int x, y, *rz= pa->rectz; - shi.lay= lay; + shade_input_initialize(&shi, pa, rl, 0); for(y=pa->disprect.ymin; ydisprect.ymax; y++) { for(x=pa->disprect.xmin; xdisprect.xmax; x++, rz++, pass+=4) { @@ -321,7 +322,6 @@ static void lamphalo_tile(RenderPart *pa, float *pass, unsigned int lay) shi.co[2]= 0.0f; renderspothalo(&shi, pass, fac); } - } else { if(R.r.mode & R_ORTHO) @@ -859,7 +859,7 @@ void zbufshadeDA_tile(RenderPart *pa) /* lamphalo after solid, before ztra, looks nicest because ztra does own halo */ if(R.flag & R_LAMPHALO) if(rl->layflag & SCE_LAY_HALO) - lamphalo_tile(pa, rl->rectf, rl->lay); + lamphalo_tile(pa, rl); /* halo before ztra, because ztra fills in zbuffer now */ if(R.flag & R_HALO) @@ -1028,7 +1028,7 @@ void zbufshade_tile(RenderPart *pa) /* lamphalo after solid, before ztra, looks nicest because ztra does own halo */ if(R.flag & R_LAMPHALO) if(rl->layflag & SCE_LAY_HALO) - lamphalo_tile(pa, rl->rectf, rl->lay); + lamphalo_tile(pa, rl); /* halo before ztra, because ztra fills in zbuffer now */ if(R.flag & R_HALO) @@ -1353,6 +1353,9 @@ static void do_bake_shade(void *handle, int x, int y, float u, float v) /* no face normal flip */ shi->puno= 0; + /* cache for shadow */ + shi->samplenr++; + if(bs->quad) shade_input_set_triangle_i(shi, vlr, 0, 2, 3); else @@ -1377,8 +1380,7 @@ static void do_bake_shade(void *handle, int x, int y, float u, float v) shade_input_set_shade_texco(shi); - if(R.r.mode & R_SHADOW) - shade_samples_do_shadow(ssamp); + shade_samples_do_AO(ssamp); if(shi->mat->nodetree && shi->mat->use_nodes) { ntreeShaderExecTree(shi->mat->nodetree, shi, &shr); diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c index a15e0d031e8..f706be36523 100644 --- a/source/blender/render/intern/source/shadeinput.c +++ b/source/blender/render/intern/source/shadeinput.c @@ -70,8 +70,8 @@ extern struct Render R; - shade_input_set_uv() <- not for ray or bake - shade_input_set_normals() - shade_samples() - - if shadow or AO - - shade_samples_do_shadow() + - if AO + - shade_samples_do_AO() - if shading happens - for each sample - shade_input_set_shade_texco() @@ -835,7 +835,7 @@ void shade_input_set_shade_texco(ShadeInput *shi) /* initialize per part, not per pixel! */ -static void shade_input_initialize(ShadeInput *shi, RenderPart *pa, RenderLayer *rl, int sample) +void shade_input_initialize(ShadeInput *shi, RenderPart *pa, RenderLayer *rl, int sample) { memset(shi, 0, sizeof(ShadeInput)); @@ -864,59 +864,24 @@ void shade_sample_initialize(ShadeSample *ssamp, RenderPart *pa, RenderLayer *rl shade_input_initialize(&ssamp->shi[a], pa, rl, a); memset(&ssamp->shr[a], 0, sizeof(ShadeResult)); } + + ssamp->samplenr= 0; /* counter, detect shadow-reuse for shaders */ } -/* for all lamps, for all samples, do shadow */ -/* renderdata mode was checked for */ -void shade_samples_do_shadow(ShadeSample *ssamp) + +/* Do AO or (future) GI */ +void shade_samples_do_AO(ShadeSample *ssamp) { - GroupObject *go; - LampRen *lar; ShadeInput *shi; int sample; - if(ssamp->shi[0].passflag & (SCE_PASS_COMBINED|SCE_PASS_DIFFUSE|SCE_PASS_SPEC|SCE_PASS_SHADOW)) { - for(go=R.lights.first; go; go= go->next) { - lar= go->lampren; - - /* if there's shadow */ - if(lar->shb || (lar->mode & LA_SHAD_RAY)) { - - for(sample=0, shi= ssamp->shi; sampletot; shi++, sample++) { - float visifac, lv[3], lampdist, inpr; - - /* tests to quickly reject */ - if(lar->mode & LA_LAYER) if((lar->lay & shi->vlr->lay)==0) continue; - if((lar->lay & shi->lay)==0) continue; - - if(!(shi->mode & MA_SHADOW) || (shi->mode & MA_SHLESS)) - continue; - - if(!( (shi->combinedflag | shi->passflag) & SCE_PASS_SHADOW)) - continue; - - visifac= lamp_get_visibility(lar, shi->co, lv, &lampdist); - if(visifac==0.0f) - continue; - - inpr= INPR(shi->vn, lv); - - /* tangential faces always look at lamp */ - if( (shi->mat->mode & MA_TANGENT_V) || (shi->vlr->flag & R_TANGENT) ) - inpr= 1.0f - inpr*inpr; - else if(inpr <= 0.0f) - continue; - - /* now we're going (1 = do it real) */ - lamp_get_shadow(lar, shi, inpr, lar->shadsamp[shi->thread].shadfac[sample], 1); - } - } - } - } + if(!(R.r.mode & R_SHADOW)) + return; + if(!(R.r.mode & R_RAYTRACE)) + return; - /* do the AO */ if(R.wrld.mode & WO_AMB_OCC) - if(ssamp->shi[0].passflag & (SCE_PASS_COMBINED|SCE_PASS_DIFFUSE|SCE_PASS_AO)) + if(ssamp->shi[0].passflag & (SCE_PASS_COMBINED|SCE_PASS_AO)) for(sample=0, shi= ssamp->shi; sampletot; shi++, sample++) if(!(shi->mode & MA_SHLESS)) if(shi->mode & MA_SHADOW) @@ -924,6 +889,7 @@ void shade_samples_do_shadow(ShadeSample *ssamp) } + static void shade_samples_fill_with_ps(ShadeSample *ssamp, PixStr *ps, int x, int y) { ShadeInput *shi; @@ -950,6 +916,7 @@ static void shade_samples_fill_with_ps(ShadeSample *ssamp, PixStr *ps, int x, in shade_input_copy_triangle(shi, shi-1); shi->mask= (1<samplenr= ssamp->samplenr++; shade_input_set_viewco(shi, xs, ys, (float)ps->z); shade_input_set_uv(shi); shade_input_set_normals(shi); @@ -970,6 +937,7 @@ static void shade_samples_fill_with_ps(ShadeSample *ssamp, PixStr *ps, int x, in ys= (float)y + 0.5f; } shi->mask= curmask; + shi->samplenr= ssamp->samplenr++; shade_input_set_viewco(shi, xs, ys, (float)ps->z); shade_input_set_uv(shi); shade_input_set_normals(shi); @@ -994,8 +962,7 @@ int shade_samples(ShadeSample *ssamp, PixStr *ps, int x, int y) int samp; /* if shadow or AO? */ - if(R.r.mode & R_SHADOW) - shade_samples_do_shadow(ssamp); + shade_samples_do_AO(ssamp); /* if shade (all shadepinputs have same passflag) */ if(ssamp->shi[0].passflag & ~(SCE_PASS_Z|SCE_PASS_INDEXOB)) { diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c index dd2cad02dc0..d6457313906 100644 --- a/source/blender/render/intern/source/shadeoutput.c +++ b/source/blender/render/intern/source/shadeoutput.c @@ -59,7 +59,7 @@ static ListBase *get_lights(ShadeInput *shi) if(shi->light_override) return &shi->light_override->gobject; - else if(shi->mat->group) + else if(shi->mat && shi->mat->group) return &shi->mat->group->gobject; else return &R.lights; @@ -1003,8 +1003,9 @@ void ambient_occlusion_to_diffuse(ShadeInput *shi, float *diff) /* result written in shadfac */ void lamp_get_shadow(LampRen *lar, ShadeInput *shi, float inp, float *shadfac, int do_real) { + LampShadowSubSample *lss= &(lar->shadsamp[shi->thread].s[shi->sample]); - if(do_real) { + if(do_real || lss->samplenr!=shi->samplenr) { shadfac[0]= shadfac[1]= shadfac[2]= shadfac[3]= 1.0f; @@ -1017,10 +1018,12 @@ void lamp_get_shadow(LampRen *lar, ShadeInput *shi, float inp, float *shadfac, i else if(lar->mode & LA_SHAD_RAY) { ray_shadow(shi, lar, shadfac); } + + QUATCOPY(lss->shadfac, shadfac); + lss->samplenr= shi->samplenr; } else { - float *fp= lar->shadsamp[shi->thread].shadfac[shi->sample]; - QUATCOPY(shadfac, fp); + QUATCOPY(shadfac, lss->shadfac); } } @@ -1455,6 +1458,7 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr) shr->diff[1]= shi->g*shi->emit; shr->diff[2]= shi->b*shi->emit; } + VECCOPY(shr->shad, shr->diff); /* AO pass */ if(R.wrld.mode & WO_AMB_OCC) { @@ -1501,7 +1505,7 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr) /* exposure correction */ if(R.wrld.exp!=0.0f || R.wrld.range!=1.0f) { - wrld_exposure_correct(shr->diff); + wrld_exposure_correct(shr->combined); /* has no spec! */ wrld_exposure_correct(shr->spec); } } diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c index 1b30cbf6037..a3b67f8e654 100644 --- a/source/blender/render/intern/source/zbuf.c +++ b/source/blender/render/intern/source/zbuf.c @@ -2813,9 +2813,6 @@ static int vergzvlak(const void *a1, const void *a2) return 0; } -/** -* Shade this face at this location in SCS. - */ static void shade_tra_samples_fill(ShadeSample *ssamp, int x, int y, int z, int facenr, int curmask) { @@ -2843,6 +2840,7 @@ static void shade_tra_samples_fill(ShadeSample *ssamp, int x, int y, int z, int shi++; } shi->mask= (1<samplenr= ssamp->samplenr++; shade_input_set_viewco(shi, xs, ys, (float)z); shade_input_set_uv(shi); shade_input_set_normals(shi); @@ -2862,6 +2860,7 @@ static void shade_tra_samples_fill(ShadeSample *ssamp, int x, int y, int z, int ys= (float)y + 0.5f; } shi->mask= curmask; + shi->samplenr= ssamp->samplenr++; shade_input_set_viewco(shi, xs, ys, (float)z); shade_input_set_uv(shi); shade_input_set_normals(shi); @@ -2881,9 +2880,8 @@ static int shade_tra_samples(ShadeSample *ssamp, int x, int y, int z, int facenr ShadeResult *shr= ssamp->shr; int samp; - /* if shadow or AO? */ - if(R.r.mode & R_SHADOW) - shade_samples_do_shadow(ssamp); + /* if AO? */ + shade_samples_do_AO(ssamp); /* if shade (all shadepinputs have same passflag) */ if(shi->passflag & ~(SCE_PASS_Z|SCE_PASS_INDEXOB)) { -- cgit v1.2.3