Shamelessly resurrecting this thread :- )
Saw this over at ChaosGroup (by user Sharktacos), the code from Disney's paper (not sure which iteration though). Supposedly you can get this working in Maya through OSL. Would love to see that...
It nicely describes the parameters and how exactly do they work in the code notes. Uses only the Schlick approximation for Fresnel, but GTR version of GGX without exposing the tail ("gamma") parameter.
I wish we could get stuff like this working too, could be nice alternative shader.
You can see some interesting things it does :- ) Specular amount is not direct multiplier of specular intensity (which is physically incorrect, such phenomenon doesn't happen), but instead normalizes IOR for non-conductors to 1.0- 1.8 . Since it's linear I presume the default 0.5 equals 1.4 ?
I can see how this can be bit limiting (only up to 1.8, but that is a lot with full grazing intensity), or precise (for those who need exact 1.423 for some zirconium or whatever), but it could be exposed perhaps (like in next shader bellow, one from Arnold).
Extended paper :
http://blog.selfshadow.com/publications/s2015-shading-course//* artist friendly metal */
float n_min( float r )
{ return (1-r )/(1+ r ); }
float n_max( float r )
{ return (1+ sqrt ( r ))/(1- sqrt ( r )); }
float get_n ( float r , float g)
{ return n_min( r )*g + (1-g)*n_max( r ); }
float get_k2 ( float r , float n)
{
float nr = (n+1)*(n+1)*r-(n-1)*(n-1);
return nr/(1-r );
}
float get_r ( float n, float k)
{ return ((n-1)*(n-1)+k*k )/(( n+1)*(n+1)+k*k); }
float get_g ( float n, float k)
{
float r = get_r (n,k);
return (n_max( r)-n )/( n_max( r)-n_min( r ));
}
float AFMF ( float r , float g, float theta )
{
float _r = clamp(r ,0 ,0.99);
float n = get_n (_r ,g);
float k2 = get_k2 (_r ,n);
float c = cos ( theta );
float rs_num = n*n + k2 - 2*n*c + c*c;
float rs_den = n*n + k2 + 2*n*c + c*c;
float rs = rs_num/ rs_den ;
float rp_num = (n*n + k2)*c*c - 2*n*c + 1;
float rp_den = (n*n + k2)*c*c + 2*n*c + 1;
float rp = rp_num/ rp_den ;
return 0.5*( rs+rp );
}
//////
color getTextureDif(string texture_name, color no_texture_default_color)
{
int channels = -1;
if (gettextureinfo(texture_name, "channels", channels))
{
return texture(texture_name, u, v);
}
return no_texture_default_color;
}
float fresnelReflectionFactor(normal bumped_normal, float ior)
{
float c = abs(dot(I, bumped_normal));
float g = ior * ior - 1.0 + c * c;
if (g > 0.0) {
g = sqrt (g);
float A = (g - c) / (g + c);
float B = (c * (g + c) - 1.0) / (c * (g - c) + 1.0);
return 0.5 * A * A * (1.0 + B * B);
}
return 1.0;
}
// Schlick simplified Fresnel function, non-metal/non-metal, no polarisation.
float SchlickFresnel(normal bumped_normal, float ior)
{
float c = abs(dot(-I, bumped_normal));
float g = (1 - ior) / (1 + ior);
g = g * g;
return g + (1 - g) * pow((1 - c), 5);
}
surface
DisneyBRDFMtl
[[ string description = "Disney Principled BRDF Material" ]]
(
string Base_Color = "color.png",
float Metallic_Amount = 0
[[ string description =
"the metallic-ness (0 = dielectric, 1 = metallic). This is a linear blend between two
different models. The metallic model has no diffuse component and also has a tinted incident
specular, equal to the base color."
]],
float Specular_Amount = 0.5
[[ string description =
"incident specular amount. This is in lieu of an explicit index-of-refraction.
normalizes ior 1.0-1.8"
]],
float Specular_Tint = 0
[[ string description =
"a concession for artistic control that tints incident specular towards the base color.
Grazing specular is still achromatic."
]],
float Roughness = 0.5
[[ string description =
"surface roughness, controls both diffuse and specular response.
R = roughness^2 for diffuse & (0.5 + roughness/2)^2 for spec"
]],
float Anisotropic = 0
[[ string description =
"degree of anisotropy. This controls the aspect ratio of the specular highlight.
(0 = isotropic, 1 = maximally anisotropic)."
]],
float Anisotropic_Rotation = 0.5,
float Sheen = 0
[[ string description =
"an additional grazing component, primarily intended for cloth."
]],
float Sheen_Tint = 0.5
[[ string description =
"amount to tint sheen towards base color."
]],
float Clearcoat = 0
[[ string description =
"a second, special-purpose specular lobe. always isotropic and non-metallic.
fixed ior=1.5. Fixed roughness=0.25. Fixed GGX gamma=2. normalizes amount 0-0.25."
]],
float Clearcoat_Gloss = 1 [[ string description =
"controls clearcoat glossiness (0 = satin appearance, 1 = gloss appearance"
]],
string Opacity = "opacity.png",
int Reflection_Subdivs = 8,
float Texture_Gamma = 1,
output color result = 1
)
{
/* Define Bump */
normal bumped_normal = N;
/* Diffuse */
color OpacityColor = getTextureDif(Opacity, color(1));
color BaseColor = getTextureDif(Base_Color, color(0.5));
BaseColor = pow(BaseColor, Texture_Gamma);
float Kd = 1;
//is there an amount?
/* Specular */
float IOR_disable = 0;
float Tail = 2.0;
float RoughnessGGX = 0;
/* Spec amount - remaps ior to normalized value */
float SpecAmount = clamp(Specular_Amount,0,1); //set min-max to 0-1
// remapping: b1 + (s-a1)*(b2-b1)/(a2-a1)
float IOR = 1 + SpecAmount*0.8; //in lieu of an explicit index-of-refraction. Normalizes ior 1.0-1.8
color Fresnel = SchlickFresnel(bumped_normal, IOR); //Fresnel_Amount
/* Spec tint */
float SpecTintAmount = clamp(Specular_Tint,0,1); //set min-max to 0-1
color TintColor= mix(1,BaseColor,SpecTintAmount); //mix between baseColor and white based on Specular_Tint amount
color Tint = mix(TintColor,1,Fresnel); //mix between tintColor and white based on Fresnel
Fresnel *= Tint; //tints incident specular towards the base color. Grazing specular is still achromatic.
Fresnel *= Specular_Amount;
/* Metallic */
color BaseMetal = pow(BaseColor,2.2);
color Edgetint = pow(BaseColor,0.2);
float thetaB = acos(dot(-I,N));
float RCH = AFMF(BaseMetal[0],Edgetint[0],thetaB);
float GCH = AFMF(BaseMetal[1],Edgetint[1],thetaB);
float BCH = AFMF(BaseMetal[2],Edgetint[2],thetaB);
float MetallicAmount = clamp(Metallic_Amount,0,1); //set min-max to 0-1. 0 = dielectric, 1 = metallic
Kd = 1 - MetallicAmount; //The metallic model has no diffuse component
color Metallic = mix(BaseMetal,Edgetint,Fresnel); // Metallic has tinted incident specular, equal to the base color.
// color Metallic = color(RCH,GCH,BCH);
color SpecColor = mix(Fresnel,Metallic,MetallicAmount); // linear blend between dielectric & metallic
/* Anisotropy */
float AniAmount = clamp(Anisotropic,0,1); //set min-max to 0-1
float AniRotation = clamp(Anisotropic_Rotation,0,1); //set min-max to 0-1
AniRotation *= 10; // not sure why this works...
/* Define Sheen */
float SheenAmount = clamp(Sheen,0,1); //set min-max to 0-1
float SheenTintAmount = clamp(Sheen_Tint,0,1); //set min-max to 0-1
float facingRatio = 1 - abs(dot(I, bumped_normal));
SheenTintAmount *= 2; // intensify tint amount
color TintBoost = transformc("hsl", BaseColor);
TintBoost[2] = TintBoost[2] + 0.5; // make the tint a brighter version of the mainColor
TintBoost[2] = clamp(TintBoost[2],0,1);
TintBoost = transformc("hsl","rgb", TintBoost);
color EdgeColor = color(0.25,0.25,0.25);
color TintEdge = EdgeColor * TintBoost; //colorize sheen with the tint
EdgeColor = mix (EdgeColor, TintEdge, SheenTintAmount); //mix between tinted & untinted sheen based on tint value
EdgeColor = clamp (EdgeColor, 0, 1);
color SheenMix = EdgeColor * facingRatio * SheenAmount;
BaseColor += SheenMix;
/* Roughness */
float RoughnessAmount = clamp(Roughness,0,1); //set min-max to 0-1
float DifRoughness = pow(RoughnessAmount,2);
float SpecRoughness = RoughnessAmount; // paper uses pow((0.5 + RoughnessAmount/2),2) in BRDF
/* diffuse */
color BaseLess = BaseColor * 0.5; // reduce diffuse by 0.5 at grazing angles for smooth surfaces
color BaseMore = BaseColor * 2.5; // increase diffuse by up to 2.5 at grazing angles for rough surfaces.
color BaseEdge = mix(BaseLess,BaseMore,RoughnessAmount);
//BaseColor = mix(BaseColor,BaseEdge,Fresnel);
/* Clearcoat */
float ClearcoatAmount = clamp(Clearcoat,0,1); //set min-max to 0-1
float ClearcoatGloss = clamp(Clearcoat_Gloss,0,1); //set min-max to 0-1
ClearcoatAmount *= 0.25; //normalizes amount 0-0.25
float ClearIOR = 1.5; // fixed ior
closure color difMain = BaseColor * Kd *
diffuse(bumped_normal, "roughness", DifRoughness);
closure color spcMain = SpecColor *
microfacet_ggx (bumped_normal, SpecRoughness, IOR_disable,
"gtr_gamma", Tail,
"subdivs", Reflection_Subdivs,
"anisotropy", AniAmount,
"aniso_rotation", AniRotation
);
closure color spcClearcoat = ClearcoatAmount *
microfacet_ggx (bumped_normal, RoughnessGGX, ClearIOR,
"gtr_gamma", Tail,
"reflection_glossiness", ClearcoatGloss,
"highlight_glossiness", ClearcoatGloss,
"subdivs", Reflection_Subdivs
);
Ci = OpacityColor * difMain + spcMain + spcClearcoat + (1.0 - OpacityColor) * transparent();
//Ci = OpacityColor * difMain + (1.0 - OpacityColor) * transparent();
}
« Last Edit: 2016-07-03, 18:51:37 by Juraj_Talcik »
Logged
Please follow my new
Instagram for latest projects, tips&tricks, short video tutorials and free models
Behance Probably best updated portfolio of my work
lysfaere.com Please check the new stuff!