Diffuse Burley + Specular Schlick-GGX Light Model
Diffuse Light based on the Disney Principled PBS diffuse light model.
Specular Light based on the Godot Specular Light Implementation.
You can download the Visual Shader Node on Itch.Io.
Shader code
// ElSuicio, 2026.
// GODOT v4.6.1.stable.
// x.com/ElSuicio
// github.com/ElSuicio
// Contact email [interdreamsoft@gmail.com]
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 fragment() {
ALBEDO = _DiffuseColor;
ROUGHNESS = _Roughness;
METALLIC = _Metallic;
SPECULAR = _Specular;
}
void light() {
vec3 n = normalize(NORMAL);
vec3 l = normalize(LIGHT);
vec3 v = normalize(VIEW);
float NdotL = min(max(dot(n, l), 1e-3), 1.0); // cos(theta_l) == cos(theta_i).
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;
/* Burley + Trowbridge-Reitz-GGX */
float FD_l = schlick_fresnel(NdotL), FD_v = schlick_fresnel(NdotV);
float FD90 = 0.5 + 2.0 * ROUGHNESS * HdotL * HdotL;
float fd = 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 ), ALBEDO, 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), ALBEDO, vec3(METALLIC));
//vec3 F = f0 + (1.0 - f0) * schlick_fresnel(HdotL);
vec3 fs = vec3(D * G * F * NdotL);
// 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;
}



