diff options
Diffstat (limited to 'servers/rendering')
33 files changed, 632 insertions, 419 deletions
diff --git a/servers/rendering/rasterizer_dummy.h b/servers/rendering/rasterizer_dummy.h index be374f1a21..987f2f4342 100644 --- a/servers/rendering/rasterizer_dummy.h +++ b/servers/rendering/rasterizer_dummy.h @@ -412,6 +412,7 @@ public: void light_set_projector(RID p_light, RID p_texture) override {} void light_set_negative(RID p_light, bool p_enable) override {} void light_set_cull_mask(RID p_light, uint32_t p_mask) override {} + void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) override {} void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) override {} void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) override {} void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) override {} @@ -560,6 +561,7 @@ public: void particles_set_speed_scale(RID p_particles, double p_scale) override {} void particles_set_use_local_coordinates(RID p_particles, bool p_enable) override {} void particles_set_process_material(RID p_particles, RID p_material) override {} + RID particles_get_process_material(RID p_particles) const override { return RID(); } void particles_set_fixed_fps(RID p_particles, int p_fps) override {} void particles_set_interpolate(RID p_particles, bool p_enable) override {} void particles_set_fractional_delta(RID p_particles, bool p_enable) override {} diff --git a/servers/rendering/renderer_compositor.cpp b/servers/rendering/renderer_compositor.cpp index 82e8bd6ef9..fa4d9c8b31 100644 --- a/servers/rendering/renderer_compositor.cpp +++ b/servers/rendering/renderer_compositor.cpp @@ -45,7 +45,7 @@ bool RendererCompositor::is_xr_enabled() const { } RendererCompositor::RendererCompositor() { - xr_enabled = GLOBAL_GET("rendering/xr/enabled"); + xr_enabled = GLOBAL_GET("xr/shaders/enabled"); } RendererCanvasRender *RendererCanvasRender::singleton = nullptr; diff --git a/servers/rendering/renderer_rd/effects_rd.cpp b/servers/rendering/renderer_rd/effects_rd.cpp index 02a0b6f184..fe3863fec7 100644 --- a/servers/rendering/renderer_rd/effects_rd.cpp +++ b/servers/rendering/renderer_rd/effects_rd.cpp @@ -332,7 +332,7 @@ void EffectsRD::copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuffer RD::get_singleton()->draw_list_draw(draw_list, true); } -void EffectsRD::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_alpha_to_zero, bool p_srgb, RID p_secondary) { +void EffectsRD::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_alpha_to_zero, bool p_srgb, RID p_secondary, bool p_multiview) { memset(©_to_fb.push_constant, 0, sizeof(CopyToFbPushConstant)); if (p_flip_y) { @@ -348,10 +348,18 @@ void EffectsRD::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, copy_to_fb.push_constant.srgb = true; } + CopyToFBMode mode; + if (p_multiview) { + mode = p_secondary.is_valid() ? COPY_TO_FB_MULTIVIEW_WITH_DEPTH : COPY_TO_FB_MULTIVIEW; + } else { + mode = p_secondary.is_valid() ? COPY_TO_FB_COPY2 : COPY_TO_FB_COPY; + } + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, p_rect); - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_to_fb.pipelines[p_secondary.is_valid() ? COPY_TO_FB_COPY2 : COPY_TO_FB_COPY].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_to_fb.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0); if (p_secondary.is_valid()) { + // TODO may need to do this differently when reading from depth buffer for multiview RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_secondary), 1); } RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); @@ -638,13 +646,13 @@ void EffectsRD::screen_space_reflection(RID p_diffuse, RID p_normal_roughness, R ssr.push_constant.metallic_mask[3] = CLAMP(p_metallic_mask.a * 255.0, 0, 255); store_camera(p_camera, ssr.push_constant.projection); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr.pipelines[(p_roughness_quality != RS::ENV_SSR_ROUGNESS_QUALITY_DISABLED) ? SCREEN_SPACE_REFLECTION_ROUGH : SCREEN_SPACE_REFLECTION_NORMAL]); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr.pipelines[(p_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) ? SCREEN_SPACE_REFLECTION_ROUGH : SCREEN_SPACE_REFLECTION_NORMAL]); RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssr.push_constant, sizeof(ScreenSpaceReflectionPushConstant)); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_output_blur, p_scale_depth), 0); - if (p_roughness_quality != RS::ENV_SSR_ROUGNESS_QUALITY_DISABLED) { + if (p_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) { RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_output, p_blur_radius), 1); } else { RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_output), 1); @@ -655,7 +663,7 @@ void EffectsRD::screen_space_reflection(RID p_diffuse, RID p_normal_roughness, R RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1); } - if (p_roughness_quality != RS::ENV_SSR_ROUGNESS_QUALITY_DISABLED) { + if (p_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) { //blur RD::get_singleton()->compute_list_add_barrier(compute_list); @@ -667,10 +675,10 @@ void EffectsRD::screen_space_reflection(RID p_diffuse, RID p_normal_roughness, R ssr_filter.push_constant.proj_info[2] = (1.0f - p_camera.matrix[0][2]) / p_camera.matrix[0][0]; ssr_filter.push_constant.proj_info[3] = (1.0f + p_camera.matrix[1][2]) / p_camera.matrix[1][1]; ssr_filter.push_constant.vertical = 0; - if (p_roughness_quality == RS::ENV_SSR_ROUGNESS_QUALITY_LOW) { + if (p_roughness_quality == RS::ENV_SSR_ROUGHNESS_QUALITY_LOW) { ssr_filter.push_constant.steps = p_max_steps / 3; ssr_filter.push_constant.increment = 3; - } else if (p_roughness_quality == RS::ENV_SSR_ROUGNESS_QUALITY_MEDIUM) { + } else if (p_roughness_quality == RS::ENV_SSR_ROUGHNESS_QUALITY_MEDIUM) { ssr_filter.push_constant.steps = p_max_steps / 2; ssr_filter.push_constant.increment = 2; } else { @@ -2032,7 +2040,7 @@ void EffectsRD::cubemap_roughness(RID p_source_rd_texture, RID p_dest_texture, u memset(&roughness.push_constant, 0, sizeof(CubemapRoughnessPushConstant)); roughness.push_constant.face_id = p_face_id > 9 ? 0 : p_face_id; - roughness.push_constant.roughness = p_roughness; + roughness.push_constant.roughness = p_roughness * p_roughness; // Shader expects roughness, not perceptual roughness, so multiply before passing in. roughness.push_constant.sample_count = p_sample_count; roughness.push_constant.use_direct_write = p_roughness == 0.0; roughness.push_constant.face_size = p_size; @@ -2040,7 +2048,7 @@ void EffectsRD::cubemap_roughness(RID p_source_rd_texture, RID p_dest_texture, u RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, roughness.compute_pipeline); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture, true), 0); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_texture), 1); RD::get_singleton()->compute_list_set_push_constant(compute_list, &roughness.push_constant, sizeof(CubemapRoughnessPushConstant)); @@ -2060,7 +2068,7 @@ void EffectsRD::cubemap_roughness_raster(RID p_source_rd_texture, RID p_dest_fra memset(&roughness.push_constant, 0, sizeof(CubemapRoughnessPushConstant)); roughness.push_constant.face_id = p_face_id; - roughness.push_constant.roughness = p_roughness; + roughness.push_constant.roughness = p_roughness * p_roughness; // Shader expects roughness, not perceptual roughness, so multiply before passing in. roughness.push_constant.sample_count = p_sample_count; roughness.push_constant.use_direct_write = p_roughness == 0.0; roughness.push_constant.face_size = p_size; @@ -2367,15 +2375,26 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) { copy_modes.push_back("\n"); copy_modes.push_back("\n#define MODE_PANORAMA_TO_DP\n"); copy_modes.push_back("\n#define MODE_TWO_SOURCES\n"); + copy_modes.push_back("\n#define MULTIVIEW\n"); + copy_modes.push_back("\n#define MULTIVIEW\n#define MODE_TWO_SOURCES\n"); copy_to_fb.shader.initialize(copy_modes); + if (!RendererCompositorRD::singleton->is_xr_enabled()) { + copy_to_fb.shader.set_variant_enabled(COPY_TO_FB_MULTIVIEW, false); + copy_to_fb.shader.set_variant_enabled(COPY_TO_FB_MULTIVIEW_WITH_DEPTH, false); + } + copy_to_fb.shader_version = copy_to_fb.shader.version_create(); //use additive for (int i = 0; i < COPY_TO_FB_MAX; i++) { - copy_to_fb.pipelines[i].setup(copy_to_fb.shader.version_get_shader(copy_to_fb.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0); + if (copy_to_fb.shader.is_variant_enabled(i)) { + copy_to_fb.pipelines[i].setup(copy_to_fb.shader.version_get_shader(copy_to_fb.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0); + } else { + copy_to_fb.pipelines[i].clear(); + } } } diff --git a/servers/rendering/renderer_rd/effects_rd.h b/servers/rendering/renderer_rd/effects_rd.h index f5e5b1ace7..eca5e09800 100644 --- a/servers/rendering/renderer_rd/effects_rd.h +++ b/servers/rendering/renderer_rd/effects_rd.h @@ -203,6 +203,9 @@ private: COPY_TO_FB_COPY, COPY_TO_FB_COPY_PANORAMA_TO_DP, COPY_TO_FB_COPY2, + + COPY_TO_FB_MULTIVIEW, + COPY_TO_FB_MULTIVIEW_WITH_DEPTH, COPY_TO_FB_MAX, }; @@ -893,7 +896,7 @@ public: bool get_prefer_raster_effects(); void fsr_upscale(RID p_source_rd_texture, RID p_secondary_texture, RID p_destination_texture, const Size2i &p_internal_size, const Size2i &p_size, float p_fsr_upscale_sharpness); - void copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_alpha_to_zero = false, bool p_srgb = false, RID p_secondary = RID()); + void copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_alpha_to_zero = false, bool p_srgb = false, RID p_secondary = RID(), bool p_multiview = false); void copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_all_source = false, bool p_8_bit_dst = false, bool p_alpha_to_one = false); void copy_cubemap_to_panorama(RID p_source_cube, RID p_dest_panorama, const Size2i &p_panorama_size, float p_lod, bool p_is_array); void copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false); diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp index 7987a98b0e..24be451e78 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp @@ -557,7 +557,7 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin actions.renames["RIM"] = "rim"; actions.renames["RIM_TINT"] = "rim_tint"; actions.renames["CLEARCOAT"] = "clearcoat"; - actions.renames["CLEARCOAT_GLOSS"] = "clearcoat_gloss"; + actions.renames["CLEARCOAT_ROUGHNESS"] = "clearcoat_roughness"; actions.renames["ANISOTROPY"] = "anisotropy"; actions.renames["ANISOTROPY_FLOW"] = "anisotropy_flow"; actions.renames["SSS_STRENGTH"] = "sss_strength"; @@ -607,7 +607,7 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin actions.usage_defines["RIM"] = "#define LIGHT_RIM_USED\n"; actions.usage_defines["RIM_TINT"] = "@RIM"; actions.usage_defines["CLEARCOAT"] = "#define LIGHT_CLEARCOAT_USED\n"; - actions.usage_defines["CLEARCOAT_GLOSS"] = "@CLEARCOAT"; + actions.usage_defines["CLEARCOAT_ROUGHNESS"] = "@CLEARCOAT"; actions.usage_defines["ANISOTROPY"] = "#define LIGHT_ANISOTROPY_USED\n"; actions.usage_defines["ANISOTROPY_FLOW"] = "@ANISOTROPY"; actions.usage_defines["AO"] = "#define AO_USED\n"; @@ -663,20 +663,12 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin actions.render_mode_defines["sss_mode_skin"] = "#define SSS_MODE_SKIN\n"; - bool force_blinn = GLOBAL_GET("rendering/shading/overrides/force_blinn_over_ggx"); - - if (!force_blinn) { - actions.render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_SCHLICK_GGX\n"; - } else { - actions.render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_BLINN\n"; - } + actions.render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_SCHLICK_GGX\n"; actions.custom_samplers["SCREEN_TEXTURE"] = "material_samplers[3]"; // linear filter with mipmaps actions.custom_samplers["DEPTH_TEXTURE"] = "material_samplers[3]"; actions.custom_samplers["NORMAL_ROUGHNESS_TEXTURE"] = "material_samplers[1]"; // linear filter - actions.render_mode_defines["specular_blinn"] = "#define SPECULAR_BLINN\n"; - actions.render_mode_defines["specular_phong"] = "#define SPECULAR_PHONG\n"; actions.render_mode_defines["specular_toon"] = "#define SPECULAR_TOON\n"; actions.render_mode_defines["specular_disabled"] = "#define SPECULAR_DISABLED\n"; actions.render_mode_defines["shadows_disabled"] = "#define SHADOWS_DISABLED\n"; diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp index 0b99948063..34b2fa9440 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp @@ -545,7 +545,7 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p actions.renames["RIM"] = "rim"; actions.renames["RIM_TINT"] = "rim_tint"; actions.renames["CLEARCOAT"] = "clearcoat"; - actions.renames["CLEARCOAT_GLOSS"] = "clearcoat_gloss"; + actions.renames["CLEARCOAT_ROUGHNESS"] = "clearcoat_roughness"; actions.renames["ANISOTROPY"] = "anisotropy"; actions.renames["ANISOTROPY_FLOW"] = "anisotropy_flow"; actions.renames["SSS_STRENGTH"] = "sss_strength"; @@ -594,7 +594,7 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p actions.usage_defines["RIM"] = "#define LIGHT_RIM_USED\n"; actions.usage_defines["RIM_TINT"] = "@RIM"; actions.usage_defines["CLEARCOAT"] = "#define LIGHT_CLEARCOAT_USED\n"; - actions.usage_defines["CLEARCOAT_GLOSS"] = "@CLEARCOAT"; + actions.usage_defines["CLEARCOAT_ROUGHNESS"] = "@CLEARCOAT"; actions.usage_defines["ANISOTROPY"] = "#define LIGHT_ANISOTROPY_USED\n"; actions.usage_defines["ANISOTROPY_FLOW"] = "@ANISOTROPY"; actions.usage_defines["AO"] = "#define AO_USED\n"; @@ -649,15 +649,8 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p actions.render_mode_defines["sss_mode_skin"] = "#define SSS_MODE_SKIN\n"; - bool force_blinn = GLOBAL_GET("rendering/shading/overrides/force_blinn_over_ggx"); - if (!force_blinn) { - actions.render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_SCHLICK_GGX\n"; - } else { - actions.render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_BLINN\n"; - } + actions.render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_SCHLICK_GGX\n"; - actions.render_mode_defines["specular_blinn"] = "#define SPECULAR_BLINN\n"; - actions.render_mode_defines["specular_phong"] = "#define SPECULAR_PHONG\n"; actions.render_mode_defines["specular_toon"] = "#define SPECULAR_TOON\n"; actions.render_mode_defines["specular_disabled"] = "#define SPECULAR_DISABLED\n"; actions.render_mode_defines["shadows_disabled"] = "#define SHADOWS_DISABLED\n"; diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp index 2f8ef696cd..606527ed24 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp @@ -39,6 +39,9 @@ void RendererCompositorRD::prepare_for_blitting_render_targets() { void RendererCompositorRD::blit_render_targets_to_screen(DisplayServer::WindowID p_screen, const BlitToScreen *p_render_targets, int p_amount) { RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin_for_screen(p_screen); + if (draw_list == RD::INVALID_ID) { + return; // Window is minimized and does not have valid swapchain, skip drawing without printing errors. + } for (int i = 0; i < p_amount; i++) { RID texture = storage->render_target_get_texture(p_render_targets[i].render_target); diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp index cb07c75db4..1a84bafbd0 100644 --- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp @@ -1894,7 +1894,6 @@ void RendererSceneGIRD::SDFGI::render_static_lights(RID p_render_buffers, uint32 RD::get_singleton()->draw_command_begin_label("SDFGI Render Static Lighs"); update_cascades(); - ; //need cascades updated for this SDFGIShader::Light lights[SDFGI::MAX_STATIC_LIGHTS]; uint32_t light_count[SDFGI::MAX_STATIC_LIGHTS]; diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index 2d34d2a2a0..8814822cda 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -1818,11 +1818,14 @@ void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) { if (rb->blur[i].mipmaps[m].fb.is_valid()) { RD::get_singleton()->free(rb->blur[i].mipmaps[m].fb); } - if (rb->blur[i].mipmaps[m].half_fb.is_valid()) { - RD::get_singleton()->free(rb->blur[i].mipmaps[m].half_fb); - } - if (rb->blur[i].mipmaps[m].half_texture.is_valid()) { - RD::get_singleton()->free(rb->blur[i].mipmaps[m].half_texture); + // texture and framebuffer in both blur mipmaps are shared, so only free from the first one + if (i == 0) { + if (rb->blur[i].mipmaps[m].half_fb.is_valid()) { + RD::get_singleton()->free(rb->blur[i].mipmaps[m].half_fb); + } + if (rb->blur[i].mipmaps[m].half_texture.is_valid()) { + RD::get_singleton()->free(rb->blur[i].mipmaps[m].half_texture); + } } } rb->blur[i].mipmaps.clear(); @@ -1977,7 +1980,7 @@ void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_frameb rb->ssr.normal_scaled = RD::get_singleton()->texture_create(tf, RD::TextureView()); } - if (ssr_roughness_quality != RS::ENV_SSR_ROUGNESS_QUALITY_DISABLED && !rb->ssr.blur_radius[0].is_valid()) { + if (ssr_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED && !rb->ssr.blur_radius[0].is_valid()) { RD::TextureFormat tf; tf.format = RD::DATA_FORMAT_R8_UNORM; tf.width = rb->internal_width / 2; @@ -3283,7 +3286,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const RS::LightType type = storage->light_get_type(base); switch (type) { case RS::LIGHT_DIRECTIONAL: { - if (r_directional_light_count >= cluster.max_directional_lights) { + if (r_directional_light_count >= cluster.max_directional_lights || storage->light_directional_is_sky_only(base)) { continue; } @@ -3437,8 +3440,22 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const continue; } + const real_t distance = camera_plane.distance_to(li->transform.origin); + + if (storage->light_is_distance_fade_enabled(li->light)) { + const float fade_begin = storage->light_get_distance_fade_begin(li->light); + const float fade_length = storage->light_get_distance_fade_length(li->light); + + if (distance > fade_begin) { + if (distance > fade_begin + fade_length) { + // Out of range, don't draw this light to improve performance. + continue; + } + } + } + cluster.omni_light_sort[cluster.omni_light_count].instance = li; - cluster.omni_light_sort[cluster.omni_light_count].depth = camera_plane.distance_to(li->transform.origin); + cluster.omni_light_sort[cluster.omni_light_count].depth = distance; cluster.omni_light_count++; } break; case RS::LIGHT_SPOT: { @@ -3446,8 +3463,22 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const continue; } + const real_t distance = camera_plane.distance_to(li->transform.origin); + + if (storage->light_is_distance_fade_enabled(li->light)) { + const float fade_begin = storage->light_get_distance_fade_begin(li->light); + const float fade_length = storage->light_get_distance_fade_length(li->light); + + if (distance > fade_begin) { + if (distance > fade_begin + fade_length) { + // Out of range, don't draw this light to improve performance. + continue; + } + } + } + cluster.spot_light_sort[cluster.spot_light_count].instance = li; - cluster.spot_light_sort[cluster.spot_light_count].depth = camera_plane.distance_to(li->transform.origin); + cluster.spot_light_sort[cluster.spot_light_count].depth = distance; cluster.spot_light_count++; } break; } @@ -3491,7 +3522,24 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const light_data.attenuation = storage->light_get_param(base, RS::LIGHT_PARAM_ATTENUATION); - float energy = sign * storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY) * Math_PI; + // Reuse fade begin, fade length and distance for shadow LOD determination later. + float fade_begin = 0.0; + float fade_length = 0.0; + real_t distance = 0.0; + + float fade = 1.0; + if (storage->light_is_distance_fade_enabled(li->light)) { + fade_begin = storage->light_get_distance_fade_begin(li->light); + fade_length = storage->light_get_distance_fade_length(li->light); + distance = camera_plane.distance_to(li->transform.origin); + + if (distance > fade_begin) { + // Use `smoothstep()` to make opacity changes more gradual and less noticeable to the player. + fade = Math::smoothstep(0.0f, 1.0f, 1.0f - float(distance - fade_begin) / fade_length); + } + } + + float energy = sign * storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY) * Math_PI * fade; light_data.color[0] = linear_col.r * energy; light_data.color[1] = linear_col.g * energy; @@ -3552,7 +3600,17 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const light_data.projector_rect[3] = 0; } - if (shadow_atlas && shadow_atlas->shadow_owners.has(li->self)) { + const bool needs_shadow = shadow_atlas && shadow_atlas->shadow_owners.has(li->self); + + bool in_shadow_range = true; + if (needs_shadow && storage->light_is_distance_fade_enabled(li->light)) { + if (distance > storage->light_get_distance_fade_shadow(li->light)) { + // Out of range, don't draw shadows to improve performance. + in_shadow_range = false; + } + } + + if (needs_shadow && in_shadow_range) { // fill in the shadow information light_data.shadow_enabled = true; diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h index 09c828ba37..47bc0af1db 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h @@ -428,7 +428,7 @@ private: bool glow_bicubic_upscale = false; bool glow_high_quality = false; - RS::EnvironmentSSRRoughnessQuality ssr_roughness_quality = RS::ENV_SSR_ROUGNESS_QUALITY_LOW; + RS::EnvironmentSSRRoughnessQuality ssr_roughness_quality = RS::ENV_SSR_ROUGHNESS_QUALITY_LOW; mutable RID_Owner<RendererSceneEnvironmentRD, true> environment_owner; diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp index 354516ae87..b44ae6cf8d 100644 --- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp @@ -473,12 +473,13 @@ void RendererSceneSkyRD::ReflectionData::create_reflection_fast_filter(RendererS } RD::get_singleton()->draw_command_end_label(); // Filter radiance } else { + RD::get_singleton()->draw_command_begin_label("Downsample radiance map"); effects->cubemap_downsample(radiance_base_cubemap, downsampled_layer.mipmaps[0].view, downsampled_layer.mipmaps[0].size); for (int i = 1; i < downsampled_layer.mipmaps.size(); i++) { effects->cubemap_downsample(downsampled_layer.mipmaps[i - 1].view, downsampled_layer.mipmaps[i].view, downsampled_layer.mipmaps[i].size); } - + RD::get_singleton()->draw_command_end_label(); // Downsample Radiance Vector<RID> views; if (p_use_arrays) { for (int i = 1; i < layers.size(); i++) { @@ -489,8 +490,9 @@ void RendererSceneSkyRD::ReflectionData::create_reflection_fast_filter(RendererS views.push_back(layers[0].views[i]); } } - + RD::get_singleton()->draw_command_begin_label("Fast filter radiance"); effects->cubemap_filter(downsampled_radiance_cubemap, views, p_use_arrays); + RD::get_singleton()->draw_command_end_label(); // Filter radiance } } @@ -500,12 +502,25 @@ void RendererSceneSkyRD::ReflectionData::create_reflection_importance_sample(Ren bool prefer_raster_effects = effects->get_prefer_raster_effects(); if (prefer_raster_effects) { - // Need to ask clayjohn but p_cube_side is set to 10, looks like in the compute shader we're doing all 6 sides in one call - // here we need to do them one by one so ignoring p_cube_side + if (p_base_layer == 1) { + RD::get_singleton()->draw_command_begin_label("Downsample radiance map"); + for (int k = 0; k < 6; k++) { + effects->cubemap_downsample_raster(radiance_base_cubemap, downsampled_layer.mipmaps[0].framebuffers[k], k, downsampled_layer.mipmaps[0].size); + } + + for (int i = 1; i < downsampled_layer.mipmaps.size(); i++) { + for (int k = 0; k < 6; k++) { + effects->cubemap_downsample_raster(downsampled_layer.mipmaps[i - 1].view, downsampled_layer.mipmaps[i].framebuffers[k], k, downsampled_layer.mipmaps[i].size); + } + } + RD::get_singleton()->draw_command_end_label(); // Downsample Radiance + } + + RD::get_singleton()->draw_command_begin_label("High Quality filter radiance"); if (p_use_arrays) { for (int k = 0; k < 6; k++) { effects->cubemap_roughness_raster( - radiance_base_cubemap, + downsampled_radiance_cubemap, layers[p_base_layer].mipmaps[0].framebuffers[k], k, p_sky_ggx_samples_quality, @@ -515,7 +530,7 @@ void RendererSceneSkyRD::ReflectionData::create_reflection_importance_sample(Ren } else { for (int k = 0; k < 6; k++) { effects->cubemap_roughness_raster( - layers[0].views[p_base_layer - 1], + downsampled_radiance_cubemap, layers[0].mipmaps[p_base_layer].framebuffers[k], k, p_sky_ggx_samples_quality, @@ -524,12 +539,22 @@ void RendererSceneSkyRD::ReflectionData::create_reflection_importance_sample(Ren } } } else { + if (p_base_layer == 1) { + RD::get_singleton()->draw_command_begin_label("Downsample radiance map"); + effects->cubemap_downsample(radiance_base_cubemap, downsampled_layer.mipmaps[0].view, downsampled_layer.mipmaps[0].size); + + for (int i = 1; i < downsampled_layer.mipmaps.size(); i++) { + effects->cubemap_downsample(downsampled_layer.mipmaps[i - 1].view, downsampled_layer.mipmaps[i].view, downsampled_layer.mipmaps[i].size); + } + RD::get_singleton()->draw_command_end_label(); // Downsample Radiance + } + + RD::get_singleton()->draw_command_begin_label("High Quality filter radiance"); if (p_use_arrays) { - //render directly to the layers - effects->cubemap_roughness(radiance_base_cubemap, layers[p_base_layer].views[0], p_cube_side, p_sky_ggx_samples_quality, float(p_base_layer) / (layers.size() - 1.0), layers[p_base_layer].mipmaps[0].size.x); + effects->cubemap_roughness(downsampled_radiance_cubemap, layers[p_base_layer].views[0], p_cube_side, p_sky_ggx_samples_quality, float(p_base_layer) / (layers.size() - 1.0), layers[p_base_layer].mipmaps[0].size.x); } else { effects->cubemap_roughness( - layers[0].views[p_base_layer - 1], + downsampled_radiance_cubemap, layers[0].views[p_base_layer], p_cube_side, p_sky_ggx_samples_quality, @@ -537,6 +562,7 @@ void RendererSceneSkyRD::ReflectionData::create_reflection_importance_sample(Ren layers[0].mipmaps[p_base_layer].size.x); } } + RD::get_singleton()->draw_command_end_label(); // Filter radiance } void RendererSceneSkyRD::ReflectionData::update_reflection_mipmaps(RendererStorageRD *p_storage, int p_start, int p_end) { diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp index f345001539..35aa0f1f31 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp @@ -3578,15 +3578,15 @@ void RendererStorageRD::mesh_instance_set_blend_shape_weight(RID p_mesh_instance void RendererStorageRD::_mesh_instance_clear(MeshInstance *mi) { for (uint32_t i = 0; i < mi->surfaces.size(); i++) { - if (mi->surfaces[i].vertex_buffer.is_valid()) { - RD::get_singleton()->free(mi->surfaces[i].vertex_buffer); - } if (mi->surfaces[i].versions) { for (uint32_t j = 0; j < mi->surfaces[i].version_count; j++) { RD::get_singleton()->free(mi->surfaces[i].versions[j].vertex_array); } memfree(mi->surfaces[i].versions); } + if (mi->surfaces[i].vertex_buffer.is_valid()) { + RD::get_singleton()->free(mi->surfaces[i].vertex_buffer); + } } mi->surfaces.clear(); @@ -4522,6 +4522,8 @@ void RendererStorageRD::_particles_free_data(Particles *particles) { particles->particle_instance_buffer = RID(); } + particles->userdata_count = 0; + if (particles->frame_params_buffer.is_valid()) { RD::get_singleton()->free(particles->frame_params_buffer); particles->frame_params_buffer = RID(); @@ -4716,6 +4718,14 @@ void RendererStorageRD::particles_set_process_material(RID p_particles, RID p_ma ERR_FAIL_COND(!particles); particles->process_material = p_material; + particles->dependency.changed_notify(DEPENDENCY_CHANGED_PARTICLES); //the instance buffer may have changed +} + +RID RendererStorageRD::particles_get_process_material(RID p_particles) const { + Particles *particles = particles_owner.get_or_null(p_particles); + ERR_FAIL_COND_V(!particles, RID()); + + return particles->process_material; } void RendererStorageRD::particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) { @@ -4852,10 +4862,13 @@ AABB RendererStorageRD::particles_get_current_aabb(RID p_particles) { if (buffer.size()) { bool first = true; - const ParticleData *particle_data = reinterpret_cast<const ParticleData *>(buffer.ptr()); + const uint8_t *data_ptr = (const uint8_t *)buffer.ptr(); + uint32_t particle_data_size = sizeof(ParticleData) + sizeof(float) * particles->userdata_count; + for (int i = 0; i < total_amount; i++) { - if (particle_data[i].active) { - Vector3 pos = Vector3(particle_data[i].xform[12], particle_data[i].xform[13], particle_data[i].xform[14]); + const ParticleData &particle_data = *(const ParticleData *)&data_ptr[particle_data_size * i]; + if (particle_data.active) { + Vector3 pos = Vector3(particle_data.xform[12], particle_data.xform[13], particle_data.xform[14]); if (!particles->use_local_coords) { pos = inv.xform(pos); } @@ -5420,6 +5433,7 @@ void RendererStorageRD::particles_set_view_axis(RID p_particles, const Vector3 & copy_push_constant.frame_remainder = particles->interpolate ? particles->frame_remainder : 0.0; copy_push_constant.total_particles = particles->amount; + copy_push_constant.copy_mode_2d = false; Vector3 axis = -p_axis; // cameras look to z negative @@ -5440,7 +5454,7 @@ void RendererStorageRD::particles_set_view_axis(RID p_particles, const Vector3 & if (do_sort) { RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, particles_shader.copy_pipelines[ParticlesShader::COPY_MODE_FILL_SORT_BUFFER]); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, particles_shader.copy_pipelines[ParticlesShader::COPY_MODE_FILL_SORT_BUFFER + particles->userdata_count * ParticlesShader::COPY_MODE_MAX]); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_copy_uniform_set, 0); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_sort_uniform_set, 1); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->trail_bind_pose_uniform_set, 2); @@ -5455,7 +5469,10 @@ void RendererStorageRD::particles_set_view_axis(RID p_particles, const Vector3 & copy_push_constant.total_particles *= copy_push_constant.total_particles; RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, particles_shader.copy_pipelines[do_sort ? ParticlesShader::COPY_MODE_FILL_INSTANCES_WITH_SORT_BUFFER : (particles->mode == RS::PARTICLES_MODE_2D ? ParticlesShader::COPY_MODE_FILL_INSTANCES_2D : ParticlesShader::COPY_MODE_FILL_INSTANCES)]); + uint32_t copy_pipeline = do_sort ? ParticlesShader::COPY_MODE_FILL_INSTANCES_WITH_SORT_BUFFER : ParticlesShader::COPY_MODE_FILL_INSTANCES; + copy_pipeline += particles->userdata_count * ParticlesShader::COPY_MODE_MAX; + copy_push_constant.copy_mode_2d = particles->mode == RS::PARTICLES_MODE_2D ? 1 : 0; + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, particles_shader.copy_pipelines[copy_pipeline]); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_copy_uniform_set, 0); if (do_sort) { RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_sort_uniform_set, 1); @@ -5470,6 +5487,19 @@ void RendererStorageRD::particles_set_view_axis(RID p_particles, const Vector3 & } void RendererStorageRD::_particles_update_buffers(Particles *particles) { + uint32_t userdata_count = 0; + + const Material *material = material_owner.get_or_null(particles->process_material); + if (material && material->shader && material->shader->data) { + const ParticlesShaderData *shader_data = static_cast<const ParticlesShaderData *>(material->shader->data); + userdata_count = shader_data->userdata_count; + } + + if (userdata_count != particles->userdata_count) { + // Mismatch userdata, re-create buffers. + _particles_free_data(particles); + } + if (particles->amount > 0 && particles->particle_buffer.is_null()) { int total_amount = particles->amount; if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) { @@ -5478,7 +5508,9 @@ void RendererStorageRD::_particles_update_buffers(Particles *particles) { uint32_t xform_size = particles->mode == RS::PARTICLES_MODE_2D ? 2 : 3; - particles->particle_buffer = RD::get_singleton()->storage_buffer_create(sizeof(ParticleData) * total_amount); + particles->particle_buffer = RD::get_singleton()->storage_buffer_create((sizeof(ParticleData) + userdata_count * sizeof(float) * 4) * total_amount); + + particles->userdata_count = userdata_count; particles->particle_instance_buffer = RD::get_singleton()->storage_buffer_create(sizeof(float) * 4 * (xform_size + 1 + 1) * total_amount); //needs to clear it @@ -5680,6 +5712,21 @@ void RendererStorageRD::update_particles() { total_amount *= particles->trail_bind_poses.size(); } + // Affect 2D only. + if (particles->use_local_coords) { + // In local mode, particle positions are calculated locally (relative to the node position) + // and they're also drawn locally. + // It works as expected, so we just pass an identity transform. + store_transform(Transform3D(), copy_push_constant.inv_emission_transform); + } else { + // In global mode, particle positions are calculated globally (relative to the canvas origin) + // but they're drawn locally. + // So, we need to pass the inverse of the emission transform to bring the + // particles to local coordinates before drawing. + Transform3D inv = particles->emission_transform.affine_inverse(); + store_transform(inv, copy_push_constant.inv_emission_transform); + } + copy_push_constant.total_particles = total_amount; copy_push_constant.frame_remainder = particles->interpolate ? particles->frame_remainder : 0.0; copy_push_constant.align_mode = particles->transform_align; @@ -5702,7 +5749,8 @@ void RendererStorageRD::update_particles() { copy_push_constant.lifetime_reverse = particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME; RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, particles_shader.copy_pipelines[particles->mode == RS::PARTICLES_MODE_2D ? ParticlesShader::COPY_MODE_FILL_INSTANCES_2D : ParticlesShader::COPY_MODE_FILL_INSTANCES]); + copy_push_constant.copy_mode_2d = particles->mode == RS::PARTICLES_MODE_2D ? 1 : 0; + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, particles_shader.copy_pipelines[ParticlesShader::COPY_MODE_FILL_INSTANCES + particles->userdata_count * ParticlesShader::COPY_MODE_MAX]); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_copy_uniform_set, 0); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->trail_bind_pose_uniform_set, 2); RD::get_singleton()->compute_list_set_push_constant(compute_list, ©_push_constant, sizeof(ParticlesShader::CopyPushConstant)); @@ -5754,6 +5802,12 @@ void RendererStorageRD::ParticlesShaderData::set_code(const String &p_code) { actions.usage_flag_pointers["COLLIDED"] = &uses_collision; + userdata_count = 0; + for (uint32_t i = 0; i < ParticlesShader::MAX_USERDATAS; i++) { + userdatas_used[i] = false; + actions.usage_flag_pointers["USERDATA" + itos(i + 1)] = &userdatas_used[i]; + } + actions.uniforms = &uniforms; Error err = base_singleton->particles_shader.compiler.compile(RS::SHADER_PARTICLES, code, &actions, path, gen_code); @@ -5763,6 +5817,12 @@ void RendererStorageRD::ParticlesShaderData::set_code(const String &p_code) { version = base_singleton->particles_shader.shader.version_create(); } + for (uint32_t i = 0; i < ParticlesShader::MAX_USERDATAS; i++) { + if (userdatas_used[i]) { + userdata_count++; + } + } + base_singleton->particles_shader.shader.version_set_compute_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_COMPUTE], gen_code.defines); ERR_FAIL_COND(!base_singleton->particles_shader.shader.version_is_valid(version)); @@ -6540,6 +6600,16 @@ void RendererStorageRD::light_set_cull_mask(RID p_light, uint32_t p_mask) { light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT); } +void RendererStorageRD::light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) { + Light *light = light_owner.get_or_null(p_light); + ERR_FAIL_COND(!light); + + light->distance_fade = p_enabled; + light->distance_fade_begin = p_begin; + light->distance_fade_shadow = p_shadow; + light->distance_fade_length = p_length; +} + void RendererStorageRD::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) { Light *light = light_owner.get_or_null(p_light); ERR_FAIL_COND(!light); @@ -9930,6 +10000,11 @@ RendererStorageRD::RendererStorageRD() { actions.renames["ACTIVE"] = "particle_active"; actions.renames["RESTART"] = "restart"; actions.renames["CUSTOM"] = "PARTICLE.custom"; + for (int i = 0; i < ParticlesShader::MAX_USERDATAS; i++) { + String udname = "USERDATA" + itos(i + 1); + actions.renames[udname] = "PARTICLE.userdata" + itos(i + 1); + actions.usage_defines[udname] = "#define USERDATA" + itos(i + 1) + "_USED\n"; + } actions.renames["TRANSFORM"] = "PARTICLE.xform"; actions.renames["TIME"] = "frame_history.data[0].time"; actions.renames["PI"] = _MKSTR(Math_PI); @@ -10034,17 +10109,26 @@ void process() { { Vector<String> copy_modes; - copy_modes.push_back("\n#define MODE_FILL_INSTANCES\n"); - copy_modes.push_back("\n#define MODE_FILL_INSTANCES\n#define MODE_2D\n"); - copy_modes.push_back("\n#define MODE_FILL_SORT_BUFFER\n#define USE_SORT_BUFFER\n"); - copy_modes.push_back("\n#define MODE_FILL_INSTANCES\n#define USE_SORT_BUFFER\n"); + for (int i = 0; i <= ParticlesShader::MAX_USERDATAS; i++) { + if (i == 0) { + copy_modes.push_back("\n#define MODE_FILL_INSTANCES\n"); + copy_modes.push_back("\n#define MODE_FILL_SORT_BUFFER\n#define USE_SORT_BUFFER\n"); + copy_modes.push_back("\n#define MODE_FILL_INSTANCES\n#define USE_SORT_BUFFER\n"); + } else { + copy_modes.push_back("\n#define MODE_FILL_INSTANCES\n#define USERDATA_COUNT " + itos(i) + "\n"); + copy_modes.push_back("\n#define MODE_FILL_SORT_BUFFER\n#define USE_SORT_BUFFER\n#define USERDATA_COUNT " + itos(i) + "\n"); + copy_modes.push_back("\n#define MODE_FILL_INSTANCES\n#define USE_SORT_BUFFER\n#define USERDATA_COUNT " + itos(i) + "\n"); + } + } particles_shader.copy_shader.initialize(copy_modes); particles_shader.copy_shader_version = particles_shader.copy_shader.version_create(); - for (int i = 0; i < ParticlesShader::COPY_MODE_MAX; i++) { - particles_shader.copy_pipelines[i] = RD::get_singleton()->compute_pipeline_create(particles_shader.copy_shader.version_get_shader(particles_shader.copy_shader_version, i)); + for (int i = 0; i <= ParticlesShader::MAX_USERDATAS; i++) { + for (int j = 0; j < ParticlesShader::COPY_MODE_MAX; j++) { + particles_shader.copy_pipelines[i * ParticlesShader::COPY_MODE_MAX + j] = RD::get_singleton()->compute_pipeline_create(particles_shader.copy_shader.version_get_shader(particles_shader.copy_shader_version, i * ParticlesShader::COPY_MODE_MAX + j)); + } } } diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h index 6febb71e93..cb35c2bf65 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.h +++ b/servers/rendering/renderer_rd/renderer_storage_rd.h @@ -751,6 +751,8 @@ private: RID particle_instance_buffer; RID frame_params_buffer; + uint32_t userdata_count = 0; + RID particles_material_uniform_set; RID particles_copy_uniform_set; RID particles_transforms_buffer_uniform_set; @@ -849,12 +851,16 @@ private: uint32_t order_by_lifetime; uint32_t lifetime_split; uint32_t lifetime_reverse; - uint32_t pad; + uint32_t copy_mode_2d; + + float inv_emission_transform[16]; }; enum { + MAX_USERDATAS = 6 + }; + enum { COPY_MODE_FILL_INSTANCES, - COPY_MODE_FILL_INSTANCES_2D, COPY_MODE_FILL_SORT_BUFFER, COPY_MODE_FILL_INSTANCES_WITH_SORT_BUFFER, COPY_MODE_MAX, @@ -862,7 +868,7 @@ private: ParticlesCopyShaderRD copy_shader; RID copy_shader_version; - RID copy_pipelines[COPY_MODE_MAX]; + RID copy_pipelines[COPY_MODE_MAX * (MAX_USERDATAS + 1)]; LocalVector<float> pose_update_buffer; @@ -888,7 +894,10 @@ private: RID pipeline; - bool uses_time; + bool uses_time = false; + + bool userdatas_used[ParticlesShader::MAX_USERDATAS] = {}; + uint32_t userdata_count = 0; virtual void set_code(const String &p_Code); virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); @@ -1024,6 +1033,10 @@ private: RS::LightBakeMode bake_mode = RS::LIGHT_BAKE_DYNAMIC; uint32_t max_sdfgi_cascade = 2; uint32_t cull_mask = 0xFFFFFFFF; + bool distance_fade = false; + real_t distance_fade_begin = 40.0; + real_t distance_fade_shadow = 50.0; + real_t distance_fade_length = 10.0; RS::LightOmniShadowMode omni_shadow_mode = RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID; RS::LightDirectionalShadowMode directional_shadow_mode = RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; bool directional_blend_splits = false; @@ -1832,6 +1845,7 @@ public: void light_set_projector(RID p_light, RID p_texture); void light_set_negative(RID p_light, bool p_enable); void light_set_cull_mask(RID p_light, uint32_t p_mask); + void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length); void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled); void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode); void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade); @@ -1890,6 +1904,26 @@ public: return light->cull_mask; } + _FORCE_INLINE_ bool light_is_distance_fade_enabled(RID p_light) { + const Light *light = light_owner.get_or_null(p_light); + return light->distance_fade; + } + + _FORCE_INLINE_ float light_get_distance_fade_begin(RID p_light) { + const Light *light = light_owner.get_or_null(p_light); + return light->distance_fade_begin; + } + + _FORCE_INLINE_ float light_get_distance_fade_shadow(RID p_light) { + const Light *light = light_owner.get_or_null(p_light); + return light->distance_fade_shadow; + } + + _FORCE_INLINE_ float light_get_distance_fade_length(RID p_light) { + const Light *light = light_owner.get_or_null(p_light); + return light->distance_fade_length; + } + _FORCE_INLINE_ bool light_has_shadow(RID p_light) const { const Light *light = light_owner.get_or_null(p_light); ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL); @@ -2162,6 +2196,8 @@ public: void particles_set_speed_scale(RID p_particles, double p_scale); void particles_set_use_local_coordinates(RID p_particles, bool p_enable); void particles_set_process_material(RID p_particles, RID p_material); + RID particles_get_process_material(RID p_particles) const; + void particles_set_fixed_fps(RID p_particles, int p_fps); void particles_set_interpolate(RID p_particles, bool p_enable); void particles_set_fractional_delta(RID p_particles, bool p_enable); diff --git a/servers/rendering/renderer_rd/shaders/copy_to_fb.glsl b/servers/rendering/renderer_rd/shaders/copy_to_fb.glsl index 2f1f9c4765..9787c9879d 100644 --- a/servers/rendering/renderer_rd/shaders/copy_to_fb.glsl +++ b/servers/rendering/renderer_rd/shaders/copy_to_fb.glsl @@ -4,7 +4,20 @@ #VERSION_DEFINES +#ifdef MULTIVIEW +#ifdef has_VK_KHR_multiview +#extension GL_EXT_multiview : enable +#define ViewIndex gl_ViewIndex +#else // has_VK_KHR_multiview +#define ViewIndex 0 +#endif // has_VK_KHR_multiview +#endif //MULTIVIEW + +#ifdef MULTIVIEW +layout(location = 0) out vec3 uv_interp; +#else layout(location = 0) out vec2 uv_interp; +#endif layout(push_constant, std430) uniform Params { vec4 section; @@ -19,9 +32,11 @@ params; void main() { vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0)); - uv_interp = base_arr[gl_VertexIndex]; - - vec2 vpos = uv_interp; + uv_interp.xy = base_arr[gl_VertexIndex]; +#ifdef MULTIVIEW + uv_interp.z = ViewIndex; +#endif + vec2 vpos = uv_interp.xy; if (params.use_section) { vpos = params.section.xy + vpos * params.section.zw; } @@ -39,6 +54,15 @@ void main() { #VERSION_DEFINES +#ifdef MULTIVIEW +#ifdef has_VK_KHR_multiview +#extension GL_EXT_multiview : enable +#define ViewIndex gl_ViewIndex +#else // has_VK_KHR_multiview +#define ViewIndex 0 +#endif // has_VK_KHR_multiview +#endif //MULTIVIEW + layout(push_constant, std430) uniform Params { vec4 section; vec2 pixel_size; @@ -52,12 +76,25 @@ layout(push_constant, std430) uniform Params { } params; +#ifdef MULTIVIEW +layout(location = 0) in vec3 uv_interp; +#else layout(location = 0) in vec2 uv_interp; +#endif +#ifdef MULTIVIEW +layout(set = 0, binding = 0) uniform sampler2DArray source_color; +#ifdef MODE_TWO_SOURCES +layout(set = 1, binding = 0) uniform sampler2DArray source_depth; +layout(location = 1) out float depth; +#endif /* MODE_TWO_SOURCES */ +#else layout(set = 0, binding = 0) uniform sampler2D source_color; #ifdef MODE_TWO_SOURCES layout(set = 1, binding = 0) uniform sampler2D source_color2; -#endif +#endif /* MODE_TWO_SOURCES */ +#endif /* MULTIVIEW */ + layout(location = 0) out vec4 frag_color; vec3 linear_to_srgb(vec3 color) { @@ -68,9 +105,14 @@ vec3 linear_to_srgb(vec3 color) { } void main() { +#ifdef MULTIVIEW + vec3 uv = uv_interp; +#else vec2 uv = uv_interp; +#endif #ifdef MODE_PANORAMA_TO_DP + // Note, multiview and panorama should not be mixed at this time //obtain normal from dual paraboloid uv #define M_PI 3.14159265359 @@ -98,10 +140,20 @@ void main() { uv = 1.0 - uv; } #endif + +#ifdef MULTIVIEW + vec4 color = textureLod(source_color, uv, 0.0); +#ifdef MODE_TWO_SOURCES + // In multiview our 2nd input will be our depth map + depth = textureLod(source_depth, uv, 0.0).r; +#endif /* MODE_TWO_SOURCES */ + +#else vec4 color = textureLod(source_color, uv, 0.0); #ifdef MODE_TWO_SOURCES color += textureLod(source_color2, uv, 0.0); -#endif +#endif /* MODE_TWO_SOURCES */ +#endif /* MULTIVIEW */ if (params.force_luminance) { color.rgb = vec3(max(max(color.r, color.g), color.b)); } diff --git a/servers/rendering/renderer_rd/shaders/cubemap_roughness.glsl b/servers/rendering/renderer_rd/shaders/cubemap_roughness.glsl index 28f4dc59ec..1d46f59408 100644 --- a/servers/rendering/renderer_rd/shaders/cubemap_roughness.glsl +++ b/servers/rendering/renderer_rd/shaders/cubemap_roughness.glsl @@ -21,24 +21,38 @@ void main() { vec2 uv = ((vec2(id.xy) * 2.0 + 1.0) / (params.face_size) - 1.0); vec3 N = texelCoordToVec(uv, id.z); - //vec4 color = color_interp; - if (params.use_direct_write) { imageStore(dest_cubemap, ivec3(id), vec4(texture(source_cube, N).rgb, 1.0)); } else { vec4 sum = vec4(0.0, 0.0, 0.0, 0.0); + float solid_angle_texel = 4.0 * M_PI / (6.0 * params.face_size * params.face_size); + float roughness2 = params.roughness * params.roughness; + float roughness4 = roughness2 * roughness2; + vec3 UpVector = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); + mat3 T; + T[0] = normalize(cross(UpVector, N)); + T[1] = cross(N, T[0]); + T[2] = N; + for (uint sampleNum = 0u; sampleNum < params.sample_count; sampleNum++) { vec2 xi = Hammersley(sampleNum, params.sample_count); - vec3 H = ImportanceSampleGGX(xi, params.roughness, N); - vec3 V = N; - vec3 L = (2.0 * dot(V, H) * H - V); + vec3 H = T * ImportanceSampleGGX(xi, roughness4); + float NdotH = dot(N, H); + vec3 L = (2.0 * NdotH * H - N); float ndotl = clamp(dot(N, L), 0.0, 1.0); if (ndotl > 0.0) { - sum.rgb += textureLod(source_cube, L, 0.0).rgb * ndotl; + float D = DistributionGGX(NdotH, roughness4); + float pdf = D * NdotH / (4.0 * NdotH) + 0.0001; + + float solid_angle_sample = 1.0 / (float(params.sample_count) * pdf + 0.0001); + + float mipLevel = params.roughness == 0.0 ? 0.0 : 0.5 * log2(solid_angle_sample / solid_angle_texel); + + sum.rgb += textureLod(source_cube, L, mipLevel).rgb * ndotl; sum.a += ndotl; } } diff --git a/servers/rendering/renderer_rd/shaders/cubemap_roughness_inc.glsl b/servers/rendering/renderer_rd/shaders/cubemap_roughness_inc.glsl index ce0a25e12f..1bee428a6f 100644 --- a/servers/rendering/renderer_rd/shaders/cubemap_roughness_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/cubemap_roughness_inc.glsl @@ -47,12 +47,10 @@ vec3 texelCoordToVec(vec2 uv, uint faceID) { return normalize(result); } -vec3 ImportanceSampleGGX(vec2 Xi, float Roughness, vec3 N) { - float a = Roughness * Roughness; // DISNEY'S ROUGHNESS [see Burley'12 siggraph] - +vec3 ImportanceSampleGGX(vec2 xi, float roughness4) { // Compute distribution direction - float Phi = 2.0 * M_PI * Xi.x; - float CosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a * a - 1.0) * Xi.y)); + float Phi = 2.0 * M_PI * xi.x; + float CosTheta = sqrt((1.0 - xi.y) / (1.0 + (roughness4 - 1.0) * xi.y)); float SinTheta = sqrt(1.0 - CosTheta * CosTheta); // Convert to spherical direction @@ -61,12 +59,15 @@ vec3 ImportanceSampleGGX(vec2 Xi, float Roughness, vec3 N) { H.y = SinTheta * sin(Phi); H.z = CosTheta; - vec3 UpVector = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); - vec3 TangentX = normalize(cross(UpVector, N)); - vec3 TangentY = cross(N, TangentX); + return H; +} + +float DistributionGGX(float NdotH, float roughness4) { + float NdotH2 = NdotH * NdotH; + float denom = (NdotH2 * (roughness4 - 1.0) + 1.0); + denom = M_PI * denom * denom; - // Tangent to world space - return TangentX * H.x + TangentY * H.y + N * H.z; + return roughness4 / denom; } // https://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html diff --git a/servers/rendering/renderer_rd/shaders/cubemap_roughness_raster.glsl b/servers/rendering/renderer_rd/shaders/cubemap_roughness_raster.glsl index 2570308816..c29accd8a7 100644 --- a/servers/rendering/renderer_rd/shaders/cubemap_roughness_raster.glsl +++ b/servers/rendering/renderer_rd/shaders/cubemap_roughness_raster.glsl @@ -42,17 +42,33 @@ void main() { } else { vec4 sum = vec4(0.0, 0.0, 0.0, 0.0); + float solid_angle_texel = 4.0 * M_PI / (6.0 * params.face_size * params.face_size); + float roughness2 = params.roughness * params.roughness; + float roughness4 = roughness2 * roughness2; + vec3 UpVector = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); + mat3 T; + T[0] = normalize(cross(UpVector, N)); + T[1] = cross(N, T[0]); + T[2] = N; + for (uint sampleNum = 0u; sampleNum < params.sample_count; sampleNum++) { vec2 xi = Hammersley(sampleNum, params.sample_count); - vec3 H = ImportanceSampleGGX(xi, params.roughness, N); - vec3 V = N; - vec3 L = (2.0 * dot(V, H) * H - V); + vec3 H = T * ImportanceSampleGGX(xi, roughness4); + float NdotH = dot(N, H); + vec3 L = (2.0 * NdotH * H - N); float ndotl = clamp(dot(N, L), 0.0, 1.0); if (ndotl > 0.0) { - sum.rgb += textureLod(source_cube, L, 0.0).rgb * ndotl; + float D = DistributionGGX(NdotH, roughness4); + float pdf = D * NdotH / (4.0 * NdotH) + 0.0001; + + float solid_angle_sample = 1.0 / (float(params.sample_count) * pdf + 0.0001); + + float mipLevel = params.roughness == 0.0 ? 0.0 : 0.5 * log2(solid_angle_sample / solid_angle_texel); + + sum.rgb += textureLod(source_cube, L, mipLevel).rgb * ndotl; sum.a += ndotl; } } diff --git a/servers/rendering/renderer_rd/shaders/particles.glsl b/servers/rendering/renderer_rd/shaders/particles.glsl index d691ea2fdf..1b1051ecfa 100644 --- a/servers/rendering/renderer_rd/shaders/particles.glsl +++ b/servers/rendering/renderer_rd/shaders/particles.glsl @@ -112,6 +112,24 @@ struct ParticleData { uint flags; vec4 color; vec4 custom; +#ifdef USERDATA1_USED + vec4 userdata1; +#endif +#ifdef USERDATA2_USED + vec4 userdata2; +#endif +#ifdef USERDATA3_USED + vec4 userdata3; +#endif +#ifdef USERDATA4_USED + vec4 userdata4; +#endif +#ifdef USERDATA5_USED + vec4 userdata5; +#endif +#ifdef USERDATA6_USED + vec4 userdata6; +#endif }; layout(set = 1, binding = 1, std430) restrict buffer Particles { diff --git a/servers/rendering/renderer_rd/shaders/particles_copy.glsl b/servers/rendering/renderer_rd/shaders/particles_copy.glsl index bb11e4c78d..afbd5a9caa 100644 --- a/servers/rendering/renderer_rd/shaders/particles_copy.glsl +++ b/servers/rendering/renderer_rd/shaders/particles_copy.glsl @@ -16,6 +16,9 @@ struct ParticleData { uint flags; vec4 color; vec4 custom; +#ifdef USERDATA_COUNT + vec4 userdata[USERDATA_COUNT]; +#endif }; layout(set = 0, binding = 1, std430) restrict readonly buffer Particles { @@ -57,7 +60,9 @@ layout(push_constant, std430) uniform Params { bool order_by_lifetime; uint lifetime_split; bool lifetime_reverse; - uint pad; + bool copy_mode_2d; + + mat4 inv_emission_transform; } params; @@ -196,30 +201,33 @@ void main() { txform = txform * trail_bind_poses.data[part_ofs]; } + if (params.copy_mode_2d) { + // In global mode, bring 2D particles to local coordinates + // as they will be drawn with the node position as origin. + txform = params.inv_emission_transform * txform; + } + txform = transpose(txform); } else { txform = mat4(vec4(0.0), vec4(0.0), vec4(0.0), vec4(0.0)); //zero scale, becomes invisible } -#ifdef MODE_2D - - uint write_offset = gl_GlobalInvocationID.x * (2 + 1 + 1); //xform + color + custom + if (params.copy_mode_2d) { + uint write_offset = gl_GlobalInvocationID.x * (2 + 1 + 1); //xform + color + custom - instances.data[write_offset + 0] = txform[0]; - instances.data[write_offset + 1] = txform[1]; - instances.data[write_offset + 2] = particles.data[particle].color; - instances.data[write_offset + 3] = particles.data[particle].custom; - -#else - - uint write_offset = gl_GlobalInvocationID.x * (3 + 1 + 1); //xform + color + custom + instances.data[write_offset + 0] = txform[0]; + instances.data[write_offset + 1] = txform[1]; + instances.data[write_offset + 2] = particles.data[particle].color; + instances.data[write_offset + 3] = particles.data[particle].custom; + } else { + uint write_offset = gl_GlobalInvocationID.x * (3 + 1 + 1); //xform + color + custom - instances.data[write_offset + 0] = txform[0]; - instances.data[write_offset + 1] = txform[1]; - instances.data[write_offset + 2] = txform[2]; - instances.data[write_offset + 3] = particles.data[particle].color; - instances.data[write_offset + 4] = particles.data[particle].custom; -#endif //MODE_2D + instances.data[write_offset + 0] = txform[0]; + instances.data[write_offset + 1] = txform[1]; + instances.data[write_offset + 2] = txform[2]; + instances.data[write_offset + 3] = particles.data[particle].color; + instances.data[write_offset + 4] = particles.data[particle].custom; + } #endif } diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl index 97f7e0a6e6..a8648fc96a 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl @@ -478,8 +478,8 @@ layout(location = 0) out vec4 frag_color; #if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) -/* Make a default specular mode SPECULAR_SCHLICK_GGX. */ -#if !defined(SPECULAR_DISABLED) && !defined(SPECULAR_SCHLICK_GGX) && !defined(SPECULAR_BLINN) && !defined(SPECULAR_PHONG) && !defined(SPECULAR_TOON) +// Default to SPECULAR_SCHLICK_GGX. +#if !defined(SPECULAR_DISABLED) && !defined(SPECULAR_SCHLICK_GGX) && !defined(SPECULAR_TOON) #define SPECULAR_SCHLICK_GGX #endif @@ -552,7 +552,6 @@ void cluster_get_item_range(uint p_offset, out uint item_min, out uint item_max, uint item_min_max = cluster_buffer.data[p_offset]; item_min = item_min_max & 0xFFFF; 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 @@ -590,7 +589,7 @@ void main() { float rim = 0.0; float rim_tint = 0.0; float clearcoat = 0.0; - float clearcoat_gloss = 0.0; + float clearcoat_roughness = 0.0; float anisotropy = 0.0; vec2 anisotropy_flow = vec2(1.0, 0.0); vec4 fog = vec4(0.0); @@ -913,7 +912,17 @@ void main() { #if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) if (scene_data.use_reflection_cubemap) { +#ifdef LIGHT_ANISOTROPY_USED + // https://google.github.io/filament/Filament.html#lighting/imagebasedlights/anisotropy + vec3 anisotropic_direction = anisotropy >= 0.0 ? binormal : tangent; + vec3 anisotropic_tangent = cross(anisotropic_direction, view); + vec3 anisotropic_normal = cross(anisotropic_tangent, anisotropic_direction); + vec3 bent_normal = normalize(mix(normal, anisotropic_normal, abs(anisotropy) * clamp(5.0 * roughness, 0.0, 1.0))); + vec3 ref_vec = reflect(-view, bent_normal); +#else vec3 ref_vec = reflect(-view, normal); +#endif + float horizon = min(1.0 + dot(ref_vec, normal), 1.0); ref_vec = scene_data.radiance_inverse_xform * ref_vec; #ifdef USE_RADIANCE_CUBEMAP_ARRAY @@ -955,6 +964,36 @@ void main() { #if defined(CUSTOM_IRRADIANCE_USED) ambient_light = mix(ambient_light, custom_irradiance.rgb, custom_irradiance.a); #endif + +#ifdef LIGHT_CLEARCOAT_USED + + if (scene_data.use_reflection_cubemap) { + vec3 n = normalize(normal_interp); // We want to use geometric normal, not normal_map + float NoV = max(dot(n, view), 0.0001); + vec3 ref_vec = reflect(-view, n); + // The clear coat layer assumes an IOR of 1.5 (4% reflectance) + float Fc = clearcoat * (0.04 + 0.96 * SchlickFresnel(NoV)); + float attenuation = 1.0 - Fc; + ambient_light *= attenuation; + specular_light *= attenuation; + + float horizon = min(1.0 + dot(ref_vec, normal), 1.0); + ref_vec = scene_data.radiance_inverse_xform * ref_vec; + float roughness_lod = mix(0.001, 0.1, clearcoat_roughness) * MAX_ROUGHNESS_LOD; +#ifdef USE_RADIANCE_CUBEMAP_ARRAY + + float lod, blend; + blend = modf(roughness_lod, lod); + vec3 clearcoat_light = texture(samplerCubeArray(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(ref_vec, lod)).rgb; + clearcoat_light = mix(clearcoat_light, texture(samplerCubeArray(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(ref_vec, lod + 1)).rgb, blend); + +#else + vec3 clearcoat_light = textureLod(samplerCube(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ref_vec, roughness_lod).rgb; + +#endif //USE_RADIANCE_CUBEMAP_ARRAY + specular_light += clearcoat_light * horizon * horizon * Fc * scene_data.ambient_light_color_energy.a; + } +#endif #endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) //radiance @@ -1203,8 +1242,16 @@ void main() { if (!bool(reflections.data[reflection_index].mask & instances.data[instance_index].layer_mask)) { continue; //not masked } - - reflection_process(reflection_index, vertex, normal, roughness, ambient_light, specular_light, ambient_accum, reflection_accum); +#ifdef LIGHT_ANISOTROPY_USED + // https://google.github.io/filament/Filament.html#lighting/imagebasedlights/anisotropy + vec3 anisotropic_direction = anisotropy >= 0.0 ? binormal : tangent; + vec3 anisotropic_tangent = cross(anisotropic_direction, view); + vec3 anisotropic_normal = cross(anisotropic_tangent, anisotropic_direction); + vec3 bent_normal = normalize(mix(normal, anisotropic_normal, abs(anisotropy) * clamp(5.0 * roughness, 0.0, 1.0))); +#else + vec3 bent_normal = normal; +#endif + reflection_process(reflection_index, vertex, bent_normal, roughness, ambient_light, specular_light, ambient_accum, reflection_accum); } } @@ -1556,10 +1603,11 @@ void main() { rim, rim_tint, #endif #ifdef LIGHT_CLEARCOAT_USED - clearcoat, clearcoat_gloss, + clearcoat, clearcoat_roughness, normalize(normal_interp), #endif #ifdef LIGHT_ANISOTROPY_USED - binormal, tangent, anisotropy, + binormal, + tangent, anisotropy, #endif diffuse_light, specular_light); @@ -1627,7 +1675,7 @@ void main() { rim_tint, #endif #ifdef LIGHT_CLEARCOAT_USED - clearcoat, clearcoat_gloss, + clearcoat, clearcoat_roughness, normalize(normal_interp), #endif #ifdef LIGHT_ANISOTROPY_USED tangent, binormal, anisotropy, @@ -1699,10 +1747,11 @@ void main() { rim_tint, #endif #ifdef LIGHT_CLEARCOAT_USED - clearcoat, clearcoat_gloss, + clearcoat, clearcoat_roughness, normalize(normal_interp), #endif #ifdef LIGHT_ANISOTROPY_USED - tangent, binormal, anisotropy, + tangent, + binormal, anisotropy, #endif diffuse_light, specular_light); } @@ -1905,7 +1954,7 @@ void main() { frag_color = vec4(albedo, alpha); #else frag_color = vec4(emission + ambient_light + diffuse_light + specular_light, alpha); - //frag_color = vec4(1.0); +//frag_color = vec4(1.0); #endif //USE_NO_SHADING // Draw "fixed" fog before volumetric fog to ensure volumetric fog can appear in front of the sky. diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl index 084e2a0673..3b110aded2 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl @@ -15,7 +15,7 @@ #include "cluster_data_inc.glsl" #include "decal_data_inc.glsl" -#if !defined(MODE_RENDER_DEPTH) || defined(MODE_RENDER_MATERIAL) || defined(MODE_RENDER_SDF) || defined(MODE_RENDER_NORMAL_ROUGHNESS) || defined(MODE_RENDER_VOXEL_GI) || defined(TANGENT_USED) || defined(NORMAL_MAP_USED) +#if !defined(MODE_RENDER_DEPTH) || defined(MODE_RENDER_MATERIAL) || defined(MODE_RENDER_SDF) || defined(MODE_RENDER_NORMAL_ROUGHNESS) || defined(MODE_RENDER_VOXEL_GI) || defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) #ifndef NORMAL_USED #define NORMAL_USED #endif 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 16f77fb91a..1c9b08b6d3 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl @@ -1,55 +1,29 @@ // Functions related to lighting -// This returns the G_GGX function divided by 2 cos_theta_m, where in practice cos_theta_m is either N.L or N.V. -// We're dividing this factor off because the overall term we'll end up looks like -// (see, for example, the first unnumbered equation in B. Burley, "Physically Based Shading at Disney", SIGGRAPH 2012): -// -// F(L.V) D(N.H) G(N.L) G(N.V) / (4 N.L N.V) -// -// We're basically regouping this as -// -// F(L.V) D(N.H) [G(N.L)/(2 N.L)] [G(N.V) / (2 N.V)] -// -// and thus, this function implements the [G(N.m)/(2 N.m)] part with m = L or V. -// -// The contents of the D and G (G1) functions (GGX) are taken from -// E. Heitz, "Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs", J. Comp. Graph. Tech. 3 (2) (2014). -// Eqns 71-72 and 85-86 (see also Eqns 43 and 80). - -float G_GGX_2cos(float cos_theta_m, float alpha) { - // Schlick's approximation - // C. Schlick, "An Inexpensive BRDF Model for Physically-based Rendering", Computer Graphics Forum. 13 (3): 233 (1994) - // Eq. (19), although see Heitz (2014) the about the problems with his derivation. - // It nevertheless approximates GGX well with k = alpha/2. - float k = 0.5 * alpha; - return 0.5 / (cos_theta_m * (1.0 - k) + k); - - // float cos2 = cos_theta_m * cos_theta_m; - // float sin2 = (1.0 - cos2); - // return 1.0 / (cos_theta_m + sqrt(cos2 + alpha * alpha * sin2)); -} - float D_GGX(float cos_theta_m, float alpha) { float alpha2 = alpha * alpha; float d = 1.0 + (alpha2 - 1.0) * cos_theta_m * cos_theta_m; return alpha2 / (M_PI * d * d); } -float G_GGX_anisotropic_2cos(float cos_theta_m, float alpha_x, float alpha_y, float cos_phi, float sin_phi) { - float cos2 = cos_theta_m * cos_theta_m; - float sin2 = (1.0 - cos2); - float s_x = alpha_x * cos_phi; - float s_y = alpha_y * sin_phi; - return 1.0 / max(cos_theta_m + sqrt(cos2 + (s_x * s_x + s_y * s_y) * sin2), 0.001); +// From Earl Hammon, Jr. "PBR Diffuse Lighting for GGX+Smith Microsurfaces" https://www.gdcvault.com/play/1024478/PBR-Diffuse-Lighting-for-GGX +float V_GGX(float NdotL, float NdotV, float alpha) { + return 0.5 / mix(2.0 * NdotL * NdotV, NdotL + NdotV, alpha); } float D_GGX_anisotropic(float cos_theta_m, float alpha_x, float alpha_y, float cos_phi, float sin_phi) { - float cos2 = cos_theta_m * cos_theta_m; - float sin2 = (1.0 - cos2); - float r_x = cos_phi / alpha_x; - float r_y = sin_phi / alpha_y; - float d = cos2 + sin2 * (r_x * r_x + r_y * r_y); - return 1.0 / max(M_PI * alpha_x * alpha_y * d * d, 0.001); + float alpha2 = alpha_x * alpha_y; + highp vec3 v = vec3(alpha_y * cos_phi, alpha_x * sin_phi, alpha2 * cos_theta_m); + highp float v2 = dot(v, v); + float w2 = alpha2 / v2; + float D = alpha2 * w2 * w2 * (1.0 / M_PI); + return D; +} + +float V_GGX_anisotropic(float alpha_x, float alpha_y, float TdotV, float TdotL, float BdotV, float BdotL, float NdotV, float NdotL) { + float Lambda_V = NdotL * length(vec3(alpha_x * TdotV, alpha_y * BdotV, NdotV)); + float Lambda_L = NdotV * length(vec3(alpha_x * TdotL, alpha_y * BdotL, NdotL)); + return 0.5 / (Lambda_V + Lambda_L); } float SchlickFresnel(float u) { @@ -58,14 +32,6 @@ float SchlickFresnel(float u) { return m2 * m2 * m; // pow(m,5) } -float GTR1(float NdotH, float a) { - if (a >= 1.0) - return 1.0 / M_PI; - float a2 = a * a; - float t = 1.0 + (a2 - 1.0) * NdotH * NdotH; - return (a2 - 1.0) / (M_PI * log(a2) * t); -} - vec3 F0(float metallic, float specular, vec3 albedo) { float dielectric = 0.16 * specular * specular; // use albedo * metallic as colored specular reflectance at 0 angle for metallic materials; @@ -87,7 +53,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte float rim, float rim_tint, #endif #ifdef LIGHT_CLEARCOAT_USED - float clearcoat, float clearcoat_gloss, + float clearcoat, float clearcoat_roughness, vec3 vertex_normal, #endif #ifdef LIGHT_ANISOTROPY_USED vec3 B, vec3 T, float anisotropy, @@ -113,13 +79,13 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte float NdotL = min(A + dot(N, L), 1.0); float cNdotL = max(NdotL, 0.0); // clamped NdotL float NdotV = dot(N, V); - float cNdotV = max(NdotV, 0.0); + float cNdotV = max(NdotV, 1e-4); -#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_BLINN) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_CLEARCOAT_USED) +#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_CLEARCOAT_USED) vec3 H = normalize(V + L); #endif -#if defined(SPECULAR_BLINN) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_CLEARCOAT_USED) +#if defined(SPECULAR_SCHLICK_GGX) float cNdotH = clamp(A + dot(N, H), 0.0, 1.0); #endif @@ -203,26 +169,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte // D -#if defined(SPECULAR_BLINN) - - //normalized blinn - float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25; - float blinn = pow(cNdotH, shininess); - blinn *= (shininess + 2.0) * (1.0 / (8.0 * M_PI)); - - specular_light += light_color * attenuation * specular_amount * blinn * f0 * orms_unpacked.w; - -#elif defined(SPECULAR_PHONG) - - vec3 R = normalize(-reflect(L, N)); - float cRdotV = clamp(A + dot(R, V), 0.0, 1.0); - float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25; - float phong = pow(cRdotV, shininess); - phong *= (shininess + 1.0) * (1.0 / (8.0 * M_PI)); - - specular_light += light_color * attenuation * specular_amount * phong * f0 * orms_unpacked.w; - -#elif defined(SPECULAR_TOON) +#if defined(SPECULAR_TOON) vec3 R = normalize(-reflect(L, N)); float RdotV = dot(R, V); @@ -236,24 +183,21 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte #elif defined(SPECULAR_SCHLICK_GGX) // shlick+ggx as default - + float alpha_ggx = roughness * roughness; #if defined(LIGHT_ANISOTROPY_USED) - float alpha_ggx = roughness * roughness; float aspect = sqrt(1.0 - anisotropy * 0.9); 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_ggx = roughness * roughness; + float G = V_GGX_anisotropic(ax, ay, dot(T, V), dot(T, L), dot(B, V), dot(B, L), cNdotV, cNdotL); +#else // LIGHT_ANISOTROPY_USED float D = D_GGX(cNdotH, alpha_ggx); - float G = G_GGX_2cos(cNdotL, alpha_ggx) * G_GGX_2cos(cNdotV, alpha_ggx); -#endif - // F + float G = V_GGX(cNdotL, cNdotV, alpha_ggx); +#endif // LIGHT_ANISOTROPY_USED + // F float cLdotH5 = SchlickFresnel(cLdotH); vec3 F = mix(vec3(cLdotH5), vec3(1.0), f0); @@ -263,18 +207,23 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte #endif #if defined(LIGHT_CLEARCOAT_USED) + // Clearcoat ignores normal_map, use vertex normal instead + float ccNdotL = max(min(A + dot(vertex_normal, L), 1.0), 0.0); + float ccNdotH = clamp(A + dot(vertex_normal, H), 0.0, 1.0); + float ccNdotV = max(dot(vertex_normal, V), 1e-4); #if !defined(SPECULAR_SCHLICK_GGX) float cLdotH5 = SchlickFresnel(cLdotH); #endif - float Dr = GTR1(cNdotH, mix(.1, .001, clearcoat_gloss)); + float Dr = D_GGX(ccNdotH, mix(0.001, 0.1, clearcoat_roughness)); + float Gr = 0.25 / (cLdotH * cLdotH); float Fr = mix(.04, 1.0, cLdotH5); - float Gr = G_GGX_2cos(cNdotL, .25) * G_GGX_2cos(cNdotV, .25); - - float clearcoat_specular_brdf_NL = 0.25 * clearcoat * Gr * Fr * Dr * cNdotL; + float clearcoat_specular_brdf_NL = clearcoat * Gr * Fr * Dr * cNdotL; specular_light += clearcoat_specular_brdf_NL * light_color * attenuation * specular_amount; -#endif + // TODO: Clearcoat adds light to the scene right now (it is non-energy conserving), both diffuse and specular need to be scaled by (1.0 - FR) + // but to do so we need to rearrange this entire function +#endif // LIGHT_CLEARCOAT_USED } #ifdef USE_SHADOW_TO_OPACITY @@ -587,7 +536,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v float rim, float rim_tint, #endif #ifdef LIGHT_CLEARCOAT_USED - float clearcoat, float clearcoat_gloss, + float clearcoat, float clearcoat_roughness, vec3 vertex_normal, #endif #ifdef LIGHT_ANISOTROPY_USED vec3 binormal, vec3 tangent, float anisotropy, @@ -711,7 +660,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v rim * omni_attenuation, rim_tint, #endif #ifdef LIGHT_CLEARCOAT_USED - clearcoat, clearcoat_gloss, + clearcoat, clearcoat_roughness, vertex_normal, #endif #ifdef LIGHT_ANISOTROPY_USED binormal, tangent, anisotropy, @@ -827,7 +776,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v float rim, float rim_tint, #endif #ifdef LIGHT_CLEARCOAT_USED - float clearcoat, float clearcoat_gloss, + float clearcoat, float clearcoat_roughness, vec3 vertex_normal, #endif #ifdef LIGHT_ANISOTROPY_USED vec3 binormal, vec3 tangent, float anisotropy, @@ -912,7 +861,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v rim * spot_attenuation, rim_tint, #endif #ifdef LIGHT_CLEARCOAT_USED - clearcoat, clearcoat_gloss, + clearcoat, clearcoat_roughness, vertex_normal, #endif #ifdef LIGHT_ANISOTROPY_USED binormal, tangent, anisotropy, diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl index 4d6a3b5864..a1cf1d3c04 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl @@ -511,8 +511,8 @@ layout(location = 0) out mediump vec4 frag_color; #if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) -/* Make a default specular mode SPECULAR_SCHLICK_GGX. */ -#if !defined(SPECULAR_DISABLED) && !defined(SPECULAR_SCHLICK_GGX) && !defined(SPECULAR_BLINN) && !defined(SPECULAR_PHONG) && !defined(SPECULAR_TOON) +// Default to SPECULAR_SCHLICK_GGX. +#if !defined(SPECULAR_DISABLED) && !defined(SPECULAR_SCHLICK_GGX) && !defined(SPECULAR_TOON) #define SPECULAR_SCHLICK_GGX #endif @@ -596,7 +596,7 @@ void main() { float rim = 0.0; float rim_tint = 0.0; float clearcoat = 0.0; - float clearcoat_gloss = 0.0; + float clearcoat_roughness = 0.0; float anisotropy = 0.0; vec2 anisotropy_flow = vec2(1.0, 0.0); vec4 fog = vec4(0.0); @@ -874,7 +874,16 @@ void main() { #if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) if (scene_data.use_reflection_cubemap) { +#ifdef LIGHT_ANISOTROPY_USED + // https://google.github.io/filament/Filament.html#lighting/imagebasedlights/anisotropy + vec3 anisotropic_direction = anisotropy >= 0.0 ? binormal : tangent; + vec3 anisotropic_tangent = cross(anisotropic_direction, view); + vec3 anisotropic_normal = cross(anisotropic_tangent, anisotropic_direction); + vec3 bent_normal = normalize(mix(normal, anisotropic_normal, abs(anisotropy) * clamp(5.0 * roughness, 0.0, 1.0))); + vec3 ref_vec = reflect(-view, bent_normal); +#else vec3 ref_vec = reflect(-view, normal); +#endif float horizon = min(1.0 + dot(ref_vec, normal), 1.0); ref_vec = scene_data.radiance_inverse_xform * ref_vec; #ifdef USE_RADIANCE_CUBEMAP_ARRAY @@ -917,7 +926,35 @@ void main() { #if defined(CUSTOM_IRRADIANCE_USED) ambient_light = mix(specular_light, custom_irradiance.rgb, custom_irradiance.a); #endif // CUSTOM_IRRADIANCE_USED +#ifdef LIGHT_CLEARCOAT_USED + + if (scene_data.use_reflection_cubemap) { + vec3 n = normalize(normal_interp); // We want to use geometric normal, not normal_map + float NoV = max(dot(n, view), 0.0001); + vec3 ref_vec = reflect(-view, n); + // The clear coat layer assumes an IOR of 1.5 (4% reflectance) + float Fc = clearcoat * (0.04 + 0.96 * SchlickFresnel(NoV)); + float attenuation = 1.0 - Fc; + ambient_light *= attenuation; + specular_light *= attenuation; + float horizon = min(1.0 + dot(ref_vec, normal), 1.0); + ref_vec = scene_data.radiance_inverse_xform * ref_vec; + float roughness_lod = mix(0.001, 0.1, clearcoat_roughness) * MAX_ROUGHNESS_LOD; +#ifdef USE_RADIANCE_CUBEMAP_ARRAY + + float lod, blend; + blend = modf(roughness_lod, lod); + vec3 clearcoat_light = texture(samplerCubeArray(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(ref_vec, lod)).rgb; + clearcoat_light = mix(clearcoat_light, texture(samplerCubeArray(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(ref_vec, lod + 1)).rgb, blend); + +#else + vec3 clearcoat_light = textureLod(samplerCube(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ref_vec, roughness_lod).rgb; + +#endif //USE_RADIANCE_CUBEMAP_ARRAY + specular_light += clearcoat_light * horizon * horizon * Fc * scene_data.ambient_light_color_energy.a; + } +#endif #endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) //radiance @@ -1002,8 +1039,16 @@ void main() { if (reflection_index == 0xFF) { break; } - - reflection_process(reflection_index, vertex, normal, roughness, ambient_light, specular_light, ambient_accum, reflection_accum); +#ifdef LIGHT_ANISOTROPY_USED + // https://google.github.io/filament/Filament.html#lighting/imagebasedlights/anisotropy + vec3 anisotropic_direction = anisotropy >= 0.0 ? binormal : tangent; + vec3 anisotropic_tangent = cross(anisotropic_direction, view); + vec3 anisotropic_normal = cross(anisotropic_tangent, anisotropic_direction); + vec3 bent_normal = normalize(mix(normal, anisotropic_normal, abs(anisotropy) * clamp(5.0 * roughness, 0.0, 1.0))); +#else + vec3 bent_normal = normal; +#endif + reflection_process(reflection_index, vertex, bent_normal, roughness, ambient_light, specular_light, ambient_accum, reflection_accum); } if (reflection_accum.a > 0.0) { @@ -1368,7 +1413,7 @@ void main() { rim, rim_tint, #endif #ifdef LIGHT_CLEARCOAT_USED - clearcoat, clearcoat_gloss, + clearcoat, clearcoat_roughness, normalize(normal_interp), #endif #ifdef LIGHT_ANISOTROPY_USED binormal, tangent, anisotropy, @@ -1415,10 +1460,11 @@ void main() { rim_tint, #endif #ifdef LIGHT_CLEARCOAT_USED - clearcoat, clearcoat_gloss, + clearcoat, clearcoat_roughness, normalize(normal_interp), #endif #ifdef LIGHT_ANISOTROPY_USED - tangent, binormal, anisotropy, + tangent, + binormal, anisotropy, #endif diffuse_light, specular_light); } @@ -1459,10 +1505,11 @@ void main() { rim_tint, #endif #ifdef LIGHT_CLEARCOAT_USED - clearcoat, clearcoat_gloss, + clearcoat, clearcoat_roughness, normalize(normal_interp), #endif #ifdef LIGHT_ANISOTROPY_USED - tangent, binormal, anisotropy, + tangent, + binormal, anisotropy, #endif diffuse_light, specular_light); } diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl index 541c0b0603..7a624c3b95 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl @@ -7,7 +7,7 @@ #include "decal_data_inc.glsl" -#if !defined(MODE_RENDER_DEPTH) || defined(MODE_RENDER_MATERIAL) || defined(TANGENT_USED) || defined(NORMAL_MAP_USED) +#if !defined(MODE_RENDER_DEPTH) || defined(MODE_RENDER_MATERIAL) || defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) #ifndef NORMAL_USED #define NORMAL_USED #endif diff --git a/servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl b/servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl index 7c8d4f7f99..7a0cea421e 100644 --- a/servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl +++ b/servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl @@ -235,7 +235,6 @@ void cluster_get_item_range(uint p_offset, out uint item_min, out uint item_max, uint item_min_max = cluster_buffer.data[p_offset]; item_min = item_min_max & 0xFFFF; 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 diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index 5b2be8e174..5bdc7ce600 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -3683,6 +3683,15 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) { _instance_update_mesh_instance(p_instance); } + if (p_instance->base_type == RS::INSTANCE_PARTICLES) { + // update the process material dependency + + RID particle_material = RSG::storage->particles_get_process_material(p_instance->base); + if (particle_material.is_valid()) { + RSG::storage->material_update_dependency(particle_material, &p_instance->dependency_tracker); + } + } + if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) { InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data); diff --git a/servers/rendering/renderer_storage.h b/servers/rendering/renderer_storage.h index 43a7778d67..762362afed 100644 --- a/servers/rendering/renderer_storage.h +++ b/servers/rendering/renderer_storage.h @@ -321,6 +321,7 @@ public: virtual void light_set_projector(RID p_light, RID p_texture) = 0; virtual void light_set_negative(RID p_light, bool p_enable) = 0; virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) = 0; + virtual void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) = 0; virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) = 0; virtual void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) = 0; virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) = 0; @@ -477,6 +478,7 @@ public: virtual void particles_set_speed_scale(RID p_particles, double p_scale) = 0; virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable) = 0; virtual void particles_set_process_material(RID p_particles, RID p_material) = 0; + virtual RID particles_get_process_material(RID p_particles) const = 0; virtual void particles_set_fixed_fps(RID p_particles, int p_fps) = 0; virtual void particles_set_interpolate(RID p_particles, bool p_enable) = 0; virtual void particles_set_fractional_delta(RID p_particles, bool p_enable) = 0; diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp index 5a84bace2d..69c017a1c8 100644 --- a/servers/rendering/renderer_viewport.cpp +++ b/servers/rendering/renderer_viewport.cpp @@ -548,7 +548,6 @@ void RendererViewport::draw_viewports() { // get our xr interface in case we need it Ref<XRInterface> xr_interface; - XRServer *xr_server = XRServer::get_singleton(); if (xr_server != nullptr) { // let our XR server know we're about to render our frames so we can get our frame timing diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h index 655a32a805..49d89bcadc 100644 --- a/servers/rendering/rendering_device.h +++ b/servers/rendering/rendering_device.h @@ -500,6 +500,7 @@ public: virtual RID texture_create(const TextureFormat &p_format, const TextureView &p_view, const Vector<Vector<uint8_t>> &p_data = Vector<Vector<uint8_t>>()) = 0; virtual RID texture_create_shared(const TextureView &p_view, RID p_with_texture) = 0; + virtual RID texture_create_from_extension(TextureType p_type, DataFormat p_format, TextureSamples p_samples, uint64_t p_flags, uint64_t p_image, uint64_t p_width, uint64_t p_height, uint64_t p_depth, uint64_t p_layers) = 0; enum TextureSliceType { TEXTURE_SLICE_2D, diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index 6d2c36537b..9ed2b2ad4f 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -346,6 +346,7 @@ public: FUNC2(light_set_projector, RID, RID) FUNC2(light_set_negative, RID, bool) FUNC2(light_set_cull_mask, RID, uint32_t) + FUNC5(light_set_distance_fade, RID, bool, float, float, float) FUNC2(light_set_reverse_cull_face_mode, RID, bool) FUNC2(light_set_bake_mode, RID, LightBakeMode) FUNC2(light_set_max_sdfgi_cascade, RID, uint32_t) diff --git a/servers/rendering/shader_compiler.cpp b/servers/rendering/shader_compiler.cpp index 5b43ca4bcd..812d636a0b 100644 --- a/servers/rendering/shader_compiler.cpp +++ b/servers/rendering/shader_compiler.cpp @@ -609,7 +609,6 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene r_gen_code.uniforms += uniform_defines[i]; } -#if 1 // add up int offset = 0; for (int i = 0; i < uniform_sizes.size(); i++) { @@ -629,41 +628,6 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene if (r_gen_code.uniform_total_size % 16 != 0) { //UBO sizes must be multiples of 16 r_gen_code.uniform_total_size += 16 - (r_gen_code.uniform_total_size % 16); } -#else - // add up - for (int i = 0; i < uniform_sizes.size(); i++) { - if (i > 0) { - int align = uniform_sizes[i - 1] % uniform_alignments[i]; - if (align != 0) { - uniform_sizes[i - 1] += uniform_alignments[i] - align; - } - - uniform_sizes[i] = uniform_sizes[i] + uniform_sizes[i - 1]; - } - } - //offset - r_gen_code.uniform_offsets.resize(uniform_sizes.size()); - for (int i = 0; i < uniform_sizes.size(); i++) { - if (i > 0) - r_gen_code.uniform_offsets[i] = uniform_sizes[i - 1]; - else - r_gen_code.uniform_offsets[i] = 0; - } - /* - for(Map<StringName,SL::ShaderNode::Uniform>::Element *E=pnode->uniforms.front();E;E=E->next()) { - if (SL::is_sampler_type(E->get().type)) { - continue; - } - - } - -*/ - if (uniform_sizes.size()) { - r_gen_code.uniform_total_size = uniform_sizes[uniform_sizes.size() - 1]; - } else { - r_gen_code.uniform_total_size = 0; - } -#endif uint32_t index = p_default_actions.base_varying_index; @@ -1409,148 +1373,4 @@ void ShaderCompiler::initialize(DefaultIdentifierActions p_actions) { } ShaderCompiler::ShaderCompiler() { -#if 0 - - /** SPATIAL SHADER **/ - - actions[RS::SHADER_SPATIAL].renames["WORLD_MATRIX"] = "world_transform"; - actions[RS::SHADER_SPATIAL].renames["INV_CAMERA_MATRIX"] = "camera_inverse_matrix"; - actions[RS::SHADER_SPATIAL].renames["CAMERA_MATRIX"] = "camera_matrix"; - actions[RS::SHADER_SPATIAL].renames["PROJECTION_MATRIX"] = "projection_matrix"; - actions[RS::SHADER_SPATIAL].renames["INV_PROJECTION_MATRIX"] = "inv_projection_matrix"; - actions[RS::SHADER_SPATIAL].renames["MODELVIEW_MATRIX"] = "modelview"; - - actions[RS::SHADER_SPATIAL].renames["VERTEX"] = "vertex.xyz"; - actions[RS::SHADER_SPATIAL].renames["NORMAL"] = "normal"; - actions[RS::SHADER_SPATIAL].renames["TANGENT"] = "tangent"; - actions[RS::SHADER_SPATIAL].renames["BINORMAL"] = "binormal"; - actions[RS::SHADER_SPATIAL].renames["POSITION"] = "position"; - actions[RS::SHADER_SPATIAL].renames["UV"] = "uv_interp"; - actions[RS::SHADER_SPATIAL].renames["UV2"] = "uv2_interp"; - actions[RS::SHADER_SPATIAL].renames["COLOR"] = "color_interp"; - actions[RS::SHADER_SPATIAL].renames["POINT_SIZE"] = "gl_PointSize"; - actions[RS::SHADER_SPATIAL].renames["INSTANCE_ID"] = "gl_InstanceID"; - - //builtins - - actions[RS::SHADER_SPATIAL].renames["TIME"] = "time"; - actions[RS::SHADER_SPATIAL].renames["VIEWPORT_SIZE"] = "viewport_size"; - - actions[RS::SHADER_SPATIAL].renames["FRAGCOORD"] = "gl_FragCoord"; - actions[RS::SHADER_SPATIAL].renames["FRONT_FACING"] = "gl_FrontFacing"; - actions[RS::SHADER_SPATIAL].renames["NORMAL_MAP"] = "normal_map"; - actions[RS::SHADER_SPATIAL].renames["NORMAL_MAP_DEPTH"] = "normal_map_depth"; - actions[RS::SHADER_SPATIAL].renames["ALBEDO"] = "albedo"; - actions[RS::SHADER_SPATIAL].renames["ALPHA"] = "alpha"; - actions[RS::SHADER_SPATIAL].renames["METALLIC"] = "metallic"; - actions[RS::SHADER_SPATIAL].renames["SPECULAR"] = "specular"; - actions[RS::SHADER_SPATIAL].renames["ROUGHNESS"] = "roughness"; - actions[RS::SHADER_SPATIAL].renames["RIM"] = "rim"; - actions[RS::SHADER_SPATIAL].renames["RIM_TINT"] = "rim_tint"; - actions[RS::SHADER_SPATIAL].renames["CLEARCOAT"] = "clearcoat"; - actions[RS::SHADER_SPATIAL].renames["CLEARCOAT_GLOSS"] = "clearcoat_gloss"; - actions[RS::SHADER_SPATIAL].renames["ANISOTROPY"] = "anisotropy"; - actions[RS::SHADER_SPATIAL].renames["ANISOTROPY_FLOW"] = "anisotropy_flow"; - actions[RS::SHADER_SPATIAL].renames["SSS_STRENGTH"] = "sss_strength"; - actions[RS::SHADER_SPATIAL].renames["TRANSMISSION"] = "transmission"; - actions[RS::SHADER_SPATIAL].renames["AO"] = "ao"; - actions[RS::SHADER_SPATIAL].renames["AO_LIGHT_AFFECT"] = "ao_light_affect"; - actions[RS::SHADER_SPATIAL].renames["EMISSION"] = "emission"; - actions[RS::SHADER_SPATIAL].renames["POINT_COORD"] = "gl_PointCoord"; - actions[RS::SHADER_SPATIAL].renames["INSTANCE_CUSTOM"] = "instance_custom"; - actions[RS::SHADER_SPATIAL].renames["SCREEN_UV"] = "screen_uv"; - actions[RS::SHADER_SPATIAL].renames["SCREEN_TEXTURE"] = "screen_texture"; - actions[RS::SHADER_SPATIAL].renames["DEPTH_TEXTURE"] = "depth_buffer"; - actions[RS::SHADER_SPATIAL].renames["DEPTH"] = "gl_FragDepth"; - actions[RS::SHADER_SPATIAL].renames["ALPHA_SCISSOR"] = "alpha_scissor"; - actions[RS::SHADER_SPATIAL].renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB"; - - //for light - actions[RS::SHADER_SPATIAL].renames["VIEW"] = "view"; - actions[RS::SHADER_SPATIAL].renames["LIGHT_COLOR"] = "light_color"; - actions[RS::SHADER_SPATIAL].renames["LIGHT"] = "light"; - actions[RS::SHADER_SPATIAL].renames["ATTENUATION"] = "attenuation"; - actions[RS::SHADER_SPATIAL].renames["DIFFUSE_LIGHT"] = "diffuse_light"; - actions[RS::SHADER_SPATIAL].renames["SPECULAR_LIGHT"] = "specular_light"; - - actions[RS::SHADER_SPATIAL].usage_defines["TANGENT"] = "#define ENABLE_TANGENT_INTERP\n"; - actions[RS::SHADER_SPATIAL].usage_defines["BINORMAL"] = "@TANGENT"; - actions[RS::SHADER_SPATIAL].usage_defines["RIM"] = "#define LIGHT_USE_RIM\n"; - actions[RS::SHADER_SPATIAL].usage_defines["RIM_TINT"] = "@RIM"; - actions[RS::SHADER_SPATIAL].usage_defines["CLEARCOAT"] = "#define LIGHT_USE_CLEARCOAT\n"; - actions[RS::SHADER_SPATIAL].usage_defines["CLEARCOAT_GLOSS"] = "@CLEARCOAT"; - actions[RS::SHADER_SPATIAL].usage_defines["ANISOTROPY"] = "#define LIGHT_USE_ANISOTROPY\n"; - actions[RS::SHADER_SPATIAL].usage_defines["ANISOTROPY_FLOW"] = "@ANISOTROPY"; - actions[RS::SHADER_SPATIAL].usage_defines["AO"] = "#define ENABLE_AO\n"; - actions[RS::SHADER_SPATIAL].usage_defines["AO_LIGHT_AFFECT"] = "#define ENABLE_AO\n"; - actions[RS::SHADER_SPATIAL].usage_defines["UV"] = "#define ENABLE_UV_INTERP\n"; - actions[RS::SHADER_SPATIAL].usage_defines["UV2"] = "#define ENABLE_UV2_INTERP\n"; - actions[RS::SHADER_SPATIAL].usage_defines["NORMAL_MAP"] = "#define ENABLE_NORMAL_MAP\n"; - actions[RS::SHADER_SPATIAL].usage_defines["NORMAL_MAP_DEPTH"] = "@NORMAL_MAP"; - actions[RS::SHADER_SPATIAL].usage_defines["COLOR"] = "#define ENABLE_COLOR_INTERP\n"; - actions[RS::SHADER_SPATIAL].usage_defines["INSTANCE_CUSTOM"] = "#define ENABLE_INSTANCE_CUSTOM\n"; - actions[RS::SHADER_SPATIAL].usage_defines["ALPHA_SCISSOR"] = "#define ALPHA_SCISSOR_USED\n"; - actions[RS::SHADER_SPATIAL].usage_defines["POSITION"] = "#define OVERRIDE_POSITION\n"; - - actions[RS::SHADER_SPATIAL].usage_defines["SSS_STRENGTH"] = "#define ENABLE_SSS\n"; - actions[RS::SHADER_SPATIAL].usage_defines["TRANSMISSION"] = "#define TRANSMISSION_USED\n"; - actions[RS::SHADER_SPATIAL].usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n"; - actions[RS::SHADER_SPATIAL].usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n"; - - actions[RS::SHADER_SPATIAL].usage_defines["DIFFUSE_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n"; - actions[RS::SHADER_SPATIAL].usage_defines["SPECULAR_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n"; - - actions[RS::SHADER_SPATIAL].render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n"; - actions[RS::SHADER_SPATIAL].render_mode_defines["world_vertex_coords"] = "#define VERTEX_WORLD_COORDS_USED\n"; - actions[RS::SHADER_SPATIAL].render_mode_defines["ensure_correct_normals"] = "#define ENSURE_CORRECT_NORMALS\n"; - actions[RS::SHADER_SPATIAL].render_mode_defines["cull_front"] = "#define DO_SIDE_CHECK\n"; - actions[RS::SHADER_SPATIAL].render_mode_defines["cull_disabled"] = "#define DO_SIDE_CHECK\n"; - - bool force_lambert = GLOBAL_GET("rendering/shading/overrides/force_lambert_over_burley"); - - if (!force_lambert) { - actions[RS::SHADER_SPATIAL].render_mode_defines["diffuse_burley"] = "#define DIFFUSE_BURLEY\n"; - } - - actions[RS::SHADER_SPATIAL].render_mode_defines["diffuse_lambert_wrap"] = "#define DIFFUSE_LAMBERT_WRAP\n"; - actions[RS::SHADER_SPATIAL].render_mode_defines["diffuse_toon"] = "#define DIFFUSE_TOON\n"; - - bool force_blinn = GLOBAL_GET("rendering/shading/overrides/force_blinn_over_ggx"); - - if (!force_blinn) { - actions[RS::SHADER_SPATIAL].render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_SCHLICK_GGX\n"; - } else { - actions[RS::SHADER_SPATIAL].render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_BLINN\n"; - } - - actions[RS::SHADER_SPATIAL].render_mode_defines["specular_blinn"] = "#define SPECULAR_BLINN\n"; - actions[RS::SHADER_SPATIAL].render_mode_defines["specular_phong"] = "#define SPECULAR_PHONG\n"; - actions[RS::SHADER_SPATIAL].render_mode_defines["specular_toon"] = "#define SPECULAR_TOON\n"; - actions[RS::SHADER_SPATIAL].render_mode_defines["specular_disabled"] = "#define SPECULAR_DISABLED\n"; - actions[RS::SHADER_SPATIAL].render_mode_defines["shadows_disabled"] = "#define SHADOWS_DISABLED\n"; - actions[RS::SHADER_SPATIAL].render_mode_defines["ambient_light_disabled"] = "#define AMBIENT_LIGHT_DISABLED\n"; - actions[RS::SHADER_SPATIAL].render_mode_defines["shadow_to_opacity"] = "#define USE_SHADOW_TO_OPACITY\n"; - - /* PARTICLES SHADER */ - - actions[RS::SHADER_PARTICLES].renames["COLOR"] = "out_color"; - actions[RS::SHADER_PARTICLES].renames["VELOCITY"] = "out_velocity_active.xyz"; - actions[RS::SHADER_PARTICLES].renames["MASS"] = "mass"; - actions[RS::SHADER_PARTICLES].renames["ACTIVE"] = "shader_active"; - actions[RS::SHADER_PARTICLES].renames["RESTART"] = "restart"; - actions[RS::SHADER_PARTICLES].renames["CUSTOM"] = "out_custom"; - actions[RS::SHADER_PARTICLES].renames["TRANSFORM"] = "xform"; - actions[RS::SHADER_PARTICLES].renames["TIME"] = "time"; - actions[RS::SHADER_PARTICLES].renames["LIFETIME"] = "lifetime"; - actions[RS::SHADER_PARTICLES].renames["DELTA"] = "local_delta"; - actions[RS::SHADER_PARTICLES].renames["NUMBER"] = "particle_number"; - actions[RS::SHADER_PARTICLES].renames["INDEX"] = "index"; - actions[RS::SHADER_PARTICLES].renames["GRAVITY"] = "current_gravity"; - actions[RS::SHADER_PARTICLES].renames["EMISSION_TRANSFORM"] = "emission_transform"; - actions[RS::SHADER_PARTICLES].renames["RANDOM_SEED"] = "random_seed"; - - actions[RS::SHADER_PARTICLES].render_mode_defines["disable_force"] = "#define DISABLE_FORCE\n"; - actions[RS::SHADER_PARTICLES].render_mode_defines["disable_velocity"] = "#define DISABLE_VELOCITY\n"; - actions[RS::SHADER_PARTICLES].render_mode_defines["keep_data"] = "#define ENABLE_KEEP_DATA\n"; -#endif } diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index 91201b2028..7683cf20b3 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "shader_language.h" + #include "core/os/os.h" #include "core/string/print_string.h" #include "servers/rendering_server.h" @@ -632,7 +633,7 @@ ShaderLanguage::Token ShaderLanguage::_get_token() { char32_t last_char = str[str.length() - 1]; - if (hexa_found) { // Integer(hex) + if (hexa_found) { // Integer (hex). if (str.size() > 11 || !str.is_valid_hex_number(true)) { // > 0xFFFFFFFF return _make_token(TK_ERROR, "Invalid (hexadecimal) numeric constant"); } diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp index b8bb211a7a..9ea98dc593 100644 --- a/servers/rendering/shader_types.cpp +++ b/servers/rendering/shader_types.cpp @@ -121,7 +121,7 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["RIM"] = ShaderLanguage::TYPE_FLOAT; shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["RIM_TINT"] = ShaderLanguage::TYPE_FLOAT; shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["CLEARCOAT"] = ShaderLanguage::TYPE_FLOAT; - shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["CLEARCOAT_GLOSS"] = ShaderLanguage::TYPE_FLOAT; + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["CLEARCOAT_ROUGHNESS"] = ShaderLanguage::TYPE_FLOAT; shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["ANISOTROPY"] = ShaderLanguage::TYPE_FLOAT; shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["ANISOTROPY_FLOW"] = ShaderLanguage::TYPE_VEC2; shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SSS_STRENGTH"] = ShaderLanguage::TYPE_FLOAT; @@ -202,7 +202,7 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "unshaded" }); shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "wireframe" }); shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "diffuse", "lambert", "lambert_wrap", "burley", "toon" }); - shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "specular", "schlick_ggx", "blinn", "phong", "toon", "disabled" }); + shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "specular", "schlick_ggx", "toon", "disabled" }); shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "skip_vertex_transform" }); shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "world_vertex_coords" }); shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "ensure_correct_normals" }); @@ -318,6 +318,12 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["MASS"] = ShaderLanguage::TYPE_FLOAT; shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["ACTIVE"] = ShaderLanguage::TYPE_BOOL; shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["CUSTOM"] = ShaderLanguage::TYPE_VEC4; + shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["USERDATA1"] = ShaderLanguage::TYPE_VEC4; + shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["USERDATA2"] = ShaderLanguage::TYPE_VEC4; + shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["USERDATA3"] = ShaderLanguage::TYPE_VEC4; + shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["USERDATA4"] = ShaderLanguage::TYPE_VEC4; + shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["USERDATA5"] = ShaderLanguage::TYPE_VEC4; + shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["USERDATA6"] = ShaderLanguage::TYPE_VEC4; shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["TRANSFORM"] = ShaderLanguage::TYPE_MAT4; shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["LIFETIME"] = constt(ShaderLanguage::TYPE_FLOAT); shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["DELTA"] = constt(ShaderLanguage::TYPE_FLOAT); @@ -338,6 +344,12 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["ACTIVE"] = ShaderLanguage::TYPE_BOOL; shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["RESTART"] = constt(ShaderLanguage::TYPE_BOOL); shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["CUSTOM"] = ShaderLanguage::TYPE_VEC4; + shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["USERDATA1"] = ShaderLanguage::TYPE_VEC4; + shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["USERDATA2"] = ShaderLanguage::TYPE_VEC4; + shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["USERDATA3"] = ShaderLanguage::TYPE_VEC4; + shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["USERDATA4"] = ShaderLanguage::TYPE_VEC4; + shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["USERDATA5"] = ShaderLanguage::TYPE_VEC4; + shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["USERDATA6"] = ShaderLanguage::TYPE_VEC4; shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["TRANSFORM"] = ShaderLanguage::TYPE_MAT4; shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["LIFETIME"] = constt(ShaderLanguage::TYPE_FLOAT); shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["DELTA"] = constt(ShaderLanguage::TYPE_FLOAT); |