Page MenuHome

improve_tangent_shading.patch

File Metadata

Author
Shinsuke Irie (irie)
Created
Nov 13 2013, 3:15 PM

improve_tangent_shading.patch

Index: blender/release/scripts/startup/bl_ui/properties_material.py
===================================================================
--- blender/release/scripts/startup/bl_ui/properties_material.py (revision 35788)
+++ blender/release/scripts/startup/bl_ui/properties_material.py (working copy)
@@ -339,8 +339,11 @@
col.prop(mat, "use_shadeless")
sub = col.column()
sub.active = not mat.use_shadeless
+ sub.prop(mat, "use_cubic")
sub.prop(mat, "use_tangent_shading")
- sub.prop(mat, "use_cubic")
+ sub = col.column()
+ sub.active = not mat.use_shadeless and mat.use_tangent_shading
+ sub.prop(mat, "anisotropy")
class MATERIAL_PT_transp(MaterialButtonsPanel, bpy.types.Panel):
Index: blender/source/blender/render/intern/source/shadeoutput.c
===================================================================
--- blender/source/blender/render/intern/source/shadeoutput.c (revision 35788)
+++ blender/source/blender/render/intern/source/shadeoutput.c (working copy)
@@ -649,7 +649,7 @@
}
/* cartoon render spec */
-static float Toon_Spec( float *n, float *l, float *v, float size, float smooth, int tangent)
+static float Toon_Spec( float *n, float *l, float *v, float factor, float size, float smooth, int tangent)
{
float h[3];
float ang;
@@ -669,7 +669,17 @@
else if( ang >= (size + smooth) || smooth == 0.0f ) rslt = 0.0f;
else rslt = 1.0f - ((ang - size) / smooth);
- return rslt;
+ if(factor < 1.0f) {
+ ang = saacos( factor );
+
+ if( ang < (M_PI_2 - smooth) ) factor = 1.0f;
+ else if( ang >= M_PI_2 || smooth == 0.0f ) factor = 0.0f;
+ else factor = (M_PI_2 - ang) / smooth;
+
+ return rslt*factor;
+ }
+ else
+ return rslt;
}
/* Ward isotropic gaussian spec */
@@ -705,7 +715,7 @@
}
/* cartoon render diffuse */
-static float Toon_Diff( float *n, float *l, float *v, float size, float smooth )
+static float Toon_Diff( float *n, float *l, float *v, float factor, float size, float smooth )
{
float rslt, ang;
@@ -717,7 +727,17 @@
else if( ang >= (size + smooth) || smooth == 0.0f ) rslt = 0.0f;
else rslt = 1.0f - ((ang - size) / smooth);
- return rslt;
+ if(factor < 1.0f) {
+ ang = saacos( (double)(factor) );
+
+ if( ang < (M_PI_2 - smooth) ) factor = 1.0f;
+ else if( ang >= M_PI_2 || smooth == 0.0f ) factor = 0.0f;
+ else factor = (M_PI_2 - ang) / smooth;
+
+ return rslt*factor;
+ }
+ else
+ return rslt;
}
/* Oren Nayar diffuse */
@@ -1225,6 +1245,7 @@
VlakRen *vlr= shi->vlr;
float lv[3], lampdist, lacol[3], shadfac[4], lashdw[3];
float i, is, i_noshad, inp, *vn, *view, vnor[3], phongcorr=1.0f;
+ float inpshad, tangfac, toonfac= 1.0f;
float visifac;
vn= shi->vn;
@@ -1270,8 +1291,11 @@
if(lar->mode & LA_TEXTURE) do_lamp_tex(lar, lv, shi, lacol, LA_TEXTURE);
if(lar->mode & LA_SHAD_TEX) do_lamp_tex(lar, lv, shi, lashdw, LA_SHAD_TEX);
- /* tangent case; calculate fake face normal, aligned with lampvector */
- /* note, vnor==vn is used as tangent trigger for buffer shadow */
+ /* dot product and reflectivity */
+ /* inp = dotproduct, is = shader result, i = lamp energy (with shadow), i_noshad = i without shadow */
+ inp= inpshad= INPR(vn, lv);
+
+ /* tangent case; calculate fake face normal, aligned with lampvector */
if(vlr->flag & R_TANGENT) {
float cross[3], nstrand[3], blend;
@@ -1302,20 +1326,56 @@
vnor[0]= -vnor[0];vnor[1]= -vnor[1];vnor[2]= -vnor[2];
vn= vnor;
+ inp= INPR(vn, lv);
}
else if (ma->mode & MA_TANGENT_V) {
- float cross[3];
- cross_v3_v3v3(cross, lv, shi->tang);
- cross_v3_v3v3(vnor, cross, shi->tang);
- normalize_v3(vnor);
- vnor[0]= -vnor[0];vnor[1]= -vnor[1];vnor[2]= -vnor[2];
- vn= vnor;
- }
+ float t[3], tl, tv, sr1tl2, sr1tv2, nvnl, nlnv;
+
+ if(equals_v3v3(vn, shi->vno)) {
+ VECCOPY(t, shi->tang);
+ } else {
+ /* normalize tangent vector for normal mapping */
+ normalize_v3_v3(t, shi->tang);
+ }
+
+ /* calculate fake face normal */
+ /* l' = (t x l) x t / |(t x l) x t| */
+ /* v' = (t x v) x t / |(t x v) x t| */
+ /* n' = (l' + v') / |l' + v'| */
+ tl= INPR(t, lv);
+ tv= INPR(t, view);
+ sr1tl2= sasqrt(1.0f - tl*tl);
+ sr1tv2= sasqrt(1.0f - tv*tv);
+
+ vnor[0]= sr1tv2*(lv[0] - tl*t[0]) + sr1tl2*(view[0] - tv*t[0]);
+ vnor[1]= sr1tv2*(lv[1] - tl*t[1]) + sr1tl2*(view[1] - tv*t[1]);
+ vnor[2]= sr1tv2*(lv[2] - tl*t[2]) + sr1tl2*(view[2] - tv*t[2]);
+
+ if(normalize_v3(vnor)) {
+
+ /* anisotropy */
+ interp_v3_v3v3(vnor, vn, vnor, ma->aniso);
+ normalize_v3(vnor);
+
+ /* estimate self-shadowing or self-occlusion */
+ nvnl= INPR(vnor, view) * INPR(vn, lv);
+ nlnv= INPR(vnor, lv) * INPR(vn, view);
+
+ if(nvnl < nlnv)
+ tangfac= (nvnl > 0.0f) ? nvnl/nlnv : 0.0f; /* microscale self-shadowing */
+ else
+ tangfac= (nlnv > 0.0f) ? nlnv/nvnl : 0.0f; /* microscale self-occlusion */
+
+ tangfac= (saasin(tangfac) + tangfac * sasqrt(1.0f - tangfac * tangfac)) * M_2_PI;
+
+ /* change face normal and dot product for both diffuse and specular */
+ vn= vnor;
+ inp= INPR(vn, lv);
+ }
+ else
+ tangfac= 1.0f;
+ }
- /* dot product and reflectivity */
- /* inp = dotproduct, is = shader result, i = lamp energy (with shadow), i_noshad = i without 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) */
/* this complex construction screams for a nicer implementation! (ton) */
if(R.r.mode & R_SHADOW) {
@@ -1323,16 +1383,20 @@
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= shi->obr->ob->smoothresh;
- if(inp>thresh)
- phongcorr= (inp-thresh)/(inp*(1.0f-thresh));
+ if(inpshad>thresh)
+ phongcorr= (inpshad-thresh)/(inpshad*(1.0f-thresh));
else
phongcorr= 0.0f;
+
+ if(ma->mode & MA_TANGENT_V) toonfac= phongcorr*inpshad;
}
else if(ma->sbias!=0.0f && ((lar->mode & LA_SHAD_RAY) || lar->shb)) {
- if(inp>ma->sbias)
- phongcorr= (inp-ma->sbias)/(inp*(1.0f-ma->sbias));
+ if(inpshad>ma->sbias)
+ phongcorr= (inpshad-ma->sbias)/(inpshad*(1.0f-ma->sbias));
else
phongcorr= 0.0f;
+
+ if(ma->mode & MA_TANGENT_V) toonfac= phongcorr*inpshad;
}
}
}
@@ -1351,26 +1415,31 @@
/* 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);
- else if(ma->diff_shader==MA_DIFF_TOON) is= Toon_Diff(vn, lv, view, ma->param[0], ma->param[1]);
+ else if(ma->diff_shader==MA_DIFF_TOON) is= Toon_Diff(vn, lv, view, toonfac, ma->param[0], ma->param[1]);
else if(ma->diff_shader==MA_DIFF_MINNAERT) is= Minnaert_Diff(inp, vn, view, ma->darkness);
else if(ma->diff_shader==MA_DIFF_FRESNEL) is= Fresnel_Diff(vn, lv, view, ma->param[0], ma->param[1]);
else is= inp; // Lambert
+
+ /* tangent shading correction */
+ if((ma->mode & MA_TANGENT_V) && (ma->diff_shader!=MA_DIFF_TOON)) is*= tangfac;
}
/* 'is' is diffuse */
if((ma->shade_flag & MA_CUBIC) && is>0.0f && is<1.0f)
is= 3.0*is*is - 2.0*is*is*is; // nicer termination of shades
- i= is*phongcorr;
+ if((ma->mode & MA_TANGENT_V) && (ma->diff_shader==MA_DIFF_TOON))
+ i= is;
+ else
+ i= is*phongcorr;
if(i>0.0f) {
i*= visifac*shi->refl;
}
i_noshad= i;
- vn= shi->vn; // bring back original vector, we use special specular shaders for tangent
- if(ma->mode & MA_TANGENT_V)
- vn= shi->tang;
+ if(vlr->flag & R_TANGENT)
+ vn= shi->vn; // bring back original vector, we use special specular shaders for strand
/* init transp shadow */
shadfac[0]= shadfac[1]= shadfac[2]= shadfac[3]= 1.0f;
@@ -1382,11 +1451,8 @@
if(ma->mode & MA_SHADOW) {
if(lar->shb || (lar->mode & LA_SHAD_RAY)) {
- if(vn==vnor) /* tangent trigger */
- lamp_get_shadow(lar, shi, INPR(shi->vn, lv), shadfac, shi->depth);
- else
- lamp_get_shadow(lar, shi, inp, shadfac, shi->depth);
-
+ lamp_get_shadow(lar, shi, inpshad, shadfac, shi->depth);
+
/* warning, here it skips the loop */
if((lar->mode & LA_ONLYSHADOW) && i>0.0) {
@@ -1430,7 +1496,10 @@
}
/* specularity */
- shadfac[3]*= phongcorr; /* note, shadfac not allowed to be stored nonlocal */
+ if(!(ma->mode & MA_TANGENT_V) || (ma->spec_shader!=MA_SPEC_TOON) || (lar->type==LA_HEMI))
+ shadfac[3]*= phongcorr; /* note, shadfac not allowed to be stored nonlocal */
+ else if(phongcorr == 0.0f)
+ shadfac[3]= 0.0f;
if(shadfac[3]>0.0f && shi->spec!=0.0f && !(lar->mode & LA_NO_SPEC) && !(lar->mode & LA_ONLYSHADOW)) {
@@ -1462,19 +1531,22 @@
float specfac, t;
if(ma->spec_shader==MA_SPEC_PHONG)
- specfac= Phong_Spec(vn, lv, view, shi->har, (vlr->flag & R_TANGENT) || (ma->mode & MA_TANGENT_V));
+ specfac= Phong_Spec(vn, lv, view, shi->har, vlr->flag & R_TANGENT);
else if(ma->spec_shader==MA_SPEC_COOKTORR)
- specfac= CookTorr_Spec(vn, lv, view, shi->har, (vlr->flag & R_TANGENT) || (ma->mode & MA_TANGENT_V));
+ specfac= CookTorr_Spec(vn, lv, view, shi->har, vlr->flag & R_TANGENT);
else if(ma->spec_shader==MA_SPEC_BLINN)
- specfac= Blinn_Spec(vn, lv, view, ma->refrac, (float)shi->har, (vlr->flag & R_TANGENT) || (ma->mode & MA_TANGENT_V));
+ specfac= Blinn_Spec(vn, lv, view, ma->refrac, (float)shi->har, vlr->flag & R_TANGENT);
else if(ma->spec_shader==MA_SPEC_WARDISO)
- specfac= WardIso_Spec( vn, lv, view, ma->rms, (vlr->flag & R_TANGENT) || (ma->mode & MA_TANGENT_V));
+ specfac= WardIso_Spec( vn, lv, view, ma->rms, vlr->flag & R_TANGENT);
else
- specfac= Toon_Spec(vn, lv, view, ma->param[2], ma->param[3], (vlr->flag & R_TANGENT) || (ma->mode & MA_TANGENT_V));
+ specfac= Toon_Spec(vn, lv, view, toonfac, ma->param[2], ma->param[3], vlr->flag & R_TANGENT);
/* area lamp correction */
if(lar->type==LA_AREA) specfac*= inp;
+ /* tangent shading correction */
+ if((ma->mode & MA_TANGENT_V) && (ma->spec_shader!=MA_SPEC_TOON)) specfac*= tangfac;
+
t= shadfac[3]*shi->spec*visifac*specfac;
if(ma->mode & MA_RAMP_SPEC) {
Index: blender/source/blender/blenkernel/intern/material.c
===================================================================
--- blender/source/blender/blenkernel/intern/material.c (revision 35788)
+++ blender/source/blender/blenkernel/intern/material.c (working copy)
@@ -113,6 +113,7 @@
ma->mirr= ma->mirg= ma->mirb= 1.0;
ma->spectra= 1.0;
ma->amb= 1.0;
+ ma->aniso= 0.8;
ma->alpha= 1.0;
ma->spec= ma->hasize= 0.5;
ma->har= 50;
Index: blender/source/blender/makesdna/DNA_material_types.h
===================================================================
--- blender/source/blender/makesdna/DNA_material_types.h (revision 35788)
+++ blender/source/blender/makesdna/DNA_material_types.h (working copy)
@@ -106,6 +106,7 @@
float dist_mir;
short fadeto_mir;
short shade_flag; /* like Cubic interpolation */
+ float aniso, pad4;
int mode, mode_l; /* mode_l is the or-ed result of all layer modes */
short flarec, starc, linec, ringc;
Index: blender/source/blender/makesrna/intern/rna_material.c
===================================================================
--- blender/source/blender/makesrna/intern/rna_material.c (revision 35788)
+++ blender/source/blender/makesrna/intern/rna_material.c (working copy)
@@ -1636,6 +1636,12 @@
RNA_def_property_ui_text(prop, "Translucency", "Amount of diffuse shading on the back side");
RNA_def_property_update(prop, 0, "rna_Material_update");
+ prop= RNA_def_property(srna, "anisotropy", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "aniso");
+ RNA_def_property_range(prop, 0, 1);
+ RNA_def_property_ui_text(prop, "Anisotropy", "Anisotropy of diffuse and specular, from 0.0 (isotropic) to 1.0 (fully anisotropic along the tangent)");
+ RNA_def_property_update(prop, 0, "rna_Material_update");
+
prop= RNA_def_property(srna, "use_cubic", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "shade_flag", MA_CUBIC);
RNA_def_property_ui_text(prop, "Cubic Interpolation", "Use cubic interpolation for diffuse values, for smoother transitions");
Index: blender/source/blender/blenloader/intern/readfile.c
===================================================================
--- blender/source/blender/blenloader/intern/readfile.c (revision 35788)
+++ blender/source/blender/blenloader/intern/readfile.c (working copy)
@@ -11562,7 +11562,11 @@
/* put compatibility code here until next subversion bump */
{
-
+ Material *ma;
+
+ for(ma = main->mat.first; ma; ma = ma->id.next){
+ ma->aniso = 1.0f;
+ }
}
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
Index: blender/source/blender/blenlib/BLI_math_base.h
===================================================================
--- blender/source/blender/blenlib/BLI_math_base.h (revision 35788)
+++ blender/source/blender/blenlib/BLI_math_base.h (working copy)
@@ -45,6 +45,9 @@
#ifndef M_PI_2
#define M_PI_2 1.57079632679489661923
#endif
+#ifndef M_2_PI
+#define M_2_PI 0.63661977236758134308
+#endif
#ifndef M_SQRT2
#define M_SQRT2 1.41421356237309504880
#endif

Event Timeline