diff options
author | Ton Roosendaal <ton@blender.org> | 2007-12-01 20:55:16 +0300 |
---|---|---|
committer | Ton Roosendaal <ton@blender.org> | 2007-12-01 20:55:16 +0300 |
commit | 4ba215478f9e1d31b13ae24c4886dabc7c2d8eb1 (patch) | |
tree | bbd06c59e4028ee9c78046c9e1d36265fd0dc51a /source/blender/render | |
parent | 448a423288a08cdc2fafd13d5769dba5b60a72a6 (diff) |
Italian community request: Area light fix!
http://peach.blender.org/index.php/area-light-fix-light-not-shadow/
Now, for every possible shadow sample, an area light calculation is
done from that position.
Diffstat (limited to 'source/blender/render')
-rw-r--r-- | source/blender/render/intern/source/convertblender.c | 8 | ||||
-rw-r--r-- | source/blender/render/intern/source/rayshade.c | 3 | ||||
-rw-r--r-- | source/blender/render/intern/source/shadeoutput.c | 56 |
3 files changed, 54 insertions, 13 deletions
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index c5044e4e334..b6e0616fbbc 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -2940,8 +2940,13 @@ static void initshadowbuf(Render *re, LampRen *lar, float mat[][4]) static void area_lamp_vectors(LampRen *lar) { - float xsize= 0.5*lar->area_size, ysize= 0.5*lar->area_sizey; + float xsize= 0.5*lar->area_size, ysize= 0.5*lar->area_sizey, multifac; + /* make it smaller, so area light can be multisampled */ + multifac= 1.0f/sqrt((float)lar->ray_totsamp); + xsize *= multifac; + ysize *= multifac; + /* corner vectors */ lar->area[0][0]= lar->co[0] - xsize*lar->mat[0][0] - ysize*lar->mat[1][0]; lar->area[0][1]= lar->co[1] - xsize*lar->mat[0][1] - ysize*lar->mat[1][1]; @@ -3076,6 +3081,7 @@ static GroupObject *add_render_lamp(Render *re, Object *ob) } area_lamp_vectors(lar); + init_jitter_plane(lar); // subsamples } else lar->ray_totsamp= 0; diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 5141841e157..a9699104e01 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -579,6 +579,9 @@ void init_jitter_plane(LampRen *lar) float *fp; int x, iter=12, tot= lar->ray_totsamp; + /* test if already initialized */ + if(lar->jitter) return; + /* at least 4, or max threads+1 tables */ if(BLENDER_MAX_THREADS < 4) x= 4; else x= BLENDER_MAX_THREADS+1; diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c index 56cb226560a..dc7dab7b1ca 100644 --- a/source/blender/render/intern/source/shadeoutput.c +++ b/source/blender/render/intern/source/shadeoutput.c @@ -421,17 +421,21 @@ static double saacos_d(double fac) } /* Stoke's form factor. Need doubles here for extreme small area sizes */ -static float area_lamp_energy(float *co, float *vn, LampRen *lar) +static float area_lamp_energy(float (*area)[3], float *co, float *vn) { double fac; double vec[4][3]; /* vectors of rendered co to vertices lamp */ double cross[4][3]; /* cross products of this */ double rad[4]; /* angles between vecs */ - VECSUB(vec[0], co, lar->area[0]); - VECSUB(vec[1], co, lar->area[1]); - VECSUB(vec[2], co, lar->area[2]); - VECSUB(vec[3], co, lar->area[3]); + /* extra test for dot */ + if ( INPR(co, vn) <= 0.0f) + return 0.0f; + + VECSUB(vec[0], co, area[0]); + VECSUB(vec[1], co, area[1]); + VECSUB(vec[2], co, area[2]); + VECSUB(vec[3], co, area[3]); Normalize_d(vec[0]); Normalize_d(vec[1]); @@ -467,7 +471,35 @@ static float area_lamp_energy(float *co, float *vn, LampRen *lar) fac+= rad[3]*(vn[0]*cross[3][0]+ vn[1]*cross[3][1]+ vn[2]*cross[3][2]); if(fac<=0.0) return 0.0; - return pow(fac*lar->areasize, lar->k); // corrected for buttons size and lar->dist^2 + return fac; +} + +static float area_lamp_energy_multisample(LampRen *lar, float *co, float *vn) +{ + /* corner vectors are moved around according lamp jitter */ + float *jitlamp= lar->jitter, vec[3]; + float area[4][3], intens= 0.0f; + int a= lar->ray_totsamp; + + + while(a--) { + vec[0]= jitlamp[0]; + vec[1]= jitlamp[1]; + vec[2]= 0.0f; + Mat3MulVecfl(lar->mat, vec); + + VECADD(area[0], lar->area[0], vec); + VECADD(area[1], lar->area[1], vec); + VECADD(area[2], lar->area[2], vec); + VECADD(area[3], lar->area[3], vec); + + intens+= area_lamp_energy(area, co, vn); + + jitlamp+= 2; + } + intens /= (float)lar->ray_totsamp; + + return pow(intens*lar->areasize, lar->k); // corrected for buttons size and lar->dist^2 } static float spec(float inp, int hard) @@ -1057,10 +1089,10 @@ float lamp_get_visibility(LampRen *lar, float *co, float *lv, float *dist) /* area type has no quad or sphere option */ if(lar->type==LA_AREA) { /* area is single sided */ - if(INPR(lv, lar->vec) > 0.0f) - visifac= 1.0f; - else - visifac= 0.0f; + //if(INPR(lv, lar->vec) > 0.0f) + // visifac= 1.0f; + //else + // visifac= 0.0f; } else { switch(lar->falloff_type) @@ -1206,7 +1238,7 @@ static void shade_one_light(LampRen *lar, ShadeInput *shi, ShadeResult *shr, int /* this complex construction screams for a nicer implementation! (ton) */ if(R.r.mode & R_SHADOW) { if(ma->mode & MA_SHADOW) { - if(lar->type==LA_HEMI); + if(lar->type==LA_HEMI || lar->type==LA_AREA); else if((ma->mode & MA_RAYBIAS) && (lar->mode & LA_SHAD_RAY) && (vlr->flag & R_SMOOTH)) { float thresh= vlr->ob->smoothresh; if(inp>thresh) @@ -1233,7 +1265,7 @@ static void shade_one_light(LampRen *lar, ShadeInput *shi, ShadeResult *shr, int else { if(lar->type==LA_AREA) - inp= area_lamp_energy(shi->co, vn, lar); + inp= area_lamp_energy_multisample(lar, shi->co, vn); /* diffuse shaders (oren nayer gets inp from area light) */ if(ma->diff_shader==MA_DIFF_ORENNAYAR) is= OrenNayar_Diff(inp, vn, lv, view, ma->roughness); |