summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gles2/shaders/scene.glsl44
-rw-r--r--drivers/gles3/shaders/scene.glsl41
2 files changed, 46 insertions, 39 deletions
diff --git a/drivers/gles2/shaders/scene.glsl b/drivers/gles2/shaders/scene.glsl
index cc3bae060f..b1a668cc07 100644
--- a/drivers/gles2/shaders/scene.glsl
+++ b/drivers/gles2/shaders/scene.glsl
@@ -897,10 +897,11 @@ varying vec2 uv2_interp;
varying vec3 view_interp;
-vec3 metallic_to_specular_color(float metallic, float specular, vec3 albedo) {
- float dielectric = (0.034 * 2.0) * specular;
- // energy conservation
- return mix(vec3(dielectric), albedo, metallic); // TODO: reference?
+vec3 F0(float metallic, float specular, vec3 albedo) {
+ float dielectric = 0.16 * specular * specular;
+ // use albedo * metallic as colored specular reflectance at 0 angle for metallic materials;
+ // see https://google.github.io/filament/Filament.md.html
+ return mix(vec3(dielectric), albedo, vec3(metallic));
}
/* clang-format off */
@@ -995,6 +996,7 @@ void light_compute(
float specular_blob_intensity,
float roughness,
float metallic,
+ float specular,
float rim,
float rim_tint,
float clearcoat,
@@ -1113,8 +1115,6 @@ LIGHT_SHADER_CODE
// D
- float specular_brdf_NL;
-
#if defined(SPECULAR_BLINN)
//normalized blinn
@@ -1125,7 +1125,7 @@ LIGHT_SHADER_CODE
float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25;
float blinn = pow(cNdotH, shininess);
blinn *= (shininess + 8.0) / (8.0 * 3.141592654);
- specular_brdf_NL = (blinn) / max(4.0 * cNdotV * cNdotL, 0.75);
+ float specular_brdf_NL = (blinn) / max(4.0 * cNdotV * cNdotL, 0.75);
#elif defined(SPECULAR_PHONG)
@@ -1134,7 +1134,7 @@ LIGHT_SHADER_CODE
float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25;
float phong = pow(cRdotV, shininess);
phong *= (shininess + 8.0) / (8.0 * 3.141592654);
- specular_brdf_NL = (phong) / max(4.0 * cNdotV * cNdotL, 0.75);
+ float specular_brdf_NL = (phong) / max(4.0 * cNdotV * cNdotL, 0.75);
#elif defined(SPECULAR_TOON)
@@ -1142,11 +1142,11 @@ LIGHT_SHADER_CODE
float RdotV = dot(R, V);
float mid = 1.0 - roughness;
mid *= mid;
- specular_brdf_NL = smoothstep(mid - roughness * 0.5, mid + roughness * 0.5, RdotV) * mid;
+ float specular_brdf_NL = smoothstep(mid - roughness * 0.5, mid + roughness * 0.5, RdotV) * mid;
#elif defined(SPECULAR_DISABLED)
// none..
- specular_brdf_NL = 0.0;
+ float specular_brdf_NL = 0.0;
#elif defined(SPECULAR_SCHLICK_GGX)
// shlick+ggx as default
@@ -1173,11 +1173,11 @@ LIGHT_SHADER_CODE
float G = G_GGX_2cos(cNdotL, alpha) * G_GGX_2cos(cNdotV, alpha);
#endif
// F
- //float F0 = 1.0;
- //float cLdotH5 = SchlickFresnel(cLdotH);
- //float F = mix(cLdotH5, 1.0, F0);
+ vec3 f0 = F0(metallic, specular, diffuse_color);
+ float cLdotH5 = SchlickFresnel(cLdotH);
+ vec3 F = mix(vec3(cLdotH5), vec3(1.0), f0);
- specular_brdf_NL = cNdotL * D /* F */ * G;
+ vec3 specular_brdf_NL = cNdotL * D * F * G;
#endif
@@ -1282,6 +1282,11 @@ void main() {
float alpha = 1.0;
float side = 1.0;
+ float specular_blob_intensity = 1.0;
+#if defined(SPECULAR_TOON)
+ specular_blob_intensity *= specular * 2.0;
+#endif
+
#if defined(ENABLE_AO)
float ao = 1.0;
float ao_light_affect = 0.0;
@@ -1691,7 +1696,7 @@ FRAGMENT_SHADER_CODE
#ifdef USE_VERTEX_LIGHTING
//vertex lighting
- specular_light += specular_interp * specular * light_att;
+ specular_light += specular_interp * specular_blob_intensity * light_att;
diffuse_light += diffuse_interp * albedo * light_att;
#else
@@ -1706,9 +1711,10 @@ FRAGMENT_SHADER_CODE
light_att,
albedo,
transmission,
- specular * light_specular,
+ specular_blob_intensity * light_specular,
roughness,
metallic,
+ specular,
rim,
rim_tint,
clearcoat,
@@ -1755,10 +1761,10 @@ FRAGMENT_SHADER_CODE
vec4 r = roughness * c0 + c1;
float ndotv = clamp(dot(normal, eye_position), 0.0, 1.0);
float a004 = min(r.x * r.x, exp2(-9.28 * ndotv)) * r.x + r.y;
- vec2 AB = vec2(-1.04, 1.04) * a004 + r.zw;
+ vec2 env = vec2(-1.04, 1.04) * a004 + r.zw;
- vec3 specular_color = metallic_to_specular_color(metallic, specular, albedo);
- specular_light *= AB.x * specular_color + AB.y;
+ vec3 f0 = F0(metallic, specular, albedo);
+ specular_light *= env.x * f0 + env.y;
#endif
}
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index bcaf4a57a8..a94558a58a 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -920,13 +920,14 @@ float GTR1(float NdotH, float a) {
return (a2 - 1.0) / (M_PI * log(a2) * t);
}
-vec3 metallic_to_specular_color(float metallic, float specular, vec3 albedo) {
- float dielectric = (0.034 * 2.0) * specular;
- // energy conservation
- return mix(vec3(dielectric), albedo, metallic); // TODO: reference?
+vec3 F0(float metallic, float specular, vec3 albedo) {
+ float dielectric = 0.16 * specular * specular;
+ // use albedo * metallic as colored specular reflectance at 0 angle for metallic materials;
+ // see https://google.github.io/filament/Filament.md.html
+ return mix(vec3(dielectric), albedo, vec3(metallic));
}
-void light_compute(vec3 N, vec3 L, vec3 V, vec3 B, vec3 T, vec3 light_color, vec3 attenuation, vec3 diffuse_color, vec3 transmission, float specular_blob_intensity, float roughness, float metallic, float rim, float rim_tint, float clearcoat, float clearcoat_gloss, float anisotropy, inout vec3 diffuse_light, inout vec3 specular_light) {
+void light_compute(vec3 N, vec3 L, vec3 V, vec3 B, vec3 T, vec3 light_color, vec3 attenuation, vec3 diffuse_color, vec3 transmission, float specular_blob_intensity, float roughness, float metallic, float specular, float rim, float rim_tint, float clearcoat, float clearcoat_gloss, float anisotropy, inout vec3 diffuse_light, inout vec3 specular_light) {
#if defined(USE_LIGHT_SHADER_CODE)
// light is written by the light shader
@@ -1085,11 +1086,11 @@ LIGHT_SHADER_CODE
float G = G_GGX_2cos(cNdotL, alpha) * G_GGX_2cos(cNdotV, alpha);
#endif
// F
- //float F0 = 1.0;
- //float cLdotH5 = SchlickFresnel(cLdotH);
- //float F = mix(cLdotH5, 1.0, F0);
+ vec3 f0 = F0(metallic, specular, diffuse_color);
+ float cLdotH5 = SchlickFresnel(cLdotH);
+ vec3 F = mix(vec3(cLdotH5), vec3(1.0), f0);
- float specular_brdf_NL = cNdotL * D /* F */ * G;
+ vec3 specular_brdf_NL = cNdotL * D * F * G;
specular_light += specular_brdf_NL * light_color * specular_blob_intensity * attenuation;
#endif
@@ -1191,7 +1192,7 @@ vec3 light_transmittance(float translucency,vec3 light_vec, vec3 normal, vec3 po
}
#endif
-void light_process_omni(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 binormal, vec3 tangent, vec3 albedo, vec3 transmission, float roughness, float metallic, float rim, float rim_tint, float clearcoat, float clearcoat_gloss, float anisotropy, float p_blob_intensity, inout vec3 diffuse_light, inout vec3 specular_light) {
+void light_process_omni(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 binormal, vec3 tangent, vec3 albedo, vec3 transmission, float roughness, float metallic, float specular, float rim, float rim_tint, float clearcoat, float clearcoat_gloss, float anisotropy, float p_blob_intensity, inout vec3 diffuse_light, inout vec3 specular_light) {
vec3 light_rel_vec = omni_lights[idx].light_pos_inv_radius.xyz - vertex;
float light_length = length(light_rel_vec);
@@ -1245,10 +1246,10 @@ void light_process_omni(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 bi
light_attenuation *= mix(omni_lights[idx].shadow_color_contact.rgb, vec3(1.0), shadow);
}
#endif //SHADOWS_DISABLED
- light_compute(normal, normalize(light_rel_vec), eye_vec, binormal, tangent, omni_lights[idx].light_color_energy.rgb, light_attenuation, albedo, transmission, omni_lights[idx].light_params.z * p_blob_intensity, roughness, metallic, rim * omni_attenuation, rim_tint, clearcoat, clearcoat_gloss, anisotropy, diffuse_light, specular_light);
+ light_compute(normal, normalize(light_rel_vec), eye_vec, binormal, tangent, omni_lights[idx].light_color_energy.rgb, light_attenuation, albedo, transmission, omni_lights[idx].light_params.z * p_blob_intensity, roughness, metallic, specular, rim * omni_attenuation, rim_tint, clearcoat, clearcoat_gloss, anisotropy, diffuse_light, specular_light);
}
-void light_process_spot(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 binormal, vec3 tangent, vec3 albedo, vec3 transmission, float roughness, float metallic, float rim, float rim_tint, float clearcoat, float clearcoat_gloss, float anisotropy, float p_blob_intensity, inout vec3 diffuse_light, inout vec3 specular_light) {
+void light_process_spot(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 binormal, vec3 tangent, vec3 albedo, vec3 transmission, float roughness, float metallic, float specular, float rim, float rim_tint, float clearcoat, float clearcoat_gloss, float anisotropy, float p_blob_intensity, inout vec3 diffuse_light, inout vec3 specular_light) {
vec3 light_rel_vec = spot_lights[idx].light_pos_inv_radius.xyz - vertex;
float light_length = length(light_rel_vec);
@@ -1280,7 +1281,7 @@ void light_process_spot(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 bi
}
#endif //SHADOWS_DISABLED
- light_compute(normal, normalize(light_rel_vec), eye_vec, binormal, tangent, spot_lights[idx].light_color_energy.rgb, light_attenuation, albedo, transmission, spot_lights[idx].light_params.z * p_blob_intensity, roughness, metallic, rim * spot_attenuation, rim_tint, clearcoat, clearcoat_gloss, anisotropy, diffuse_light, specular_light);
+ light_compute(normal, normalize(light_rel_vec), eye_vec, binormal, tangent, spot_lights[idx].light_color_energy.rgb, light_attenuation, albedo, transmission, spot_lights[idx].light_params.z * p_blob_intensity, roughness, metallic, specular, rim * spot_attenuation, rim_tint, clearcoat, clearcoat_gloss, anisotropy, diffuse_light, specular_light);
}
void reflection_process(int idx, vec3 vertex, vec3 normal, vec3 binormal, vec3 tangent, float roughness, float anisotropy, vec3 ambient, vec3 skybox, inout highp vec4 reflection_accum, inout highp vec4 ambient_accum) {
@@ -1895,7 +1896,7 @@ FRAGMENT_SHADER_CODE
specular_light *= mix(vec3(1.0), light_attenuation, specular_light_interp.a);
#else
- light_compute(normal, -light_direction_attenuation.xyz, eye_vec, binormal, tangent, light_color_energy.rgb, light_attenuation, albedo, transmission, light_params.z * specular_blob_intensity, roughness, metallic, rim, rim_tint, clearcoat, clearcoat_gloss, anisotropy, diffuse_light, specular_light);
+ light_compute(normal, -light_direction_attenuation.xyz, eye_vec, binormal, tangent, light_color_energy.rgb, light_attenuation, albedo, transmission, light_params.z * specular_blob_intensity, roughness, metallic, specular, rim, rim_tint, clearcoat, clearcoat_gloss, anisotropy, diffuse_light, specular_light);
#endif
#endif //#USE_LIGHT_DIRECTIONAL
@@ -1969,11 +1970,11 @@ FRAGMENT_SHADER_CODE
#else
for (int i = 0; i < omni_light_count; i++) {
- light_process_omni(omni_light_indices[i], vertex, eye_vec, normal, binormal, tangent, albedo, transmission, roughness, metallic, rim, rim_tint, clearcoat, clearcoat_gloss, anisotropy, specular_blob_intensity, diffuse_light, specular_light);
+ light_process_omni(omni_light_indices[i], vertex, eye_vec, normal, binormal, tangent, albedo, transmission, roughness, metallic, specular, rim, rim_tint, clearcoat, clearcoat_gloss, anisotropy, specular_blob_intensity, diffuse_light, specular_light);
}
for (int i = 0; i < spot_light_count; i++) {
- light_process_spot(spot_light_indices[i], vertex, eye_vec, normal, binormal, tangent, albedo, transmission, roughness, metallic, rim, rim_tint, clearcoat, clearcoat_gloss, anisotropy, specular_blob_intensity, diffuse_light, specular_light);
+ light_process_spot(spot_light_indices[i], vertex, eye_vec, normal, binormal, tangent, albedo, transmission, roughness, metallic, specular, rim, rim_tint, clearcoat, clearcoat_gloss, anisotropy, specular_blob_intensity, diffuse_light, specular_light);
}
#endif //USE_VERTEX_LIGHTING
@@ -1994,7 +1995,7 @@ FRAGMENT_SHADER_CODE
diffuse_light *= ao_light_affect;
#endif
- //energy conservation
+ // base color remapping
diffuse_light *= 1.0 - metallic; // TODO: avoid all diffuse and ambient light calculations when metallic == 1 up to this point
ambient_light *= 1.0 - metallic;
@@ -2011,10 +2012,10 @@ FRAGMENT_SHADER_CODE
vec4 r = roughness * c0 + c1;
float ndotv = clamp(dot(normal, eye_vec), 0.0, 1.0);
float a004 = min(r.x * r.x, exp2(-9.28 * ndotv)) * r.x + r.y;
- vec2 AB = vec2(-1.04, 1.04) * a004 + r.zw;
+ vec2 env = vec2(-1.04, 1.04) * a004 + r.zw;
- vec3 specular_color = metallic_to_specular_color(metallic, specular, albedo);
- specular_light *= AB.x * specular_color + AB.y;
+ vec3 f0 = F0(metallic, specular, albedo);
+ specular_light *= env.x * f0 + env.y;
#endif
}