Revision control

Copy as Markdown

// Copyright (C) 2026 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef SHEEN_GLSLIB
#define SHEEN_GLSLIB 1
#ifndef M_PI
#define M_PI 3.14159265359
#endif
// Charlie sheen distribution (Estevez and Kulla 2017)
float qt_D_Charlie(in float sheenRoughness, in float NdotH)
{
float alpha = clamp(sheenRoughness * sheenRoughness, 0.000001, 1.0);
float invAlpha = 1.0 / alpha;
float cos2h = NdotH * NdotH;
float sin2h = max(1.0 - cos2h, 0.0078125); // 2^-7, so sin2h^2 does not underflow in fp16
return (2.0 + invAlpha) * pow(sin2h, invAlpha * 0.5) / (2.0 * M_PI);
}
// Neubelt and Pettineo 2013 visibility, as permitted by KHR_materials_sheen
float qt_V_Neubelt(in float NdotL, in float NdotV)
{
return clamp(1.0 / (4.0 * (NdotL + NdotV - NdotL * NdotV)), 0.0, 1.0);
}
vec3 qt_sheenBSDF(in vec3 normal, in vec3 L, in vec3 V, in vec3 lightColor,
in vec3 sheenColor, in float sheenRoughness)
{
vec3 H = normalize(L + V);
float NdotL = clamp(dot(normal, L), 0.0, 1.0);
float NdotV = clamp(dot(normal, V), 0.0, 1.0);
float NdotH = clamp(dot(normal, H), 0.0, 1.0);
float D = qt_D_Charlie(sheenRoughness, NdotH);
float Vis = qt_V_Neubelt(NdotL, NdotV);
return sheenColor * D * Vis * NdotL * lightColor;
}
// Directional albedo of qt_D_Charlie with qt_V_Neubelt, fitted to the
// numerically integrated values with a maximum error of 0.03
float qt_E_sheen(in float NdotV, in float sheenRoughness)
{
float r = clamp(sheenRoughness, 0.0, 1.0);
float t = 1.0 / (r + 0.05);
float t2 = t * t;
float a = -1.3278 + 0.5106 * r - 0.2782 * t - 0.1400 * t2;
float b = 1.2805 - 0.4833 * r - 0.8451 * t - 0.0904 * t2;
float c = -0.8153 - 0.1470 * r + 0.3803 * t - 0.0222 * t2;
return clamp(exp((a + b * NdotV) * NdotV + c), 0.0, 1.0);
}
// Energy left for the layers beneath the sheen, from the view direction only
float qt_sheenAlbedoScaling(in vec3 sheenColor, in float NdotV, in float sheenRoughness)
{
float maxSheen = max(max(sheenColor.r, sheenColor.g), sheenColor.b);
return 1.0 - maxSheen * qt_E_sheen(NdotV, sheenRoughness);
}
#endif // SHEEN_GLSLIB