Page MenuHome

improve_tangent_shading_r47152.patch

File Metadata

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

improve_tangent_shading_r47152.patch

Index: release/scripts/startup/bl_ui/properties_material.py
===================================================================
--- release/scripts/startup/bl_ui/properties_material.py (revision 47152)
+++ release/scripts/startup/bl_ui/properties_material.py (working copy)
@@ -344,8 +344,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, Panel):
Index: source/blender/render/intern/source/shadeoutput.c
===================================================================
--- source/blender/render/intern/source/shadeoutput.c (revision 47152)
+++ source/blender/render/intern/source/shadeoutput.c (working copy)
@@ -661,7 +661,7 @@
}
/* cartoon render spec */
-static float Toon_Spec(const float n[3], const float l[3], const float v[3], float size, float smooth, int tangent)
+static float Toon_Spec(const float n[3], const float l[3], const float v[3], float factor, float size, float smooth, int tangent)
{
float h[3];
float ang;
@@ -681,7 +681,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 */
@@ -717,7 +727,7 @@
}
/* cartoon render diffuse */
-static float Toon_Diff(const float n[3], const float l[3], const float UNUSED(v[3]), float size, float smooth)
+static float Toon_Diff(const float n[3], const float l[3], const float UNUSED(v[3]), float factor, float size, float smooth)
{
float rslt, ang;
@@ -729,7 +739,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 */
@@ -1255,6 +1275,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;
@@ -1300,8 +1321,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= dot_v3v3(vn, lv);
+
+ /* tangent case; calculate fake face normal, aligned with lampvector */
if (vlr->flag & R_TANGENT) {
float cross[3], nstrand[3], blend;
@@ -1332,20 +1356,56 @@
vnor[0]= -vnor[0];vnor[1]= -vnor[1];vnor[2]= -vnor[2];
vn= vnor;
+ inp= dot_v3v3(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= dot_v3v3(t, lv);
+ tv= dot_v3v3(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= dot_v3v3(vnor, view) * dot_v3v3(vn, lv);
+ nlnv= dot_v3v3(vnor, lv) * dot_v3v3(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= dot_v3v3(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= dot_v3v3(vn, lv);
-
/* 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) {
@@ -1353,16 +1413,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;
}
}
}
@@ -1381,26 +1445,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.0f*is*is - 2.0f*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;
@@ -1412,11 +1481,8 @@
if (ma->mode & MA_SHADOW) {
if (lar->shb || (lar->mode & LA_SHAD_RAY)) {
- if (vn==vnor) /* tangent trigger */
- lamp_get_shadow(lar, shi, dot_v3v3(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.0f) {
@@ -1460,7 +1526,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))
+ 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)) {
@@ -1492,19 +1561,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: source/blender/blenkernel/BKE_blender.h
===================================================================
--- source/blender/blenkernel/BKE_blender.h (revision 47152)
+++ source/blender/blenkernel/BKE_blender.h (working copy)
@@ -42,7 +42,7 @@
* and keep comment above the defines.
* Use STRINGIFY() rather than defining with quotes */
#define BLENDER_VERSION 263
-#define BLENDER_SUBVERSION 7
+#define BLENDER_SUBVERSION 8
#define BLENDER_MINVERSION 250
#define BLENDER_MINSUBVERSION 0
Index: source/blender/blenkernel/intern/material.c
===================================================================
--- source/blender/blenkernel/intern/material.c (revision 47152)
+++ source/blender/blenkernel/intern/material.c (working copy)
@@ -115,6 +115,7 @@
ma->mirr = ma->mirg = ma->mirb = 1.0;
ma->spectra = 1.0;
ma->amb = 1.0;
+ ma->aniso = 1.0;
ma->alpha = 1.0;
ma->spec = ma->hasize = 0.5;
ma->har = 50;
Index: source/blender/makesdna/DNA_material_types.h
===================================================================
--- source/blender/makesdna/DNA_material_types.h (revision 47152)
+++ source/blender/makesdna/DNA_material_types.h (working copy)
@@ -115,6 +115,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: source/blender/makesrna/intern/rna_material.c
===================================================================
--- source/blender/makesrna/intern/rna_material.c (revision 47152)
+++ source/blender/makesrna/intern/rna_material.c (working copy)
@@ -1770,6 +1770,14 @@
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.0f, 1.0f);
+ 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",
Index: source/blender/blenlib/BLI_math_base.h
===================================================================
--- source/blender/blenlib/BLI_math_base.h (revision 47152)
+++ source/blender/blenlib/BLI_math_base.h (working copy)
@@ -47,6 +47,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
Index: source/blender/blenloader/intern/readfile.c
===================================================================
--- source/blender/blenloader/intern/readfile.c (revision 47152)
+++ source/blender/blenloader/intern/readfile.c (working copy)
@@ -7519,6 +7519,15 @@
}
}
+ if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 8))
+ {
+ 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! */
/* WATCH IT 2!: Userdef struct init has to be in editors/interface/resources.c! */
{

Event Timeline