diff options
Diffstat (limited to 'drivers/gles3/shaders/scene.glsl')
-rw-r--r-- | drivers/gles3/shaders/scene.glsl | 126 |
1 files changed, 99 insertions, 27 deletions
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index fbea4bdbe4..ed176c7829 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -2,8 +2,11 @@ #[modes] mode_color = #define BASE_PASS +mode_color_instancing = #define BASE_PASS \n#define USE_INSTANCING mode_additive = #define USE_ADDITIVE_LIGHTING +mode_additive_instancing = #define USE_ADDITIVE_LIGHTING \n#define USE_INSTANCING mode_depth = #define MODE_RENDER_DEPTH +mode_depth_instancing = #define MODE_RENDER_DEPTH \n#define USE_INSTANCING #[specializations] @@ -13,6 +16,7 @@ DISABLE_LIGHT_OMNI = false DISABLE_LIGHT_SPOT = false DISABLE_FOG = false USE_RADIANCE_MAP = true +USE_MULTIVIEW = false #[vertex] @@ -32,8 +36,8 @@ USE_RADIANCE_MAP = true /* from RenderingServer: ARRAY_VERTEX = 0, // RG32F or RGB32F (depending on 2D bit) -ARRAY_NORMAL = 1, // A2B10G10R10, A is ignored. -ARRAY_TANGENT = 2, // A2B10G10R10, A flips sign of binormal. +ARRAY_NORMAL = 1, // RG16 octahedral compression +ARRAY_TANGENT = 2, // RG16 octahedral compression, sign stored in sign of G ARRAY_COLOR = 3, // RGBA8 ARRAY_TEX_UV = 4, // RG32F ARRAY_TEX_UV2 = 5, // RG32F @@ -43,8 +47,6 @@ ARRAY_CUSTOM2 = 8, ARRAY_CUSTOM3 = 9, ARRAY_BONES = 10, // RGBA16UI (x2 if 8 weights) ARRAY_WEIGHTS = 11, // RGBA16UNORM (x2 if 8 weights) -ARRAY_INDEX = 12, // 16 or 32 bits depending on length > 0xFFFF. -ARRAY_MAX = 13 */ /* INPUT ATTRIBS */ @@ -53,11 +55,11 @@ layout(location = 0) in highp vec3 vertex_attrib; /* clang-format on */ #ifdef NORMAL_USED -layout(location = 1) in vec3 normal_attrib; +layout(location = 1) in vec2 normal_attrib; #endif #if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) -layout(location = 2) in vec4 tangent_attrib; +layout(location = 2) in vec2 tangent_attrib; #endif #if defined(COLOR_USED) @@ -96,8 +98,22 @@ layout(location = 10) in uvec4 bone_attrib; layout(location = 11) in vec4 weight_attrib; #endif -layout(std140) uniform GlobalVariableData { //ubo:1 - vec4 global_variables[MAX_GLOBAL_VARIABLES]; +vec3 oct_to_vec3(vec2 e) { + vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y)); + float t = max(-v.z, 0.0); + v.xy += t * -sign(v.xy); + return v; +} + +#ifdef USE_INSTANCING +layout(location = 12) in highp vec4 instance_xform0; +layout(location = 13) in highp vec4 instance_xform1; +layout(location = 14) in highp vec4 instance_xform2; +layout(location = 15) in highp uvec4 instance_color_custom_data; // Color packed into xy, Custom data into zw. +#endif + +layout(std140) uniform GlobalShaderUniformData { //ubo:1 + vec4 global_shader_uniforms[MAX_GLOBAL_SHADER_UNIFORMS]; }; layout(std140) uniform SceneData { // ubo:2 @@ -138,6 +154,15 @@ layout(std140) uniform SceneData { // ubo:2 } scene_data; +#ifdef USE_MULTIVIEW +layout(std140) uniform MultiviewData { // ubo:8 + highp mat4 projection_matrix_view[MAX_VIEWS]; + highp mat4 inv_projection_matrix_view[MAX_VIEWS]; + highp vec4 eye_offset[MAX_VIEWS]; +} +multiview_data; +#endif + uniform highp mat4 world_transform; #ifdef USE_LIGHTMAP @@ -195,20 +220,29 @@ void main() { highp vec3 vertex = vertex_attrib; highp mat4 model_matrix = world_transform; +#ifdef USE_INSTANCING + highp mat4 m = mat4(instance_xform0, instance_xform1, instance_xform2, vec4(0.0, 0.0, 0.0, 1.0)); + model_matrix = model_matrix * transpose(m); +#endif #ifdef NORMAL_USED - vec3 normal = normal_attrib * 2.0 - 1.0; + vec3 normal = oct_to_vec3(normal_attrib * 2.0 - 1.0); #endif highp mat3 model_normal_matrix = mat3(model_matrix); #if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) - vec3 tangent = tangent_attrib.xyz * 2.0 - 1.0; - float binormalf = tangent_attrib.a * 2.0 - 1.0; + vec2 signed_tangent_attrib = tangent_attrib * 2.0 - 1.0; + vec3 tangent = oct_to_vec3(vec2(signed_tangent_attrib.x, abs(signed_tangent_attrib.y) * 2.0 - 1.0)); + float binormalf = sign(signed_tangent_attrib.y); vec3 binormal = normalize(cross(normal, tangent) * binormalf); #endif #if defined(COLOR_USED) color_interp = color_attrib; +#ifdef USE_INSTANCING + vec4 instance_color = vec4(unpackHalf2x16(instance_color_custom_data.x), unpackHalf2x16(instance_color_custom_data.y)); + color_interp *= instance_color; +#endif #endif #if defined(UV_USED) @@ -226,10 +260,20 @@ void main() { #if defined(OVERRIDE_POSITION) highp vec4 position; #endif - highp mat4 projection_matrix = scene_data.projection_matrix; - highp mat4 inv_projection_matrix = scene_data.inv_projection_matrix; +#ifdef USE_MULTIVIEW + mat4 projection_matrix = multiview_data.projection_matrix_view[ViewIndex]; + mat4 inv_projection_matrix = multiview_data.inv_projection_matrix_view[ViewIndex]; +#else + mat4 projection_matrix = scene_data.projection_matrix; + mat4 inv_projection_matrix = scene_data.inv_projection_matrix; +#endif //USE_MULTIVIEW + +#ifdef USE_INSTANCING + vec4 instance_custom = vec4(unpackHalf2x16(instance_color_custom_data.z), unpackHalf2x16(instance_color_custom_data.w)); +#else vec4 instance_custom = vec4(0.0); +#endif // Using world coordinates #if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED) @@ -311,7 +355,6 @@ void main() { /* clang-format off */ #[fragment] - // Default to SPECULAR_SCHLICK_GGX. #if !defined(SPECULAR_DISABLED) && !defined(SPECULAR_SCHLICK_GGX) && !defined(SPECULAR_TOON) #define SPECULAR_SCHLICK_GGX @@ -379,8 +422,8 @@ uniform samplerCube radiance_map; // texunit:-2 #endif -layout(std140) uniform GlobalVariableData { //ubo:1 - vec4 global_variables[MAX_GLOBAL_VARIABLES]; +layout(std140) uniform GlobalShaderUniformData { //ubo:1 + vec4 global_shader_uniforms[MAX_GLOBAL_SHADER_UNIFORMS]; }; /* Material Uniforms */ @@ -435,6 +478,15 @@ layout(std140) uniform SceneData { // ubo:2 } scene_data; +#ifdef USE_MULTIVIEW +layout(std140) uniform MultiviewData { // ubo:8 + highp mat4 projection_matrix_view[MAX_VIEWS]; + highp mat4 inv_projection_matrix_view[MAX_VIEWS]; + highp vec4 eye_offset[MAX_VIEWS]; +} +multiview_data; +#endif + /* clang-format off */ #GLOBALS @@ -475,7 +527,7 @@ struct LightData { //this structure needs to be as packed as possible mediump float cone_attenuation; mediump float cone_angle; mediump float specular_amount; - bool shadow_enabled; + mediump float shadow_opacity; }; #ifndef DISABLE_LIGHT_OMNI layout(std140) uniform OmniLightData { // ubo:5 @@ -502,8 +554,13 @@ uniform highp samplerCubeShadow positional_shadow; // texunit:-4 #endif // !defined(DISABLE_LIGHT_OMNI) && !defined(DISABLE_LIGHT_SPOT) -uniform highp sampler2D screen_texture; // texunit:-5 +#ifdef USE_MULTIVIEW +uniform highp sampler2DArray depth_buffer; // texunit:-6 +uniform highp sampler2DArray screen_texture; // texunit:-5 +#else uniform highp sampler2D depth_buffer; // texunit:-6 +uniform highp sampler2D screen_texture; // texunit:-5 +#endif uniform highp mat4 world_transform; uniform mediump float opaque_prepass_threshold; @@ -601,11 +658,12 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte float diffuse_brdf_NL; // BRDF times N.L for calculating diffuse radiance #if defined(DIFFUSE_LAMBERT_WRAP) - // energy conserving lambert wrap shader - diffuse_brdf_NL = max(0.0, (NdotL + roughness) / ((1.0 + roughness) * (1.0 + roughness))); + // Energy conserving lambert wrap shader. + // https://web.archive.org/web/20210228210901/http://blog.stevemcauley.com/2011/12/03/energy-conserving-wrapped-diffuse/ + diffuse_brdf_NL = max(0.0, (NdotL + roughness) / ((1.0 + roughness) * (1.0 + roughness))) * (1.0 / M_PI); #elif defined(DIFFUSE_TOON) - diffuse_brdf_NL = smoothstep(-roughness, max(roughness, 0.01), NdotL); + diffuse_brdf_NL = smoothstep(-roughness, max(roughness, 0.01), NdotL) * (1.0 / M_PI); #elif defined(DIFFUSE_BURLEY) @@ -666,7 +724,10 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte #endif // LIGHT_ANISOTROPY_USED // F float cLdotH5 = SchlickFresnel(cLdotH); - vec3 F = mix(vec3(cLdotH5), vec3(1.0), f0); + // Calculate Fresnel using cheap approximate specular occlusion term from Filament: + // https://google.github.io/filament/Filament.html#lighting/occlusion/specularocclusion + float f90 = clamp(50.0 * f0.g, 0.0, 1.0); + vec3 F = f0 + (f90 - f0) * cLdotH5; vec3 specular_brdf_NL = cNdotL * D * F * G; @@ -731,7 +792,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f if (omni_lights[idx].size > 0.0) { float t = omni_lights[idx].size / max(0.001, light_length); - size_A = max(0.0, 1.0 - 1 / sqrt(1 + t * t)); + size_A = max(0.0, 1.0 - 1.0 / sqrt(1.0 + t * t)); } light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, omni_attenuation, f0, roughness, metallic, omni_lights[idx].specular_amount, albedo, alpha, @@ -780,7 +841,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 f if (spot_lights[idx].size > 0.0) { float t = spot_lights[idx].size / max(0.001, light_length); - size_A = max(0.0, 1.0 - 1 / sqrt(1 + t * t)); + size_A = max(0.0, 1.0 - 1.0 / sqrt(1.0 + t * t)); } light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, spot_attenuation, f0, roughness, metallic, spot_lights[idx].specular_amount, albedo, alpha, @@ -852,7 +913,11 @@ vec4 fog_process(vec3 vertex) { void main() { //lay out everything, whatever is unused is optimized away anyway vec3 vertex = vertex_interp; +#ifdef USE_MULTIVIEW + vec3 view = -normalize(vertex_interp - multiview_data.eye_offset[ViewIndex].xyz); +#else vec3 view = -normalize(vertex_interp); +#endif vec3 albedo = vec3(1.0); vec3 backlight = vec3(0.0); vec4 transmittance_color = vec4(0.0, 0.0, 0.0, 1.0); @@ -1029,6 +1094,7 @@ void main() { #else vec3 ref_vec = reflect(-view, normal); #endif + ref_vec = mix(ref_vec, normal, roughness * roughness); float horizon = min(1.0 + dot(ref_vec, normal), 1.0); ref_vec = scene_data.radiance_inverse_xform * ref_vec; specular_light = textureLod(radiance_map, ref_vec, roughness * RADIANCE_MAX_LOD).rgb; @@ -1063,9 +1129,15 @@ void main() { #if defined(CUSTOM_IRRADIANCE_USED) ambient_light = mix(ambient_light, custom_irradiance.rgb, custom_irradiance.a); #endif // CUSTOM_IRRADIANCE_USED - ambient_light *= albedo.rgb; - ambient_light *= ao; + { +#if defined(AMBIENT_LIGHT_DISABLED) + ambient_light = vec3(0.0, 0.0, 0.0); +#else + ambient_light *= albedo.rgb; + ambient_light *= ao; +#endif // AMBIENT_LIGHT_DISABLED + } // convert ao to direct light ao ao = mix(1.0, ao, ao_light_affect); @@ -1087,7 +1159,7 @@ void main() { 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; - specular_light *= env.x * f0 + env.y; + specular_light *= env.x * f0 + env.y * clamp(50.0 * f0.g, 0.0, 1.0); #endif } |