| /**************************************************************************** |
| ** |
| ** Copyright (C) 2014 NVIDIA Corporation. |
| ** Copyright (C) 2019 The Qt Company Ltd. |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** This file is part of Qt 3D Studio. |
| ** |
| ** $QT_BEGIN_LICENSE:GPL$ |
| ** Commercial License Usage |
| ** Licensees holding valid commercial Qt licenses may use this file in |
| ** accordance with the commercial license agreement provided with the |
| ** Software or, alternatively, in accordance with the terms contained in |
| ** a written agreement between you and The Qt Company. For licensing terms |
| ** and conditions see https://www.qt.io/terms-conditions. For further |
| ** information use the contact form at https://www.qt.io/contact-us. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU |
| ** General Public License version 3 or (at your option) any later version |
| ** approved by the KDE Free Qt Foundation. The licenses are as published by |
| ** the Free Software Foundation and appearing in the file LICENSE.GPL3 |
| ** included in the packaging of this file. Please review the following |
| ** information to ensure the GNU General Public License requirements will |
| ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| #ifndef PHYS_GLOSSY_BSDF_GLSLLIB |
| #define PHYS_GLOSSY_BSDF_GLSLLIB 1 |
| |
| float sqr(float v) |
| { |
| return v*v; |
| } |
| |
| float Gterm(float cosTheta, float roughness) |
| { |
| float k = roughness * 0.31830988618; // roughness / pi |
| return clamp((cosTheta / (cosTheta*(1.0-k) + k) + (1.0 - k*k)) * 0.5, 0.0, 1.0); |
| } |
| |
| float SmithGGXMasking(in float NdotL, in float NdotV, in float a2) |
| { |
| float ia2 = 1.0 - a2; |
| float A = NdotV * sqrt(a2 + ia2 * NdotL * NdotL); |
| float B = NdotL * sqrt(a2 + ia2 * NdotV * NdotV); |
| return 2.0 * NdotL * NdotV / (A + B); |
| } |
| |
| // Isotropic GGX + smith |
| vec4 kggxGlossyBSDFMtl(in vec3 N, in vec3 L, in vec3 V, in vec3 lightSpecular, in float roughness) |
| { |
| vec4 rgba = vec4(0.0, 0.0, 0.0, 1.0); |
| float NdotL = dot(N, L); |
| if (NdotL > 0.0) { |
| float NdotV = dot(N, V); |
| vec3 H = normalize(L + V); |
| float NdotH = dot(N, H); |
| float a2 = roughness * roughness; |
| float G2 = SmithGGXMasking(NdotL, NdotV, a2); |
| float D = a2 / (3.1415926535 * sqr(sqr(NdotH) * (a2 - 1.0) + 1.0)); |
| rgba.rgb = lightSpecular * G2 * D / (4.0 * NdotV * NdotH); |
| } |
| return rgba; |
| } |
| |
| vec4 kggxGlossyDefaultMtl(in vec3 normal, in vec3 tangent, in vec3 L, in vec3 V, |
| in vec3 lightSpecular, in vec3 materialSpecular, in float roughness) |
| { |
| return vec4(materialSpecular, 1.0) * kggxGlossyBSDFMtl(normal, L, V, lightSpecular, roughness); |
| } |
| |
| // To be exact, this is not the Ward lobe as Ward originally described (there are a few flaws in |
| // the original paper, which had spawned half a dozen corrective measures as papers of their own). |
| // This is a Ward-Duer variant with Geisler-Moroder's modified normalization factor which serves |
| // to bound the albedo. |
| vec4 wardGlossyBSDF(in mat3 tanFrame, in vec3 L, in vec3 V, in vec3 lightSpecular, |
| in float roughness) |
| { |
| vec4 rgba = vec4(0.0, 0.0, 0.0, 1.0); |
| vec3 H = normalize(L + V); |
| |
| // specular |
| float ax = clamp(roughness, 0.0001, 1.0); |
| |
| float NdotL = dot(tanFrame[2], L); |
| float HdotL = clamp(dot(H, L), 0.0, 1.0); |
| |
| vec3 Haf = L + V; |
| |
| float HdotN = clamp(dot(H, tanFrame[2]), 0.0001, 1.0); |
| float HdotX = clamp(abs(dot(H, tanFrame[0])), 0.0001, 1.0); |
| float HdotY = clamp(abs(dot(H, tanFrame[1])), 0.0001, 1.0); |
| |
| float exponent = -(sqr(HdotX/ax) + sqr(HdotY/ax)); |
| exponent /= sqr(HdotN); |
| float PDF = exp(exponent) / (4.0 * 3.1415926535 * ax * ax); |
| PDF *= 4.0 * dot(Haf, Haf) / sqr(sqr(dot(Haf,tanFrame[2]))); |
| |
| rgba.rgb = Gterm(HdotL, ax) * lightSpecular * PDF * max(NdotL, 0.0); |
| |
| return rgba; |
| } |
| |
| vec4 wardGlossyDefaultMtl(in vec3 normal, in vec3 tangent, in vec3 L, in vec3 V, |
| in vec3 lightSpecular, in vec3 materialSpecular, in float roughness) |
| { |
| vec3 bitan = normalize(cross(normal, tangent)); |
| mat3 tanFrame = mat3(normalize(cross(bitan, normal)), bitan, normal); |
| return vec4(materialSpecular, 1.0) * wardGlossyBSDF(tanFrame, L, V, lightSpecular, roughness); |
| } |
| |
| #endif |