/* * Copyright 2011-2017 Blender Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "stdosl.h" #include "node_fresnel.h" shader node_principled_bsdf( string distribution = "Multiscatter GGX", color BaseColor = color(0.8, 0.8, 0.8), float Subsurface = 0.0, vector SubsurfaceRadius = vector(1.0, 1.0, 1.0), color SubsurfaceColor = color(0.7, 0.1, 0.1), float Metallic = 0.0, float Specular = 0.5, float SpecularTint = 0.0, float Roughness = 0.5, float Anisotropic = 0.0, float AnisotropicRotation = 0.0, float Sheen = 0.0, float SheenTint = 0.5, float Clearcoat = 0.0, float ClearcoatRoughness = 0.03, float IOR = 1.45, float Transmission = 0.0, float TransmissionRoughness = 0.0, normal Normal = N, normal ClearcoatNormal = N, normal Tangent = normalize(dPdu), output closure color BSDF = 0) { float f = max(IOR, 1e-5); float diffuse_weight = (1.0 - clamp(Metallic, 0.0, 1.0)) * (1.0 - clamp(Transmission, 0.0, 1.0)); float final_transmission = clamp(Transmission, 0.0, 1.0) * (1.0 - clamp(Metallic, 0.0, 1.0)); float specular_weight = (1.0 - final_transmission); vector T = Tangent; float m_cdlum = luminance(BaseColor); color m_ctint = m_cdlum > 0.0 ? BaseColor / m_cdlum : color(0.0, 0.0, 0.0); // normalize lum. to isolate hue+sat /* rotate tangent */ if (AnisotropicRotation != 0.0) T = rotate(T, AnisotropicRotation * M_2PI, point(0.0, 0.0, 0.0), Normal); if (diffuse_weight > 1e-5) { if (Subsurface > 1e-5) { color mixed_ss_base_color = SubsurfaceColor * Subsurface + BaseColor * (1.0 - Subsurface); BSDF = mixed_ss_base_color * bssrdf_principled(Normal, Subsurface * SubsurfaceRadius, 0.0, SubsurfaceColor, Roughness); } else { BSDF = BaseColor * principled_diffuse(Normal, Roughness); } if (Sheen > 1e-5) { color sheen_color = color(1.0, 1.0, 1.0) * (1.0 - SheenTint) + m_ctint * SheenTint; BSDF = BSDF + sheen_color * Sheen * principled_sheen(Normal); } BSDF = BSDF * diffuse_weight; } if (specular_weight > 1e-5) { float aspect = sqrt(1.0 - Anisotropic * 0.9); float r2 = Roughness * Roughness; float alpha_x = r2 / aspect; float alpha_y = r2 * aspect; color tmp_col = color(1.0, 1.0, 1.0) * (1.0 - SpecularTint) + m_ctint * SpecularTint; color Cspec0 = (Specular * 0.08 * tmp_col) * (1.0 - Metallic) + BaseColor * Metallic; if (distribution == "GGX" || Roughness <= 0.075) { BSDF = BSDF + specular_weight * microfacet_ggx_aniso_fresnel(Normal, T, alpha_x, alpha_y, (2.0 / (1.0 - sqrt(0.08 * Specular))) - 1.0, BaseColor, Cspec0); } else { BSDF = BSDF + specular_weight * microfacet_multi_ggx_aniso_fresnel(Normal, T, alpha_x, alpha_y, (2.0 / (1.0 - sqrt(0.08 * Specular))) - 1.0, BaseColor, Cspec0); } } if (final_transmission > 1e-5) { color Cspec0 = BaseColor * SpecularTint + color(1.0, 1.0, 1.0) * (1.0 - SpecularTint); float eta = backfacing() ? 1.0 / f : f; if (distribution == "GGX" || Roughness <= 5e-2) { float cosNO = dot(Normal, I); float Fr = fresnel_dielectric_cos(cosNO, eta); float refl_roughness = Roughness; if (Roughness <= 1e-2) refl_roughness = 0.0; float transmission_roughness = refl_roughness; if (distribution == "GGX") transmission_roughness = 1.0 - (1.0 - refl_roughness) * (1.0 - TransmissionRoughness); BSDF = BSDF + final_transmission * (Fr * microfacet_ggx_fresnel(Normal, refl_roughness * refl_roughness, eta, BaseColor, Cspec0) + (1.0 - Fr) * BaseColor * microfacet_ggx_refraction(Normal, transmission_roughness * transmission_roughness, eta)); } else { BSDF = BSDF + final_transmission * microfacet_multi_ggx_glass_fresnel(Normal, Roughness * Roughness, eta, BaseColor, Cspec0); } } if (Clearcoat > 1e-5) { BSDF = BSDF + principled_clearcoat(ClearcoatNormal, Clearcoat, ClearcoatRoughness * ClearcoatRoughness); } }