Optimized GGX specular shader (godot 3.x)
ported from John Hale (@FilmicWorlds)
http://www.twitter.com/@filmicworlds
http://filmicworlds.com/blog/optimizing-ggx-shaders-with-dotlh/
Shader code
shader_type spatial;
render_mode ambient_light_disabled;
//render_mode skip_vertex_transform;
uniform sampler2D _albedo:hint_albedo;
varying vec4 vector_ws;
varying vec4 vector_os;
float pow_4(float x)
{
return x*x*x*x;
}
float saturate_f(float x)
{
return max(0,min(1,x));
}
float LightingFuncGGX_OPT4(vec3 N, vec3 V, vec3 L, float roughness, float F0)
{
vec3 H = normalize(V+L);
float nDotL = saturate_f(dot(N,L));
float lDotH = saturate_f(dot(L,H));
float nDotH = saturate_f(dot(N,H));
float D = texture(_albedo, vec2(nDotH)+roughness).x;//textureLod(_albedo, vec2(nDotH),roughness).x;
vec2 FV_helper = texture(_albedo, vec2(lDotH)+roughness).yz;//textureLod(_albedo, vec2(lDotH),roughness).yz;
float FV = F0*FV_helper.x + (1.0-F0)*FV_helper.y;
float specular = nDotL * D*FV;
return specular;
}
float LightingFuncGGX_OPT4_T(vec3 N, vec3 V, vec3 L, float roughness, float F0,sampler2D _texture)
{
vec3 H = normalize(V+L);
float nDotL = saturate_f(dot(N,L));
float lDotH = saturate_f(dot(L,H));
float nDotH = saturate_f(dot(N,H));
float D = texture(_texture, vec2(nDotH)+roughness).x;//textureLod(_albedo, vec2(nDotH),roughness).x;
vec2 FV_helper = texture(_texture, vec2(lDotH)+roughness).yz;//textureLod(_albedo, vec2(lDotH),roughness).yz;
float FV = F0*FV_helper.x + (1.0-F0)*FV_helper.y;
float specular = nDotL * D*FV;
return specular;
}
vec3 saturate_v3(vec3 value)
{
vec3 result;
result.x = max(0,min(1,value.x));
result.y= max(0,min(1,value.y));
result.z== max(0,min(1,value.z));
return result;
}
void vertex()
{
vector_os.xyz = VERTEX;
vector_ws= WORLD_MATRIX* vec4(vector_os.xyz,1.0);
}
void light()
{
vec3 i = ATTENUATION;
vec3 l = LIGHT;
vec3 n = NORMAL;
vec3 viewDirection= normalize(CAMERA_MATRIX[3]-vector_ws).xyz;
float roughness=ROUGHNESS;
vec3 optimizedGGX = vec3(LightingFuncGGX_OPT4(n,viewDirection,l,roughness,dot(WORLD_MATRIX[3].xyz,LIGHT)));
SPECULAR_LIGHT += optimizedGGX.xyz;
}
