Index: source/blender/render/intern/source/shadeoutput.c =================================================================== --- source/blender/render/intern/source/shadeoutput.c (revision 14882) +++ source/blender/render/intern/source/shadeoutput.c (working copy) @@ -666,9 +666,9 @@ } /* Ward isotropic gaussian spec */ -static float WardIso_Spec( float *n, float *l, float *v, float rms, int tangent) +static float WardIso_Spec(float *n, float *l, float *v, float rms, int tangent) { - float i, nh, nv, nl, h[3], angle, alpha; + float i, nh, nv, nl, h[3], angle, alpha, alpha2; /* half-way vector */ @@ -692,13 +692,54 @@ angle = tan(saacos(nh)); alpha = MAX2(rms, 0.001f); - i= nl * (1.0f/(4.0f*M_PI*alpha*alpha)) * (exp( -(angle*angle)/(alpha*alpha))/(sqrt(nv*nl))); + alpha2 = alpha * alpha; + i= nl * (1.0f/(4.0f*M_PI*alpha2)) * (exp( -(angle*angle)/alpha2)/(sqrt(nv*nl))); return i; } +/* Beckmann spec */ +static float Beckmann_Spec(float *n, float *l, float *v, float slope, float gloss, int phong_hard, int tangent) +{ + float i, nh, a, b, c, d, e, h[3], angle; + + /* Half-way vector */ + h[0] = l[0] + v[0]; + h[1] = l[1] + v[1]; + h[2] = l[2] + v[2]; + Normalize(h); + + /* Dot product between surface normal and half-way vector */ + nh = n[0]*h[0] + n[1]*h[1] + n[2]*h[2]; + if (tangent) nh = sasqrt(1.0f - nh*nh); + if (nh <= 0.0f) nh = 0.001f; + + /* Use the Beckmann distribution to calculate the specular light */ + angle = saacos(nh); + a = tan(angle) / slope; + b = cos(angle); + c = b * b; + d = - (a * b); + e = 4.0f * slope * slope * c * c; + i = exp(d) / e; + + /* Add some phong highlight */ + if (gloss > 0.0f) { + if (nh > 0.0f) nh = spec(angle, phong_hard); + else nh = 0.0f; + i = i*(1.0f - gloss) + nh*gloss; + } + + /* Make sure it's within range */ + if (i < 0.0f) i = 0.0f; + else if (i > 1.0f) i = 1.0f; + + return i; + +} + /* 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 size, float smooth) { float rslt, ang; @@ -717,11 +758,12 @@ /* 'nl' is either dot product, or return value of area light */ /* in latter case, only last multiplication uses 'nl' */ -static float OrenNayar_Diff(float nl, float *n, float *l, float *v, float rough ) +static float OrenNayar_Diff(float nl, float *n, float *l, float *v, float rough) { float i, nh, nv, vh, realnl, h[3]; float a, b, t, A, B; float Lit_A, View_A, Lit_B[3], View_B[3]; + float rough2; h[0]= v[0]+l[0]; h[1]= v[1]+l[1]; @@ -766,8 +808,9 @@ b = Lit_A; } - A = 1.0f - (0.5f * ((rough * rough) / ((rough * rough) + 0.33f))); - B = 0.45f * ((rough * rough) / ((rough * rough) + 0.09f)); + rough2 = rough * rough; + A = 1.0f - (0.5f * (rough2 / (rough2 + 0.33f))); + B = 0.45f * (rough2 / (rough2 + 0.09f)); b*= 0.95f; /* prevent tangens from shooting to inf, 'nl' can be not a dot product here. */ /* overflow only happens with extreme size area light, and higher roughness */ @@ -1416,8 +1459,10 @@ specfac= Blinn_Spec(vn, lv, view, ma->refrac, (float)shi->har, (vlr->flag & R_TANGENT) || (ma->mode & MA_TANGENT_V)); 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)); - else + else if(ma->spec_shader==MA_SPEC_TOON) specfac= Toon_Spec(vn, lv, view, ma->param[2], ma->param[3], (vlr->flag & R_TANGENT) || (ma->mode & MA_TANGENT_V)); + else + specfac= Beckmann_Spec(vn, lv, view, ma->slope, ma->gloss, 40.0f, (vlr->flag & R_TANGENT) || (ma->mode & MA_TANGENT_V)); /* area lamp correction */ if(lar->type==LA_AREA) specfac*= inp; Index: source/blender/python/api2_2x/Material.c =================================================================== --- source/blender/python/api2_2x/Material.c (revision 14882) +++ source/blender/python/api2_2x/Material.c (working copy) @@ -396,6 +396,7 @@ PyConstant_Insert(c, "SPEC_BLINN", PyInt_FromLong(MA_SPEC_BLINN)); PyConstant_Insert(c, "SPEC_TOON", PyInt_FromLong(MA_SPEC_TOON)); PyConstant_Insert(c, "SPEC_WARDISO", PyInt_FromLong(MA_SPEC_WARDISO)); + PyConstant_Insert(c, "SPEC_BECKMANN", PyInt_FromLong(MA_SPEC_BECKMANN)); } Index: source/blender/blenkernel/intern/material.c =================================================================== --- source/blender/blenkernel/intern/material.c (revision 14882) +++ source/blender/blenkernel/intern/material.c (working copy) @@ -123,6 +123,7 @@ ma->param[3]= 0.1; ma->rms= 0.1; ma->darkness= 1.0; + ma->slope= 0.1; ma->strand_sta= ma->strand_end= 1.0f; Index: source/blender/makesdna/DNA_material_types.h =================================================================== --- source/blender/makesdna/DNA_material_types.h (revision 14882) +++ source/blender/makesdna/DNA_material_types.h (working copy) @@ -100,6 +100,7 @@ float param[4]; /* size, smooth, size, smooth, for toonshader */ float rms; float darkness; + float slope, gloss; short texco, mapto; /* ramp colors */ @@ -217,6 +218,7 @@ #define MA_SPEC_BLINN 2 #define MA_SPEC_TOON 3 #define MA_SPEC_WARDISO 4 +#define MA_SPEC_BECKMANN 5 /* dynamode */ #define MA_DRAW_DYNABUTS 1 Index: source/blender/src/buttons_shading.c =================================================================== --- source/blender/src/buttons_shading.c (revision 14882) +++ source/blender/src/buttons_shading.c (working copy) @@ -3868,7 +3868,7 @@ } else { char *str1= "Diffuse Shader%t|Lambert %x0|Oren-Nayar %x1|Toon %x2|Minnaert %x3|Fresnel %x4"; - char *str2= "Specular Shader%t|CookTorr %x0|Phong %x1|Blinn %x2|Toon %x3|WardIso %x4"; + char *str2= "Specular Shader%t|CookTorr %x0|Phong %x1|Blinn %x2|Toon %x3|WardIso %x4|Beckmann %x5"; /* diff shader buttons */ uiDefButS(block, MENU, B_MATPRV, str1, 9, 180,78,19, &(ma->diff_shader), 0.0, 0.0, 0, 0, "Creates a diffuse shader"); @@ -3905,6 +3905,10 @@ } if(ma->spec_shader==MA_SPEC_WARDISO) uiDefButF(block, NUMSLI, B_MATPRV, "rms:", 90, 100,150,19, &(ma->rms), 0.0, 0.4, 0, 0, "Sets the standard deviation of surface slope"); + if(ma->spec_shader==MA_SPEC_BECKMANN) { + uiDefButF(block, NUMSLI, B_MATPRV, "Slope:", 90, 100,150,19, &(ma->slope), 0.0, 0.4, 0, 0, "Sets the average slope of the microfacets"); + uiDefButF(block, NUMSLI, B_MATPRV, "Gloss:", 90, 80,150,19, &(ma->gloss), 0.0, 1.0, 0, 0, "Set the amount of added gloss"); + } /* default shading variables */ uiBlockBeginAlign(block); uiDefButF(block, NUMSLI, B_MATPRV, "Tralu ", 9,30,150,19, &(ma->translucency), 0.0, 1.0, 100, 2, "Translucency, amount of diffuse shading of the back side"); Index: source/blender/blenloader/intern/readfile.c =================================================================== --- source/blender/blenloader/intern/readfile.c (revision 14882) +++ source/blender/blenloader/intern/readfile.c (working copy) @@ -6137,6 +6137,7 @@ if(ma->darkness==0.0) { ma->rms=0.1f; ma->darkness=1.0f; + ma->slope=0.1f; } }