Description
Changelog
Reviews
This is an addon for Godot 4.4+ that adds the Schlick-GGX node to the visual shader system. This node outputs the Specular Light based on the Godot Specular Light Implementation.

GDSL:
shader_type spatial;
const float INV_PI = 0.31830988618379067154;
group_uniforms _BurleyGGX;
uniform vec3 _DiffuseColor : source_color = vec3(1.0);
uniform float _Roughness : hint_range(0.0, 1.0, 1e-3) = 1.0;
uniform float _Metallic : hint_range(0.0, 1.0, 1e-3) = 0.0;
uniform float _Specular : hint_range(0.0, 1.0, 1e-3) = 0.5;
float schlick_fresnel(float u)
{
float m = clamp(1.0 - u, 0.0, 1.0);
return m * m * m * m * m; // pow(m, 5).
}
void brdf(
in vec3 n,
in vec3 l,
in vec3 v,
in vec3 rho,
in float roughness,
in float metallic,
in float specular,
inout vec3 fd,
inout vec3 fs
)
{
float NdotL = dot(n, l); // cos(theta_l) == cos(theta_i).
if(NdotL < 0.0)
{
return;
}
float NdotV = min(max(dot(n, v), 1e-3), 1.0); // cos(theta_v) == cos(theta_r).
vec3 h = normalize(v + l);
float HdotN = dot(h, n); // cos(theta_h).
float HdotL = dot(h, l); // cos(theta_d).
float alpha = roughness * roughness;
float alpha2 = alpha * alpha;
// https://media.disneyanimation.com/uploads/production/publication_asset/48/asset/s2012_pbs_disney_brdf_notes_v3.pdf
/* Burley */
float FD_l = schlick_fresnel(NdotL), FD_v = schlick_fresnel(NdotV);
float retroreflection = roughness * HdotL * HdotL;
float FD90 = 0.5 + 2.0 * retroreflection;
fd = vec3(INV_PI * mix(1.0, FD90, FD_l) * mix(1.0, FD90, FD_v) * NdotL);
/* Normal Distribution Function (GGX) */
float t = 1.0 + (alpha2 - 1.0) * HdotN * HdotN;
float D = alpha2 / (PI * t * t);
/* Geometric Function (Implicit) */
float G = 0.5 / mix(2.0 * NdotL * NdotV, NdotL + NdotV, alpha);
/* Geometric Function (Smith-GGX) */
//float GL = 1.0 / (NdotL + sqrt(alpha2 + (1.0 - alpha2) * (NdotL * NdotL)));
//float GV = 1.0 / (NdotV + sqrt(alpha2 + (1.0 - alpha2) * (NdotV * NdotV)));
//float G = GL * GV;
/* Godot Fresnel Function (Schlick’s Approximation) */
float dielectric = 0.16 * specular * specular;
vec3 f0 = mix(vec3( dielectric ), rho, vec3( metallic ));
float f90 = clamp(dot(f0, vec3(16.5)), metallic, 1.0);
vec3 F = f0 + (f90 - f0) * schlick_fresnel(HdotL);
/* Fresnel Function (Schlick’s Approximation) */
//vec3 f0 = mix(vec3(specular * 0.08), rho, vec3(metallic));
//vec3 F = f0 + (1.0 - f0) * schlick_fresnel(HdotL);
fs = D * G * F * NdotL;
}
void fragment() {
ALBEDO = _DiffuseColor;
ROUGHNESS = _Roughness;
METALLIC = _Metallic;
SPECULAR = _Specular;
}
void light() {
vec3 n = normalize(NORMAL);
vec3 l = normalize(LIGHT);
vec3 v = normalize(VIEW);
vec3 fd = vec3(0.0);
vec3 fs = vec3(0.0);
brdf(n, l, v, ALBEDO, ROUGHNESS, METALLIC, _Specular, fd, fs);
// To compare with the Slice-Image.
//vec3 radiance = (LIGHT_COLOR / PI) * ATTENUATION;
// In PI light units.
vec3 radiance = LIGHT_COLOR * ATTENUATION;
DIFFUSE_LIGHT += radiance * fd;
SPECULAR_LIGHT += radiance * fs;
}
[ Support Email: [email protected] ]
Changelog for version v1.0.3
No changelog provided for this version.