From cfac8972e1def8b79f27fc8251e4aacf698bf245 Mon Sep 17 00:00:00 2001 From: reduz Date: Fri, 13 Aug 2021 14:27:33 -0300 Subject: More optimizations on the mobile renderer. * Specialization constants used to disable anything not needed to draw * Added softshadow and projector support on mobile. This new approach ensures mobile shaders are smaller and more efficient, but relies on more pipeline versions compiled on demand. As a result, random stalls can ocur like in Godot 3.x. These will be solved by using background compilation and fallbacks eventually (but needs to be tested first). --- .../forward_mobile/render_forward_mobile.cpp | 67 +++++++++++++---- .../forward_mobile/render_forward_mobile.h | 35 ++++++--- .../renderer_rd/shaders/scene_forward_mobile.glsl | 83 +++++++++++++++------- 3 files changed, 139 insertions(+), 46 deletions(-) (limited to 'servers/rendering') diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp index f810ae2454..ab052885c6 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -664,6 +664,23 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color _pre_opaque_render(p_render_data, false, false, RID(), RID()); + uint32_t spec_constant_base_flags = 0; + + { + //figure out spec constants + + if (p_render_data->directional_light_count > 0) { + if (p_render_data->directional_light_soft_shadows) { + spec_constant_base_flags |= 1 << SPEC_CONSTANT_USING_DIRECTIONAL_SOFT_SHADOWS; + } + } else { + spec_constant_base_flags |= 1 << SPEC_CONSTANT_DISABLE_DIRECTIONAL_LIGHTS; + } + + if (!is_environment(p_render_data->environment) || environment_is_fog_enabled(p_render_data->environment)) { + spec_constant_base_flags |= 1 << SPEC_CONSTANT_DISABLE_FOG; + } + } { if (render_buffer) { RD::get_singleton()->draw_command_begin_label("Render 3D Pass"); @@ -706,7 +723,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color } RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer); - RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold, p_render_data->view_count); + RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, spec_constant_base_flags, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold, p_render_data->view_count); render_list_params.framebuffer_format = fb_format; if ((uint32_t)render_list_params.element_count > render_list_thread_threshold && false) { // secondary command buffers need more testing at this time @@ -760,7 +777,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color if (using_subpass_transparent) { RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer); - RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold, p_render_data->view_count); + RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, spec_constant_base_flags, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold, p_render_data->view_count); render_list_params.framebuffer_format = fb_format; if ((uint32_t)render_list_params.element_count > render_list_thread_threshold && false) { // secondary command buffers need more testing at this time @@ -797,7 +814,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color // _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false); RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer); - RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold, p_render_data->view_count); + RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, spec_constant_base_flags, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold, p_render_data->view_count); render_list_params.framebuffer_format = fb_format; if ((uint32_t)render_list_params.element_count > render_list_thread_threshold && false) { // secondary command buffers need more testing at this time @@ -924,7 +941,7 @@ void RenderForwardMobile::_render_shadow_end(uint32_t p_barrier) { for (uint32_t i = 0; i < scene_state.shadow_passes.size(); i++) { SceneState::ShadowPass &shadow_pass = scene_state.shadow_passes[i]; - RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, shadow_pass.rp_uniform_set, false, Vector2(), shadow_pass.camera_plane, shadow_pass.lod_distance_multiplier, shadow_pass.screen_lod_threshold, 1, shadow_pass.element_from, RD::BARRIER_MASK_NO_BARRIER); + RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, shadow_pass.rp_uniform_set, 0, false, Vector2(), shadow_pass.camera_plane, shadow_pass.lod_distance_multiplier, shadow_pass.screen_lod_threshold, 1, shadow_pass.element_from, RD::BARRIER_MASK_NO_BARRIER); _render_list_with_threads(&render_list_parameters, shadow_pass.framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, shadow_pass.initial_depth_action, shadow_pass.final_depth_action, Vector(), 1.0, 0, shadow_pass.rect); } @@ -964,7 +981,7 @@ void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, c RENDER_TIMESTAMP("Render Material"); { - RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, rp_uniform_set); + RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, rp_uniform_set, 0); //regular forward for now Vector clear; clear.push_back(Color(0, 0, 0, 0)); @@ -1005,7 +1022,7 @@ void RenderForwardMobile::_render_uv2(const PagedArray &p_in RENDER_TIMESTAMP("Render Material"); { - RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, rp_uniform_set, true); + RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, rp_uniform_set, true, 0); //regular forward for now Vector clear; clear.push_back(Color(0, 0, 0, 0)); @@ -1079,7 +1096,7 @@ void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const { //regular forward for now - RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), false, pass_mode, rp_uniform_set); + RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), false, pass_mode, rp_uniform_set, 0); _render_list_with_threads(&render_list_params, p_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ); } RD::get_singleton()->draw_command_end_label(); @@ -1722,7 +1739,7 @@ void RenderForwardMobile::_render_list_with_threads(RenderListParameters *p_para } } -void RenderForwardMobile::_fill_push_constant_instance_indices(GeometryInstanceForwardMobile::PushConstant *p_push_constant, const GeometryInstanceForwardMobile *p_instance) { +void RenderForwardMobile::_fill_push_constant_instance_indices(GeometryInstanceForwardMobile::PushConstant *p_push_constant, uint32_t &spec_constants, const GeometryInstanceForwardMobile *p_instance) { // first zero out our indices p_push_constant->omni_lights[0] = 0xFFFF; @@ -1737,6 +1754,19 @@ void RenderForwardMobile::_fill_push_constant_instance_indices(GeometryInstanceF p_push_constant->reflection_probes[0] = 0xFFFF; p_push_constant->reflection_probes[1] = 0xFFFF; + if (p_instance->omni_light_count == 0) { + spec_constants |= 1 << SPEC_CONSTANT_DISABLE_OMNI_LIGHTS; + } + if (p_instance->spot_light_count == 0) { + spec_constants |= 1 << SPEC_CONSTANT_DISABLE_SPOT_LIGHTS; + } + if (p_instance->reflection_probe_count == 0) { + spec_constants |= 1 << SPEC_CONSTANT_DISABLE_REFLECTION_PROBES; + } + if (p_instance->decals_count == 0) { + spec_constants |= 1 << SPEC_CONSTANT_DISABLE_DECALS; + } + for (uint32_t i = 0; i < MAX_RDL_CULL; i++) { uint32_t ofs = i < 4 ? 0 : 1; uint32_t shift = (i & 0x3) << 3; @@ -1784,6 +1814,8 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr const RenderElementInfo &element_info = p_params->element_info[i]; const GeometryInstanceForwardMobile *inst = surf->owner; + uint32_t base_spec_constants = p_params->spec_constant_base_flags; + // GeometryInstanceForwardMobile::PushConstant push_constant = inst->push_constant; GeometryInstanceForwardMobile::PushConstant push_constant; @@ -1819,7 +1851,13 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr mesh_surface = surf->surface_shadow; } else { - _fill_push_constant_instance_indices(&push_constant, inst); + if (inst->use_projector) { + base_spec_constants |= 1 << SPEC_CONSTANT_USING_PROJECTOR; + } + if (inst->use_soft_shadow) { + base_spec_constants |= 1 << SPEC_CONSTANT_USING_SOFT_SHADOWS; + } + _fill_push_constant_instance_indices(&push_constant, base_spec_constants, inst); #ifdef DEBUG_ENABLED if (unlikely(get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_LIGHTING)) { @@ -1911,7 +1949,7 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr prev_index_array_rd = index_array_rd; } - RID pipeline_rd = pipeline->get_render_pipeline(vertex_format, framebuffer_format, p_params->force_wireframe, p_params->subpass); + RID pipeline_rd = pipeline->get_render_pipeline(vertex_format, framebuffer_format, p_params->force_wireframe, p_params->subpass, base_spec_constants); if (pipeline_rd != prev_pipeline_rd) { // checking with prev shader does not make so much sense, as @@ -2170,6 +2208,11 @@ void RenderForwardMobile::geometry_instance_pair_voxel_gi_instances(GeometryInst } void RenderForwardMobile::geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) { + GeometryInstanceForwardMobile *ginstance = static_cast(p_geometry_instance); + ERR_FAIL_COND(!ginstance); + + ginstance->use_projector = p_projector; + ginstance->use_soft_shadow = p_softshadow; } void RenderForwardMobile::_geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance) { @@ -2548,12 +2591,12 @@ void RenderForwardMobile::_update_shader_quality_settings() { spec_constants.push_back(sc); sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL; - sc.constant_id = SPEC_CONSTANT_DECAL_FILTER; + sc.constant_id = SPEC_CONSTANT_DECAL_USE_MIPMAPS; sc.bool_value = decals_get_filter() == RS::DECAL_FILTER_NEAREST_MIPMAPS || decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS || decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC; spec_constants.push_back(sc); - sc.constant_id = SPEC_CONSTANT_PROJECTOR_FILTER; + sc.constant_id = SPEC_CONSTANT_PROJECTOR_USE_MIPMAPS; sc.bool_value = light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS || light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS || light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC; spec_constants.push_back(sc); diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h index b981592840..764d8e80df 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h @@ -65,12 +65,27 @@ protected: }; enum { - SPEC_CONSTANT_SOFT_SHADOW_SAMPLES = 6, - SPEC_CONSTANT_PENUMBRA_SHADOW_SAMPLES = 7, - SPEC_CONSTANT_DIRECTIONAL_SOFT_SHADOW_SAMPLES = 8, - SPEC_CONSTANT_DIRECTIONAL_PENUMBRA_SHADOW_SAMPLES = 9, - SPEC_CONSTANT_DECAL_FILTER = 10, - SPEC_CONSTANT_PROJECTOR_FILTER = 11, + + SPEC_CONSTANT_USING_PROJECTOR = 0, + SPEC_CONSTANT_USING_SOFT_SHADOWS = 1, + SPEC_CONSTANT_USING_DIRECTIONAL_SOFT_SHADOWS = 2, + + SPEC_CONSTANT_SOFT_SHADOW_SAMPLES = 3, + SPEC_CONSTANT_PENUMBRA_SHADOW_SAMPLES = 4, + SPEC_CONSTANT_DIRECTIONAL_SOFT_SHADOW_SAMPLES = 5, + SPEC_CONSTANT_DIRECTIONAL_PENUMBRA_SHADOW_SAMPLES = 6, + + SPEC_CONSTANT_DECAL_USE_MIPMAPS = 7, + SPEC_CONSTANT_PROJECTOR_USE_MIPMAPS = 8, + + SPEC_CONSTANT_DISABLE_OMNI_LIGHTS = 9, + SPEC_CONSTANT_DISABLE_SPOT_LIGHTS = 10, + SPEC_CONSTANT_DISABLE_REFLECTION_PROBES = 11, + SPEC_CONSTANT_DISABLE_DIRECTIONAL_LIGHTS = 12, + + SPEC_CONSTANT_DISABLE_DECALS = 13, + SPEC_CONSTANT_DISABLE_FOG = 14, + }; enum { @@ -159,6 +174,7 @@ protected: bool force_wireframe = false; Vector2 uv_offset; Plane lod_plane; + uint32_t spec_constant_base_flags = 0; float lod_distance_multiplier = 0.0; float screen_lod_threshold = 0.0; RD::FramebufferFormatID framebuffer_format = 0; @@ -166,7 +182,7 @@ protected: uint32_t barrier = RD::BARRIER_MASK_ALL; uint32_t subpass = 0; - RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL) { + RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, RID p_render_pass_uniform_set, uint32_t p_spec_constant_base_flags = 0, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL) { elements = p_elements; element_info = p_element_info; element_count = p_element_count; @@ -182,6 +198,7 @@ protected: screen_lod_threshold = p_screen_lod_threshold; element_offset = p_element_offset; barrier = p_barrier; + spec_constant_base_flags = p_spec_constant_base_flags; } }; @@ -526,6 +543,8 @@ protected: RID transforms_uniform_set; float depth = 0; bool mirror = false; + bool use_projector = false; + bool use_soft_shadow = false; Transform3D transform; bool store_transform_cache = true; // if true we copy our transform into our PushConstant, if false we use our transforms UBO and clear our PushConstants transform bool non_uniform_scale = false; @@ -584,7 +603,7 @@ protected: dirty_list_element(this) {} }; - _FORCE_INLINE_ void _fill_push_constant_instance_indices(GeometryInstanceForwardMobile::PushConstant *p_push_constant, const GeometryInstanceForwardMobile *p_instance); + _FORCE_INLINE_ void _fill_push_constant_instance_indices(GeometryInstanceForwardMobile::PushConstant *p_push_constant, uint32_t &spec_constants, const GeometryInstanceForwardMobile *p_instance); void _update_shader_quality_settings() override; diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl index 2babe92c1c..663100a0b3 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl @@ -373,26 +373,38 @@ void main() { //use medium precision for floats on mobile. precision mediump float; +precision highp int; /* Specialization Constants */ -/* Specialization Constants (Toggles) */ +#if !defined(MODE_RENDER_DEPTH) + +#if !defined(MODE_UNSHADED) + +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 = 2) const bool sc_use_directional_soft_shadows = false; -layout(constant_id = 0) const bool sc_use_forward_gi = false; -layout(constant_id = 1) const bool sc_use_light_projector = false; -layout(constant_id = 2) const bool sc_use_light_soft_shadows = false; -layout(constant_id = 3) const bool sc_use_directional_soft_shadows = false; +layout(constant_id = 3) const uint sc_soft_shadow_samples = 4; +layout(constant_id = 4) const uint sc_penumbra_shadow_samples = 4; -/* Specialization Constants (Values) */ +layout(constant_id = 5) const uint sc_directional_soft_shadow_samples = 4; +layout(constant_id = 6) const uint sc_directional_penumbra_shadow_samples = 4; -layout(constant_id = 6) const uint sc_soft_shadow_samples = 4; -layout(constant_id = 7) const uint sc_penumbra_shadow_samples = 4; +layout(constant_id = 8) const bool sc_projector_use_mipmaps = true; -layout(constant_id = 8) const uint sc_directional_soft_shadow_samples = 4; -layout(constant_id = 9) const uint sc_directional_penumbra_shadow_samples = 4; +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; -layout(constant_id = 10) const bool sc_decal_use_mipmaps = true; -layout(constant_id = 11) const bool sc_projector_use_mipmaps = true; +#endif //!MODE_UNSHADED + +layout(constant_id = 7) const bool sc_decal_use_mipmaps = true; +layout(constant_id = 13) const bool sc_disable_decals = false; +layout(constant_id = 14) const bool sc_disable_fog = false; + +#endif //!MODE_RENDER_DEPTH /* Include our forward mobile UBOs definitions etc. */ #include "scene_forward_mobile_inc.glsl" @@ -735,7 +747,7 @@ void main() { // to maximize VGPR usage // Draw "fixed" fog before volumetric fog to ensure volumetric fog can appear in front of the sky. - if (scene_data.fog_enabled) { + if (!sc_disable_fog && scene_data.fog_enabled) { fog = fog_process(vertex); } @@ -753,7 +765,7 @@ void main() { vec3 vertex_ddx = dFdx(vertex); vec3 vertex_ddy = dFdy(vertex); - { //Decals + if (!sc_disable_decals) { //Decals // must implement uint decal_indices = draw_call.decals.x; @@ -774,25 +786,35 @@ void main() { continue; //out of decal } - //we need ddx/ddy for mipmaps, so simulate them - vec2 ddx = (decals.data[decal_index].xform * vec4(vertex_ddx, 0.0)).xz; - vec2 ddy = (decals.data[decal_index].xform * vec4(vertex_ddy, 0.0)).xz; - float fade = pow(1.0 - (uv_local.y > 0.0 ? uv_local.y : -uv_local.y), uv_local.y > 0.0 ? decals.data[decal_index].upper_fade : decals.data[decal_index].lower_fade); if (decals.data[decal_index].normal_fade > 0.0) { fade *= smoothstep(decals.data[decal_index].normal_fade, 1.0, dot(normal_interp, decals.data[decal_index].normal) * 0.5 + 0.5); } + //we need ddx/ddy for mipmaps, so simulate them + vec2 ddx = (decals.data[decal_index].xform * vec4(vertex_ddx, 0.0)).xz; + vec2 ddy = (decals.data[decal_index].xform * vec4(vertex_ddy, 0.0)).xz; + if (decals.data[decal_index].albedo_rect != vec4(0.0)) { //has albedo - vec4 decal_albedo = textureGrad(sampler2D(decal_atlas_srgb, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uv_local.xz * decals.data[decal_index].albedo_rect.zw + decals.data[decal_index].albedo_rect.xy, ddx * decals.data[decal_index].albedo_rect.zw, ddy * decals.data[decal_index].albedo_rect.zw); + vec4 decal_albedo; + if (sc_decal_use_mipmaps) { + decal_albedo = textureGrad(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].albedo_rect.zw + decals.data[decal_index].albedo_rect.xy, ddx * decals.data[decal_index].albedo_rect.zw, ddy * decals.data[decal_index].albedo_rect.zw); + } else { + decal_albedo = textureLod(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].albedo_rect.zw + decals.data[decal_index].albedo_rect.xy, 0.0); + } decal_albedo *= decals.data[decal_index].modulate; decal_albedo.a *= fade; albedo = mix(albedo, decal_albedo.rgb, decal_albedo.a * decals.data[decal_index].albedo_mix); if (decals.data[decal_index].normal_rect != vec4(0.0)) { - vec3 decal_normal = textureGrad(sampler2D(decal_atlas, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uv_local.xz * decals.data[decal_index].normal_rect.zw + decals.data[decal_index].normal_rect.xy, ddx * decals.data[decal_index].normal_rect.zw, ddy * decals.data[decal_index].normal_rect.zw).xyz; + vec3 decal_normal; + if (sc_decal_use_mipmaps) { + decal_normal = textureGrad(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].normal_rect.zw + decals.data[decal_index].normal_rect.xy, ddx * decals.data[decal_index].normal_rect.zw, ddy * decals.data[decal_index].normal_rect.zw).xyz; + } else { + decal_normal = textureLod(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].normal_rect.zw + decals.data[decal_index].normal_rect.xy, 0.0).xyz; + } decal_normal.xy = decal_normal.xy * vec2(2.0, -2.0) - vec2(1.0, -1.0); //users prefer flipped y normal maps in most authoring software decal_normal.z = sqrt(max(0.0, 1.0 - dot(decal_normal.xy, decal_normal.xy))); //convert to view space, use xzy because y is up @@ -802,7 +824,12 @@ void main() { } if (decals.data[decal_index].orm_rect != vec4(0.0)) { - vec3 decal_orm = textureGrad(sampler2D(decal_atlas, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uv_local.xz * decals.data[decal_index].orm_rect.zw + decals.data[decal_index].orm_rect.xy, ddx * decals.data[decal_index].orm_rect.zw, ddy * decals.data[decal_index].orm_rect.zw).xyz; + vec3 decal_orm; + if (sc_decal_use_mipmaps) { + decal_orm = textureGrad(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].orm_rect.zw + decals.data[decal_index].orm_rect.xy, ddx * decals.data[decal_index].orm_rect.zw, ddy * decals.data[decal_index].orm_rect.zw).xyz; + } else { + decal_orm = textureLod(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].orm_rect.zw + decals.data[decal_index].orm_rect.xy, 0.0).xyz; + } ao = mix(ao, decal_orm.r, decal_albedo.a); roughness = mix(roughness, decal_orm.g, decal_albedo.a); metallic = mix(metallic, decal_orm.b, decal_albedo.a); @@ -811,7 +838,11 @@ void main() { if (decals.data[decal_index].emission_rect != vec4(0.0)) { //emission is additive, so its independent from albedo - emission += textureGrad(sampler2D(decal_atlas_srgb, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, ddx * decals.data[decal_index].emission_rect.zw, ddy * decals.data[decal_index].emission_rect.zw).xyz * decals.data[decal_index].emission_energy * fade; + if (sc_decal_use_mipmaps) { + emission += textureGrad(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, ddx * decals.data[decal_index].emission_rect.zw, ddy * decals.data[decal_index].emission_rect.zw).xyz * decals.data[decal_index].emission_energy * fade; + } else { + emission += textureLod(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, 0.0).xyz * decals.data[decal_index].emission_energy * fade; + } } } } //Decals @@ -951,7 +982,7 @@ void main() { // skipping ssao, do we remove ssao totally? - { //Reflection probes + if (!sc_disable_reflection_probes) { //Reflection probes vec4 reflection_accum = vec4(0.0, 0.0, 0.0, 0.0); vec4 ambient_accum = vec4(0.0, 0.0, 0.0, 0.0); @@ -1017,7 +1048,7 @@ void main() { // LIGHTING #if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) - { //directional light + if (!sc_disable_directional_lights) { //directional light // Do shadow and lighting in two passes to reduce register pressure uint shadow0 = 0; @@ -1347,7 +1378,7 @@ void main() { } } //directional light - { //omni lights + if (!sc_disable_omni_lights) { //omni lights uint light_indices = draw_call.omni_lights.x; for (uint i = 0; i < 8; i++) { uint light_index = light_indices & 0xFF; @@ -1394,7 +1425,7 @@ void main() { } } //omni lights - { //spot lights + if (!sc_disable_spot_lights) { //spot lights uint light_indices = draw_call.spot_lights.x; for (uint i = 0; i < 8; i++) { -- cgit v1.2.3