From 1eaf5f03fcf19ba1bd3d8812856c73c39d4e7b72 Mon Sep 17 00:00:00 2001 From: ywmaa Date: Thu, 19 Oct 2023 19:10:10 +0300 Subject: [PATCH] Implement vertex shading for Vulkan --- drivers/gles3/shaders/scene.glsl | 4 - .../scene_forward_clustered.glsl | 413 +++++++++++++++++- .../forward_mobile/scene_forward_mobile.glsl | 292 ++++++++++++- .../shaders/scene_forward_lights_inc.glsl | 23 +- 4 files changed, 708 insertions(+), 24 deletions(-) diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index 73e24ef92e2c..d4765361d7c2 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -763,10 +763,6 @@ void main() { #endif // ADDITIVE_SPOT - diffuse_light_interp.rgb *= albedo; - diffuse_light_interp.rgb *= 1.0 - metallic; - vec3 additive_light_color = diffuse_light_interp.rgb + specular_light_interp.rgb; - #endif // USE_ADDITIVE_LIGHTING #endif //!MODE_RENDER_DEPTH #endif // USE_VERTEX_LIGHTING diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl index 20b080da4d8b..50e3a096b698 100644 --- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl @@ -67,6 +67,28 @@ layout(location = 13) in vec4 previous_normal_attrib; #endif // MOTION_VECTORS +#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) && defined(USE_VERTEX_LIGHTING) +/* Specialization Constants (Toggles) */ + +layout(constant_id = 2) const bool sc_use_light_soft_shadows = false; + +/* Specialization Constants (Values) */ + +layout(constant_id = 8) const uint sc_directional_soft_shadow_samples = 4; +layout(constant_id = 11) const bool sc_projector_use_mipmaps = true; + +// not used in clustered renderer but we share some code with the mobile renderer that requires this. +const float sc_luminance_multiplier = 1.0; + +// Default to SPECULAR_SCHLICK_GGX. +#if !defined(SPECULAR_DISABLED) && !defined(SPECULAR_SCHLICK_GGX) && !defined(SPECULAR_TOON) +#define SPECULAR_SCHLICK_GGX +#endif + +#include "../scene_forward_lights_inc.glsl" + +#endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) && defined(USE_VERTEX_LIGHTING) + 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); @@ -154,7 +176,10 @@ ivec2 multiview_uv(ivec2 uv) { return uv; } #endif //USE_MULTIVIEW - +#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) && defined(USE_VERTEX_LIGHTING) +layout(location = 12) highp out vec4 diffuse_light_interp; +layout(location = 13) highp out vec4 specular_light_interp; +#endif invariant gl_Position; #GLOBALS @@ -186,6 +211,23 @@ vec3 double_add_vec3(vec3 base_a, vec3 prec_a, vec3 base_b, vec3 prec_b, out vec } #endif +#ifdef USE_VERTEX_LIGHTING +void cluster_get_item_range(uint p_offset, out uint item_min, out uint item_max, out uint item_from, out uint item_to) { + uint item_min_max = cluster_buffer.data[p_offset]; + item_min = item_min_max & 0xFFFFu; + item_max = item_min_max >> 16; + + item_from = item_min >> 5; + item_to = (item_max == 0) ? 0 : ((item_max - 1) >> 5) + 1; //side effect of how it is stored, as item_max 0 means no elements +} + +uint cluster_get_range_clip_mask(uint i, uint z_min, uint z_max) { + int local_min = clamp(int(z_min) - int(i) * 32, 0, 31); + int mask_width = min(int(z_max) - int(z_min), 32 - local_min); + return bitfieldInsert(uint(0), uint(0xFFFFFFFF), local_min, mask_width); +} +#endif // USE_VERTEX_LIGHTING + void vertex_shader(vec3 vertex_input, #ifdef NORMAL_USED in vec3 normal_input, @@ -484,6 +526,362 @@ void vertex_shader(vec3 vertex_input, #ifdef MOTION_VECTORS screen_pos = gl_Position; #endif +#ifdef USE_VERTEX_LIGHTING + //lay out everything, whatever is unused is optimized away anyway + vec3 albedo = vec3(1.0); + vec3 backlight = vec3(0.0); + vec4 transmittance_color = vec4(0.0); + float transmittance_depth = 0.0; + float transmittance_boost = 0.0; + float metallic = 0.0; + float specular = 0.5; + vec3 emission = vec3(0.0); + float rim = 0.0; + float rim_tint = 0.0; + float clearcoat = 0.0; + float clearcoat_roughness = 0.0; + float anisotropy = 0.0; + vec2 anisotropy_flow = vec2(1.0, 0.0); +#ifndef FOG_DISABLED + vec4 fog = vec4(0.0); +#endif // !FOG_DISABLED +#if defined(CUSTOM_RADIANCE_USED) + vec4 custom_radiance = vec4(0.0); +#endif +#if defined(CUSTOM_IRRADIANCE_USED) + vec4 custom_irradiance = vec4(0.0); +#endif + + float ao = 1.0; + float ao_light_affect = 0.0; + + float alpha = 1.0; +#endif // USE_VERTEX_LIGHTING +// VERTEX LIGHTING +#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) && defined(USE_VERTEX_LIGHTING) + vec3 ambient_light = vec3(0.0, 0.0, 0.0); + diffuse_light_interp = vec4(0.0); + specular_light_interp = vec4(0.0); + +#ifdef USE_MULTIVIEW + // UV in our combined frustum space is used for certain screen uv processes where it's + // overkill to render separate left and right eye views + vec2 combined_uv = (combined_projected.xy / combined_projected.w) * 0.5 + 0.5; + + uvec2 cluster_pos = uvec2(combined_uv.xy / scene_data.screen_pixel_size) >> implementation_data.cluster_shift; + vec3 view = -normalize(vertex_interp - eye_offset); +#else + uvec2 cluster_pos = uvec2(gl_Position.xy) >> implementation_data.cluster_shift; + vec3 view = -normalize(vertex_interp); +#endif + uint cluster_offset = (implementation_data.cluster_width * cluster_pos.y + cluster_pos.x) * (implementation_data.max_cluster_element_count_div_32 + 32); + + uint cluster_z = uint(clamp((-vertex.z / scene_data.z_far) * 32.0, 0.0, 31.0)); + //used for interpolating anything cluster related + vec3 vertex_ddx = vec3(0); // Fake variable + vec3 vertex_ddy = vec3(0); // Fake variable + // convert ao to direct light ao + ao = mix(1.0, ao, ao_light_affect); + + //this saves some VGPRs + vec3 f0 = F0(metallic, specular, albedo); + + { +#if defined(DIFFUSE_TOON) + //simplify for toon, as + specular_light_interp.rgb *= specular * metallic * albedo * 2.0; +#else + + // scales the specular reflections, needs to 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, view), 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; + + specular_light_interp.rgb *= env.x * f0 + env.y * clamp(50.0 * f0.g, metallic, 1.0); +#endif + } + +#if !defined(MODE_RENDER_DEPTH) + //this saves some VGPRs + uint orms = packUnorm4x8(vec4(ao, roughness, metallic, specular)); +#endif + + { // Directional light. + + for (uint i = 0; i < 8; i++) { + if (i >= scene_data.directional_light_count) { + break; + } + + if (!bool(directional_lights.data[i].mask & instances.data[instance_index].layer_mask)) { + continue; //not masked + } + +#ifdef LIGHT_TRANSMITTANCE_USED + float transmittance_z = transmittance_depth; + + if (directional_lights.data[i].shadow_opacity > 0.001) { + float depth_z = -vertex.z; + + if (depth_z < directional_lights.data[i].shadow_split_offsets.x) { + vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.x, 1.0); + vec4 trans_coord = directional_lights.data[i].shadow_matrix1 * trans_vertex; + trans_coord /= trans_coord.w; + + float shadow_z = textureLod(sampler2D(directional_shadow_atlas, SAMPLER_LINEAR_CLAMP), trans_coord.xy, 0.0).r; + shadow_z *= directional_lights.data[i].shadow_z_range.x; + float z = trans_coord.z * directional_lights.data[i].shadow_z_range.x; + + transmittance_z = z - shadow_z; + } else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) { + vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.y, 1.0); + vec4 trans_coord = directional_lights.data[i].shadow_matrix2 * trans_vertex; + trans_coord /= trans_coord.w; + + float shadow_z = textureLod(sampler2D(directional_shadow_atlas, SAMPLER_LINEAR_CLAMP), trans_coord.xy, 0.0).r; + shadow_z *= directional_lights.data[i].shadow_z_range.y; + float z = trans_coord.z * directional_lights.data[i].shadow_z_range.y; + + transmittance_z = z - shadow_z; + } else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) { + vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.z, 1.0); + vec4 trans_coord = directional_lights.data[i].shadow_matrix3 * trans_vertex; + trans_coord /= trans_coord.w; + + float shadow_z = textureLod(sampler2D(directional_shadow_atlas, SAMPLER_LINEAR_CLAMP), trans_coord.xy, 0.0).r; + shadow_z *= directional_lights.data[i].shadow_z_range.z; + float z = trans_coord.z * directional_lights.data[i].shadow_z_range.z; + + transmittance_z = z - shadow_z; + + } else { + vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.w, 1.0); + vec4 trans_coord = directional_lights.data[i].shadow_matrix4 * trans_vertex; + trans_coord /= trans_coord.w; + + float shadow_z = textureLod(sampler2D(directional_shadow_atlas, SAMPLER_LINEAR_CLAMP), trans_coord.xy, 0.0).r; + shadow_z *= directional_lights.data[i].shadow_z_range.w; + float z = trans_coord.z * directional_lights.data[i].shadow_z_range.w; + + transmittance_z = z - shadow_z; + } + } +#endif + + float shadow = 1.0; + +#ifdef DEBUG_DRAW_PSSM_SPLITS + vec3 tint = vec3(1.0); + if (-vertex.z < directional_lights.data[i].shadow_split_offsets.x) { + tint = vec3(1.0, 0.0, 0.0); + } else if (-vertex.z < directional_lights.data[i].shadow_split_offsets.y) { + tint = vec3(0.0, 1.0, 0.0); + } else if (-vertex.z < directional_lights.data[i].shadow_split_offsets.z) { + tint = vec3(0.0, 0.0, 1.0); + } else { + tint = vec3(1.0, 1.0, 0.0); + } + tint = mix(tint, vec3(1.0), shadow); + shadow = 1.0; +#endif + + float size_A = sc_use_light_soft_shadows ? directional_lights.data[i].size : 0.0; + + light_compute(normal, directional_lights.data[i].direction, normalize(view), size_A, +#ifndef DEBUG_DRAW_PSSM_SPLITS + directional_lights.data[i].color * directional_lights.data[i].energy, +#else + directional_lights.data[i].color * directional_lights.data[i].energy * tint, +#endif + true, 1.0, f0, orms, 1.0, albedo, alpha, +#ifdef LIGHT_BACKLIGHT_USED + backlight, +#endif +#ifdef LIGHT_TRANSMITTANCE_USED + transmittance_color, + transmittance_depth, + transmittance_boost, + transmittance_z, +#endif +#ifdef LIGHT_RIM_USED + rim, rim_tint, +#endif +#ifdef LIGHT_CLEARCOAT_USED + clearcoat, clearcoat_roughness, normalize(normal_interp), +#endif +#ifdef LIGHT_ANISOTROPY_USED + binormal, + tangent, anisotropy, +#endif + diffuse_light_interp.rgb, + specular_light_interp.rgb); + } + } + + { //omni lights + + uint cluster_omni_offset = cluster_offset; + + uint item_min; + uint item_max; + uint item_from; + uint item_to; + + cluster_get_item_range(cluster_omni_offset + implementation_data.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to); + +#ifdef USE_SUBGROUPS + item_from = subgroupBroadcastFirst(subgroupMin(item_from)); + item_to = subgroupBroadcastFirst(subgroupMax(item_to)); +#endif + + for (uint i = item_from; i < item_to; i++) { + uint mask = cluster_buffer.data[cluster_omni_offset + i]; + mask &= cluster_get_range_clip_mask(i, item_min, item_max); +#ifdef USE_SUBGROUPS + uint merged_mask = subgroupBroadcastFirst(subgroupOr(mask)); +#else + uint merged_mask = mask; +#endif + + while (merged_mask != 0) { + uint bit = findMSB(merged_mask); + merged_mask &= ~(1u << bit); +#ifdef USE_SUBGROUPS + if (((1u << bit) & mask) == 0) { //do not process if not originally here + continue; + } +#endif + uint light_index = 32 * i + bit; + + if (!bool(omni_lights.data[light_index].mask & instances.data[instance_index].layer_mask)) { + continue; //not masked + } + + if (omni_lights.data[light_index].bake_mode == LIGHT_BAKE_STATIC && bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP)) { + continue; // Statically baked light and object uses lightmap, skip + } + + light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, 1.0, albedo, alpha, +#ifdef LIGHT_BACKLIGHT_USED + backlight, +#endif +#ifdef LIGHT_TRANSMITTANCE_USED + transmittance_color, + transmittance_depth, + transmittance_boost, +#endif +#ifdef LIGHT_RIM_USED + rim, + rim_tint, +#endif +#ifdef LIGHT_CLEARCOAT_USED + clearcoat, clearcoat_roughness, normalize(normal_interp), +#endif +#ifdef LIGHT_ANISOTROPY_USED + tangent, binormal, anisotropy, +#endif + diffuse_light_interp.rgb, specular_light_interp.rgb); + } + } + } + + { //spot lights + + uint cluster_spot_offset = cluster_offset + implementation_data.cluster_type_size; + + uint item_min; + uint item_max; + uint item_from; + uint item_to; + + cluster_get_item_range(cluster_spot_offset + implementation_data.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to); + +#ifdef USE_SUBGROUPS + item_from = subgroupBroadcastFirst(subgroupMin(item_from)); + item_to = subgroupBroadcastFirst(subgroupMax(item_to)); +#endif + + for (uint i = item_from; i < item_to; i++) { + uint mask = cluster_buffer.data[cluster_spot_offset + i]; + mask &= cluster_get_range_clip_mask(i, item_min, item_max); +#ifdef USE_SUBGROUPS + uint merged_mask = subgroupBroadcastFirst(subgroupOr(mask)); +#else + uint merged_mask = mask; +#endif + + while (merged_mask != 0) { + uint bit = findMSB(merged_mask); + merged_mask &= ~(1u << bit); +#ifdef USE_SUBGROUPS + if (((1u << bit) & mask) == 0) { //do not process if not originally here + continue; + } +#endif + + uint light_index = 32 * i + bit; + + if (!bool(spot_lights.data[light_index].mask & instances.data[instance_index].layer_mask)) { + continue; //not masked + } + + if (spot_lights.data[light_index].bake_mode == LIGHT_BAKE_STATIC && bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP)) { + continue; // Statically baked light and object uses lightmap, skip + } + + light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, 1.0, albedo, alpha, +#ifdef LIGHT_BACKLIGHT_USED + backlight, +#endif +#ifdef LIGHT_TRANSMITTANCE_USED + transmittance_color, + transmittance_depth, + transmittance_boost, +#endif +#ifdef LIGHT_RIM_USED + rim, + rim_tint, +#endif +#ifdef LIGHT_CLEARCOAT_USED + clearcoat, clearcoat_roughness, normalize(normal_interp), +#endif +#ifdef LIGHT_ANISOTROPY_USED + tangent, + binormal, anisotropy, +#endif + diffuse_light_interp.rgb, specular_light_interp.rgb); + } + } + } + +#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; + } +#else +#ifdef MODE_RENDER_DEPTH +#ifdef USE_OPAQUE_PREPASS + + if (alpha < scene_data.opaque_prepass_threshold) { + discard; + } + +#endif // USE_OPAQUE_PREPASS +#endif // MODE_RENDER_DEPTH +#endif // ALPHA_SCISSOR_USED + +#endif // USE_SHADOW_TO_OPACITY + +#endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) && defined(USE_VERTEX_LIGHTING) #ifdef MODE_RENDER_DEPTH if (scene_data.pancake_shadows) { @@ -725,7 +1123,10 @@ ivec2 multiview_uv(ivec2 uv) { return uv; } #endif //USE_MULTIVIEW - +#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) && defined(USE_VERTEX_LIGHTING) +layout(location = 12) highp in vec4 diffuse_light_interp; +layout(location = 13) highp in vec4 specular_light_interp; +#endif //defines to keep compatibility with vertex #ifdef USE_MULTIVIEW @@ -1751,7 +2152,11 @@ void fragment_shader(in SceneData scene_data) { #endif // LIGHTING -#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) +#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) && defined(USE_VERTEX_LIGHTING) // Pass Vertex Lighting colors + specular_light = specular_light_interp.rgb; + diffuse_light = diffuse_light_interp.rgb; +#endif +#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) && !defined(USE_VERTEX_LIGHTING) { // Directional light. @@ -2250,7 +2655,7 @@ void fragment_shader(in SceneData scene_data) { #endif // !MODE_RENDER_DEPTH #endif // USE_SHADOW_TO_OPACITY -#endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) +#endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) && !defined(USE_VERTEX_LIGHTING) #ifdef MODE_RENDER_DEPTH diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl index 1637326b48c4..392b99255d2c 100644 --- a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl @@ -59,6 +59,29 @@ layout(location = 10) in uvec4 bone_attrib; layout(location = 11) in vec4 weight_attrib; #endif +#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) && defined(USE_VERTEX_LIGHTING) + +layout(constant_id = 0) const bool sc_use_light_projector = false; +layout(constant_id = 1) const bool sc_use_light_soft_shadows = false; +layout(constant_id = 8) const bool sc_projector_use_mipmaps = true; + +layout(constant_id = 9) const bool sc_disable_omni_lights = false; +layout(constant_id = 10) const bool sc_disable_spot_lights = false; +layout(constant_id = 11) const bool sc_disable_reflection_probes = false; +layout(constant_id = 12) const bool sc_disable_directional_lights = false; + +// This is just here for reflection_process we are going to import from scene_forward_lights_inc +layout(constant_id = 15) const float sc_luminance_multiplier = 2.0; + +// Default to SPECULAR_SCHLICK_GGX. +#if !defined(SPECULAR_DISABLED) && !defined(SPECULAR_SCHLICK_GGX) && !defined(SPECULAR_TOON) +#define SPECULAR_SCHLICK_GGX +#endif + +#include "../scene_forward_lights_inc.glsl" + +#endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) && defined(USE_VERTEX_LIGHTING) + 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); @@ -100,7 +123,10 @@ layout(location = 4) mediump out vec2 uv2_interp; layout(location = 5) mediump out vec3 tangent_interp; layout(location = 6) mediump out vec3 binormal_interp; #endif - +#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) && defined(USE_VERTEX_LIGHTING) +layout(location = 7) highp out vec4 diffuse_light_interp; +layout(location = 8) highp out vec4 specular_light_interp; +#endif #ifdef MATERIAL_UNIFORMS_USED layout(set = MATERIAL_UNIFORM_SET, binding = 0, std140) uniform MaterialUniforms{ @@ -182,6 +208,38 @@ void main() { mat4 model_matrix = instances.data[draw_call.instance_index].transform; mat4 inv_view_matrix = scene_data.inv_view_matrix; +#ifdef USE_VERTEX_LIGHTING + //lay out everything, whatever is unused is optimized away anyway + vec3 albedo = vec3(1.0); + vec3 backlight = vec3(0.0); + vec4 transmittance_color = vec4(0.0); + float transmittance_depth = 0.0; + float transmittance_boost = 0.0; + float metallic = 0.0; + float specular = 0.5; + vec3 emission = vec3(0.0); + float rim = 0.0; + float rim_tint = 0.0; + float clearcoat = 0.0; + float clearcoat_roughness = 0.0; + float anisotropy = 0.0; + vec2 anisotropy_flow = vec2(1.0, 0.0); +#ifndef FOG_DISABLED + vec4 fog = vec4(0.0); +#endif // !FOG_DISABLED +#if defined(CUSTOM_RADIANCE_USED) + vec4 custom_radiance = vec4(0.0); +#endif +#if defined(CUSTOM_IRRADIANCE_USED) + vec4 custom_irradiance = vec4(0.0); +#endif + + float ao = 1.0; + float ao_light_affect = 0.0; + + float alpha = 1.0; +#endif // USE_VERTEX_LIGHTING + #ifdef USE_DOUBLE_PRECISION vec3 model_precision = vec3(model_matrix[0][3], model_matrix[1][3], model_matrix[2][3]); model_matrix[0][3] = 0.0; @@ -445,6 +503,221 @@ void main() { binormal_interp = binormal; #endif +// VERTEX LIGHTING +#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) && defined(USE_VERTEX_LIGHTING) + vec3 ambient_light = vec3(0.0, 0.0, 0.0); +#ifdef USE_MULTIVIEW + vec3 view = -normalize(vertex_interp - eye_offset); +#else + vec3 view = -normalize(vertex_interp); +#endif +#ifndef MODE_RENDER_DEPTH + + vec3 vertex_ddx = vec3(0); // Fake variable + vec3 vertex_ddy = vec3(0); // Fake variable +#endif //!MODE_RENDER_DEPTH + + // convert ao to direct light ao + ao = mix(1.0, ao, ao_light_affect); + + //this saves some VGPRs + vec3 f0 = F0(metallic, specular, albedo); + diffuse_light_interp = vec4(0.0); + specular_light_interp = vec4(0.0); + { +#if defined(DIFFUSE_TOON) + //simplify for toon, as + specular_light_interp.rgb *= specular * metallic * albedo * 2.0; +#else + + // scales the specular reflections, needs to 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, view), 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; + + specular_light_interp.rgb *= env.x * f0 + env.y * clamp(50.0 * f0.g, metallic, 1.0); +#endif + } + +#if !defined(MODE_RENDER_DEPTH) + //this saves some VGPRs + uint orms = packUnorm4x8(vec4(ao, roughness, metallic, specular)); +#endif + + if (!sc_disable_directional_lights) { //directional light + for (uint i = 0; i < 8; i++) { + if (i >= scene_data.directional_light_count) { + break; + } + + if (!bool(directional_lights.data[i].mask & instances.data[draw_call.instance_index].layer_mask)) { + continue; //not masked + } + + // We're not doing light transmittence + + float shadow = 1.0; + +#ifdef DEBUG_DRAW_PSSM_SPLITS + vec3 tint = vec3(1.0); + if (-vertex.z < directional_lights.data[i].shadow_split_offsets.x) { + tint = vec3(1.0, 0.0, 0.0); + } else if (-vertex.z < directional_lights.data[i].shadow_split_offsets.y) { + tint = vec3(0.0, 1.0, 0.0); + } else if (-vertex.z < directional_lights.data[i].shadow_split_offsets.z) { + tint = vec3(0.0, 0.0, 1.0); + } else { + tint = vec3(1.0, 1.0, 0.0); + } + tint = mix(tint, vec3(1.0), shadow); + shadow = 1.0; +#endif + + light_compute(normal, directional_lights.data[i].direction, normalize(view), 0.0, +#ifndef DEBUG_DRAW_PSSM_SPLITS + directional_lights.data[i].color * directional_lights.data[i].energy, +#else + directional_lights.data[i].color * directional_lights.data[i].energy * tint, +#endif + true, 1.0, f0, orms, 1.0, albedo, alpha, +#ifdef LIGHT_BACKLIGHT_USED + backlight, +#endif +/* not supported here +#ifdef LIGHT_TRANSMITTANCE_USED + transmittance_color, + transmittance_depth, + transmittance_boost, + transmittance_z, +#endif +*/ +#ifdef LIGHT_RIM_USED + rim, rim_tint, +#endif +#ifdef LIGHT_CLEARCOAT_USED + clearcoat, clearcoat_roughness, normalize(normal_interp), +#endif +#ifdef LIGHT_ANISOTROPY_USED + binormal, tangent, anisotropy, +#endif +#ifdef USE_SOFT_SHADOW + directional_lights.data[i].size, +#endif + diffuse_light_interp.rgb, + specular_light_interp.rgb); + } + } //directional light + + if (!sc_disable_omni_lights) { //omni lights + uint light_indices = instances.data[draw_call.instance_index].omni_lights.x; + for (uint i = 0; i < 8; i++) { + uint light_index = light_indices & 0xFF; + if (i == 3) { + light_indices = instances.data[draw_call.instance_index].omni_lights.y; + } else { + light_indices = light_indices >> 8; + } + + if (light_index == 0xFF) { + break; + } + + light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, 1.0, albedo, alpha, +#ifdef LIGHT_BACKLIGHT_USED + backlight, +#endif +/* +#ifdef LIGHT_TRANSMITTANCE_USED + transmittance_color, + transmittance_depth, + transmittance_boost, +#endif +*/ +#ifdef LIGHT_RIM_USED + rim, + rim_tint, +#endif +#ifdef LIGHT_CLEARCOAT_USED + clearcoat, clearcoat_roughness, normalize(normal_interp), +#endif +#ifdef LIGHT_ANISOTROPY_USED + tangent, + binormal, anisotropy, +#endif + diffuse_light_interp.rgb, specular_light_interp.rgb); + } + } //omni lights + + if (!sc_disable_spot_lights) { //spot lights + + uint light_indices = instances.data[draw_call.instance_index].spot_lights.x; + for (uint i = 0; i < 8; i++) { + uint light_index = light_indices & 0xFF; + if (i == 3) { + light_indices = instances.data[draw_call.instance_index].spot_lights.y; + } else { + light_indices = light_indices >> 8; + } + + if (light_index == 0xFF) { + break; + } + + light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, 1.0, albedo, alpha, +#ifdef LIGHT_BACKLIGHT_USED + backlight, +#endif +/* +#ifdef LIGHT_TRANSMITTANCE_USED + transmittance_color, + transmittance_depth, + transmittance_boost, +#endif +*/ +#ifdef LIGHT_RIM_USED + rim, + rim_tint, +#endif +#ifdef LIGHT_CLEARCOAT_USED + clearcoat, clearcoat_roughness, normalize(normal_interp), +#endif +#ifdef LIGHT_ANISOTROPY_USED + tangent, + binormal, anisotropy, +#endif + diffuse_light_interp.rgb, specular_light_interp.rgb); + } + } //spot lights + +#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; + } +#else +#ifdef MODE_RENDER_DEPTH +#ifdef USE_OPAQUE_PREPASS + + if (alpha < scene_data.opaque_prepass_threshold) { + discard; + } + +#endif // USE_OPAQUE_PREPASS +#endif // MODE_RENDER_DEPTH +#endif // !ALPHA_SCISSOR_USED + +#endif // USE_SHADOW_TO_OPACITY + +#endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) && defined(USE_VERTEX_LIGHTING) + #ifdef MODE_RENDER_DEPTH #ifdef MODE_DUAL_PARABOLOID @@ -559,6 +832,11 @@ layout(location = 5) mediump in vec3 tangent_interp; layout(location = 6) mediump in vec3 binormal_interp; #endif +#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) && defined(USE_VERTEX_LIGHTING) +layout(location = 7) highp in vec4 diffuse_light_interp; +layout(location = 8) highp in vec4 specular_light_interp; +#endif + #ifdef MODE_DUAL_PARABOLOID layout(location = 9) highp in float dp_clip; @@ -643,7 +921,7 @@ layout(location = 0) out mediump vec4 frag_color; #include "../scene_forward_aa_inc.glsl" -#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) +#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) // && !defined(USE_VERTEX_LIGHTING) // Default to SPECULAR_SCHLICK_GGX. #if !defined(SPECULAR_DISABLED) && !defined(SPECULAR_SCHLICK_GGX) && !defined(SPECULAR_TOON) @@ -652,7 +930,7 @@ layout(location = 0) out mediump vec4 frag_color; #include "../scene_forward_lights_inc.glsl" -#endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) +#endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) && !defined(USE_VERTEX_LIGHTING) #ifndef MODE_RENDER_DEPTH @@ -1316,7 +1594,11 @@ void main() { #endif // LIGHTING -#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) +#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) && defined(USE_VERTEX_LIGHTING) // Pass Vertex Lighting colors + specular_light = specular_light_interp.rgb; + diffuse_light = diffuse_light_interp.rgb; +#endif +#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) && !defined(USE_VERTEX_LIGHTING) if (!sc_disable_directional_lights) { //directional light #ifndef SHADOWS_DISABLED @@ -1771,7 +2053,7 @@ void main() { #endif // !MODE_RENDER_DEPTH #endif // USE_SHADOW_TO_OPACITY -#endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) +#endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) && !defined(USE_VERTEX_LIGHTING) #ifdef MODE_RENDER_DEPTH diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl index 40ca74ae07ce..8dd59dd9523e 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl @@ -255,7 +255,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, bool is_di #endif //defined(LIGHT_CODE_USED) } -#ifndef SHADOWS_DISABLED +#if !defined(SHADOWS_DISABLED) && !defined(USE_VERTEX_LIGHTING) // Interleaved Gradient Noise // https://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare @@ -401,8 +401,7 @@ float sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex } } -#endif // SHADOWS_DISABLED - +#endif // !defined(SHADOWS_DISABLED) && !defined(USE_VERTEX_LIGHTING) float get_omni_attenuation(float distance, float inv_range, float decay) { float nd = distance * inv_range; nd *= nd; @@ -413,7 +412,7 @@ float get_omni_attenuation(float distance, float inv_range, float decay) { } float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) { -#ifndef SHADOWS_DISABLED +#if !defined(SHADOWS_DISABLED) && !defined(USE_VERTEX_LIGHTING) if (omni_lights.data[idx].shadow_opacity > 0.001) { // there is a shadowmap vec2 texel_size = scene_data_block.data.shadow_atlas_pixel_size; @@ -542,7 +541,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) { return shadow; } -#endif +#endif // !defined(SHADOWS_DISABLED) && !defined(USE_VERTEX_LIGHTING) return 1.0; } @@ -578,7 +577,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v float t = omni_lights.data[idx].size / max(0.001, light_length); size_A = max(0.0, 1.0 - 1 / sqrt(1 + t * t)); } - +#ifndef USE_VERTEX_LIGHTING #ifdef LIGHT_TRANSMITTANCE_USED float transmittance_z = transmittance_depth; //no transmittance by default transmittance_color.a *= light_attenuation; @@ -667,7 +666,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v color *= proj.rgb * proj.a; } } - +#endif // !USE_VERTEX_LIGHTING light_attenuation *= shadow; light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, false, light_attenuation, f0, orms, omni_lights.data[idx].specular_amount, albedo, alpha, @@ -694,7 +693,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v } float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) { -#ifndef SHADOWS_DISABLED +#if !defined(SHADOWS_DISABLED) && !defined(USE_VERTEX_LIGHTING) if (spot_lights.data[idx].shadow_opacity > 0.001) { vec3 light_rel_vec = spot_lights.data[idx].position - vertex; float light_length = length(light_rel_vec); @@ -771,8 +770,7 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) { return shadow; } -#endif // SHADOWS_DISABLED - +#endif // !defined(SHADOWS_DISABLED) && !defined(USE_VERTEX_LIGHTING) return 1.0; } @@ -831,6 +829,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v size_A = max(0.0, 1.0 - 1 / sqrt(1 + t * t)); } +#ifndef USE_VERTEX_LIGHTING #ifdef LIGHT_TRANSMITTANCE_USED float transmittance_z = transmittance_depth; transmittance_color.a *= light_attenuation; @@ -875,6 +874,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v color *= proj.rgb * proj.a; } } +#endif // !USE_VERTEX_LIGHTING light_attenuation *= shadow; light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, false, light_attenuation, f0, orms, spot_lights.data[idx].specular_amount, albedo, alpha, @@ -978,7 +978,7 @@ void reflection_process(uint ref_index, vec3 vertex, vec3 ref_vec, vec3 normal, } break; } } - +#ifndef USE_VERTEX_LIGHTING float blur_shadow(float shadow) { return shadow; #if 0 @@ -998,3 +998,4 @@ float blur_shadow(float shadow) { return shadow; #endif } +#endif // !USE_VERTEX_LIGHTING \ No newline at end of file