blob: 7ebf8da6f38bfe5951b1fe8cf748e3acbeab5b84 [file] [log] [blame]
/****************************************************************************
**
** 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