diff options
Diffstat (limited to 'drivers/gles3/shaders/scene.glsl')
-rw-r--r-- | drivers/gles3/shaders/scene.glsl | 229 |
1 files changed, 132 insertions, 97 deletions
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index 630e1c2089..f08d3f4d23 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -993,7 +993,7 @@ vec3 F0(float metallic, float specular, vec3 albedo) { 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 specular, 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, inout float alpha) { #if defined(USE_LIGHT_SHADER_CODE) // light is written by the light shader @@ -1135,19 +1135,19 @@ LIGHT_SHADER_CODE #if defined(LIGHT_USE_ANISOTROPY) - float alpha = roughness * roughness; + float alpha_ggx = roughness * roughness; float aspect = sqrt(1.0 - anisotropy * 0.9); - float ax = alpha / aspect; - float ay = alpha * aspect; + float ax = alpha_ggx / aspect; + float ay = alpha_ggx * aspect; float XdotH = dot(T, H); float YdotH = dot(B, H); float D = D_GGX_anisotropic(cNdotH, ax, ay, XdotH, YdotH); float G = G_GGX_anisotropic_2cos(cNdotL, ax, ay, XdotH, YdotH) * G_GGX_anisotropic_2cos(cNdotV, ax, ay, XdotH, YdotH); #else - float alpha = roughness * roughness; - float D = D_GGX(cNdotH, alpha); - float G = G_GGX_2cos(cNdotL, alpha) * G_GGX_2cos(cNdotV, alpha); + float alpha_ggx = roughness * roughness; + float D = D_GGX(cNdotH, alpha_ggx); + float G = G_GGX_2cos(cNdotL, alpha_ggx) * G_GGX_2cos(cNdotV, alpha_ggx); #endif // F vec3 f0 = F0(metallic, specular, diffuse_color); @@ -1174,6 +1174,10 @@ LIGHT_SHADER_CODE #endif } +#ifdef USE_SHADOW_TO_OPACITY + alpha = min(alpha, clamp(1.0 - length(attenuation), 0.0, 1.0)); +#endif + #endif //defined(USE_LIGHT_SHADER_CODE) } @@ -1250,7 +1254,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 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) { +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, inout float alpha) { vec3 light_rel_vec = omni_lights[idx].light_pos_inv_radius.xyz - vertex; float light_length = length(light_rel_vec); @@ -1304,10 +1308,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, specular, 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, alpha); } -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) { +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, inout float alpha) { vec3 light_rel_vec = spot_lights[idx].light_pos_inv_radius.xyz - vertex; float light_length = length(light_rel_vec); @@ -1339,7 +1343,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, specular, 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, alpha); } 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) { @@ -1705,11 +1709,13 @@ FRAGMENT_SHADER_CODE /* clang-format on */ } +#if !defined(USE_SHADOW_TO_OPACITY) + #if defined(ALPHA_SCISSOR_USED) if (alpha < alpha_scissor) { discard; } -#endif +#endif // ALPHA_SCISSOR_USED #ifdef USE_OPAQUE_PREPASS @@ -1717,7 +1723,9 @@ FRAGMENT_SHADER_CODE discard; } -#endif +#endif // USE_OPAQUE_PREPASS + +#endif // !USE_SHADOW_TO_OPACITY #if defined(ENABLE_NORMALMAP) @@ -1802,6 +1810,7 @@ FRAGMENT_SHADER_CODE ambient_light = vec3(0.0, 0.0, 0.0); #else ambient_light = ambient_light_color.rgb; + env_reflection_light = bg_color.rgb * bg_energy; #endif //AMBIENT_LIGHT_DISABLED #endif @@ -1809,10 +1818,98 @@ FRAGMENT_SHADER_CODE ambient_light *= ambient_energy; float specular_blob_intensity = 1.0; + #if defined(SPECULAR_TOON) specular_blob_intensity *= specular * 2.0; #endif +#ifdef USE_GI_PROBES + gi_probes_compute(vertex, normal, roughness, env_reflection_light, ambient_light); + +#endif + +#ifdef USE_LIGHTMAP + ambient_light = texture(lightmap, uv2).rgb * lightmap_energy; +#endif + +#ifdef USE_LIGHTMAP_CAPTURE + { + vec3 cone_dirs[12] = vec3[]( + vec3(0.0, 0.0, 1.0), + vec3(0.866025, 0.0, 0.5), + vec3(0.267617, 0.823639, 0.5), + vec3(-0.700629, 0.509037, 0.5), + vec3(-0.700629, -0.509037, 0.5), + vec3(0.267617, -0.823639, 0.5), + vec3(0.0, 0.0, -1.0), + vec3(0.866025, 0.0, -0.5), + vec3(0.267617, 0.823639, -0.5), + vec3(-0.700629, 0.509037, -0.5), + vec3(-0.700629, -0.509037, -0.5), + vec3(0.267617, -0.823639, -0.5)); + + vec3 local_normal = normalize(camera_matrix * vec4(normal, 0.0)).xyz; + vec4 captured = vec4(0.0); + float sum = 0.0; + for (int i = 0; i < 12; i++) { + float amount = max(0.0, dot(local_normal, cone_dirs[i])); //not correct, but creates a nice wrap around effect + captured += lightmap_captures[i] * amount; + sum += amount; + } + + captured /= sum; + + if (lightmap_capture_sky) { + ambient_light = mix(ambient_light, captured.rgb, captured.a); + } else { + ambient_light = captured.rgb; + } + } +#endif + +#ifdef USE_FORWARD_LIGHTING + + highp vec4 reflection_accum = vec4(0.0, 0.0, 0.0, 0.0); + highp vec4 ambient_accum = vec4(0.0, 0.0, 0.0, 0.0); + for (int i = 0; i < reflection_count; i++) { + reflection_process(reflection_indices[i], vertex, normal, binormal, tangent, roughness, anisotropy, ambient_light, env_reflection_light, reflection_accum, ambient_accum); + } + + if (reflection_accum.a > 0.0) { + specular_light += reflection_accum.rgb / reflection_accum.a; + } else { + specular_light += env_reflection_light; + } +#if !defined(USE_LIGHTMAP) && !defined(USE_LIGHTMAP_CAPTURE) + if (ambient_accum.a > 0.0) { + ambient_light = ambient_accum.rgb / ambient_accum.a; + } +#endif +#endif + + { + +#if defined(DIFFUSE_TOON) + //simplify for toon, as + specular_light *= specular * metallic * albedo * 2.0; +#else + + // scales the specular reflections, needs to be be computed before lighting happens, + // but after environment, GI, and reflection probes are added + // Environment brdf approximation (Lazarov 2013) + // see https://www.unrealengine.com/en-US/blog/physically-based-shading-on-mobile + const vec4 c0 = vec4(-1.0, -0.0275, -0.572, 0.022); + const vec4 c1 = vec4(1.0, 0.0425, 1.04, -0.04); + 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 env = vec2(-1.04, 1.04) * a004 + r.zw; + + vec3 f0 = F0(metallic, specular, albedo); + specular_light *= env.x * f0 + env.y; +#endif + } + #if defined(USE_LIGHT_DIRECTIONAL) vec3 light_attenuation = vec3(1.0); @@ -1955,91 +2052,49 @@ 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, specular, 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, alpha); #endif #endif //#USE_LIGHT_DIRECTIONAL -#ifdef USE_GI_PROBES - gi_probes_compute(vertex, normal, roughness, env_reflection_light, ambient_light); - -#endif - -#ifdef USE_LIGHTMAP - ambient_light = texture(lightmap, uv2).rgb * lightmap_energy; -#endif - -#ifdef USE_LIGHTMAP_CAPTURE - { - vec3 cone_dirs[12] = vec3[]( - vec3(0.0, 0.0, 1.0), - vec3(0.866025, 0.0, 0.5), - vec3(0.267617, 0.823639, 0.5), - vec3(-0.700629, 0.509037, 0.5), - vec3(-0.700629, -0.509037, 0.5), - vec3(0.267617, -0.823639, 0.5), - vec3(0.0, 0.0, -1.0), - vec3(0.866025, 0.0, -0.5), - vec3(0.267617, 0.823639, -0.5), - vec3(-0.700629, 0.509037, -0.5), - vec3(-0.700629, -0.509037, -0.5), - vec3(0.267617, -0.823639, -0.5)); - - vec3 local_normal = normalize(camera_matrix * vec4(normal, 0.0)).xyz; - vec4 captured = vec4(0.0); - float sum = 0.0; - for (int i = 0; i < 12; i++) { - float amount = max(0.0, dot(local_normal, cone_dirs[i])); //not correct, but creates a nice wrap around effect - captured += lightmap_captures[i] * amount; - sum += amount; - } - - captured /= sum; - - if (lightmap_capture_sky) { - ambient_light = mix(ambient_light, captured.rgb, captured.a); - } else { - ambient_light = captured.rgb; - } - } -#endif - #ifdef USE_FORWARD_LIGHTING - highp vec4 reflection_accum = vec4(0.0, 0.0, 0.0, 0.0); - highp vec4 ambient_accum = vec4(0.0, 0.0, 0.0, 0.0); - for (int i = 0; i < reflection_count; i++) { - reflection_process(reflection_indices[i], vertex, normal, binormal, tangent, roughness, anisotropy, ambient_light, env_reflection_light, reflection_accum, ambient_accum); - } - - if (reflection_accum.a > 0.0) { - specular_light += reflection_accum.rgb / reflection_accum.a; - } else { - specular_light += env_reflection_light; - } -#if !defined(USE_LIGHTMAP) && !defined(USE_LIGHTMAP_CAPTURE) - if (ambient_accum.a > 0.0) { - ambient_light = ambient_accum.rgb / ambient_accum.a; - } -#endif - #ifdef USE_VERTEX_LIGHTING diffuse_light *= albedo; #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, specular, 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, alpha); } 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, specular, 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, alpha); } #endif //USE_VERTEX_LIGHTING #endif +#ifdef USE_SHADOW_TO_OPACITY + alpha = min(alpha, clamp(length(ambient_light), 0.0, 1.0)); + +#if defined(ALPHA_SCISSOR_USED) + if (alpha < alpha_scissor) { + discard; + } +#endif // ALPHA_SCISSOR_USED + +#ifdef USE_OPAQUE_PREPASS + + if (alpha < opaque_prepass_threshold) { + discard; + } + +#endif // USE_OPAQUE_PREPASS + +#endif // USE_SHADOW_TO_OPACITY + #ifdef RENDER_DEPTH //nothing happens, so a tree-ssa optimizer will result in no fragment shader :) #else @@ -2058,26 +2113,6 @@ FRAGMENT_SHADER_CODE 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; - { - -#if defined(DIFFUSE_TOON) - //simplify for toon, as - specular_light *= specular * metallic * albedo * 2.0; -#else - // Environment brdf approximation (Lazarov 2013) - // see https://www.unrealengine.com/en-US/blog/physically-based-shading-on-mobile - const vec4 c0 = vec4(-1.0, -0.0275, -0.572, 0.022); - const vec4 c1 = vec4(1.0, 0.0425, 1.04, -0.04); - 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 env = vec2(-1.04, 1.04) * a004 + r.zw; - - vec3 f0 = F0(metallic, specular, albedo); - specular_light *= env.x * f0 + env.y; -#endif - } - if (fog_color_enabled.a > 0.5) { float fog_amount = 0.0; |