(function (global, factory) { if (typeof define === "function" && define.amd) { define(["exports", "../ShaderNode.js"], factory); } else if (typeof exports !== "undefined") { factory(exports, require("../ShaderNode.js")); } else { var mod = { exports: {} }; factory(mod.exports, global.ShaderNode); global.BSDFs = mod.exports; } })(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : this, function (_exports, _ShaderNode) { "use strict"; Object.defineProperty(_exports, "__esModule", { value: true }); _exports.getDistanceAttenuation = _exports.V_GGX_SmithCorrelated = _exports.RE_Direct_Physical = _exports.PhysicalLightingModel = _exports.F_Schlick = _exports.D_GGX = _exports.BRDF_Specular_GGX = _exports.BRDF_Lambert = void 0; var F_Schlick = new _ShaderNode.ShaderNode(function (inputs) { var f0 = inputs.f0, f90 = inputs.f90, dotVH = inputs.dotVH; // Original approximation by Christophe Schlick '94 // float fresnel = pow( 1.0 - dotVH, 5.0 ); // Optimized variant (presented by Epic at SIGGRAPH '13) // https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf var fresnel = (0, _ShaderNode.exp2)((0, _ShaderNode.mul)((0, _ShaderNode.sub)((0, _ShaderNode.mul)(-5.55473, dotVH), 6.98316), dotVH)); return (0, _ShaderNode.add)((0, _ShaderNode.mul)(f0, (0, _ShaderNode.sub)(1.0, fresnel)), (0, _ShaderNode.mul)(f90, fresnel)); }); // validated _exports.F_Schlick = F_Schlick; var BRDF_Lambert = new _ShaderNode.ShaderNode(function (inputs) { return (0, _ShaderNode.mul)(_ShaderNode.RECIPROCAL_PI, inputs.diffuseColor); // punctual light }); // validated _exports.BRDF_Lambert = BRDF_Lambert; var getDistanceAttenuation = new _ShaderNode.ShaderNode(function (inputs) { var lightDistance = inputs.lightDistance, cutoffDistance = inputs.cutoffDistance, decayExponent = inputs.decayExponent; return (0, _ShaderNode.cond)((0, _ShaderNode.and)((0, _ShaderNode.greaterThan)(cutoffDistance, 0), (0, _ShaderNode.greaterThan)(decayExponent, 0)), (0, _ShaderNode.pow)((0, _ShaderNode.saturate)((0, _ShaderNode.add)((0, _ShaderNode.div)((0, _ShaderNode.negate)(lightDistance), cutoffDistance), 1.0)), decayExponent), 1.0); }); // validated // // STANDARD // // Moving Frostbite to Physically Based Rendering 3.0 - page 12, listing 2 // https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf _exports.getDistanceAttenuation = getDistanceAttenuation; var V_GGX_SmithCorrelated = new _ShaderNode.ShaderNode(function (inputs) { var alpha = inputs.alpha, dotNL = inputs.dotNL, dotNV = inputs.dotNV; var a2 = (0, _ShaderNode.pow2)(alpha); var gv = (0, _ShaderNode.mul)(dotNL, (0, _ShaderNode.sqrt)((0, _ShaderNode.add)(a2, (0, _ShaderNode.mul)((0, _ShaderNode.sub)(1.0, a2), (0, _ShaderNode.pow2)(dotNV))))); var gl = (0, _ShaderNode.mul)(dotNV, (0, _ShaderNode.sqrt)((0, _ShaderNode.add)(a2, (0, _ShaderNode.mul)((0, _ShaderNode.sub)(1.0, a2), (0, _ShaderNode.pow2)(dotNL))))); return (0, _ShaderNode.div)(0.5, (0, _ShaderNode.max)((0, _ShaderNode.add)(gv, gl), _ShaderNode.EPSILON)); }); // validated // Microfacet Models for Refraction through Rough Surfaces - equation (33) // http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html // alpha is "roughness squared" in Disney’s reparameterization _exports.V_GGX_SmithCorrelated = V_GGX_SmithCorrelated; var D_GGX = new _ShaderNode.ShaderNode(function (inputs) { var alpha = inputs.alpha, dotNH = inputs.dotNH; var a2 = (0, _ShaderNode.pow2)(alpha); var denom = (0, _ShaderNode.add)((0, _ShaderNode.mul)((0, _ShaderNode.pow2)(dotNH), (0, _ShaderNode.sub)(a2, 1.0)), 1.0); // avoid alpha = 0 with dotNH = 1 return (0, _ShaderNode.mul)(_ShaderNode.RECIPROCAL_PI, (0, _ShaderNode.div)(a2, (0, _ShaderNode.pow2)(denom))); }); // validated // GGX Distribution, Schlick Fresnel, GGX_SmithCorrelated Visibility _exports.D_GGX = D_GGX; var BRDF_Specular_GGX = new _ShaderNode.ShaderNode(function (inputs) { var lightDirection = inputs.lightDirection, f0 = inputs.f0, f90 = inputs.f90, roughness = inputs.roughness; var alpha = (0, _ShaderNode.pow2)(roughness); // UE4's roughness var halfDir = (0, _ShaderNode.normalize)((0, _ShaderNode.add)(lightDirection, _ShaderNode.positionViewDirection)); var dotNL = (0, _ShaderNode.saturate)((0, _ShaderNode.dot)(_ShaderNode.transformedNormalView, lightDirection)); var dotNV = (0, _ShaderNode.saturate)((0, _ShaderNode.dot)(_ShaderNode.transformedNormalView, _ShaderNode.positionViewDirection)); var dotNH = (0, _ShaderNode.saturate)((0, _ShaderNode.dot)(_ShaderNode.transformedNormalView, halfDir)); var dotVH = (0, _ShaderNode.saturate)((0, _ShaderNode.dot)(_ShaderNode.positionViewDirection, halfDir)); var F = F_Schlick({ f0: f0, f90: f90, dotVH: dotVH }); var V = V_GGX_SmithCorrelated({ alpha: alpha, dotNL: dotNL, dotNV: dotNV }); var D = D_GGX({ alpha: alpha, dotNH: dotNH }); return (0, _ShaderNode.mul)(F, (0, _ShaderNode.mul)(V, D)); }); // validated _exports.BRDF_Specular_GGX = BRDF_Specular_GGX; var RE_Direct_Physical = new _ShaderNode.ShaderNode(function (inputs) { var lightDirection = inputs.lightDirection, lightColor = inputs.lightColor, directDiffuse = inputs.directDiffuse, directSpecular = inputs.directSpecular; var dotNL = (0, _ShaderNode.saturate)((0, _ShaderNode.dot)(_ShaderNode.transformedNormalView, lightDirection)); var irradiance = (0, _ShaderNode.mul)(dotNL, lightColor); irradiance = (0, _ShaderNode.mul)(irradiance, _ShaderNode.PI); // punctual light (0, _ShaderNode.addTo)(directDiffuse, (0, _ShaderNode.mul)(irradiance, BRDF_Lambert({ diffuseColor: _ShaderNode.diffuseColor }))); (0, _ShaderNode.addTo)(directSpecular, (0, _ShaderNode.mul)(irradiance, BRDF_Specular_GGX({ lightDirection: lightDirection, f0: _ShaderNode.specularColor, f90: 1, roughness: _ShaderNode.roughness }))); }); _exports.RE_Direct_Physical = RE_Direct_Physical; var PhysicalLightingModel = new _ShaderNode.ShaderNode(function (inputs /*, builder*/ ) { // PHYSICALLY_CORRECT_LIGHTS <-> builder.renderer.physicallyCorrectLights === true RE_Direct_Physical(inputs); }); _exports.PhysicalLightingModel = PhysicalLightingModel; });