diff options
Diffstat (limited to 'drivers/gles3/shaders/scene.glsl')
-rw-r--r-- | drivers/gles3/shaders/scene.glsl | 95 |
1 files changed, 77 insertions, 18 deletions
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index d4079c4b4f..86aac2801a 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -165,18 +165,68 @@ uniform int spot_light_count; out vec4 diffuse_light_interp; out vec4 specular_light_interp; + void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, float roughness, inout vec3 diffuse, inout vec3 specular) { - float dotNL = max(dot(N, L), 0.0); - diffuse += dotNL * light_color / M_PI; + + float NdotL = dot(N, L); + float cNdotL = max(NdotL, 0.0); // clamped NdotL + float NdotV = dot(N, V); + float cNdotV = max(NdotV, 0.0); + +#if defined(DIFFUSE_OREN_NAYAR) + vec3 diffuse_brdf_NL; +#else + float diffuse_brdf_NL; // BRDF times N.L for calculating diffuse radiance +#endif + +#if defined(DIFFUSE_LAMBERT_WRAP) + // energy conserving lambert wrap shader + diffuse_brdf_NL = max(0.0, (NdotL + roughness) / ((1.0 + roughness) * (1.0 + roughness))); + +#elif defined(DIFFUSE_OREN_NAYAR) + + { + // see http://mimosa-pudica.net/improved-oren-nayar.html + float LdotV = dot(L, V); + + float s = LdotV - NdotL * NdotV; + float t = mix(1.0, max(NdotL, NdotV), step(0.0, s)); + + float sigma2 = roughness * roughness; // TODO: this needs checking + vec3 A = 1.0 + sigma2 * (-0.5 / (sigma2 + 0.33) + 0.17 * diffuse_color / (sigma2 + 0.13)); + float B = 0.45 * sigma2 / (sigma2 + 0.09); + + diffuse_brdf_NL = cNdotL * (A + vec3(B) * s / t) * (1.0 / M_PI); + } +#else + // lambert by default for everything else + diffuse_brdf_NL = cNdotL * (1.0 / M_PI); +#endif + + diffuse += light_color * diffuse_brdf_NL; if (roughness > 0.0) { + // D + float specular_brdf_NL = 0.0; + +#if !defined(SPECULAR_DISABLED) + //normalized blinn always unless disabled vec3 H = normalize(V + L); - float dotNH = max(dot(N, H), 0.0); - float intensity = (roughness >= 1.0 ? 1.0 : pow(dotNH, (1.0 - roughness) * 256.0)); - specular += light_color * intensity; + float cNdotH = max(dot(N, H), 0.0); + float cVdotH = max(dot(V, H), 0.0); + float cLdotH = max(dot(L, H), 0.0); + float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25; + float blinn = pow(cNdotH, shininess); + blinn *= (shininess + 8.0) * (1.0 / (8.0 * M_PI)); + specular_brdf_NL = (blinn) / max(4.0 * cNdotV * cNdotL, 0.75); +#endif + + specular += specular_brdf_NL * light_color * (1.0 / M_PI); } + + } void light_process_omni(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, float roughness, inout vec3 diffuse, inout vec3 specular) { @@ -306,6 +356,10 @@ void main() { uv2_interp = uv2_attrib; #endif +#ifdef OVERRIDE_POSITION + highp vec4 position; +#endif + #if defined(USE_INSTANCING) && defined(ENABLE_INSTANCE_CUSTOM) vec4 instance_custom = instance_custom_data; #else @@ -461,7 +515,11 @@ VERTEX_SHADER_CODE #endif //RENDER_DEPTH +#ifdef OVERRIDE_POSITION + gl_Position = position; +#else gl_Position = projection_matrix * vec4(vertex_interp, 1.0); +#endif position_interp = gl_Position; @@ -1504,7 +1562,7 @@ void gi_probe_compute(mediump sampler3D probe, mat4 probe_xform, vec3 bounds, ve //irradiance - vec3 irr_light = voxel_cone_trace(probe, cell_size, probe_pos, environment, blend_ambient, ref_vec, max(min_ref_tan, tan(roughness * 0.5 * M_PI)), max_distance, p_bias); + vec3 irr_light = voxel_cone_trace(probe, cell_size, probe_pos, environment, blend_ambient, ref_vec, max(min_ref_tan, tan(roughness * 0.5 * M_PI * 0.99)), max_distance, p_bias); irr_light *= multiplier; //irr_light=vec3(0.0); @@ -1565,6 +1623,7 @@ void main() { //lay out everything, whathever is unused is optimized away anyway highp vec3 vertex = vertex_interp; + vec3 view = -normalize(vertex_interp); vec3 albedo = vec3(1.0); vec3 transmission = vec3(0.0); float metallic = 0.0; @@ -1585,24 +1644,24 @@ void main() { float alpha = 1.0; -#if defined(DO_SIDE_CHECK) - float side = gl_FrontFacing ? 1.0 : -1.0; -#else - float side = 1.0; -#endif - #if defined(ALPHA_SCISSOR_USED) float alpha_scissor = 0.5; #endif #if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) - vec3 binormal = normalize(binormal_interp) * side; - vec3 tangent = normalize(tangent_interp) * side; + vec3 binormal = normalize(binormal_interp); + vec3 tangent = normalize(tangent_interp); #else vec3 binormal = vec3(0.0); vec3 tangent = vec3(0.0); #endif - vec3 normal = normalize(normal_interp) * side; + vec3 normal = normalize(normal_interp); + +#if defined(DO_SIDE_CHECK) + if (!gl_FrontFacing) { + normal = -normal; + } +#endif #if defined(ENABLE_UV_INTERP) vec2 uv = uv_interp; @@ -1658,7 +1717,7 @@ FRAGMENT_SHADER_CODE normalmap.xy = normalmap.xy * 2.0 - 1.0; normalmap.z = sqrt(max(0.0, 1.0 - dot(normalmap.xy, normalmap.xy))); //always ignore Z, as it can be RG packed, Z may be pos/neg, etc. - normal = normalize(mix(normal_interp, tangent * normalmap.x + binormal * normalmap.y + normal * normalmap.z, normaldepth)) * side; + normal = normalize(mix(normal, tangent * normalmap.x + binormal * normalmap.y + normal * normalmap.z, normaldepth)); #endif @@ -1699,7 +1758,7 @@ FRAGMENT_SHADER_CODE vec3 ambient_light; vec3 env_reflection_light = vec3(0.0, 0.0, 0.0); - vec3 eye_vec = -normalize(vertex_interp); + vec3 eye_vec = view; #ifdef USE_RADIANCE_MAP @@ -2027,7 +2086,7 @@ FRAGMENT_SHADER_CODE //apply fog if (fog_depth_enabled) { - float fog_far = fog_depth_end > 0 ? fog_depth_end : z_far; + float fog_far = fog_depth_end > 0.0 ? fog_depth_end : z_far; float fog_z = smoothstep(fog_depth_begin, fog_far, length(vertex)); |