summaryrefslogtreecommitdiff
path: root/servers/rendering
diff options
context:
space:
mode:
Diffstat (limited to 'servers/rendering')
-rw-r--r--servers/rendering/rasterizer_dummy.h32
-rw-r--r--servers/rendering/renderer_canvas_cull.cpp3
-rw-r--r--servers/rendering/renderer_canvas_cull.h2
-rw-r--r--servers/rendering/renderer_compositor.h3
-rw-r--r--servers/rendering/renderer_rd/cluster_builder_rd.cpp8
-rw-r--r--servers/rendering/renderer_rd/cluster_builder_rd.h2
-rw-r--r--servers/rendering/renderer_rd/effects_rd.cpp67
-rw-r--r--servers/rendering/renderer_rd/effects_rd.h28
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp158
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h23
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp98
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h23
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp28
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h6
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp17
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h4
-rw-r--r--servers/rendering/renderer_rd/pipeline_cache_rd.cpp6
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp23
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.h4
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.cpp6
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.h2
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp9
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_environment_rd.h9
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp34
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp968
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.h194
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp30
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_sky_rd.h4
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.cpp352
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.h56
-rw-r--r--servers/rendering/renderer_rd/shader_compiler_rd.cpp31
-rw-r--r--servers/rendering/renderer_rd/shader_rd.cpp3
-rw-r--r--servers/rendering/renderer_rd/shaders/canvas.glsl45
-rw-r--r--servers/rendering/renderer_rd/shaders/fsr_upscale.glsl173
-rw-r--r--servers/rendering/renderer_rd/shaders/particles.glsl10
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_aa_inc.glsl5
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl133
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl4
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl63
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl59
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl3
-rw-r--r--servers/rendering/renderer_rd/shaders/tonemap.glsl6
-rw-r--r--servers/rendering/renderer_rd/shaders/volumetric_fog.glsl755
-rw-r--r--servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl776
-rw-r--r--servers/rendering/renderer_scene.h10
-rw-r--r--servers/rendering/renderer_scene_cull.cpp276
-rw-r--r--servers/rendering/renderer_scene_cull.h50
-rw-r--r--servers/rendering/renderer_scene_render.cpp8
-rw-r--r--servers/rendering/renderer_scene_render.h15
-rw-r--r--servers/rendering/renderer_storage.h17
-rw-r--r--servers/rendering/renderer_viewport.cpp121
-rw-r--r--servers/rendering/renderer_viewport.h15
-rw-r--r--servers/rendering/rendering_device.cpp10
-rw-r--r--servers/rendering/rendering_device.h1
-rw-r--r--servers/rendering/rendering_device_binds.h2
-rw-r--r--servers/rendering/rendering_server_default.cpp26
-rw-r--r--servers/rendering/rendering_server_default.h36
-rw-r--r--servers/rendering/shader_language.cpp476
-rw-r--r--servers/rendering/shader_language.h14
-rw-r--r--servers/rendering/shader_types.cpp45
-rw-r--r--servers/rendering/shader_warnings.cpp4
-rw-r--r--servers/rendering/shader_warnings.h2
62 files changed, 3906 insertions, 1487 deletions
diff --git a/servers/rendering/rasterizer_dummy.h b/servers/rendering/rasterizer_dummy.h
index 7821210284..3451ea2d39 100644
--- a/servers/rendering/rasterizer_dummy.h
+++ b/servers/rendering/rasterizer_dummy.h
@@ -55,6 +55,9 @@ public:
void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) override {}
void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) override {}
void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) override {}
+ void geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) override {}
+ void geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) override {}
+ void geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) override {}
uint32_t geometry_instance_get_pair_mask() override { return 0; }
void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) override {}
@@ -125,7 +128,7 @@ public:
void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) override {}
void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) override {}
- void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount) override {}
+ void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) override {}
void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) override {}
void environment_set_volumetric_fog_filter_active(bool p_enable) override {}
@@ -152,6 +155,12 @@ public:
void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override {}
void light_instance_mark_visible(RID p_light_instance) override {}
+ RID fog_volume_instance_create(RID p_fog_volume) override { return RID(); }
+ void fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) override {}
+ void fog_volume_instance_set_active(RID p_fog_volume_instance, bool p_active) override {}
+ RID fog_volume_instance_get_volume(RID p_fog_volume_instance) const override { return RID(); }
+ Vector3 fog_volume_instance_get_position(RID p_fog_volume_instance) const override { return Vector3(); }
+
RID reflection_atlas_create() override { return RID(); }
int reflection_atlas_get_size(RID p_ref_atlas) const override { return 0; }
void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) override {}
@@ -177,7 +186,7 @@ public:
void voxel_gi_set_quality(RS::VoxelGIQuality) override {}
- void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_info = nullptr) override {}
+ void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_info = nullptr) override {}
void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override {}
void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) override {}
@@ -186,7 +195,7 @@ public:
void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) override {}
RID render_buffers_create() override { return RID(); }
- void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) override {}
+ void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) override {}
void gi_set_use_half_resolution(bool p_enable) override {}
void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_curve) override {}
@@ -249,7 +258,7 @@ public:
Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const override { return Ref<Image>(); }
Vector<Ref<Image>> texture_3d_get(RID p_texture) const override { return Vector<Ref<Image>>(); }
- void texture_replace(RID p_texture, RID p_by_texture) override {}
+ void texture_replace(RID p_texture, RID p_by_texture) override { free(p_by_texture); }
void texture_set_size_override(RID p_texture, int p_width, int p_height) override {}
void texture_set_path(RID p_texture, const String &p_path) override {}
@@ -284,8 +293,8 @@ public:
String shader_get_code(RID p_shader) const override { return ""; }
void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const override {}
- void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) override {}
- RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const override { return RID(); }
+ void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) override {}
+ RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const override { return RID(); }
Variant shader_get_param_default(RID p_material, const StringName &p_param) const override { return Variant(); }
RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const override { return RS::ShaderNativeSourceCode(); };
@@ -607,6 +616,17 @@ public:
void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) override {}
void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) override {}
+ /* FOG VOLUMES */
+
+ RID fog_volume_allocate() override { return RID(); }
+ void fog_volume_initialize(RID p_rid) override {}
+
+ void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) override {}
+ void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) override {}
+ void fog_volume_set_material(RID p_fog_volume, RID p_material) override {}
+ AABB fog_volume_get_aabb(RID p_fog_volume) const override { return AABB(); }
+ RS::FogVolumeShape fog_volume_get_shape(RID p_fog_volume) const override { return RS::FOG_VOLUME_SHAPE_BOX; }
+
/* VISIBILITY NOTIFIER */
virtual RID visibility_notifier_allocate() override { return RID(); }
virtual void visibility_notifier_initialize(RID p_notifier) override {}
diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp
index 46683e8e68..7b70483571 100644
--- a/servers/rendering/renderer_canvas_cull.cpp
+++ b/servers/rendering/renderer_canvas_cull.cpp
@@ -137,8 +137,7 @@ void RendererCanvasCull::_attach_canvas_item_for_draw(RendererCanvasCull::Item *
// We have two choices now, if user has drawn something, we must assume users wants to draw the "mask", so compute the size based on this.
// If nothing has been drawn, we just take it over and draw it ourselves.
- if (ci->canvas_group->fit_empty && (ci->commands == nullptr ||
- (ci->commands->next == nullptr && ci->commands->type == RendererCanvasCull::Item::Command::TYPE_RECT && (static_cast<RendererCanvasCull::Item::CommandRect *>(ci->commands)->flags & RendererCanvasRender::CANVAS_RECT_IS_GROUP)))) {
+ if (ci->canvas_group->fit_empty && (ci->commands == nullptr || (ci->commands->next == nullptr && ci->commands->type == RendererCanvasCull::Item::Command::TYPE_RECT && (static_cast<RendererCanvasCull::Item::CommandRect *>(ci->commands)->flags & RendererCanvasRender::CANVAS_RECT_IS_GROUP)))) {
// No commands, or sole command is the one used to draw, so we (re)create the draw command.
ci->clear();
diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h
index a2fdf95c76..bdd61123df 100644
--- a/servers/rendering/renderer_canvas_cull.h
+++ b/servers/rendering/renderer_canvas_cull.h
@@ -152,7 +152,7 @@ public:
void erase_item(Item *p_item) {
int idx = find_item(p_item);
if (idx >= 0) {
- child_items.remove(idx);
+ child_items.remove_at(idx);
}
}
diff --git a/servers/rendering/renderer_compositor.h b/servers/rendering/renderer_compositor.h
index 1971c3e781..4526354d17 100644
--- a/servers/rendering/renderer_compositor.h
+++ b/servers/rendering/renderer_compositor.h
@@ -67,6 +67,7 @@ private:
protected:
static RendererCompositor *(*_create_func)();
+ bool back_end = false;
public:
static RendererCompositor *create();
@@ -88,7 +89,7 @@ public:
virtual uint64_t get_frame_number() const = 0;
virtual double get_frame_delta_time() const = 0;
- virtual bool is_low_end() const = 0;
+ _FORCE_INLINE_ virtual bool is_low_end() const { return back_end; };
virtual bool is_xr_enabled() const;
RendererCompositor();
diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.cpp b/servers/rendering/renderer_rd/cluster_builder_rd.cpp
index b952ecbff0..4a98cf0831 100644
--- a/servers/rendering/renderer_rd/cluster_builder_rd.cpp
+++ b/servers/rendering/renderer_rd/cluster_builder_rd.cpp
@@ -460,14 +460,6 @@ void ClusterBuilderRD::bake_cluster() {
RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(ClusterBuilderSharedDataRD::ClusterRender::PushConstant));
uint32_t instances = 1;
-#if 0
- for (uint32_t j = i+1; j < element_count; j++) {
- if (elements[i].type!=elements[j].type) {
- break;
- }
- instances++;
- }
-#endif
RD::get_singleton()->draw_list_draw(draw_list, true, instances);
i += instances;
}
diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.h b/servers/rendering/renderer_rd/cluster_builder_rd.h
index c0c03eb26a..feafd4c2db 100644
--- a/servers/rendering/renderer_rd/cluster_builder_rd.h
+++ b/servers/rendering/renderer_rd/cluster_builder_rd.h
@@ -289,7 +289,7 @@ public:
e.touches_near = min_d < z_near;
} else {
//contains camera inside light
- Plane base_plane(xform.origin, -xform.basis.get_axis(Vector3::AXIS_Z));
+ Plane base_plane(-xform.basis.get_axis(Vector3::AXIS_Z), xform.origin);
float dist = base_plane.distance_to(Vector3());
if (dist >= 0 && dist < radius) {
//inside, check angle
diff --git a/servers/rendering/renderer_rd/effects_rd.cpp b/servers/rendering/renderer_rd/effects_rd.cpp
index c69408a30b..cf943901d4 100644
--- a/servers/rendering/renderer_rd/effects_rd.cpp
+++ b/servers/rendering/renderer_rd/effects_rd.cpp
@@ -237,6 +237,43 @@ RID EffectsRD::_get_compute_uniform_set_from_image_pair(RID p_texture1, RID p_te
return uniform_set;
}
+void EffectsRD::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) {
+ memset(&FSR_upscale.push_constant, 0, sizeof(FSRUpscalePushConstant));
+
+ int dispatch_x = (p_size.x + 15) / 16;
+ int dispatch_y = (p_size.y + 15) / 16;
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, FSR_upscale.pipeline);
+
+ FSR_upscale.push_constant.resolution_width = p_internal_size.width;
+ FSR_upscale.push_constant.resolution_height = p_internal_size.height;
+ FSR_upscale.push_constant.upscaled_width = p_size.width;
+ FSR_upscale.push_constant.upscaled_height = p_size.height;
+ FSR_upscale.push_constant.sharpness = p_fsr_upscale_sharpness;
+
+ //FSR Easc
+ FSR_upscale.push_constant.pass = FSR_UPSCALE_PASS_EASU;
+ 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_uniform_set_from_image(p_secondary_texture), 1);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &FSR_upscale.push_constant, sizeof(FSRUpscalePushConstant));
+
+ RD::get_singleton()->compute_list_dispatch(compute_list, dispatch_x, dispatch_y, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ //FSR Rcas
+ FSR_upscale.push_constant.pass = FSR_UPSCALE_PASS_RCAS;
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_secondary_texture), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_destination_texture), 1);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &FSR_upscale.push_constant, sizeof(FSRUpscalePushConstant));
+
+ RD::get_singleton()->compute_list_dispatch(compute_list, dispatch_x, dispatch_y, 1);
+
+ RD::get_singleton()->compute_list_end(compute_list);
+}
+
void EffectsRD::copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_uv_rect, RD::DrawListID p_draw_list, bool p_flip_y, bool p_panorama) {
memset(&copy_to_fb.push_constant, 0, sizeof(CopyToFbPushConstant));
@@ -443,7 +480,7 @@ void EffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_texture, RID p_back
RD::get_singleton()->compute_list_end();
}
-void EffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_treshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) {
+void EffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) {
ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the gaussian glow with the mobile renderer.");
memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
@@ -456,7 +493,7 @@ void EffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const
copy.push_constant.glow_strength = p_strength;
copy.push_constant.glow_bloom = p_bloom;
- copy.push_constant.glow_hdr_threshold = p_hdr_bleed_treshold;
+ copy.push_constant.glow_hdr_threshold = p_hdr_bleed_threshold;
copy.push_constant.glow_hdr_scale = p_hdr_bleed_scale;
copy.push_constant.glow_exposure = p_exposure;
copy.push_constant.glow_white = 0; //actually unused
@@ -479,7 +516,7 @@ void EffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const
RD::get_singleton()->compute_list_end();
}
-void EffectsRD::gaussian_glow_raster(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_treshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) {
+void EffectsRD::gaussian_glow_raster(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) {
ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of the gaussian glow with the clustered renderer.");
memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
@@ -492,7 +529,7 @@ void EffectsRD::gaussian_glow_raster(RID p_source_rd_texture, RID p_framebuffer_
blur_raster.push_constant.glow_strength = p_strength;
blur_raster.push_constant.glow_bloom = p_bloom;
- blur_raster.push_constant.glow_hdr_threshold = p_hdr_bleed_treshold;
+ blur_raster.push_constant.glow_hdr_threshold = p_hdr_bleed_threshold;
blur_raster.push_constant.glow_hdr_scale = p_hdr_bleed_scale;
blur_raster.push_constant.glow_exposure = p_exposure;
blur_raster.push_constant.glow_white = 0; //actually unused
@@ -1888,6 +1925,27 @@ void EffectsRD::sort_buffer(RID p_uniform_set, int p_size) {
}
EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
+ {
+ Vector<String> FSR_upscale_modes;
+
+#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+ // MoltenVK does not support some of the operations used by the normal mode of FSR. Fallback works just fine though.
+ FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n");
+#else
+ // Everyone else can use normal mode when available.
+ if (RD::get_singleton()->get_device_capabilities()->supports_fsr_half_float) {
+ FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_NORMAL\n");
+ } else {
+ FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n");
+ }
+#endif
+
+ FSR_upscale.shader.initialize(FSR_upscale_modes);
+
+ FSR_upscale.shader_version = FSR_upscale.shader.version_create();
+ FSR_upscale.pipeline = RD::get_singleton()->compute_pipeline_create(FSR_upscale.shader.version_get_shader(FSR_upscale.shader_version, 0));
+ }
+
prefer_raster_effects = p_prefer_raster_effects;
if (prefer_raster_effects) {
@@ -2523,6 +2581,7 @@ EffectsRD::~EffectsRD() {
RD::get_singleton()->free(index_buffer); //array gets freed as dependency
RD::get_singleton()->free(filter.coefficient_buffer);
+ FSR_upscale.shader.version_free(FSR_upscale.shader_version);
if (prefer_raster_effects) {
blur_raster.shader.version_free(blur_raster.shader_version);
bokeh.raster_shader.version_free(blur_raster.shader_version);
diff --git a/servers/rendering/renderer_rd/effects_rd.h b/servers/rendering/renderer_rd/effects_rd.h
index 0db0919dbc..6037127e82 100644
--- a/servers/rendering/renderer_rd/effects_rd.h
+++ b/servers/rendering/renderer_rd/effects_rd.h
@@ -45,6 +45,7 @@
#include "servers/rendering/renderer_rd/shaders/cubemap_filter_raster.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/cubemap_roughness.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/cubemap_roughness_raster.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/fsr_upscale.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/luminance_reduce.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/luminance_reduce_raster.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/resolve.glsl.gen.h"
@@ -69,6 +70,28 @@ class EffectsRD {
private:
bool prefer_raster_effects;
+ enum FSRUpscalePass {
+ FSR_UPSCALE_PASS_EASU = 0,
+ FSR_UPSCALE_PASS_RCAS = 1
+ };
+
+ struct FSRUpscalePushConstant {
+ float resolution_width;
+ float resolution_height;
+ float upscaled_width;
+ float upscaled_height;
+ float sharpness;
+ int pass;
+ int _unused0, _unused1;
+ };
+
+ struct FSRUpscale {
+ FSRUpscalePushConstant push_constant;
+ FsrUpscaleShaderRD shader;
+ RID shader_version;
+ RID pipeline;
+ } FSR_upscale;
+
enum BlurRasterMode {
BLUR_MIPMAP,
@@ -754,6 +777,7 @@ private:
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_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);
@@ -762,8 +786,8 @@ public:
void copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_uv_rect, RD::DrawListID p_draw_list, bool p_flip_y = false, bool p_panorama = false);
void gaussian_blur(RID p_source_rd_texture, RID p_texture, RID p_back_texture, const Rect2i &p_region, bool p_8bit_dst = false);
void set_color(RID p_dest_texture, const Color &p_color, const Rect2i &p_region, bool p_8bit_dst = false);
- void gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_treshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
- void gaussian_glow_raster(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_treshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
+ void gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
+ void gaussian_glow_raster(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
void cubemap_roughness(RID p_source_rd_texture, RID p_dest_texture, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size);
void cubemap_roughness_raster(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size);
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
index 6a3b9726da..03ce2690bf 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
@@ -328,10 +328,20 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
push_constant.uv_offset = 0;
}
+ bool should_request_redraw = false;
+
for (uint32_t i = p_from_element; i < p_to_element; i++) {
const GeometryInstanceSurfaceDataCache *surf = p_params->elements[i];
const RenderElementInfo &element_info = p_params->element_info[i];
+ if ((p_pass_mode == PASS_MODE_COLOR || p_pass_mode == PASS_MODE_COLOR_SPECULAR) && !(surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE)) {
+ continue; // Objects with "Depth-prepass" transparency are included in both render lists, but should only be rendered in the transparent pass
+ }
+
+ if (surf->owner->instance_count == 0) {
+ continue;
+ }
+
push_constant.base_index = i + p_params->element_offset;
RID material_uniform_set;
@@ -365,6 +375,11 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
continue;
}
+ //request a redraw if one of the shaders uses TIME
+ if (shader->uses_time) {
+ should_request_redraw = true;
+ }
+
//find cull variant
SceneShaderForwardClustered::ShaderData::CullVariant cull_variant;
@@ -381,7 +396,7 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
RS::PrimitiveType primitive = surf->primitive;
RID xforms_uniform_set = surf->owner->transforms_uniform_set;
- SceneShaderForwardClustered::ShaderVersion shader_version = SceneShaderForwardClustered::SHADER_VERSION_MAX; // Assigned to silence wrong -Wmaybe-initialized.
+ SceneShaderForwardClustered::PipelineVersion pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_MAX; // Assigned to silence wrong -Wmaybe-initialized.
uint32_t pipeline_specialization = 0;
@@ -399,48 +414,54 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
}
switch (p_pass_mode) {
- case PASS_MODE_COLOR:
+ case PASS_MODE_COLOR: {
+ if (element_info.uses_lightmap) {
+ pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS;
+ } else {
+ pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_OPAQUE_PASS;
+ }
+ } break;
case PASS_MODE_COLOR_TRANSPARENT: {
if (element_info.uses_lightmap) {
- shader_version = SceneShaderForwardClustered::SHADER_VERSION_LIGHTMAP_COLOR_PASS;
+ pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS;
} else {
if (element_info.uses_forward_gi) {
pipeline_specialization |= SceneShaderForwardClustered::SHADER_SPECIALIZATION_FORWARD_GI;
}
- shader_version = SceneShaderForwardClustered::SHADER_VERSION_COLOR_PASS;
+ pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_TRANSPARENT_PASS;
}
} break;
case PASS_MODE_COLOR_SPECULAR: {
if (element_info.uses_lightmap) {
- shader_version = SceneShaderForwardClustered::SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR;
+ pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS_WITH_SEPARATE_SPECULAR;
} else {
- shader_version = SceneShaderForwardClustered::SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR;
+ pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_OPAQUE_PASS_WITH_SEPARATE_SPECULAR;
}
} break;
case PASS_MODE_SHADOW:
case PASS_MODE_DEPTH: {
- shader_version = SceneShaderForwardClustered::SHADER_VERSION_DEPTH_PASS;
+ pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS;
} break;
case PASS_MODE_SHADOW_DP: {
- shader_version = SceneShaderForwardClustered::SHADER_VERSION_DEPTH_PASS_DP;
+ pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_DP;
} break;
case PASS_MODE_DEPTH_NORMAL_ROUGHNESS: {
- shader_version = SceneShaderForwardClustered::SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS;
+ pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS;
} break;
case PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI: {
- shader_version = SceneShaderForwardClustered::SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI;
+ pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI;
} break;
case PASS_MODE_DEPTH_MATERIAL: {
- shader_version = SceneShaderForwardClustered::SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL;
+ pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_WITH_MATERIAL;
} break;
case PASS_MODE_SDF: {
- shader_version = SceneShaderForwardClustered::SHADER_VERSION_DEPTH_PASS_WITH_SDF;
+ pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_WITH_SDF;
} break;
}
PipelineCacheRD *pipeline = nullptr;
- pipeline = &shader->pipelines[cull_variant][primitive][shader_version];
+ pipeline = &shader->pipelines[cull_variant][primitive][pipeline_version];
RD::VertexFormatID vertex_format = -1;
RID vertex_array_rd;
@@ -500,6 +521,11 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid(), instance_count);
i += element_info.repeat - 1; //skip equal elements
}
+
+ // Make the actual redraw request
+ if (should_request_redraw) {
+ RenderingServerDefault::redraw_request();
+ }
}
void RenderForwardClustered::_render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element) {
@@ -757,9 +783,6 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
scene_state.ubo.fog_density = environment_get_fog_density(p_render_data->environment);
scene_state.ubo.fog_height = environment_get_fog_height(p_render_data->environment);
scene_state.ubo.fog_height_density = environment_get_fog_height_density(p_render_data->environment);
- if (scene_state.ubo.fog_height_density >= 0.0001) {
- scene_state.ubo.fog_height_density = 1.0 / scene_state.ubo.fog_height_density;
- }
scene_state.ubo.fog_aerial_perspective = environment_get_fog_aerial_perspective(p_render_data->environment);
Color fog_color = environment_get_fog_light_color(p_render_data->environment).to_linear();
@@ -907,7 +930,7 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
}
uint32_t lightmap_captures_used = 0;
- Plane near_plane(p_render_data->cam_transform.origin, -p_render_data->cam_transform.basis.get_axis(Vector3::AXIS_Z));
+ Plane near_plane = Plane(-p_render_data->cam_transform.basis.get_axis(Vector3::AXIS_Z), p_render_data->cam_transform.origin);
near_plane.d += p_render_data->cam_projection.get_z_near();
float z_max = p_render_data->cam_projection.get_z_far() - p_render_data->cam_projection.get_z_near();
@@ -937,10 +960,23 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
}
bool uses_lightmap = false;
bool uses_gi = false;
+ float fade_alpha = 1.0;
+
+ if (inst->fade_near || inst->fade_far) {
+ float fade_dist = inst->transform.origin.distance_to(p_render_data->cam_transform.origin);
+ if (inst->fade_far && fade_dist > inst->fade_far_begin) {
+ fade_alpha = MAX(0.0, 1.0 - (fade_dist - inst->fade_far_begin) / (inst->fade_far_end - inst->fade_far_begin));
+ } else if (inst->fade_near && fade_dist < inst->fade_near_end) {
+ fade_alpha = MAX(0.0, (fade_dist - inst->fade_near_begin) / (inst->fade_near_end - inst->fade_near_begin));
+ }
+ }
- if (p_render_list == RENDER_LIST_OPAQUE) {
- //setup GI
+ fade_alpha *= inst->force_alpha * inst->parent_fade_alpha;
+ flags = (flags & ~INSTANCE_DATA_FLAGS_FADE_MASK) | (uint32_t(fade_alpha * 255.0) << INSTANCE_DATA_FLAGS_FADE_SHIFT);
+
+ if (p_render_list == RENDER_LIST_OPAQUE) {
+ // Setup GI
if (inst->lightmap_instance.is_valid()) {
int32_t lightmap_cull_index = -1;
for (uint32_t j = 0; j < scene_state.lightmaps_used; j++) {
@@ -1071,6 +1107,11 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
#else
bool force_alpha = false;
#endif
+
+ if (fade_alpha < 0.999) {
+ force_alpha = true;
+ }
+
if (!force_alpha && (surf->flags & (GeometryInstanceSurfaceDataCache::FLAG_PASS_DEPTH | GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE))) {
rl->add_element(surf);
}
@@ -1169,6 +1210,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
scene_state.ubo.viewport_size[0] = vp_he.x;
scene_state.ubo.viewport_size[1] = vp_he.y;
scene_state.ubo.directional_light_count = 0;
+ scene_state.ubo.opaque_prepass_threshold = 0.99f;
Size2i screen_size;
RID opaque_framebuffer;
@@ -1412,6 +1454,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
RD::get_singleton()->draw_command_begin_label("Render Opaque Pass");
scene_state.ubo.directional_light_count = p_render_data->directional_light_count;
+ scene_state.ubo.opaque_prepass_threshold = 0.0f;
_setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, p_render_data->render_buffers.is_valid());
@@ -1545,7 +1588,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
_setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false);
{
- RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), false, PASS_MODE_COLOR, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), false, PASS_MODE_COLOR_TRANSPARENT, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold);
_render_list_with_threads(&render_list_params, alpha_framebuffer, can_continue_color ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, can_continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ);
}
@@ -1595,6 +1638,7 @@ void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const Page
render_data.render_info = p_render_info;
scene_state.ubo.dual_paraboloid_side = p_use_dp_flip ? -1 : 1;
+ scene_state.ubo.opaque_prepass_threshold = 0.1f;
_setup_environment(&render_data, true, Vector2(1, 1), !p_flip_y, Color(), false, p_use_pancake, shadow_pass_index);
@@ -1681,6 +1725,7 @@ void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, con
_update_render_base_uniform_set();
scene_state.ubo.dual_paraboloid_side = 0;
+ scene_state.ubo.opaque_prepass_threshold = 0.0;
_setup_environment(&render_data, true, Vector2(1, 1), true, Color(), false, false);
@@ -1718,6 +1763,7 @@ void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform
scene_state.ubo.dual_paraboloid_side = 0;
scene_state.ubo.material_uv2_mode = false;
+ scene_state.ubo.opaque_prepass_threshold = 0.0f;
_setup_environment(&render_data, true, Vector2(1, 1), false, Color());
@@ -1761,6 +1807,7 @@ void RenderForwardClustered::_render_uv2(const PagedArray<GeometryInstance *> &p
scene_state.ubo.dual_paraboloid_side = 0;
scene_state.ubo.material_uv2_mode = true;
+ scene_state.ubo.opaque_prepass_threshold = 0.0;
_setup_environment(&render_data, true, Vector2(1, 1), false, Color());
@@ -1907,7 +1954,9 @@ void RenderForwardClustered::_base_uniforms_changed() {
}
void RenderForwardClustered::_update_render_base_uniform_set() {
- if (render_base_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set) || (lightmap_texture_array_version != storage->lightmap_array_get_version())) {
+ if (render_base_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set) || (lightmap_texture_array_version != storage->lightmap_array_get_version()) || base_uniform_set_updated) {
+ base_uniform_set_updated = false;
+
if (render_base_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) {
RD::get_singleton()->free(render_base_uniform_set);
}
@@ -1922,18 +1971,18 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
u.binding = 1;
u.ids.resize(12);
RID *ids_ptr = u.ids.ptrw();
- ids_ptr[0] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[1] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[2] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[3] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[4] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[5] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[6] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[7] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[8] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[9] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[10] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[11] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[0] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[1] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[2] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[3] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[4] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[5] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[6] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[7] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[8] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[9] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[10] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[11] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
uniforms.push_back(u);
}
@@ -1952,19 +2001,19 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
RID sampler;
switch (decals_get_filter()) {
case RS::DECAL_FILTER_NEAREST: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::DECAL_FILTER_NEAREST_MIPMAPS: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::DECAL_FILTER_LINEAR: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::DECAL_FILTER_LINEAR_MIPMAPS: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
}
@@ -1979,19 +2028,19 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
RID sampler;
switch (light_projectors_get_filter()) {
case RS::LIGHT_PROJECTOR_FILTER_NEAREST: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::LIGHT_PROJECTOR_FILTER_LINEAR: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
}
@@ -2881,6 +2930,29 @@ void RenderForwardClustered::geometry_instance_set_lod_bias(GeometryInstance *p_
ERR_FAIL_COND(!ginstance);
ginstance->lod_bias = p_lod_bias;
}
+void RenderForwardClustered::geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) {
+ GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
+ ERR_FAIL_COND(!ginstance);
+ ginstance->fade_near = p_enable_near;
+ ginstance->fade_near_begin = p_near_begin;
+ ginstance->fade_near_end = p_near_end;
+ ginstance->fade_far = p_enable_far;
+ ginstance->fade_far_begin = p_far_begin;
+ ginstance->fade_far_end = p_far_end;
+}
+
+void RenderForwardClustered::geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) {
+ GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
+ ERR_FAIL_COND(!ginstance);
+ ginstance->parent_fade_alpha = p_alpha;
+}
+
+void RenderForwardClustered::geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) {
+ GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
+ ERR_FAIL_COND(!ginstance);
+ ginstance->force_alpha = CLAMP(1.0 - p_transparency, 0, 1);
+}
+
void RenderForwardClustered::geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) {
GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
ERR_FAIL_COND(!ginstance);
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
index ff3d2fc6cb..d6ab4d1db2 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
@@ -129,6 +129,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
virtual void _base_uniforms_changed() override;
virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) override;
+ bool base_uniform_set_updated = false;
void _update_render_base_uniform_set();
RID _setup_sdfgi_render_pass_uniform_set(RID p_albedo_texture, RID p_emission_texture, RID p_emission_aniso_texture, RID p_geom_facing_texture);
RID _setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, bool p_use_directional_shadow_atlas = false, int p_index = 0);
@@ -208,6 +209,8 @@ class RenderForwardClustered : public RendererSceneRenderRD {
INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA = 1 << 15,
INSTANCE_DATA_FLAGS_PARTICLE_TRAIL_SHIFT = 16,
INSTANCE_DATA_FLAGS_PARTICLE_TRAIL_MASK = 0xFF,
+ INSTANCE_DATA_FLAGS_FADE_SHIFT = 24,
+ INSTANCE_DATA_FLAGS_FADE_MASK = 0xFF << INSTANCE_DATA_FLAGS_FADE_SHIFT
};
struct SceneState {
@@ -255,7 +258,8 @@ class RenderForwardClustered : public RendererSceneRenderRD {
float roughness_limiter_amount;
float roughness_limiter_limit;
- uint32_t roughness_limiter_pad[2];
+ float opaque_prepass_threshold;
+ uint32_t roughness_limiter_pad;
float sdf_to_bounds[16];
@@ -466,6 +470,15 @@ class RenderForwardClustered : public RendererSceneRenderRD {
bool can_sdfgi = false;
bool using_projectors = false;
bool using_softshadows = false;
+ bool fade_near = false;
+ float fade_near_begin = 0;
+ float fade_near_end = 0;
+ bool fade_far = false;
+ float fade_far_begin = 0;
+ float fade_far_end = 0;
+ float force_alpha = 1.0;
+ float parent_fade_alpha = 1.0;
+
//used during setup
uint32_t base_flags = 0;
Transform3D transform;
@@ -591,6 +604,11 @@ protected:
virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) override;
public:
+ _FORCE_INLINE_ virtual void update_uniform_sets() override {
+ base_uniform_set_updated = true;
+ _update_render_base_uniform_set();
+ }
+
virtual GeometryInstance *geometry_instance_create(RID p_base) override;
virtual void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override;
virtual void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override;
@@ -599,6 +617,9 @@ public:
virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) override;
virtual void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) override;
virtual void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) override;
+ virtual void geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) override;
+ virtual void geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) override;
+ virtual void geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) override;
virtual void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) override;
virtual void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) override;
virtual void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override;
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 a1c3481ed6..768bd1de9d 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
@@ -267,8 +267,26 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
RD::RenderPrimitive primitive_rd = uses_point_size ? RD::RENDER_PRIMITIVE_POINTS : primitive_rd_table[j];
- for (int k = 0; k < SHADER_VERSION_MAX; k++) {
- if (!static_cast<SceneShaderForwardClustered *>(singleton)->shader.is_variant_enabled(k)) {
+ for (int k = 0; k < PIPELINE_VERSION_MAX; k++) {
+ ShaderVersion shader_version;
+ static const ShaderVersion shader_version_table[PIPELINE_VERSION_MAX] = {
+ SHADER_VERSION_DEPTH_PASS,
+ SHADER_VERSION_DEPTH_PASS_DP,
+ SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS,
+ SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI,
+ SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL,
+ SHADER_VERSION_DEPTH_PASS_WITH_SDF,
+ SHADER_VERSION_COLOR_PASS,
+ SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR,
+ SHADER_VERSION_COLOR_PASS,
+ SHADER_VERSION_LIGHTMAP_COLOR_PASS,
+ SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR,
+ SHADER_VERSION_LIGHTMAP_COLOR_PASS,
+ };
+
+ shader_version = shader_version_table[k];
+
+ if (!static_cast<SceneShaderForwardClustered *>(singleton)->shader.is_variant_enabled(shader_version)) {
continue;
}
RD::PipelineRasterizationState raster_state;
@@ -279,8 +297,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
RD::PipelineDepthStencilState depth_stencil = depth_stencil_state;
RD::PipelineMultisampleState multisample_state;
- if (uses_alpha || uses_blend_alpha) {
- // only allow these flags to go through if we have some form of msaa
+ if (k == PIPELINE_VERSION_TRANSPARENT_PASS || k == PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS) {
if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE) {
multisample_state.enable_alpha_to_coverage = true;
} else if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE) {
@@ -288,43 +305,29 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
multisample_state.enable_alpha_to_one = true;
}
- if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS) {
- blend_state = blend_state_blend;
- if (depth_draw == DEPTH_DRAW_OPAQUE) {
- depth_stencil.enable_depth_write = false; //alpha does not draw depth
- }
- } else if (uses_depth_pre_pass && (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_DP || k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS || k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL)) {
- if (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_DP) {
- //none, blend state contains nothing
- } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL) {
- blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way
- } else {
- blend_state = blend_state_opaque; //writes to normal and roughness in opaque way
- }
- } else {
- pipelines[i][j][k].clear();
- continue; // do not use this version (will error if using it is attempted)
+ blend_state = blend_state_blend;
+
+ if (depth_draw == DEPTH_DRAW_OPAQUE) {
+ depth_stencil.enable_depth_write = false; //alpha does not draw depth
}
+ } else if (k == PIPELINE_VERSION_OPAQUE_PASS || k == PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS) {
+ blend_state = blend_state_opaque;
+ } else if (k == PIPELINE_VERSION_DEPTH_PASS || k == PIPELINE_VERSION_DEPTH_PASS_DP) {
+ //none, leave empty
+ } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS) {
+ blend_state = blend_state_depth_normal_roughness;
+ } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI) {
+ blend_state = blend_state_depth_normal_roughness_giprobe;
+ } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_MATERIAL) {
+ blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way
+ } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_SDF) {
+ blend_state = RD::PipelineColorBlendState(); //no color targets for SDF
} else {
- if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS) {
- blend_state = blend_state_opaque;
- } else if (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_DP) {
- //none, leave empty
- } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS) {
- blend_state = blend_state_depth_normal_roughness;
- } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI) {
- blend_state = blend_state_depth_normal_roughness_giprobe;
- } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL) {
- blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way
- } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_SDF) {
- blend_state = RD::PipelineColorBlendState(); //no color targets for SDF
- } else {
- //specular write
- blend_state = blend_state_opaque_specular;
- }
+ //specular write
+ blend_state = blend_state_opaque_specular;
}
- RID shader_variant = shader_singleton->shader.version_get_shader(version, k);
+ RID shader_variant = shader_singleton->shader.version_get_shader(version, shader_version);
pipelines[i][j][k].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0, singleton->default_specialization_constants);
}
}
@@ -333,11 +336,20 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
valid = true;
}
-void SceneShaderForwardClustered::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) {
+void SceneShaderForwardClustered::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
if (!p_texture.is_valid()) {
- default_texture_params.erase(p_name);
+ if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
+ default_texture_params[p_name].erase(p_index);
+
+ if (default_texture_params[p_name].is_empty()) {
+ default_texture_params.erase(p_name);
+ }
+ }
} else {
- default_texture_params[p_name] = p_texture;
+ if (!default_texture_params.has(p_name)) {
+ default_texture_params[p_name] = Map<int, RID>();
+ }
+ default_texture_params[p_name][p_index] = p_texture;
}
}
@@ -573,6 +585,7 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
actions.renames["CUSTOM1"] = "custom1_attrib";
actions.renames["CUSTOM2"] = "custom2_attrib";
actions.renames["CUSTOM3"] = "custom3_attrib";
+ actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB";
// not implemented but need these just in case code is in the shaders
actions.renames["VIEW_INDEX"] = "0";
@@ -637,6 +650,7 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
actions.render_mode_defines["cull_front"] = "#define DO_SIDE_CHECK\n";
actions.render_mode_defines["cull_disabled"] = "#define DO_SIDE_CHECK\n";
actions.render_mode_defines["particle_trails"] = "#define USE_PARTICLE_TRAILS\n";
+ actions.render_mode_defines["depth_draw_opaque"] = "#define USE_OPAQUE_PREPASS\n";
bool force_lambert = GLOBAL_GET("rendering/shading/overrides/force_lambert_over_burley");
@@ -657,6 +671,10 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
actions.render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_BLINN\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";
diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
index 09ef425e2e..f2a55939f4 100644
--- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
@@ -55,10 +55,25 @@ public:
SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR,
SHADER_VERSION_LIGHTMAP_COLOR_PASS,
SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR,
-
SHADER_VERSION_MAX
};
+ enum PipelineVersion {
+ PIPELINE_VERSION_DEPTH_PASS,
+ PIPELINE_VERSION_DEPTH_PASS_DP,
+ PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS,
+ PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI,
+ PIPELINE_VERSION_DEPTH_PASS_WITH_MATERIAL,
+ PIPELINE_VERSION_DEPTH_PASS_WITH_SDF,
+ PIPELINE_VERSION_OPAQUE_PASS,
+ PIPELINE_VERSION_OPAQUE_PASS_WITH_SEPARATE_SPECULAR,
+ PIPELINE_VERSION_TRANSPARENT_PASS,
+ PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS,
+ PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS_WITH_SEPARATE_SPECULAR,
+ PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS,
+ PIPELINE_VERSION_MAX
+ };
+
enum ShaderSpecializations {
SHADER_SPECIALIZATION_FORWARD_GI = 1 << 0,
SHADER_SPECIALIZATION_PROJECTOR = 1 << 1,
@@ -109,7 +124,7 @@ public:
bool valid;
RID version;
uint32_t vertex_input_mask;
- PipelineCacheRD pipelines[CULL_VARIANT_MAX][RS::PRIMITIVE_MAX][SHADER_VERSION_MAX];
+ PipelineCacheRD pipelines[CULL_VARIANT_MAX][RS::PRIMITIVE_MAX][PIPELINE_VERSION_MAX];
String path;
@@ -120,7 +135,7 @@ public:
uint32_t ubo_size;
String code;
- Map<StringName, RID> default_texture_params;
+ Map<StringName, Map<int, RID>> default_texture_params;
DepthDraw depth_draw;
DepthTest depth_test;
@@ -151,7 +166,7 @@ public:
uint32_t index = 0;
virtual void set_code(const String &p_Code);
- virtual void set_default_texture_param(const StringName &p_name, RID p_texture);
+ virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
index 6937df85fb..445623fb86 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -483,6 +483,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
scene_state.ubo.viewport_size[0] = vp_he.x;
scene_state.ubo.viewport_size[1] = vp_he.y;
scene_state.ubo.directional_light_count = 0;
+ scene_state.ubo.opaque_prepass_threshold = 0.0;
// We can only use our full subpass approach if we're:
// - not reading from SCREEN_TEXTURE/DEPTH_TEXTURE
@@ -793,7 +794,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
if (using_subpass_transparent) {
RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer);
- RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, spec_constant_base_flags, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold, p_render_data->view_count);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, PASS_MODE_COLOR_TRANSPARENT, rp_uniform_set, spec_constant_base_flags, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold, p_render_data->view_count);
render_list_params.framebuffer_format = fb_format;
if ((uint32_t)render_list_params.element_count > render_list_thread_threshold && false) {
// secondary command buffers need more testing at this time
@@ -897,6 +898,7 @@ void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedAr
render_data.lod_distance_multiplier = p_lod_distance_multiplier;
scene_state.ubo.dual_paraboloid_side = p_use_dp_flip ? -1 : 1;
+ scene_state.ubo.opaque_prepass_threshold = 0.1;
_setup_environment(&render_data, true, Vector2(1, 1), !p_flip_y, Color(), false, p_use_pancake, shadow_pass_index);
@@ -978,6 +980,7 @@ void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, c
scene_state.ubo.dual_paraboloid_side = 0;
scene_state.ubo.material_uv2_mode = false;
+ scene_state.ubo.opaque_prepass_threshold = 0.0f;
RenderDataRD render_data;
render_data.cam_projection = p_cam_projection;
@@ -1089,6 +1092,7 @@ void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const
_update_render_base_uniform_set();
scene_state.ubo.dual_paraboloid_side = 0;
+ scene_state.ubo.opaque_prepass_threshold = 0.0;
RenderDataRD render_data;
render_data.cam_projection = p_cam_projection;
@@ -1322,7 +1326,7 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const
}
uint32_t lightmap_captures_used = 0;
- Plane near_plane(p_render_data->cam_transform.origin, -p_render_data->cam_transform.basis.get_axis(Vector3::AXIS_Z));
+ Plane near_plane(-p_render_data->cam_transform.basis.get_axis(Vector3::AXIS_Z), p_render_data->cam_transform.origin);
near_plane.d += p_render_data->cam_projection.get_z_near();
float z_max = p_render_data->cam_projection.get_z_far() - p_render_data->cam_projection.get_z_near();
@@ -1447,13 +1451,13 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const
}
// ADD Element
- if (p_pass_mode == PASS_MODE_COLOR) {
+ if (p_pass_mode == PASS_MODE_COLOR || p_pass_mode == PASS_MODE_COLOR_TRANSPARENT) {
#ifdef DEBUG_ENABLED
bool force_alpha = unlikely(get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_OVERDRAW);
#else
bool force_alpha = false;
#endif
- if (!force_alpha && (surf->flags & (GeometryInstanceSurfaceDataCache::FLAG_PASS_DEPTH | GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE))) {
+ if (!force_alpha && (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE)) {
rl->add_element(surf);
}
if (force_alpha || (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_ALPHA)) {
@@ -1637,9 +1641,6 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data,
scene_state.ubo.fog_density = environment_get_fog_density(p_render_data->environment);
scene_state.ubo.fog_height = environment_get_fog_height(p_render_data->environment);
scene_state.ubo.fog_height_density = environment_get_fog_height_density(p_render_data->environment);
- if (scene_state.ubo.fog_height_density >= 0.0001) {
- scene_state.ubo.fog_height_density = 1.0 / scene_state.ubo.fog_height_density;
- }
scene_state.ubo.fog_aerial_perspective = environment_get_fog_aerial_perspective(p_render_data->environment);
Color fog_color = environment_get_fog_light_color(p_render_data->environment).to_linear();
@@ -1824,6 +1825,10 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
const RenderElementInfo &element_info = p_params->element_info[i];
const GeometryInstanceForwardMobile *inst = surf->owner;
+ if (inst->instance_count == 0) {
+ continue;
+ }
+
uint32_t base_spec_constants = p_params->spec_constant_base_flags;
// GeometryInstanceForwardMobile::PushConstant push_constant = inst->push_constant;
@@ -2075,6 +2080,15 @@ void RenderForwardMobile::geometry_instance_set_lod_bias(GeometryInstance *p_geo
ginstance->lod_bias = p_lod_bias;
}
+void RenderForwardMobile::geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) {
+}
+
+void RenderForwardMobile::geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) {
+}
+
+void RenderForwardMobile::geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) {
+}
+
void RenderForwardMobile::geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) {
GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
ERR_FAIL_COND(!ginstance);
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
index 36a92e1464..485d08b589 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
@@ -292,7 +292,8 @@ protected:
float roughness_limiter_amount;
float roughness_limiter_limit;
- uint32_t roughness_limiter_pad[2];
+ float opaque_prepass_threshold;
+ uint32_t roughness_limiter_pad;
// Fog
uint32_t fog_enabled;
@@ -632,6 +633,9 @@ public:
virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) override;
virtual void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) override;
virtual void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) override;
+ virtual void geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) override;
+ virtual void geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) override;
+ virtual void geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) override;
virtual void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) override;
virtual void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) override;
virtual void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override;
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 16d650a540..e6d9a60f94 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
@@ -325,11 +325,20 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
valid = true;
}
-void SceneShaderForwardMobile::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) {
+void SceneShaderForwardMobile::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
if (!p_texture.is_valid()) {
- default_texture_params.erase(p_name);
+ if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
+ default_texture_params[p_name].erase(p_index);
+
+ if (default_texture_params[p_name].is_empty()) {
+ default_texture_params.erase(p_name);
+ }
+ }
} else {
- default_texture_params[p_name] = p_texture;
+ if (!default_texture_params.has(p_name)) {
+ default_texture_params[p_name] = Map<int, RID>();
+ }
+ default_texture_params[p_name][p_index] = p_texture;
}
}
@@ -564,6 +573,7 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
actions.renames["CUSTOM1"] = "custom1_attrib";
actions.renames["CUSTOM2"] = "custom2_attrib";
actions.renames["CUSTOM3"] = "custom3_attrib";
+ actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB";
actions.renames["VIEW_INDEX"] = "ViewIndex";
actions.renames["VIEW_MONO_LEFT"] = "0";
@@ -627,6 +637,7 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
actions.render_mode_defines["cull_front"] = "#define DO_SIDE_CHECK\n";
actions.render_mode_defines["cull_disabled"] = "#define DO_SIDE_CHECK\n";
actions.render_mode_defines["particle_trails"] = "#define USE_PARTICLE_TRAILS\n";
+ actions.render_mode_defines["depth_draw_opaque"] = "#define USE_OPAQUE_PREPASS\n";
bool force_lambert = GLOBAL_GET("rendering/shading/overrides/force_lambert_over_burley");
if (!force_lambert) {
diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
index e1c10f0206..392fac1e3e 100644
--- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
@@ -111,7 +111,7 @@ public:
uint32_t ubo_size;
String code;
- Map<StringName, RID> default_texture_params;
+ Map<StringName, Map<int, RID>> default_texture_params;
DepthDraw depth_draw;
DepthTest depth_test;
@@ -141,7 +141,7 @@ public:
uint32_t index = 0;
virtual void set_code(const String &p_Code);
- virtual void set_default_texture_param(const StringName &p_name, RID p_texture);
+ virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
diff --git a/servers/rendering/renderer_rd/pipeline_cache_rd.cpp b/servers/rendering/renderer_rd/pipeline_cache_rd.cpp
index aefe926cb0..0d60052666 100644
--- a/servers/rendering/renderer_rd/pipeline_cache_rd.cpp
+++ b/servers/rendering/renderer_rd/pipeline_cache_rd.cpp
@@ -35,8 +35,10 @@ RID PipelineCacheRD::_generate_version(RD::VertexFormatID p_vertex_format_id, RD
RD::PipelineMultisampleState multisample_state_version = multisample_state;
multisample_state_version.sample_count = RD::get_singleton()->framebuffer_format_get_texture_samples(p_framebuffer_format_id, p_render_pass);
+ bool wireframe = p_wireframe || rasterization_state.wireframe;
+
RD::PipelineRasterizationState raster_state_version = rasterization_state;
- raster_state_version.wireframe = p_wireframe;
+ raster_state_version.wireframe = wireframe;
Vector<RD::PipelineSpecializationConstant> specialization_constants = base_specialization_constants;
@@ -59,7 +61,7 @@ RID PipelineCacheRD::_generate_version(RD::VertexFormatID p_vertex_format_id, RD
versions = (Version *)memrealloc(versions, sizeof(Version) * (version_count + 1));
versions[version_count].framebuffer_id = p_framebuffer_format_id;
versions[version_count].vertex_id = p_vertex_format_id;
- versions[version_count].wireframe = p_wireframe;
+ versions[version_count].wireframe = wireframe;
versions[version_count].pipeline = pipeline;
versions[version_count].render_pass = p_render_pass;
versions[version_count].bool_specializations = p_bool_specializations;
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
index c69c9eeadf..d013099cce 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "renderer_canvas_render_rd.h"
+
#include "core/config/project_settings.h"
#include "core/math/geometry_2d.h"
#include "core/math/math_defs.h"
@@ -757,6 +758,10 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
instance_count = storage->multimesh_get_instances_to_draw(multimesh);
+ if (instance_count == 0) {
+ break;
+ }
+
RID uniform_set = storage->multimesh_get_2d_uniform_set(multimesh, shader.default_version_rd_shader, TRANSFORMS_UNIFORM_SET);
RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, uniform_set, TRANSFORMS_UNIFORM_SET);
push_constant.flags |= 1; //multimesh, trails disabled
@@ -1585,9 +1590,6 @@ void RendererCanvasRenderRD::light_update_shadow(RID p_rid, int p_shadow_index,
push_constant.z_far = p_far;
push_constant.pad = 0;
- /*if (i == 0)
- *p_xform_cache = projection;*/
-
LightOccluderInstance *instance = p_occluders;
while (instance) {
@@ -2122,11 +2124,20 @@ void RendererCanvasRenderRD::ShaderData::set_code(const String &p_code) {
valid = true;
}
-void RendererCanvasRenderRD::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) {
+void RendererCanvasRenderRD::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
if (!p_texture.is_valid()) {
- default_texture_params.erase(p_name);
+ if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
+ default_texture_params[p_name].erase(p_index);
+
+ if (default_texture_params[p_name].is_empty()) {
+ default_texture_params.erase(p_name);
+ }
+ }
} else {
- default_texture_params[p_name] = p_texture;
+ if (!default_texture_params.has(p_name)) {
+ default_texture_params[p_name] = Map<int, RID>();
+ }
+ default_texture_params[p_name][p_index] = p_texture;
}
}
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
index ec7d7e2854..26ccbd3bf5 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
@@ -173,14 +173,14 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
uint32_t ubo_size;
String code;
- Map<StringName, RID> default_texture_params;
+ Map<StringName, Map<int, RID>> default_texture_params;
bool uses_screen_texture = false;
bool uses_sdf = false;
bool uses_time = false;
virtual void set_code(const String &p_Code);
- virtual void set_default_texture_param(const StringName &p_name, RID p_texture);
+ virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
index 559e6d5ad7..522a8e8112 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
@@ -281,12 +281,12 @@ RendererCompositorRD::RendererCompositorRD() {
storage = memnew(RendererStorageRD);
canvas = memnew(RendererCanvasRenderRD(storage));
- uint32_t back_end = GLOBAL_GET("rendering/vulkan/rendering/back_end");
+ back_end = (bool)(int)GLOBAL_GET("rendering/vulkan/rendering/back_end");
uint32_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE);
- if (back_end == 1 || textures_per_stage < 48) {
+ if (back_end || textures_per_stage < 48) {
scene = memnew(RendererSceneRenderImplementation::RenderForwardMobile(storage));
- } else { // back_end == 0
+ } else { // back_end == false
// default to our high end renderer
scene = memnew(RendererSceneRenderImplementation::RenderForwardClustered(storage));
}
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h
index 0230c46800..f69e40e0ff 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.h
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h
@@ -116,8 +116,6 @@ public:
_create_func = _create_current;
}
- virtual bool is_low_end() const { return false; }
-
static RendererCompositorRD *singleton;
RendererCompositorRD();
~RendererCompositorRD();
diff --git a/servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp
index bb7fbbcdc2..550e59ba98 100644
--- a/servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp
@@ -92,16 +92,19 @@ void RendererSceneEnvironmentRD::set_fog(bool p_enable, const Color &p_light_col
fog_aerial_perspective = p_fog_aerial_perspective;
}
-void RendererSceneEnvironmentRD::set_volumetric_fog(bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount) {
+void RendererSceneEnvironmentRD::set_volumetric_fog(bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) {
volumetric_fog_enabled = p_enable;
volumetric_fog_density = p_density;
- volumetric_fog_light = p_light;
- volumetric_fog_light_energy = p_light_energy;
+ volumetric_fog_scattering = p_albedo;
+ volumetric_fog_emission = p_emission;
+ volumetric_fog_emission_energy = p_emission_energy;
+ volumetric_fog_anisotropy = p_anisotropy,
volumetric_fog_length = p_length;
volumetric_fog_detail_spread = p_detail_spread;
volumetric_fog_gi_inject = p_gi_inject;
volumetric_fog_temporal_reprojection = p_temporal_reprojection;
volumetric_fog_temporal_reprojection_amount = p_temporal_reprojection_amount;
+ volumetric_fog_ambient_inject = p_ambient_inject;
}
void RendererSceneEnvironmentRD::set_ssr(bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) {
diff --git a/servers/rendering/renderer_rd/renderer_scene_environment_rd.h b/servers/rendering/renderer_rd/renderer_scene_environment_rd.h
index bc47abbff5..ec9cb4a798 100644
--- a/servers/rendering/renderer_rd/renderer_scene_environment_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_environment_rd.h
@@ -79,13 +79,16 @@ public:
///
bool volumetric_fog_enabled = false;
float volumetric_fog_density = 0.01;
- Color volumetric_fog_light = Color(0, 0, 0);
- float volumetric_fog_light_energy = 0.0;
+ Color volumetric_fog_scattering = Color(1, 1, 1);
+ Color volumetric_fog_emission = Color(0, 0, 0);
+ float volumetric_fog_emission_energy = 0.0;
+ float volumetric_fog_anisotropy = 0.2;
float volumetric_fog_length = 64.0;
float volumetric_fog_detail_spread = 2.0;
float volumetric_fog_gi_inject = 0.0;
bool volumetric_fog_temporal_reprojection = true;
float volumetric_fog_temporal_reprojection_amount = 0.9;
+ float volumetric_fog_ambient_inject = 0.0;
/// Glow
@@ -146,7 +149,7 @@ public:
void set_glow(bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap);
void set_sdfgi(bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias);
void set_fog(bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_fog_aerial_perspective);
- void set_volumetric_fog(bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount);
+ void set_volumetric_fog(bool p_enable, float p_density, const Color &p_scatterin, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject);
void set_ssr(bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance);
void set_ssao(bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect);
};
diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp
index ea73dbf26e..5acb1cb99c 100644
--- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp
@@ -1305,7 +1305,6 @@ void RendererSceneGIRD::SDFGI::debug_probes(RD::DrawListID p_draw_list, RID p_fr
RD::get_singleton()->draw_list_draw(p_draw_list, false, total_probes, total_points);
if (gi->sdfgi_debug_probe_dir != Vector3()) {
- print_line("CLICK DEBUG ME?");
uint32_t cascade = 0;
Vector3 offset = Vector3((Vector3i(1, 1, 1) * -int32_t(cascade_size >> 1) + cascades[cascade].position)) * cascades[cascade].cell_size * Vector3(1.0, 1.0 / y_mult, 1.0);
Vector3 probe_size = cascades[cascade].cell_size * (cascade_size / SDFGI::PROBE_DIVISOR) * Vector3(1.0, 1.0 / y_mult, 1.0);
@@ -1333,11 +1332,6 @@ void RendererSceneGIRD::SDFGI::debug_probes(RD::DrawListID p_draw_list, RID p_fr
}
}
- if (gi->sdfgi_debug_probe_enabled) {
- print_line("found: " + gi->sdfgi_debug_probe_index);
- } else {
- print_line("no found");
- }
gi->sdfgi_debug_probe_dir = Vector3();
}
@@ -3098,12 +3092,14 @@ void RendererSceneGIRD::setup_voxel_gi_instances(RID p_render_buffers, const Tra
}
rb->gi.uniform_set = RID();
if (rb->volumetric_fog) {
- if (RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->uniform_set)) {
- RD::get_singleton()->free(rb->volumetric_fog->uniform_set);
- RD::get_singleton()->free(rb->volumetric_fog->uniform_set2);
+ if (RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->fog_uniform_set)) {
+ RD::get_singleton()->free(rb->volumetric_fog->fog_uniform_set);
+ RD::get_singleton()->free(rb->volumetric_fog->process_uniform_set);
+ RD::get_singleton()->free(rb->volumetric_fog->process_uniform_set2);
}
- rb->volumetric_fog->uniform_set = RID();
- rb->volumetric_fog->uniform_set2 = RID();
+ rb->volumetric_fog->fog_uniform_set = RID();
+ rb->volumetric_fog->process_uniform_set = RID();
+ rb->volumetric_fog->process_uniform_set2 = RID();
}
}
@@ -3130,8 +3126,8 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_
RD::TextureFormat tf;
tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- tf.width = rb->width;
- tf.height = rb->height;
+ tf.width = rb->internal_width;
+ tf.height = rb->internal_height;
if (half_resolution) {
tf.width >>= 1;
tf.height >>= 1;
@@ -3144,13 +3140,13 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_
PushConstant push_constant;
- push_constant.screen_size[0] = rb->width;
- push_constant.screen_size[1] = rb->height;
+ push_constant.screen_size[0] = rb->internal_width;
+ push_constant.screen_size[1] = rb->internal_height;
push_constant.z_near = p_projection.get_z_near();
push_constant.z_far = p_projection.get_z_far();
push_constant.orthogonal = p_projection.is_orthogonal();
- push_constant.proj_info[0] = -2.0f / (rb->width * p_projection.matrix[0][0]);
- push_constant.proj_info[1] = -2.0f / (rb->height * p_projection.matrix[1][1]);
+ push_constant.proj_info[0] = -2.0f / (rb->internal_width * p_projection.matrix[0][0]);
+ push_constant.proj_info[1] = -2.0f / (rb->internal_height * p_projection.matrix[1][1]);
push_constant.proj_info[2] = (1.0f - p_projection.matrix[0][2]) / p_projection.matrix[0][0];
push_constant.proj_info[3] = (1.0f + p_projection.matrix[1][2]) / p_projection.matrix[1][1];
push_constant.max_voxel_gi_instances = MIN((uint64_t)MAX_VOXEL_GI_INSTANCES, p_voxel_gi_instances.size());
@@ -3342,9 +3338,9 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant));
if (rb->gi.using_half_size_gi) {
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->width >> 1, rb->height >> 1, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->internal_width >> 1, rb->internal_height >> 1, 1);
} else {
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->width, rb->height, 1);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->internal_width, rb->internal_height, 1);
}
//do barrier later to allow oeverlap
//RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER); //no barriers, let other compute, raster and transfer happen at the same time
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index bd8e950e70..ae8d91a73b 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -365,7 +365,7 @@ float RendererSceneRenderRD::environment_get_fog_aerial_perspective(RID p_env) c
return env->fog_aerial_perspective;
}
-void RendererSceneRenderRD::environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount) {
+void RendererSceneRenderRD::environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) {
RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
ERR_FAIL_COND(!env);
@@ -373,7 +373,7 @@ void RendererSceneRenderRD::environment_set_volumetric_fog(RID p_env, bool p_ena
return;
}
- env->set_volumetric_fog(p_enable, p_density, p_light, p_light_energy, p_length, p_detail_spread, p_gi_inject, p_temporal_reprojection, p_temporal_reprojection_amount);
+ env->set_volumetric_fog(p_enable, p_density, p_albedo, p_emission, p_emission_energy, p_anisotropy, p_length, p_detail_spread, p_gi_inject, p_temporal_reprojection, p_temporal_reprojection_amount, p_ambient_inject);
}
void RendererSceneRenderRD::environment_set_volumetric_fog_volume_size(int p_size, int p_depth) {
@@ -499,6 +499,37 @@ Ref<Image> RendererSceneRenderRD::environment_bake_panorama(RID p_env, bool p_ba
////////////////////////////////////////////////////////////
+RID RendererSceneRenderRD::fog_volume_instance_create(RID p_fog_volume) {
+ FogVolumeInstance fvi;
+ fvi.volume = p_fog_volume;
+ return fog_volume_instance_owner.make_rid(fvi);
+}
+void RendererSceneRenderRD::fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) {
+ FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance);
+ ERR_FAIL_COND(!fvi);
+ fvi->transform = p_transform;
+}
+void RendererSceneRenderRD::fog_volume_instance_set_active(RID p_fog_volume_instance, bool p_active) {
+ FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance);
+ ERR_FAIL_COND(!fvi);
+ fvi->active = p_active;
+}
+
+RID RendererSceneRenderRD::fog_volume_instance_get_volume(RID p_fog_volume_instance) const {
+ FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance);
+ ERR_FAIL_COND_V(!fvi, RID());
+ return fvi->volume;
+}
+
+Vector3 RendererSceneRenderRD::fog_volume_instance_get_position(RID p_fog_volume_instance) const {
+ FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance);
+ ERR_FAIL_COND_V(!fvi, Vector3());
+
+ return fvi->transform.get_origin();
+}
+
+////////////////////////////////////////////////////////////
+
RID RendererSceneRenderRD::reflection_atlas_create() {
ReflectionAtlas ra;
ra.count = GLOBAL_GET("rendering/reflections/reflection_atlas/reflection_count");
@@ -1472,8 +1503,8 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) {
RD::TextureFormat tf;
tf.format = _render_buffers_get_color_format(); // RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- tf.width = rb->width;
- tf.height = rb->height;
+ tf.width = rb->internal_width;
+ tf.height = rb->internal_height;
tf.texture_type = rb->view_count > 1 ? RD::TEXTURE_TYPE_2D_ARRAY : RD::TEXTURE_TYPE_2D;
tf.array_layers = rb->view_count;
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
@@ -1484,6 +1515,10 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) {
}
tf.mipmaps = mipmaps_required;
+ rb->sss_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
+
+ tf.width = rb->internal_width;
+ tf.height = rb->internal_height;
rb->blur[0].texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
//the second one is smaller (only used for separatable part of blur)
tf.width >>= 1;
@@ -1491,8 +1526,8 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) {
tf.mipmaps--;
rb->blur[1].texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
- int base_width = rb->width;
- int base_height = rb->height;
+ int base_width = rb->internal_width;
+ int base_height = rb->internal_height;
for (uint32_t i = 0; i < mipmaps_required; i++) {
RenderBuffers::Blur::Mipmap mm;
@@ -1546,8 +1581,8 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) {
// create 4 weight textures, 2 full size, 2 half size
tf.format = RD::DATA_FORMAT_R16_SFLOAT; // We could probably use DATA_FORMAT_R8_SNORM if we don't pre-multiply by blur_size but that depends on whether we can remove DEPTH_GAP
- tf.width = rb->width;
- tf.height = rb->height;
+ tf.width = rb->internal_width;
+ tf.height = rb->internal_height;
tf.texture_type = rb->view_count > 1 ? RD::TEXTURE_TYPE_2D_ARRAY : RD::TEXTURE_TYPE_2D;
tf.array_layers = rb->view_count;
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
@@ -1625,8 +1660,8 @@ void RendererSceneRenderRD::_allocate_depth_backbuffer_textures(RenderBuffers *r
void RendererSceneRenderRD::_allocate_luminance_textures(RenderBuffers *rb) {
ERR_FAIL_COND(!rb->luminance.current.is_null());
- int w = rb->width;
- int h = rb->height;
+ int w = rb->internal_width;
+ int h = rb->internal_height;
while (true) {
w = MAX(w / 8, 1);
@@ -1678,9 +1713,26 @@ void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) {
rb->texture_fb = RID();
}
- if (rb->texture.is_valid()) {
- RD::get_singleton()->free(rb->texture);
+ if (rb->internal_texture == rb->texture && rb->internal_texture.is_valid()) {
+ RD::get_singleton()->free(rb->internal_texture);
rb->texture = RID();
+ rb->internal_texture = RID();
+ rb->upscale_texture = RID();
+ } else {
+ if (rb->texture.is_valid()) {
+ RD::get_singleton()->free(rb->texture);
+ rb->texture = RID();
+ }
+
+ if (rb->internal_texture.is_valid()) {
+ RD::get_singleton()->free(rb->internal_texture);
+ rb->internal_texture = RID();
+ }
+
+ if (rb->upscale_texture.is_valid()) {
+ RD::get_singleton()->free(rb->upscale_texture);
+ rb->upscale_texture = RID();
+ }
}
if (rb->depth_texture.is_valid()) {
@@ -1698,6 +1750,11 @@ void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) {
rb->depth_back_texture = RID();
}
+ if (rb->sss_texture.is_valid()) {
+ RD::get_singleton()->free(rb->sss_texture);
+ rb->sss_texture = RID();
+ }
+
for (int i = 0; i < 2; i++) {
for (int m = 0; m < rb->blur[i].mipmaps.size(); m++) {
// do we free the texture slice here? or is it enough to free the main texture?
@@ -1787,7 +1844,7 @@ void RendererSceneRenderRD::_process_sss(RID p_render_buffers, const CameraMatri
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb);
- bool can_use_effects = rb->width >= 8 && rb->height >= 8;
+ bool can_use_effects = rb->internal_width >= 8 && rb->internal_height >= 8;
if (!can_use_effects) {
//just copy
@@ -1798,18 +1855,18 @@ void RendererSceneRenderRD::_process_sss(RID p_render_buffers, const CameraMatri
_allocate_blur_textures(rb);
}
- storage->get_effects()->sub_surface_scattering(rb->texture, rb->blur[0].mipmaps[0].texture, rb->depth_texture, p_camera, Size2i(rb->width, rb->height), sss_scale, sss_depth_scale, sss_quality);
+ storage->get_effects()->sub_surface_scattering(rb->internal_texture, rb->sss_texture, rb->depth_texture, p_camera, Size2i(rb->internal_width, rb->internal_height), sss_scale, sss_depth_scale, sss_quality);
}
void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_framebuffer, RID p_normal_buffer, RID p_specular_buffer, RID p_metallic, const Color &p_metallic_mask, RID p_environment, const CameraMatrix &p_projection, bool p_use_additive) {
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb);
- bool can_use_effects = rb->width >= 8 && rb->height >= 8;
+ bool can_use_effects = rb->internal_width >= 8 && rb->internal_height >= 8;
if (!can_use_effects) {
//just copy
- storage->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->texture, RID());
+ storage->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, RID());
return;
}
@@ -1821,8 +1878,8 @@ void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_frameb
if (rb->ssr.depth_scaled.is_null()) {
RD::TextureFormat tf;
tf.format = RD::DATA_FORMAT_R32_SFLOAT;
- tf.width = rb->width / 2;
- tf.height = rb->height / 2;
+ tf.width = rb->internal_width / 2;
+ tf.height = rb->internal_height / 2;
tf.texture_type = RD::TEXTURE_TYPE_2D;
tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT;
@@ -1836,8 +1893,8 @@ void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_frameb
if (ssr_roughness_quality != RS::ENV_SSR_ROUGNESS_QUALITY_DISABLED && !rb->ssr.blur_radius[0].is_valid()) {
RD::TextureFormat tf;
tf.format = RD::DATA_FORMAT_R8_UNORM;
- tf.width = rb->width / 2;
- tf.height = rb->height / 2;
+ tf.width = rb->internal_width / 2;
+ tf.height = rb->internal_height / 2;
tf.texture_type = RD::TEXTURE_TYPE_2D;
tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
@@ -1849,8 +1906,8 @@ void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_frameb
_allocate_blur_textures(rb);
}
- storage->get_effects()->screen_space_reflection(rb->texture, p_normal_buffer, ssr_roughness_quality, rb->ssr.blur_radius[0], rb->ssr.blur_radius[1], p_metallic, p_metallic_mask, rb->depth_texture, rb->ssr.depth_scaled, rb->ssr.normal_scaled, rb->blur[0].mipmaps[1].texture, rb->blur[1].mipmaps[0].texture, Size2i(rb->width / 2, rb->height / 2), env->ssr_max_steps, env->ssr_fade_in, env->ssr_fade_out, env->ssr_depth_tolerance, p_projection);
- storage->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->texture, rb->blur[0].mipmaps[1].texture);
+ storage->get_effects()->screen_space_reflection(rb->internal_texture, p_normal_buffer, ssr_roughness_quality, rb->ssr.blur_radius[0], rb->ssr.blur_radius[1], p_metallic, p_metallic_mask, rb->depth_texture, rb->ssr.depth_scaled, rb->ssr.normal_scaled, rb->blur[0].mipmaps[1].texture, rb->blur[1].mipmaps[0].texture, Size2i(rb->internal_width / 2, rb->internal_height / 2), env->ssr_max_steps, env->ssr_fade_in, env->ssr_fade_out, env->ssr_depth_tolerance, p_projection);
+ storage->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, rb->blur[0].mipmaps[1].texture);
}
void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection) {
@@ -1887,15 +1944,15 @@ void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environmen
int half_width;
int half_height;
if (ssao_half_size) {
- buffer_width = (rb->width + 3) / 4;
- buffer_height = (rb->height + 3) / 4;
- half_width = (rb->width + 7) / 8;
- half_height = (rb->height + 7) / 8;
+ buffer_width = (rb->internal_width + 3) / 4;
+ buffer_height = (rb->internal_height + 3) / 4;
+ half_width = (rb->internal_width + 7) / 8;
+ half_height = (rb->internal_height + 7) / 8;
} else {
- buffer_width = (rb->width + 1) / 2;
- buffer_height = (rb->height + 1) / 2;
- half_width = (rb->width + 3) / 4;
- half_height = (rb->height + 3) / 4;
+ buffer_width = (rb->internal_width + 1) / 2;
+ buffer_height = (rb->internal_height + 1) / 2;
+ half_width = (rb->internal_width + 3) / 4;
+ half_height = (rb->internal_height + 3) / 4;
}
bool uniform_sets_are_invalid = false;
if (rb->ssao.depth.is_null()) {
@@ -1967,8 +2024,8 @@ void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environmen
{
RD::TextureFormat tf;
tf.format = RD::DATA_FORMAT_R8_UNORM;
- tf.width = rb->width;
- tf.height = rb->height;
+ tf.width = rb->internal_width;
+ tf.height = rb->internal_height;
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
rb->ssao.ao_final = RD::get_singleton()->texture_create(tf, RD::TextureView());
RD::get_singleton()->set_resource_name(rb->ssao.ao_final, "SSAO Final");
@@ -1991,7 +2048,7 @@ void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environmen
settings.blur_passes = ssao_blur_passes;
settings.fadeout_from = ssao_fadeout_from;
settings.fadeout_to = ssao_fadeout_to;
- settings.full_screen_size = Size2i(rb->width, rb->height);
+ settings.full_screen_size = Size2i(rb->internal_width, rb->internal_height);
settings.half_screen_size = Size2i(buffer_width, buffer_height);
settings.quarter_screen_size = Size2i(half_width, half_height);
@@ -2055,7 +2112,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
ERR_FAIL_COND(!rb);
RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_render_data->environment);
- //glow (if enabled)
+ // Glow and override exposure (if enabled).
CameraEffects *camfx = camera_effects_owner.get_or_null(p_render_data->camera_effects);
bool can_use_effects = rb->width >= 8 && rb->height >= 8;
@@ -2071,9 +2128,9 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
EffectsRD::BokehBuffers buffers;
- // textures we use
- buffers.base_texture_size = Size2i(rb->width, rb->height);
- buffers.base_texture = rb->texture;
+ // Textures we use
+ buffers.base_texture_size = Size2i(rb->internal_width, rb->internal_height);
+ buffers.base_texture = rb->internal_texture;
buffers.depth_texture = rb->depth_texture;
buffers.secondary_texture = rb->blur[0].mipmaps[0].texture;
buffers.half_texture[0] = rb->blur[1].mipmaps[0].texture;
@@ -2083,7 +2140,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
if (can_use_storage) {
storage->get_effects()->bokeh_dof(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, dof_blur_use_jitter, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_ortogonal);
} else {
- // set framebuffers
+ // Set framebuffers.
buffers.base_fb = rb->texture_fb;
buffers.secondary_fb = rb->weight_buffers[1].fb;
buffers.half_fb[0] = rb->weight_buffers[2].fb;
@@ -2093,7 +2150,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
buffers.weight_texture[2] = rb->weight_buffers[2].weight;
buffers.weight_texture[3] = rb->weight_buffers[3].weight;
- // set weight buffers
+ // Set weight buffers.
buffers.base_weight_fb = rb->base_weight_fb;
storage->get_effects()->bokeh_dof_raster(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_ortogonal);
@@ -2112,17 +2169,17 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
double step = env->auto_exp_speed * time_step;
if (can_use_storage) {
- storage->get_effects()->luminance_reduction(rb->texture, Size2i(rb->width, rb->height), rb->luminance.reduce, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate);
+ storage->get_effects()->luminance_reduction(rb->internal_texture, Size2i(rb->internal_width, rb->internal_height), rb->luminance.reduce, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate);
} else {
- storage->get_effects()->luminance_reduction_raster(rb->texture, Size2i(rb->width, rb->height), rb->luminance.reduce, rb->luminance.fb, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate);
+ storage->get_effects()->luminance_reduction_raster(rb->internal_texture, Size2i(rb->internal_width, rb->internal_height), rb->luminance.reduce, rb->luminance.fb, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate);
}
- //swap final reduce with prev luminance
+ // Swap final reduce with prev luminance.
SWAP(rb->luminance.current, rb->luminance.reduce.write[rb->luminance.reduce.size() - 1]);
if (!can_use_storage) {
SWAP(rb->luminance.current_fb, rb->luminance.fb.write[rb->luminance.fb.size() - 1]);
}
- RenderingServerDefault::redraw_request(); //redraw all the time if auto exposure rendering is on
+ RenderingServerDefault::redraw_request(); // Redraw all the time if auto exposure rendering is on.
RD::get_singleton()->draw_command_end_label();
}
@@ -2157,9 +2214,9 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
luminance_texture = rb->luminance.current;
}
if (can_use_storage) {
- storage->get_effects()->gaussian_glow(rb->texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale);
+ storage->get_effects()->gaussian_glow(rb->internal_texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale);
} else {
- storage->get_effects()->gaussian_glow_raster(rb->texture, rb->blur[1].mipmaps[i].half_fb, rb->blur[1].mipmaps[i].half_texture, rb->blur[1].mipmaps[i].fb, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale);
+ storage->get_effects()->gaussian_glow_raster(rb->internal_texture, rb->blur[1].mipmaps[i].half_fb, rb->blur[1].mipmaps[i].half_texture, rb->blur[1].mipmaps[i].fb, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale);
}
} else {
if (can_use_storage) {
@@ -2176,7 +2233,6 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
{
RD::get_singleton()->draw_command_begin_label("Tonemap");
- //tonemap
EffectsRD::TonemapSettings tonemap;
if (can_use_effects && env && env->auto_exposure && rb->luminance.current.is_valid()) {
@@ -2207,7 +2263,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
}
tonemap.use_debanding = rb->use_debanding;
- tonemap.texture_size = Vector2i(rb->width, rb->height);
+ tonemap.texture_size = Vector2i(rb->internal_width, rb->internal_height);
if (env) {
tonemap.tonemap_mode = env->tone_mapper;
@@ -2215,6 +2271,10 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
tonemap.exposure = env->exposure;
}
+ if (camfx && camfx->override_exposure_enabled) {
+ tonemap.exposure = camfx->override_exposure;
+ }
+
tonemap.use_color_correction = false;
tonemap.use_1d_color_correction = false;
tonemap.color_correction_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
@@ -2234,7 +2294,15 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
tonemap.luminance_multiplier = _render_buffers_get_luminance_multiplier();
tonemap.view_count = p_render_data->view_count;
- storage->get_effects()->tonemapper(rb->texture, storage->render_target_get_rd_framebuffer(rb->render_target), tonemap);
+ storage->get_effects()->tonemapper(rb->internal_texture, storage->render_target_get_rd_framebuffer(rb->render_target), tonemap);
+
+ RD::get_singleton()->draw_command_end_label();
+ }
+
+ if (can_use_effects && can_use_storage && (rb->internal_width != rb->width || rb->internal_height != rb->height)) {
+ RD::get_singleton()->draw_command_begin_label("FSR Upscale");
+
+ storage->get_effects()->fsr_upscale(rb->internal_texture, rb->upscale_texture, rb->texture, Size2i(rb->internal_width, rb->internal_height), Size2i(rb->width, rb->height), rb->fsr_sharpness);
RD::get_singleton()->draw_command_end_label();
}
@@ -2249,6 +2317,8 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr
ERR_FAIL_COND(!rb);
RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_render_data->environment);
+ // Override exposure (if enabled).
+ CameraEffects *camfx = camera_effects_owner.get_or_null(p_render_data->camera_effects);
bool can_use_effects = rb->width >= 8 && rb->height >= 8;
@@ -2262,6 +2332,10 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr
tonemap.white = env->white;
}
+ if (camfx && camfx->override_exposure_enabled) {
+ tonemap.exposure = camfx->override_exposure;
+ }
+
// We don't support glow or auto exposure here, if they are needed, don't use subpasses!
// The problem is that we need to use the result so far and process them before we can
// apply this to our results.
@@ -2588,14 +2662,28 @@ bool RendererSceneRenderRD::_render_buffers_can_be_storage() {
return true;
}
-void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) {
+void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) {
ERR_FAIL_COND_MSG(p_view_count == 0, "Must have at least 1 view");
+ if (!_render_buffers_can_be_storage()) {
+ p_internal_height = p_height;
+ p_internal_width = p_width;
+ }
+
+ if (p_width != p_internal_width) {
+ float fsr_mipmap_bias = -log2f(p_width / p_internal_width) + p_fsr_mipmap_bias;
+ storage->sampler_rd_configure_custom(fsr_mipmap_bias);
+ update_uniform_sets();
+ }
+
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
// Should we add an overrule per viewport?
+ rb->internal_width = p_internal_width;
+ rb->internal_height = p_internal_height;
rb->width = p_width;
rb->height = p_height;
+ rb->fsr_sharpness = p_fsr_sharpness;
rb->render_target = p_render_target;
rb->msaa = p_msaa;
rb->screen_space_aa = p_screen_space_aa;
@@ -2617,8 +2705,8 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
}
tf.format = _render_buffers_get_color_format();
- tf.width = rb->width;
- tf.height = rb->height;
+ tf.width = rb->internal_width; // If set to rb->width, msaa won't crash
+ tf.height = rb->internal_height; // If set to rb->width, msaa won't crash
tf.array_layers = rb->view_count; // create a layer for every view
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | (_render_buffers_can_be_storage() ? RD::TEXTURE_USAGE_STORAGE_BIT : 0) | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
if (rb->msaa != RS::VIEWPORT_MSAA_DISABLED) {
@@ -2626,7 +2714,17 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
}
tf.usage_bits |= RD::TEXTURE_USAGE_INPUT_ATTACHMENT_BIT; // only needed when using subpasses in the mobile renderer
- rb->texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ rb->internal_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
+
+ if ((p_internal_width != p_width || p_internal_height != p_height)) {
+ tf.width = rb->width;
+ tf.height = rb->height;
+ rb->texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ rb->upscale_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ } else {
+ rb->texture = rb->internal_texture;
+ rb->upscale_texture = rb->internal_texture;
+ }
}
{
@@ -2640,8 +2738,8 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
tf.format = RD::DATA_FORMAT_R32_SFLOAT;
}
- tf.width = rb->width;
- tf.height = rb->height;
+ tf.width = rb->internal_width;
+ tf.height = rb->internal_height;
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT;
tf.array_layers = rb->view_count; // create a layer for every view
@@ -2657,16 +2755,16 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
if (!_render_buffers_can_be_storage()) {
// ONLY USED ON MOBILE RENDERER, ONLY USED FOR POST EFFECTS!
Vector<RID> fb;
- fb.push_back(rb->texture);
+ fb.push_back(rb->internal_texture);
rb->texture_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, rb->view_count);
}
RID target_texture = storage->render_target_get_rd_texture(rb->render_target);
- rb->data->configure(rb->texture, rb->depth_texture, target_texture, rb->width, rb->height, p_msaa, p_view_count);
+ rb->data->configure(rb->internal_texture, rb->depth_texture, target_texture, p_internal_width, p_internal_height, p_msaa, p_view_count);
if (is_clustered_enabled()) {
- rb->cluster_builder->setup(Size2i(rb->width, rb->height), max_cluster_elements, rb->depth_texture, storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED), rb->texture);
+ rb->cluster_builder->setup(Size2i(p_internal_width, p_internal_height), max_cluster_elements, rb->depth_texture, storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED), rb->internal_texture);
}
}
@@ -2696,9 +2794,14 @@ void RendererSceneRenderRD::shadows_quality_set(RS::ShadowQuality p_quality) {
switch (shadows_quality) {
case RS::SHADOW_QUALITY_HARD: {
penumbra_shadow_samples = 4;
- soft_shadow_samples = 1;
+ soft_shadow_samples = 0;
shadows_quality_radius = 1.0;
} break;
+ case RS::SHADOW_QUALITY_SOFT_VERY_LOW: {
+ penumbra_shadow_samples = 4;
+ soft_shadow_samples = 1;
+ shadows_quality_radius = 1.5;
+ } break;
case RS::SHADOW_QUALITY_SOFT_LOW: {
penumbra_shadow_samples = 8;
soft_shadow_samples = 4;
@@ -2738,9 +2841,14 @@ void RendererSceneRenderRD::directional_shadow_quality_set(RS::ShadowQuality p_q
switch (directional_shadow_quality) {
case RS::SHADOW_QUALITY_HARD: {
directional_penumbra_shadow_samples = 4;
- directional_soft_shadow_samples = 1;
+ directional_soft_shadow_samples = 0;
directional_shadow_quality_radius = 1.0;
} break;
+ case RS::SHADOW_QUALITY_SOFT_VERY_LOW: {
+ directional_penumbra_shadow_samples = 4;
+ directional_soft_shadow_samples = 1;
+ directional_shadow_quality_radius = 1.5;
+ } break;
case RS::SHADOW_QUALITY_SOFT_LOW: {
directional_penumbra_shadow_samples = 8;
directional_soft_shadow_samples = 4;
@@ -2886,7 +2994,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
r_positional_light_count = 0;
sky.sky_scene_state.ubo.directional_light_count = 0;
- Plane camera_plane(p_camera_transform.origin, -p_camera_transform.basis.get_axis(Vector3::AXIS_Z).normalized());
+ Plane camera_plane(-p_camera_transform.basis.get_axis(Vector3::AXIS_Z).normalized(), p_camera_transform.origin);
cluster.omni_light_count = 0;
cluster.spot_light_count = 0;
@@ -3026,7 +3134,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
RS::LightDirectionalShadowMode smode = storage->light_directional_get_shadow_mode(base);
int limit = smode == RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL ? 0 : (smode == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS ? 1 : 3);
- light_data.blend_splits = storage->light_directional_get_blend_splits(base);
+ light_data.blend_splits = (smode != RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL) && storage->light_directional_get_blend_splits(base);
for (int j = 0; j < 4; j++) {
Rect2 atlas_rect = li->shadow_transform[j].atlas_rect;
CameraMatrix matrix = li->shadow_transform[j].camera;
@@ -3462,6 +3570,189 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
}
}
+////////////////////////////////////////////////////////////////////////////////
+// FOG SHADER
+
+void RendererSceneRenderRD::FogShaderData::set_code(const String &p_code) {
+ //compile
+
+ code = p_code;
+ valid = false;
+ ubo_size = 0;
+ uniforms.clear();
+
+ if (code == String()) {
+ return; //just invalid, but no error
+ }
+
+ ShaderCompilerRD::GeneratedCode gen_code;
+ ShaderCompilerRD::IdentifierActions actions;
+ actions.entry_point_stages["fog"] = ShaderCompilerRD::STAGE_COMPUTE;
+
+ uses_time = false;
+
+ actions.usage_flag_pointers["TIME"] = &uses_time;
+
+ actions.uniforms = &uniforms;
+
+ RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton;
+
+ Error err = scene_singleton->volumetric_fog.compiler.compile(RS::SHADER_FOG, code, &actions, path, gen_code);
+ ERR_FAIL_COND_MSG(err != OK, "Fog shader compilation failed.");
+
+ if (version.is_null()) {
+ version = scene_singleton->volumetric_fog.shader.version_create();
+ }
+
+ scene_singleton->volumetric_fog.shader.version_set_compute_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompilerRD::STAGE_COMPUTE], gen_code.defines);
+ ERR_FAIL_COND(!scene_singleton->volumetric_fog.shader.version_is_valid(version));
+
+ ubo_size = gen_code.uniform_total_size;
+ ubo_offsets = gen_code.uniform_offsets;
+ texture_uniforms = gen_code.texture_uniforms;
+
+ pipeline = RD::get_singleton()->compute_pipeline_create(scene_singleton->volumetric_fog.shader.version_get_shader(version, 0));
+
+ valid = true;
+}
+
+void RendererSceneRenderRD::FogShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
+ if (!p_texture.is_valid()) {
+ if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
+ default_texture_params[p_name].erase(p_index);
+
+ if (default_texture_params[p_name].is_empty()) {
+ default_texture_params.erase(p_name);
+ }
+ }
+ } else {
+ if (!default_texture_params.has(p_name)) {
+ default_texture_params[p_name] = Map<int, RID>();
+ }
+ default_texture_params[p_name][p_index] = p_texture;
+ }
+}
+
+void RendererSceneRenderRD::FogShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
+ Map<int, StringName> order;
+
+ for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) {
+ if (E->get().scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E->get().scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
+ continue;
+ }
+
+ if (E->get().texture_order >= 0) {
+ order[E->get().texture_order + 100000] = E->key();
+ } else {
+ order[E->get().order] = E->key();
+ }
+ }
+
+ for (Map<int, StringName>::Element *E = order.front(); E; E = E->next()) {
+ PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E->get()]);
+ pi.name = E->get();
+ p_param_list->push_back(pi);
+ }
+}
+
+void RendererSceneRenderRD::FogShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const {
+ for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) {
+ if (E->get().scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
+ continue;
+ }
+
+ RendererStorage::InstanceShaderParam p;
+ p.info = ShaderLanguage::uniform_to_property_info(E->get());
+ p.info.name = E->key(); //supply name
+ p.index = E->get().instance_index;
+ p.default_value = ShaderLanguage::constant_value_to_variant(E->get().default_value, E->get().type, E->get().array_size, E->get().hint);
+ p_param_list->push_back(p);
+ }
+}
+
+bool RendererSceneRenderRD::FogShaderData::is_param_texture(const StringName &p_param) const {
+ if (!uniforms.has(p_param)) {
+ return false;
+ }
+
+ return uniforms[p_param].texture_order >= 0;
+}
+
+bool RendererSceneRenderRD::FogShaderData::is_animated() const {
+ return false;
+}
+
+bool RendererSceneRenderRD::FogShaderData::casts_shadows() const {
+ return false;
+}
+
+Variant RendererSceneRenderRD::FogShaderData::get_default_parameter(const StringName &p_parameter) const {
+ if (uniforms.has(p_parameter)) {
+ ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter];
+ Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
+ return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint);
+ }
+ return Variant();
+}
+
+RS::ShaderNativeSourceCode RendererSceneRenderRD::FogShaderData::get_native_source_code() const {
+ RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton;
+
+ return scene_singleton->volumetric_fog.shader.version_get_native_source_code(version);
+}
+
+RendererSceneRenderRD::FogShaderData::FogShaderData() {
+ valid = false;
+}
+
+RendererSceneRenderRD::FogShaderData::~FogShaderData() {
+ RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton;
+ ERR_FAIL_COND(!scene_singleton);
+ //pipeline variants will clear themselves if shader is gone
+ if (version.is_valid()) {
+ scene_singleton->volumetric_fog.shader.version_free(version);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Fog material
+
+bool RendererSceneRenderRD::FogMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
+ RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton;
+
+ uniform_set_updated = true;
+
+ return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, scene_singleton->volumetric_fog.shader.version_get_shader(shader_data->version, 0), VolumetricFogShader::FogSet::FOG_SET_MATERIAL);
+}
+
+RendererSceneRenderRD::FogMaterialData::~FogMaterialData() {
+ free_parameters_uniform_set(uniform_set);
+}
+
+RendererStorageRD::ShaderData *RendererSceneRenderRD::_create_fog_shader_func() {
+ FogShaderData *shader_data = memnew(FogShaderData);
+ return shader_data;
+}
+
+RendererStorageRD::ShaderData *RendererSceneRenderRD::_create_fog_shader_funcs() {
+ return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->_create_fog_shader_func();
+};
+
+RendererStorageRD::MaterialData *RendererSceneRenderRD::_create_fog_material_func(FogShaderData *p_shader) {
+ FogMaterialData *material_data = memnew(FogMaterialData);
+ material_data->shader_data = p_shader;
+ material_data->last_frame = false;
+ //update will happen later anyway so do nothing.
+ return material_data;
+}
+
+RendererStorageRD::MaterialData *RendererSceneRenderRD::_create_fog_material_funcs(RendererStorageRD::ShaderData *p_shader) {
+ return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->_create_fog_material_func(static_cast<FogShaderData *>(p_shader));
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// Volumetric Fog
+
void RendererSceneRenderRD::_volumetric_fog_erase(RenderBuffers *rb) {
ERR_FAIL_COND(!rb->volumetric_fog);
@@ -3469,11 +3760,14 @@ void RendererSceneRenderRD::_volumetric_fog_erase(RenderBuffers *rb) {
RD::get_singleton()->free(rb->volumetric_fog->light_density_map);
RD::get_singleton()->free(rb->volumetric_fog->fog_map);
- if (rb->volumetric_fog->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->uniform_set)) {
- RD::get_singleton()->free(rb->volumetric_fog->uniform_set);
+ if (rb->volumetric_fog->fog_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->fog_uniform_set)) {
+ RD::get_singleton()->free(rb->volumetric_fog->fog_uniform_set);
}
- if (rb->volumetric_fog->uniform_set2.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->uniform_set2)) {
- RD::get_singleton()->free(rb->volumetric_fog->uniform_set2);
+ if (rb->volumetric_fog->process_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->process_uniform_set)) {
+ RD::get_singleton()->free(rb->volumetric_fog->process_uniform_set);
+ }
+ if (rb->volumetric_fog->process_uniform_set2.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->process_uniform_set2)) {
+ RD::get_singleton()->free(rb->volumetric_fog->process_uniform_set2);
}
if (rb->volumetric_fog->sdfgi_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->sdfgi_uniform_set)) {
RD::get_singleton()->free(rb->volumetric_fog->sdfgi_uniform_set);
@@ -3487,7 +3781,26 @@ void RendererSceneRenderRD::_volumetric_fog_erase(RenderBuffers *rb) {
rb->volumetric_fog = nullptr;
}
-void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count) {
+Vector3i RendererSceneRenderRD::_point_get_position_in_froxel_volume(const Vector3 &p_point, float fog_end, const Vector2 &fog_near_size, const Vector2 &fog_far_size, float volumetric_fog_detail_spread, const Vector3 &fog_size, const Transform3D &p_cam_transform) {
+ Vector3 view_position = p_cam_transform.affine_inverse().xform(p_point);
+ view_position.z = MIN(view_position.z, -0.01); // Clamp to the front of camera
+ Vector3 fog_position = Vector3(0, 0, 0);
+
+ view_position.y = -view_position.y;
+ fog_position.z = -view_position.z / fog_end;
+ fog_position.x = (view_position.x / (2 * (fog_near_size.x * (1.0 - fog_position.z) + fog_far_size.x * fog_position.z))) + 0.5;
+ fog_position.y = (view_position.y / (2 * (fog_near_size.y * (1.0 - fog_position.z) + fog_far_size.y * fog_position.z))) + 0.5;
+ fog_position.z = Math::pow(float(fog_position.z), float(1.0 / volumetric_fog_detail_spread));
+ fog_position = fog_position * fog_size - Vector3(0.5, 0.5, 0.5);
+
+ fog_position.x = CLAMP(fog_position.x, 0.0, fog_size.x);
+ fog_position.y = CLAMP(fog_position.y, 0.0, fog_size.y);
+ fog_position.z = CLAMP(fog_position.z, 0.0, fog_size.z);
+
+ return Vector3i(fog_position);
+}
+
+void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes) {
ERR_FAIL_COND(!is_clustered_enabled()); // can't use volumetric fog without clustered
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb);
@@ -3510,6 +3823,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
}
RENDER_TIMESTAMP(">Volumetric Fog");
+ RD::get_singleton()->draw_command_begin_label("Volumetric Fog");
if (env && env->volumetric_fog_enabled && !rb->volumetric_fog) {
//required volumetric fog but not existing, create
@@ -3527,15 +3841,43 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
rb->volumetric_fog->light_density_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(rb->volumetric_fog->light_density_map, "Fog light-density map");
tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
rb->volumetric_fog->prev_light_density_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(rb->volumetric_fog->prev_light_density_map, "Fog previous light-density map");
RD::get_singleton()->texture_clear(rb->volumetric_fog->prev_light_density_map, Color(0, 0, 0, 0), 0, 1, 0, 1);
tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
rb->volumetric_fog->fog_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(rb->volumetric_fog->fog_map, "Fog map");
+
+#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+ Vector<uint8_t> dm;
+ dm.resize(target_width * target_height * volumetric_fog_depth * 4);
+ dm.fill(0);
+
+ rb->volumetric_fog->density_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm);
+ RD::get_singleton()->set_resource_name(rb->volumetric_fog->density_map, "Fog density map");
+ rb->volumetric_fog->light_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm);
+ RD::get_singleton()->set_resource_name(rb->volumetric_fog->light_map, "Fog light map");
+ rb->volumetric_fog->emissive_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm);
+ RD::get_singleton()->set_resource_name(rb->volumetric_fog->emissive_map, "Fog emissive map");
+#else
+ tf.format = RD::DATA_FORMAT_R32_UINT;
+ tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
+ rb->volumetric_fog->density_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(rb->volumetric_fog->density_map, "Fog density map");
+ RD::get_singleton()->texture_clear(rb->volumetric_fog->density_map, Color(0, 0, 0, 0), 0, 1, 0, 1);
+ rb->volumetric_fog->light_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(rb->volumetric_fog->light_map, "Fog light map");
+ RD::get_singleton()->texture_clear(rb->volumetric_fog->light_map, Color(0, 0, 0, 0), 0, 1, 0, 1);
+ rb->volumetric_fog->emissive_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(rb->volumetric_fog->emissive_map, "Fog emissive map");
+ RD::get_singleton()->texture_clear(rb->volumetric_fog->emissive_map, Color(0, 0, 0, 0), 0, 1, 0, 1);
+#endif
Vector<RD::Uniform> uniforms;
{
@@ -3549,12 +3891,210 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
rb->volumetric_fog->sky_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sky.sky_shader.default_shader_rd, RendererSceneSkyRD::SKY_SET_FOG);
}
- //update volumetric fog
+ if (p_fog_volumes.size() > 0) {
+ RD::get_singleton()->draw_command_begin_label("Render Volumetric Fog Volumes");
- if (rb->volumetric_fog->uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->uniform_set)) {
- //re create uniform set if needed
+ RENDER_TIMESTAMP("Render Fog Volumes");
+
+ VolumetricFogShader::VolumeUBO params;
+
+ Vector2 frustum_near_size = p_cam_projection.get_viewport_half_extents();
+ Vector2 frustum_far_size = p_cam_projection.get_far_plane_half_extents();
+ float z_near = p_cam_projection.get_z_near();
+ float z_far = p_cam_projection.get_z_far();
+ float fog_end = env->volumetric_fog_length;
+
+ Vector2 fog_far_size = frustum_near_size.lerp(frustum_far_size, (fog_end - z_near) / (z_far - z_near));
+ Vector2 fog_near_size;
+ if (p_cam_projection.is_orthogonal()) {
+ fog_near_size = fog_far_size;
+ } else {
+ fog_near_size = Vector2();
+ }
+
+ params.fog_frustum_size_begin[0] = fog_near_size.x;
+ params.fog_frustum_size_begin[1] = fog_near_size.y;
+ params.fog_frustum_size_end[0] = fog_far_size.x;
+ params.fog_frustum_size_end[1] = fog_far_size.y;
+
+ params.fog_frustum_end = fog_end;
+ params.z_near = z_near;
+ params.z_far = z_far;
+ params.time = time;
+
+ params.fog_volume_size[0] = rb->volumetric_fog->width;
+ params.fog_volume_size[1] = rb->volumetric_fog->height;
+ params.fog_volume_size[2] = rb->volumetric_fog->depth;
+
+ params.use_temporal_reprojection = env->volumetric_fog_temporal_reprojection;
+ params.temporal_frame = RSG::rasterizer->get_frame_number() % VolumetricFog::MAX_TEMPORAL_FRAMES;
+ params.detail_spread = env->volumetric_fog_detail_spread;
+ params.temporal_blend = env->volumetric_fog_temporal_reprojection_amount;
+
+ Transform3D to_prev_cam_view = rb->volumetric_fog->prev_cam_transform.affine_inverse() * p_cam_transform;
+ storage->store_transform(to_prev_cam_view, params.to_prev_view);
+ storage->store_transform(p_cam_transform, params.transform);
+
+ RD::get_singleton()->buffer_update(volumetric_fog.volume_ubo, 0, sizeof(VolumetricFogShader::VolumeUBO), &params, RD::BARRIER_MASK_COMPUTE);
+
+ if (rb->volumetric_fog->fog_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->fog_uniform_set)) {
+ Vector<RD::Uniform> uniforms;
+
+ {
+ RD::Uniform u;
+#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+#else
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+#endif
+ u.binding = 1;
+ u.ids.push_back(rb->volumetric_fog->emissive_map);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 2;
+ u.ids.push_back(volumetric_fog.volume_ubo);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+#else
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+#endif
+ u.binding = 3;
+ u.ids.push_back(rb->volumetric_fog->density_map);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+#else
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+#endif
+ u.binding = 4;
+ u.ids.push_back(rb->volumetric_fog->light_map);
+ uniforms.push_back(u);
+ }
+
+ rb->volumetric_fog->fog_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.default_shader_rd, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS);
+ }
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ bool any_uses_time = false;
+
+ for (int i = 0; i < (int)p_fog_volumes.size(); i++) {
+ FogVolumeInstance *fog_volume_instance = fog_volume_instance_owner.get_or_null(p_fog_volumes[i]);
+ ERR_FAIL_COND(!fog_volume_instance);
+ RID fog_volume = fog_volume_instance->volume;
+
+ RID fog_material = storage->fog_volume_get_material(fog_volume);
+
+ FogMaterialData *material = nullptr;
+
+ if (fog_material.is_valid()) {
+ material = (FogMaterialData *)storage->material_get_data(fog_material, RendererStorageRD::SHADER_TYPE_FOG);
+ if (!material || !material->shader_data->valid) {
+ material = nullptr;
+ }
+ }
+
+ if (!material) {
+ fog_material = volumetric_fog.default_material;
+ material = (FogMaterialData *)storage->material_get_data(fog_material, RendererStorageRD::SHADER_TYPE_FOG);
+ }
+
+ ERR_FAIL_COND(!material);
+
+ FogShaderData *shader_data = material->shader_data;
+
+ ERR_FAIL_COND(!shader_data);
+
+ any_uses_time |= shader_data->uses_time;
+
+ Vector3i min = Vector3i();
+ Vector3i max = Vector3i();
+ Vector3i kernel_size = Vector3i();
+
+ Vector3 position = fog_volume_instance->transform.get_origin();
+ RS::FogVolumeShape volume_type = storage->fog_volume_get_shape(fog_volume);
+ Vector3 extents = storage->fog_volume_get_extents(fog_volume);
+
+ if (volume_type == RS::FOG_VOLUME_SHAPE_BOX || volume_type == RS::FOG_VOLUME_SHAPE_ELLIPSOID) {
+ Vector3i points[8];
+ points[0] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform);
+ points[1] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform);
+ points[2] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, -extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform);
+ points[3] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, -extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform);
+ points[4] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform);
+ points[5] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform);
+ points[6] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, -extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform);
+ points[7] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, -extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform);
+
+ min = Vector3i(int32_t(rb->volumetric_fog->width) - 1, int32_t(rb->volumetric_fog->height) - 1, int32_t(rb->volumetric_fog->depth) - 1);
+ max = Vector3i(1, 1, 1);
+
+ for (int j = 0; j < 8; j++) {
+ min = Vector3i(MIN(min.x, points[j].x), MIN(min.y, points[j].y), MIN(min.z, points[j].z));
+ max = Vector3i(MAX(max.x, points[j].x), MAX(max.y, points[j].y), MAX(max.z, points[j].z));
+ }
+
+ kernel_size = max - min;
+ } else {
+ // Volume type global runs on all cells
+ extents = Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth);
+ min = Vector3i(0, 0, 0);
+ kernel_size = Vector3i(int32_t(rb->volumetric_fog->width), int32_t(rb->volumetric_fog->height), int32_t(rb->volumetric_fog->depth));
+ }
+
+ if (kernel_size.x == 0 || kernel_size.y == 0 || kernel_size.z == 0) {
+ continue;
+ }
+
+ volumetric_fog.push_constant.position[0] = position.x;
+ volumetric_fog.push_constant.position[1] = position.y;
+ volumetric_fog.push_constant.position[2] = position.z;
+ volumetric_fog.push_constant.extents[0] = extents.x;
+ volumetric_fog.push_constant.extents[1] = extents.y;
+ volumetric_fog.push_constant.extents[2] = extents.z;
+ volumetric_fog.push_constant.corner[0] = min.x;
+ volumetric_fog.push_constant.corner[1] = min.y;
+ volumetric_fog.push_constant.corner[2] = min.z;
+ volumetric_fog.push_constant.shape = uint32_t(storage->fog_volume_get_shape(fog_volume));
+ storage->store_transform(fog_volume_instance->transform.affine_inverse(), volumetric_fog.push_constant.transform);
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, shader_data->pipeline);
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->fog_uniform_set, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &volumetric_fog.push_constant, sizeof(VolumetricFogShader::FogPushConstant));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, volumetric_fog.base_uniform_set, VolumetricFogShader::FogSet::FOG_SET_BASE);
+ if (material->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(material->uniform_set)) { // Material may not have a uniform set.
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, material->uniform_set, VolumetricFogShader::FogSet::FOG_SET_MATERIAL);
+ }
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, kernel_size.x, kernel_size.y, kernel_size.z);
+ }
+ if (any_uses_time || env->volumetric_fog_temporal_reprojection) {
+ RenderingServerDefault::redraw_request();
+ }
+
+ RD::get_singleton()->draw_command_end_label();
+
+ RD::get_singleton()->compute_list_end();
+ }
+
+ if (rb->volumetric_fog->process_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->process_uniform_set)) {
+ //re create uniform set if needed
Vector<RD::Uniform> uniforms;
+ Vector<RD::Uniform> copy_uniforms;
{
RD::Uniform u;
@@ -3568,6 +4108,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
}
uniforms.push_back(u);
+ copy_uniforms.push_back(u);
}
{
@@ -3580,6 +4121,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK));
}
uniforms.push_back(u);
+ copy_uniforms.push_back(u);
}
{
@@ -3588,6 +4130,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
u.binding = 3;
u.ids.push_back(get_omni_light_buffer());
uniforms.push_back(u);
+ copy_uniforms.push_back(u);
}
{
RD::Uniform u;
@@ -3595,6 +4138,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
u.binding = 4;
u.ids.push_back(get_spot_light_buffer());
uniforms.push_back(u);
+ copy_uniforms.push_back(u);
}
{
@@ -3603,6 +4147,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
u.binding = 5;
u.ids.push_back(get_directional_light_buffer());
uniforms.push_back(u);
+ copy_uniforms.push_back(u);
}
{
@@ -3611,6 +4156,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
u.binding = 6;
u.ids.push_back(rb->cluster_builder->get_cluster_buffer());
uniforms.push_back(u);
+ copy_uniforms.push_back(u);
}
{
@@ -3619,6 +4165,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
u.binding = 7;
u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
uniforms.push_back(u);
+ copy_uniforms.push_back(u);
}
{
@@ -3627,6 +4174,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
u.binding = 8;
u.ids.push_back(rb->volumetric_fog->light_density_map);
uniforms.push_back(u);
+ copy_uniforms.push_back(u);
}
{
@@ -3639,10 +4187,19 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
{
RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 9;
+ u.ids.push_back(rb->volumetric_fog->prev_light_density_map);
+ copy_uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
u.binding = 10;
u.ids.push_back(shadow_sampler);
uniforms.push_back(u);
+ copy_uniforms.push_back(u);
}
{
@@ -3651,6 +4208,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
u.binding = 11;
u.ids.push_back(render_buffers_get_voxel_gi_buffer(p_render_buffers));
uniforms.push_back(u);
+ copy_uniforms.push_back(u);
}
{
@@ -3661,6 +4219,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
u.ids.push_back(rb->gi.voxel_gi_textures[i]);
}
uniforms.push_back(u);
+ copy_uniforms.push_back(u);
}
{
RD::Uniform u;
@@ -3668,6 +4227,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
u.binding = 13;
u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
uniforms.push_back(u);
+ copy_uniforms.push_back(u);
}
{
RD::Uniform u;
@@ -3675,6 +4235,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
u.binding = 14;
u.ids.push_back(volumetric_fog.params_ubo);
uniforms.push_back(u);
+ copy_uniforms.push_back(u);
}
{
RD::Uniform u;
@@ -3683,12 +4244,58 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
u.ids.push_back(rb->volumetric_fog->prev_light_density_map);
uniforms.push_back(u);
}
+ {
+ RD::Uniform u;
+#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+#else
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+#endif
+ u.binding = 16;
+ u.ids.push_back(rb->volumetric_fog->density_map);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+#else
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+#endif
+ u.binding = 17;
+ u.ids.push_back(rb->volumetric_fog->light_map);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+#else
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+#endif
+ u.binding = 18;
+ u.ids.push_back(rb->volumetric_fog->emissive_map);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 19;
+ RID radiance_texture = storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
+ RID sky_texture = env->sky.is_valid() ? sky.sky_get_radiance_texture_rd(env->sky) : RID();
+ u.ids.push_back(sky_texture.is_valid() ? sky_texture : radiance_texture);
+ uniforms.push_back(u);
+ }
+
+ rb->volumetric_fog->copy_uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY), 0);
- rb->volumetric_fog->uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.shader.version_get_shader(volumetric_fog.shader_version, 0), 0);
+ rb->volumetric_fog->process_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY), 0);
SWAP(uniforms.write[7].ids.write[0], uniforms.write[8].ids.write[0]);
- rb->volumetric_fog->uniform_set2 = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.shader.version_get_shader(volumetric_fog.shader_version, 0), 0);
+ rb->volumetric_fog->process_uniform_set2 = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, 0), 0);
}
bool using_sdfgi = env->volumetric_fog_gi_inject > 0.0001 && env->sdfgi_enabled && (rb->sdfgi != nullptr);
@@ -3721,7 +4328,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
uniforms.push_back(u);
}
- rb->volumetric_fog->sdfgi_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.shader.version_get_shader(volumetric_fog.shader_version, VOLUMETRIC_FOG_SHADER_DENSITY_WITH_SDFGI), 1);
+ rb->volumetric_fog->sdfgi_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI), 1);
}
}
@@ -3750,23 +4357,35 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
params.fog_frustum_size_end[0] = fog_far_size.x;
params.fog_frustum_size_end[1] = fog_far_size.y;
- params.z_near = z_near;
+ params.ambient_inject = env->volumetric_fog_ambient_inject * env->ambient_light_energy;
params.z_far = z_far;
params.fog_frustum_end = fog_end;
+ Color ambient_color = env->ambient_light.to_linear();
+ params.ambient_color[0] = ambient_color.r;
+ params.ambient_color[1] = ambient_color.g;
+ params.ambient_color[2] = ambient_color.b;
+ params.sky_contribution = env->ambient_sky_contribution;
+
params.fog_volume_size[0] = rb->volumetric_fog->width;
params.fog_volume_size[1] = rb->volumetric_fog->height;
params.fog_volume_size[2] = rb->volumetric_fog->depth;
params.directional_light_count = p_directional_light_count;
- Color light = env->volumetric_fog_light.to_linear();
- params.light_energy[0] = light.r * env->volumetric_fog_light_energy;
- params.light_energy[1] = light.g * env->volumetric_fog_light_energy;
- params.light_energy[2] = light.b * env->volumetric_fog_light_energy;
+ Color emission = env->volumetric_fog_emission.to_linear();
+ params.base_emission[0] = emission.r * env->volumetric_fog_emission_energy;
+ params.base_emission[1] = emission.g * env->volumetric_fog_emission_energy;
+ params.base_emission[2] = emission.b * env->volumetric_fog_emission_energy;
params.base_density = env->volumetric_fog_density;
+ Color base_scattering = env->volumetric_fog_scattering.to_linear();
+ params.base_scattering[0] = base_scattering.r;
+ params.base_scattering[1] = base_scattering.g;
+ params.base_scattering[2] = base_scattering.b;
+ params.phase_g = env->volumetric_fog_anisotropy;
+
params.detail_spread = env->volumetric_fog_detail_spread;
params.gi_inject = env->volumetric_fog_gi_inject;
@@ -3806,10 +4425,9 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
params.screen_size[1] = rb->height;
}
- /* Vector2 dssize = directional_shadow_get_size();
- push_constant.directional_shadow_pixel_size[0] = 1.0 / dssize.x;
- push_constant.directional_shadow_pixel_size[1] = 1.0 / dssize.y;
-*/
+ Basis sky_transform = env->sky_orientation;
+ sky_transform = sky_transform.inverse() * p_cam_transform.basis;
+ RendererStorageRD::store_transform_3x3(sky_transform, params.radiance_inverse_xform);
RD::get_singleton()->draw_command_begin_label("Render Volumetric Fog");
@@ -3818,33 +4436,32 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- bool use_filter = volumetric_fog_filter_active;
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[using_sdfgi ? VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI : VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY]);
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.pipelines[using_sdfgi ? VOLUMETRIC_FOG_SHADER_DENSITY_WITH_SDFGI : VOLUMETRIC_FOG_SHADER_DENSITY]);
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->uniform_set, 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->process_uniform_set, 0);
if (using_sdfgi) {
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->sdfgi_uniform_set, 1);
}
RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ // Copy fog to history buffer
+ if (env->volumetric_fog_temporal_reprojection) {
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->copy_uniform_set, 0);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ }
RD::get_singleton()->draw_command_end_label();
- RD::get_singleton()->compute_list_end();
-
- RD::get_singleton()->texture_copy(rb->volumetric_fog->light_density_map, rb->volumetric_fog->prev_light_density_map, Vector3(0, 0, 0), Vector3(0, 0, 0), Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), 0, 0, 0, 0);
-
- compute_list = RD::get_singleton()->compute_list_begin();
-
- if (use_filter) {
+ if (volumetric_fog_filter_active) {
RD::get_singleton()->draw_command_begin_label("Filter Fog");
RENDER_TIMESTAMP("Filter Fog");
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.pipelines[VOLUMETRIC_FOG_SHADER_FILTER]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->uniform_set, 0);
-
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FILTER]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->process_uniform_set, 0);
RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth);
RD::get_singleton()->compute_list_end();
@@ -3854,11 +4471,8 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
RD::get_singleton()->buffer_update(volumetric_fog.params_ubo, 0, sizeof(VolumetricFogShader::ParamsUBO), &params);
compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.pipelines[VOLUMETRIC_FOG_SHADER_FILTER]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->uniform_set2, 0);
- if (using_sdfgi) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->sdfgi_uniform_set, 1);
- }
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FILTER]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->process_uniform_set2, 0);
RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth);
RD::get_singleton()->compute_list_add_barrier(compute_list);
@@ -3868,14 +4482,15 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
RENDER_TIMESTAMP("Integrate Fog");
RD::get_singleton()->draw_command_begin_label("Integrate Fog");
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.pipelines[VOLUMETRIC_FOG_SHADER_FOG]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->uniform_set, 0);
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->process_uniform_set, 0);
RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, 1);
RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_RASTER);
RENDER_TIMESTAMP("<Volumetric Fog");
RD::get_singleton()->draw_command_end_label();
+ RD::get_singleton()->draw_command_end_label();
rb->volumetric_fog->prev_cam_transform = p_cam_transform;
}
@@ -3928,7 +4543,7 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
render_state.shadows.clear();
render_state.directional_shadows.clear();
- Plane camera_plane(p_render_data->cam_transform.origin, -p_render_data->cam_transform.basis.get_axis(Vector3::AXIS_Z));
+ Plane camera_plane(-p_render_data->cam_transform.basis.get_axis(Vector3::AXIS_Z), p_render_data->cam_transform.origin);
float lod_distance_multiplier = p_render_data->cam_projection.get_lod_multiplier();
{
for (int i = 0; i < render_state.render_shadow_count; i++) {
@@ -4043,12 +4658,12 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
}
}
if (is_volumetric_supported()) {
- _update_volumetric_fog(p_render_data->render_buffers, p_render_data->environment, p_render_data->cam_projection, p_render_data->cam_transform, p_render_data->shadow_atlas, directional_light_count, directional_shadows, positional_light_count, render_state.voxel_gi_count);
+ _update_volumetric_fog(p_render_data->render_buffers, p_render_data->environment, p_render_data->cam_projection, p_render_data->cam_transform, p_render_data->shadow_atlas, directional_light_count, directional_shadows, positional_light_count, render_state.voxel_gi_count, *p_render_data->fog_volumes);
}
}
}
-void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data, RendererScene::RenderInfo *r_render_info) {
+void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data, RendererScene::RenderInfo *r_render_info) {
// getting this here now so we can direct call a bunch of things more easily
RenderBuffers *rb = nullptr;
if (p_render_buffers.is_valid()) {
@@ -4081,6 +4696,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData
render_data.voxel_gi_instances = &p_voxel_gi_instances;
render_data.decals = &p_decals;
render_data.lightmaps = &p_lightmaps;
+ render_data.fog_volumes = &p_fog_volumes;
render_data.environment = p_environment;
render_data.camera_effects = p_camera_effects;
render_data.shadow_atlas = p_shadow_atlas;
@@ -4090,7 +4706,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData
// this should be the same for all cameras..
render_data.lod_distance_multiplier = p_camera_data->main_projection.get_lod_multiplier();
- render_data.lod_camera_plane = Plane(p_camera_data->main_transform.get_origin(), -p_camera_data->main_transform.basis.get_axis(Vector3::AXIS_Z));
+ render_data.lod_camera_plane = Plane(-p_camera_data->main_transform.basis.get_axis(Vector3::AXIS_Z), p_camera_data->main_transform.get_origin());
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_DISABLE_LOD) {
render_data.screen_lod_threshold = 0.0;
@@ -4183,9 +4799,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData
if (p_render_buffers.is_valid()) {
/*
_debug_draw_cluster(p_render_buffers);
-
RENDER_TIMESTAMP("Tonemap");
-
_render_buffers_post_process_and_tonemap(&render_data);
*/
@@ -4502,7 +5116,8 @@ bool RendererSceneRenderRD::free(RID p_rid) {
} else if (shadow_atlas_owner.owns(p_rid)) {
shadow_atlas_set_size(p_rid, 0);
shadow_atlas_owner.free(p_rid);
-
+ } else if (fog_volume_instance_owner.owns(p_rid)) {
+ fog_volume_instance_owner.free(p_rid);
} else {
return false;
}
@@ -4743,18 +5358,124 @@ void RendererSceneRenderRD::init() {
}
if (is_volumetric_supported()) {
- String defines = "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(cluster.max_directional_lights) + "\n";
- Vector<String> volumetric_fog_modes;
- volumetric_fog_modes.push_back("\n#define MODE_DENSITY\n");
- volumetric_fog_modes.push_back("\n#define MODE_DENSITY\n#define ENABLE_SDFGI\n");
- volumetric_fog_modes.push_back("\n#define MODE_FILTER\n");
- volumetric_fog_modes.push_back("\n#define MODE_FOG\n");
- volumetric_fog.shader.initialize(volumetric_fog_modes, defines);
- volumetric_fog.shader_version = volumetric_fog.shader.version_create();
- for (int i = 0; i < VOLUMETRIC_FOG_SHADER_MAX; i++) {
- volumetric_fog.pipelines[i] = RD::get_singleton()->compute_pipeline_create(volumetric_fog.shader.version_get_shader(volumetric_fog.shader_version, i));
+ {
+ // Initialize local fog shader
+ Vector<String> volumetric_fog_modes;
+ volumetric_fog_modes.push_back("");
+ volumetric_fog.shader.initialize(volumetric_fog_modes);
+
+ storage->shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_FOG, _create_fog_shader_funcs);
+ storage->material_set_data_request_function(RendererStorageRD::SHADER_TYPE_FOG, _create_fog_material_funcs);
+ volumetric_fog.volume_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(VolumetricFogShader::VolumeUBO));
+ }
+
+ {
+ ShaderCompilerRD::DefaultIdentifierActions actions;
+
+ actions.renames["TIME"] = "scene_params.time";
+ actions.renames["PI"] = _MKSTR(Math_PI);
+ actions.renames["TAU"] = _MKSTR(Math_TAU);
+ actions.renames["E"] = _MKSTR(Math_E);
+ actions.renames["WORLD_POSITION"] = "world.xyz";
+ actions.renames["OBJECT_POSITION"] = "params.position";
+ actions.renames["UVW"] = "uvw";
+ actions.renames["EXTENTS"] = "params.extents";
+ actions.renames["ALBEDO"] = "albedo";
+ actions.renames["DENSITY"] = "density";
+ actions.renames["EMISSION"] = "emission";
+ actions.renames["SDF"] = "sdf";
+
+ actions.usage_defines["SDF"] = "#define SDF_USED\n";
+ actions.usage_defines["DENSITY"] = "#define DENSITY_USED\n";
+ actions.usage_defines["ALBEDO"] = "#define ALBEDO_USED\n";
+ actions.usage_defines["EMISSION"] = "#define EMISSION_USED\n";
+
+ actions.sampler_array_name = "material_samplers";
+ actions.base_texture_binding_index = 1;
+ actions.texture_layout_set = VolumetricFogShader::FogSet::FOG_SET_MATERIAL;
+ actions.base_uniform_string = "material.";
+
+ actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
+ actions.default_repeat = ShaderLanguage::REPEAT_DISABLE;
+ actions.global_buffer_array_variable = "global_variables.data";
+
+ volumetric_fog.compiler.initialize(actions);
+ }
+
+ {
+ // default material and shader for fog shader
+ volumetric_fog.default_shader = storage->shader_allocate();
+ storage->shader_initialize(volumetric_fog.default_shader);
+ storage->shader_set_code(volumetric_fog.default_shader, R"(
+// Default fog shader.
+
+shader_type fog;
+
+void fog() {
+ DENSITY = 1.0;
+ ALBEDO = vec3(1.0);
+}
+)");
+ volumetric_fog.default_material = storage->material_allocate();
+ storage->material_initialize(volumetric_fog.default_material);
+ storage->material_set_shader(volumetric_fog.default_material, volumetric_fog.default_shader);
+
+ FogMaterialData *md = (FogMaterialData *)storage->material_get_data(volumetric_fog.default_material, RendererStorageRD::SHADER_TYPE_FOG);
+ volumetric_fog.default_shader_rd = volumetric_fog.shader.version_get_shader(md->shader_data->version, 0);
+
+ Vector<RD::Uniform> uniforms;
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
+ u.binding = 1;
+ u.ids.resize(12);
+ RID *ids_ptr = u.ids.ptrw();
+ ids_ptr[0] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[1] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[2] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[3] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[4] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[5] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[6] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[7] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[8] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[9] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[10] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[11] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 2;
+ u.ids.push_back(storage->global_variables_get_storage_buffer());
+ uniforms.push_back(u);
+ }
+
+ volumetric_fog.base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.default_shader_rd, VolumetricFogShader::FogSet::FOG_SET_BASE);
+ }
+ {
+ String defines = "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(cluster.max_directional_lights) + "\n";
+ defines += "\n#define MAX_SKY_LOD " + itos(get_roughness_layers() - 1) + ".0\n";
+ if (is_using_radiance_cubemap_array()) {
+ defines += "\n#define USE_RADIANCE_CUBEMAP_ARRAY \n";
+ }
+ Vector<String> volumetric_fog_modes;
+ volumetric_fog_modes.push_back("\n#define MODE_DENSITY\n");
+ volumetric_fog_modes.push_back("\n#define MODE_DENSITY\n#define ENABLE_SDFGI\n");
+ volumetric_fog_modes.push_back("\n#define MODE_FILTER\n");
+ volumetric_fog_modes.push_back("\n#define MODE_FOG\n");
+ volumetric_fog_modes.push_back("\n#define MODE_COPY\n");
+
+ volumetric_fog.process_shader.initialize(volumetric_fog_modes, defines);
+ volumetric_fog.process_shader_version = volumetric_fog.process_shader.version_create();
+ for (int i = 0; i < VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_MAX; i++) {
+ volumetric_fog.process_pipelines[i] = RD::get_singleton()->compute_pipeline_create(volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, i));
+ }
+ volumetric_fog.params_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(VolumetricFogShader::ParamsUBO));
}
- volumetric_fog.params_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(VolumetricFogShader::ParamsUBO));
}
{
@@ -4805,9 +5526,14 @@ RendererSceneRenderRD::~RendererSceneRenderRD() {
if (is_dynamic_gi_supported()) {
gi.free();
+ }
- volumetric_fog.shader.version_free(volumetric_fog.shader_version);
+ if (is_volumetric_supported()) {
+ volumetric_fog.process_shader.version_free(volumetric_fog.process_shader_version);
+ RD::get_singleton()->free(volumetric_fog.volume_ubo);
RD::get_singleton()->free(volumetric_fog.params_ubo);
+ storage->free(volumetric_fog.default_shader);
+ storage->free(volumetric_fog.default_material);
}
RendererSceneSkyRD::SkyMaterialData *md = (RendererSceneSkyRD::SkyMaterialData *)storage->material_get_data(sky.sky_shader.default_material, RendererStorageRD::SHADER_TYPE_SKY);
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
index d74848f0af..98ab1a2c3c 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
@@ -40,6 +40,7 @@
#include "servers/rendering/renderer_rd/renderer_scene_sky_rd.h"
#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
#include "servers/rendering/renderer_rd/shaders/volumetric_fog.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl.gen.h"
#include "servers/rendering/renderer_scene.h"
#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering/rendering_device.h"
@@ -64,6 +65,7 @@ struct RenderDataRD {
const PagedArray<RID> *voxel_gi_instances = nullptr;
const PagedArray<RID> *decals = nullptr;
const PagedArray<RID> *lightmaps = nullptr;
+ const PagedArray<RID> *fog_volumes = nullptr;
RID environment = RID();
RID camera_effects = RID();
RID shadow_atlas = RID();
@@ -393,6 +395,16 @@ private:
mutable RID_Owner<LightInstance> light_instance_owner;
+ /* FOG VOLUMES */
+
+ struct FogVolumeInstance {
+ RID volume;
+ Transform3D transform;
+ bool active = false;
+ };
+
+ mutable RID_Owner<FogVolumeInstance> fog_volume_instance_owner;
+
/* ENVIRONMENT */
RS::EnvironmentSSAOQuality ssao_quality = RS::ENV_SSAO_QUALITY_MEDIUM;
@@ -444,7 +456,11 @@ private:
struct RenderBuffers {
RenderBufferData *data = nullptr;
- int width = 0, height = 0;
+ int internal_width = 0;
+ int internal_height = 0;
+ int width = 0;
+ int height = 0;
+ float fsr_sharpness = 0.2f;
RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED;
RS::ViewportScreenSpaceAA screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED;
bool use_debanding = false;
@@ -454,9 +470,12 @@ private:
uint64_t auto_exposure_version = 1;
- RID texture; //main texture for rendering to, must be filled after done rendering
+ RID sss_texture; //texture for sss. This needs to be a different resolution than blur[0]
+ RID internal_texture; //main texture for rendering to, must be filled after done rendering
+ RID texture; //upscaled version of main texture (This uses the same resource as internal_texture if there is no upscaling)
RID depth_texture; //main depth texture
RID texture_fb; // framebuffer for the main texture, ONLY USED FOR MOBILE RENDERER POST EFFECTS, DO NOT USE FOR RENDERING 3D!!!
+ RID upscale_texture; //used when upscaling internal_texture (This uses the same resource as internal_texture if there is no upscaling)
RendererSceneGIRD::SDFGI *sdfgi = nullptr;
VolumetricFog *volumetric_fog = nullptr;
@@ -718,10 +737,15 @@ private:
RID light_density_map;
RID prev_light_density_map;
-
RID fog_map;
- RID uniform_set;
- RID uniform_set2;
+ RID density_map;
+ RID light_map;
+ RID emissive_map;
+
+ RID fog_uniform_set;
+ RID copy_uniform_set;
+ RID process_uniform_set;
+ RID process_uniform_set2;
RID sdfgi_uniform_set;
RID sky_uniform_set;
@@ -730,30 +754,91 @@ private:
Transform3D prev_cam_transform;
};
- enum {
- VOLUMETRIC_FOG_SHADER_DENSITY,
- VOLUMETRIC_FOG_SHADER_DENSITY_WITH_SDFGI,
- VOLUMETRIC_FOG_SHADER_FILTER,
- VOLUMETRIC_FOG_SHADER_FOG,
- VOLUMETRIC_FOG_SHADER_MAX,
- };
-
struct VolumetricFogShader {
- struct ParamsUBO {
+ enum FogSet {
+ FOG_SET_BASE,
+ FOG_SET_UNIFORMS,
+ FOG_SET_MATERIAL,
+ FOG_SET_MAX,
+ };
+
+ struct FogPushConstant {
+ float position[3];
+ float pad;
+
+ float extents[3];
+ float pad2;
+
+ int32_t corner[3];
+ uint32_t shape;
+
+ float transform[16];
+ };
+
+ struct VolumeUBO {
float fog_frustum_size_begin[2];
float fog_frustum_size_end[2];
float fog_frustum_end;
float z_near;
float z_far;
+ float time;
+
+ int32_t fog_volume_size[3];
+ uint32_t directional_light_count;
+
+ uint32_t use_temporal_reprojection;
+ uint32_t temporal_frame;
+ float detail_spread;
+ float temporal_blend;
+
+ float to_prev_view[16];
+ float transform[16];
+ };
+
+ ShaderCompilerRD compiler;
+ VolumetricFogShaderRD shader;
+ FogPushConstant push_constant;
+ RID volume_ubo;
+
+ RID default_shader;
+ RID default_material;
+ RID default_shader_rd;
+
+ RID base_uniform_set;
+
+ RID params_ubo;
+
+ enum {
+ VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY,
+ VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI,
+ VOLUMETRIC_FOG_PROCESS_SHADER_FILTER,
+ VOLUMETRIC_FOG_PROCESS_SHADER_FOG,
+ VOLUMETRIC_FOG_PROCESS_SHADER_COPY,
+ VOLUMETRIC_FOG_PROCESS_SHADER_MAX,
+ };
+
+ struct ParamsUBO {
+ float fog_frustum_size_begin[2];
+ float fog_frustum_size_end[2];
+
+ float fog_frustum_end;
+ float ambient_inject;
+ float z_far;
uint32_t filter_axis;
+ float ambient_color[3];
+ float sky_contribution;
+
int32_t fog_volume_size[3];
uint32_t directional_light_count;
- float light_energy[3];
+ float base_emission[3];
float base_density;
+ float base_scattering[3];
+ float phase_g;
+
float detail_spread;
float gi_inject;
uint32_t max_voxel_gi_instances;
@@ -770,13 +855,13 @@ private:
float cam_rotation[12];
float to_prev_view[16];
+ float radiance_inverse_xform[12];
};
- VolumetricFogShaderRD shader;
+ VolumetricFogProcessShaderRD process_shader;
- RID params_ubo;
- RID shader_version;
- RID pipelines[VOLUMETRIC_FOG_SHADER_MAX];
+ RID process_shader_version;
+ RID process_pipelines[VOLUMETRIC_FOG_PROCESS_SHADER_MAX];
} volumetric_fog;
@@ -784,8 +869,57 @@ private:
uint32_t volumetric_fog_size = 128;
bool volumetric_fog_filter_active = true;
+ Vector3i _point_get_position_in_froxel_volume(const Vector3 &p_point, float fog_end, const Vector2 &fog_near_size, const Vector2 &fog_far_size, float volumetric_fog_detail_spread, const Vector3 &fog_size, const Transform3D &p_cam_transform);
void _volumetric_fog_erase(RenderBuffers *rb);
- void _update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count);
+ void _update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes);
+
+ struct FogShaderData : public RendererStorageRD::ShaderData {
+ bool valid;
+ RID version;
+
+ RID pipeline;
+ Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
+ Vector<ShaderCompilerRD::GeneratedCode::Texture> texture_uniforms;
+
+ Vector<uint32_t> ubo_offsets;
+ uint32_t ubo_size;
+
+ String path;
+ String code;
+ Map<StringName, Map<int, RID>> default_texture_params;
+
+ bool uses_time;
+
+ virtual void set_code(const String &p_Code);
+ virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
+ virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
+ virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
+ virtual bool is_param_texture(const StringName &p_param) const;
+ virtual bool is_animated() const;
+ virtual bool casts_shadows() const;
+ virtual Variant get_default_parameter(const StringName &p_parameter) const;
+ virtual RS::ShaderNativeSourceCode get_native_source_code() const;
+ FogShaderData();
+ virtual ~FogShaderData();
+ };
+
+ struct FogMaterialData : public RendererStorageRD::MaterialData {
+ uint64_t last_frame;
+ FogShaderData *shader_data;
+ RID uniform_set;
+ bool uniform_set_updated;
+
+ virtual void set_render_priority(int p_priority) {}
+ virtual void set_next_pass(RID p_pass) {}
+ virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
+ virtual ~FogMaterialData();
+ };
+
+ RendererStorageRD::ShaderData *_create_fog_shader_func();
+ static RendererStorageRD::ShaderData *_create_fog_shader_funcs();
+
+ RendererStorageRD::MaterialData *_create_fog_material_func(FogShaderData *p_shader);
+ static RendererStorageRD::MaterialData *_create_fog_material_funcs(RendererStorageRD::ShaderData *p_shader);
RID shadow_sampler;
@@ -904,7 +1038,7 @@ public:
float environment_get_fog_height_density(RID p_env) const;
float environment_get_fog_aerial_perspective(RID p_env) const;
- virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount) override;
+ virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) override;
virtual void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) override;
virtual void environment_set_volumetric_fog_filter_active(bool p_enable) override;
@@ -931,6 +1065,8 @@ public:
virtual Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) override;
+ /* CAMERA EFFECTS */
+
virtual RID camera_effects_allocate() override;
virtual void camera_effects_initialize(RID p_rid) override;
@@ -946,6 +1082,8 @@ public:
return camfx && (camfx->dof_blur_near_enabled || camfx->dof_blur_far_enabled) && camfx->dof_blur_amount > 0.0;
}
+ /* LIGHT INSTANCE API */
+
virtual RID light_instance_create(RID p_light) override;
virtual void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) override;
virtual void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) override;
@@ -1082,6 +1220,14 @@ public:
return li->light_type;
}
+ /* FOG VOLUMES */
+
+ virtual RID fog_volume_instance_create(RID p_fog_volume) override;
+ virtual void fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) override;
+ virtual void fog_volume_instance_set_active(RID p_fog_volume_instance, bool p_active) override;
+ virtual RID fog_volume_instance_get_volume(RID p_fog_volume_instance) const override;
+ virtual Vector3 fog_volume_instance_get_position(RID p_fog_volume_instance) const override;
+
virtual RID reflection_atlas_create() override;
virtual void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) override;
virtual int reflection_atlas_get_size(RID p_ref_atlas) const override;
@@ -1193,7 +1339,7 @@ public:
virtual RD::DataFormat _render_buffers_get_color_format();
virtual bool _render_buffers_can_be_storage();
virtual RID render_buffers_create() override;
- virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) override;
+ virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) override;
virtual void gi_set_use_half_resolution(bool p_enable) override;
RID render_buffers_get_depth_texture(RID p_render_buffers);
@@ -1224,7 +1370,9 @@ public:
float render_buffers_get_volumetric_fog_end(RID p_render_buffers);
float render_buffers_get_volumetric_fog_detail_spread(RID p_render_buffers);
- virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override;
+ virtual void update_uniform_sets(){};
+
+ virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override;
virtual void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
index 5814c164cc..a9c39fb937 100644
--- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
@@ -137,11 +137,20 @@ void RendererSceneSkyRD::SkyShaderData::set_code(const String &p_code) {
valid = true;
}
-void RendererSceneSkyRD::SkyShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) {
+void RendererSceneSkyRD::SkyShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
if (!p_texture.is_valid()) {
- default_texture_params.erase(p_name);
+ if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
+ default_texture_params[p_name].erase(p_index);
+
+ if (default_texture_params[p_name].is_empty()) {
+ default_texture_params.erase(p_name);
+ }
+ }
} else {
- default_texture_params[p_name] = p_texture;
+ if (!default_texture_params.has(p_name)) {
+ default_texture_params[p_name] = Map<int, RID>();
+ }
+ default_texture_params[p_name][p_index] = p_texture;
}
}
@@ -292,7 +301,12 @@ void RendererSceneSkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_uniform_set, 1);
}
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_texture_set, 2);
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, sky_scene_state.fog_uniform_set, 3);
+ // Fog uniform set can be invalidated before drawing, so validate at draw time
+ if (sky_scene_state.fog_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sky_scene_state.fog_uniform_set)) {
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, sky_scene_state.fog_uniform_set, 3);
+ } else {
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, sky_scene_state.default_fog_uniform_set, 3);
+ }
}
RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
@@ -1165,14 +1179,8 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b
} else {
sky_scene_state.ubo.volumetric_fog_detail_spread = 1.0;
}
- }
- RID fog_uniform_set = p_scene_render->render_buffers_get_volumetric_fog_sky_uniform_set(p_render_buffers);
-
- if (fog_uniform_set != RID()) {
- sky_scene_state.fog_uniform_set = fog_uniform_set;
- } else {
- sky_scene_state.fog_uniform_set = sky_scene_state.default_fog_uniform_set;
+ sky_scene_state.fog_uniform_set = p_scene_render->render_buffers_get_volumetric_fog_sky_uniform_set(p_render_buffers);
}
}
diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
index 7f563c9bc4..8689395bea 100644
--- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
@@ -118,7 +118,7 @@ private:
String path;
String code;
- Map<StringName, RID> default_texture_params;
+ Map<StringName, Map<int, RID>> default_texture_params;
bool uses_time;
bool uses_position;
@@ -127,7 +127,7 @@ private:
bool uses_light;
virtual void set_code(const String &p_Code);
- virtual void set_default_texture_param(const StringName &p_name, RID p_texture);
+ virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
index 2ece60e107..cd5d70e12f 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
@@ -1034,7 +1034,7 @@ Ref<Image> RendererStorageRD::texture_2d_get(RID p_texture) const {
ERR_FAIL_COND_V(!tex, Ref<Image>());
#ifdef TOOLS_ENABLED
- if (tex->image_cache_2d.is_valid()) {
+ if (tex->image_cache_2d.is_valid() && !tex->is_render_target) {
return tex->image_cache_2d;
}
#endif
@@ -1049,7 +1049,7 @@ Ref<Image> RendererStorageRD::texture_2d_get(RID p_texture) const {
}
#ifdef TOOLS_ENABLED
- if (Engine::get_singleton()->is_editor_hint()) {
+ if (Engine::get_singleton()->is_editor_hint() && !tex->is_render_target) {
tex->image_cache_2d = image;
}
#endif
@@ -1227,6 +1227,100 @@ RendererStorageRD::CanvasTexture::~CanvasTexture() {
clear_sets();
}
+void RendererStorageRD::sampler_rd_configure_custom(float p_mipmap_bias) {
+ for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
+ for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
+ RD::SamplerState sampler_state;
+ switch (i) {
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST: {
+ sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
+ sampler_state.max_lod = 0;
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR: {
+ sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
+ sampler_state.max_lod = 0;
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: {
+ sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
+ if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+ } else {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+ }
+ sampler_state.lod_bias = p_mipmap_bias;
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: {
+ sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
+ if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+ } else {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+ }
+ sampler_state.lod_bias = p_mipmap_bias;
+
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC: {
+ sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
+ if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+ } else {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+ }
+ sampler_state.lod_bias = p_mipmap_bias;
+ sampler_state.use_anisotropy = true;
+ sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level"));
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC: {
+ sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
+ if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+ } else {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+ }
+ sampler_state.lod_bias = p_mipmap_bias;
+ sampler_state.use_anisotropy = true;
+ sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level"));
+
+ } break;
+ default: {
+ }
+ }
+ switch (j) {
+ case RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED: {
+ sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
+ sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
+ sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
+
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED: {
+ sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_REPEAT;
+ sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_REPEAT;
+ sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_REPEAT;
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR: {
+ sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
+ sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
+ sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
+ } break;
+ default: {
+ }
+ }
+
+ if (custom_rd_samplers[i][j].is_valid()) {
+ RD::get_singleton()->free(custom_rd_samplers[i][j]);
+ }
+
+ custom_rd_samplers[i][j] = RD::get_singleton()->sampler_create(sampler_state);
+ }
+ }
+}
+
RID RendererStorageRD::canvas_texture_allocate() {
return canvas_texture_owner.allocate_rid();
}
@@ -1399,6 +1493,8 @@ void RendererStorageRD::shader_set_code(RID p_shader, const String &p_code) {
new_type = SHADER_TYPE_3D;
} else if (mode_string == "sky") {
new_type = SHADER_TYPE_SKY;
+ } else if (mode_string == "fog") {
+ new_type = SHADER_TYPE_FOG;
} else {
new_type = SHADER_TYPE_MAX;
}
@@ -1438,8 +1534,10 @@ void RendererStorageRD::shader_set_code(RID p_shader, const String &p_code) {
}
if (shader->data) {
- for (const KeyValue<StringName, RID> &E : shader->default_texture_parameter) {
- shader->data->set_default_texture_param(E.key, E.value);
+ for (const KeyValue<StringName, Map<int, RID>> &E : shader->default_texture_parameter) {
+ for (const KeyValue<int, RID> &E2 : E.value) {
+ shader->data->set_default_texture_param(E.key, E2.value, E2.key);
+ }
}
}
}
@@ -1469,17 +1567,26 @@ void RendererStorageRD::shader_get_param_list(RID p_shader, List<PropertyInfo> *
}
}
-void RendererStorageRD::shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) {
+void RendererStorageRD::shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) {
Shader *shader = shader_owner.get_or_null(p_shader);
ERR_FAIL_COND(!shader);
if (p_texture.is_valid() && texture_owner.owns(p_texture)) {
- shader->default_texture_parameter[p_name] = p_texture;
+ if (!shader->default_texture_parameter.has(p_name)) {
+ shader->default_texture_parameter[p_name] = Map<int, RID>();
+ }
+ shader->default_texture_parameter[p_name][p_index] = p_texture;
} else {
- shader->default_texture_parameter.erase(p_name);
+ if (shader->default_texture_parameter.has(p_name) && shader->default_texture_parameter[p_name].has(p_index)) {
+ shader->default_texture_parameter[p_name].erase(p_index);
+
+ if (shader->default_texture_parameter[p_name].is_empty()) {
+ shader->default_texture_parameter.erase(p_name);
+ }
+ }
}
if (shader->data) {
- shader->data->set_default_texture_param(p_name, p_texture);
+ shader->data->set_default_texture_param(p_name, p_texture, p_index);
}
for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) {
Material *material = E->get();
@@ -1487,11 +1594,11 @@ void RendererStorageRD::shader_set_default_texture_param(RID p_shader, const Str
}
}
-RID RendererStorageRD::shader_get_default_texture_param(RID p_shader, const StringName &p_name) const {
+RID RendererStorageRD::shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const {
Shader *shader = shader_owner.get_or_null(p_shader);
ERR_FAIL_COND_V(!shader, RID());
- if (shader->default_texture_parameter.has(p_name)) {
- return shader->default_texture_parameter[p_name];
+ if (shader->default_texture_parameter.has(p_name) && shader->default_texture_parameter[p_name].has(p_index)) {
+ return shader->default_texture_parameter[p_name][p_index];
}
return RID();
@@ -2545,7 +2652,17 @@ void RendererStorageRD::MaterialData::update_uniform_buffer(const Map<StringName
//regular uniform
uint32_t offset = p_uniform_offsets[E.value.order];
#ifdef DEBUG_ENABLED
- uint32_t size = ShaderLanguage::get_type_size(E.value.type);
+ uint32_t size = 0U;
+ // The following code enforces a 16-byte alignment of uniform arrays.
+ if (E.value.array_size > 0) {
+ size = ShaderLanguage::get_type_size(E.value.type) * E.value.array_size;
+ int m = (16 * E.value.array_size);
+ if ((size % m) != 0U) {
+ size += m - (size % m);
+ }
+ } else {
+ size = ShaderLanguage::get_type_size(E.value.type);
+ }
ERR_CONTINUE(offset + size > p_buffer_size);
#endif
uint8_t *data = &p_buffer[offset];
@@ -2608,7 +2725,7 @@ RendererStorageRD::MaterialData::~MaterialData() {
}
}
-void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, RID> &p_default_textures, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) {
+void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, Map<int, RID>> &p_default_textures, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) {
RendererStorageRD *singleton = (RendererStorageRD *)RendererStorage::base_singleton;
#ifdef TOOLS_ENABLED
Texture *roughness_detect_texture = nullptr;
@@ -2671,17 +2788,19 @@ void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Vari
if (uniform_array_size > 0) {
if (textures.size() < uniform_array_size) {
- const Map<StringName, RID>::Element *W = p_default_textures.find(uniform_name);
- if (W) {
- for (int j = textures.size(); j < uniform_array_size; j++) {
- textures.push_back(W->get());
+ const Map<StringName, Map<int, RID>>::Element *W = p_default_textures.find(uniform_name);
+ for (int j = textures.size(); j < uniform_array_size; j++) {
+ if (W && W->get().has(j)) {
+ textures.push_back(W->get()[j]);
+ } else {
+ textures.push_back(RID());
}
}
}
} else if (textures.is_empty()) {
- const Map<StringName, RID>::Element *W = p_default_textures.find(uniform_name);
- if (W) {
- textures.push_back(W->get());
+ const Map<StringName, Map<int, RID>>::Element *W = p_default_textures.find(uniform_name);
+ if (W && W->get().has(0)) {
+ textures.push_back(W->get()[0]);
}
}
}
@@ -2690,20 +2809,56 @@ void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Vari
if (textures.is_empty()) {
//check default usage
- switch (p_texture_uniforms[i].hint) {
- case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK:
- case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: {
- rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_BLACK);
+ switch (p_texture_uniforms[i].type) {
+ case ShaderLanguage::TYPE_ISAMPLER2D:
+ case ShaderLanguage::TYPE_USAMPLER2D:
+ case ShaderLanguage::TYPE_SAMPLER2D: {
+ switch (p_texture_uniforms[i].hint) {
+ case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK:
+ case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: {
+ rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_BLACK);
+ } break;
+ case ShaderLanguage::ShaderNode::Uniform::HINT_NONE: {
+ rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL);
+ } break;
+ case ShaderLanguage::ShaderNode::Uniform::HINT_ANISO: {
+ rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_ANISO);
+ } break;
+ default: {
+ rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE);
+ } break;
+ }
} break;
- case ShaderLanguage::ShaderNode::Uniform::HINT_NONE: {
- rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL);
+
+ case ShaderLanguage::TYPE_SAMPLERCUBE: {
+ switch (p_texture_uniforms[i].hint) {
+ case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK:
+ case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: {
+ rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
+ } break;
+ default: {
+ rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_WHITE);
+ } break;
+ }
} break;
- case ShaderLanguage::ShaderNode::Uniform::HINT_ANISO: {
- rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_ANISO);
+ case ShaderLanguage::TYPE_SAMPLERCUBEARRAY: {
+ rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK);
} break;
- default: {
- rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE);
+
+ case ShaderLanguage::TYPE_ISAMPLER3D:
+ case ShaderLanguage::TYPE_USAMPLER3D:
+ case ShaderLanguage::TYPE_SAMPLER3D: {
+ rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_3D_WHITE);
} break;
+
+ case ShaderLanguage::TYPE_ISAMPLER2DARRAY:
+ case ShaderLanguage::TYPE_USAMPLER2DARRAY:
+ case ShaderLanguage::TYPE_SAMPLER2DARRAY: {
+ rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
+ } break;
+
+ default: {
+ }
}
#ifdef TOOLS_ENABLED
if (roughness_detect_texture && normal_detect_texture && normal_detect_texture->path != String()) {
@@ -2793,7 +2948,7 @@ void RendererStorageRD::MaterialData::free_parameters_uniform_set(RID p_uniform_
}
}
-bool RendererStorageRD::MaterialData::update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, RID> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier) {
+bool RendererStorageRD::MaterialData::update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, Map<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier) {
if ((uint32_t)ubo_data.size() != p_ubo_size) {
p_uniform_dirty = true;
if (uniform_buffer.is_valid()) {
@@ -2817,7 +2972,7 @@ bool RendererStorageRD::MaterialData::update_parameters_uniform_set(const Map<St
//check whether buffer changed
if (p_uniform_dirty && ubo_data.size()) {
- update_uniform_buffer(p_uniforms, p_uniform_offsets, p_parameters, ubo_data.ptrw(), ubo_data.size(), false);
+ update_uniform_buffer(p_uniforms, p_uniform_offsets, p_parameters, ubo_data.ptrw(), ubo_data.size(), true);
RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw(), p_barrier);
}
@@ -4379,7 +4534,8 @@ void RendererStorageRD::_update_dirty_multimeshes() {
if (multimesh->data_cache_dirty_regions[i]) {
uint32_t offset = i * region_size;
uint32_t size = multimesh->stride_cache * (uint32_t)multimesh->instances * (uint32_t)sizeof(float);
- RD::get_singleton()->buffer_update(multimesh->buffer, offset, MIN(region_size, size - offset), &data[i * region_size]);
+ uint32_t region_start_index = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * i;
+ RD::get_singleton()->buffer_update(multimesh->buffer, offset, MIN(region_size, size - offset), &data[region_start_index]);
}
}
}
@@ -5707,11 +5863,20 @@ void RendererStorageRD::ParticlesShaderData::set_code(const String &p_code) {
valid = true;
}
-void RendererStorageRD::ParticlesShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) {
+void RendererStorageRD::ParticlesShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
if (!p_texture.is_valid()) {
- default_texture_params.erase(p_name);
+ if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
+ default_texture_params[p_name].erase(p_index);
+
+ if (default_texture_params[p_name].is_empty()) {
+ default_texture_params.erase(p_name);
+ }
+ }
} else {
- default_texture_params[p_name] = p_texture;
+ if (!default_texture_params.has(p_name)) {
+ default_texture_params[p_name] = Map<int, RID>();
+ }
+ default_texture_params[p_name][p_index] = p_texture;
}
}
@@ -6000,6 +6165,82 @@ void RendererStorageRD::particles_collision_instance_set_active(RID p_collision_
pci->active = p_active;
}
+/* FOG VOLUMES */
+
+RID RendererStorageRD::fog_volume_allocate() {
+ return fog_volume_owner.allocate_rid();
+}
+void RendererStorageRD::fog_volume_initialize(RID p_rid) {
+ fog_volume_owner.initialize_rid(p_rid, FogVolume());
+}
+
+void RendererStorageRD::fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) {
+ FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
+ ERR_FAIL_COND(!fog_volume);
+
+ if (p_shape == fog_volume->shape) {
+ return;
+ }
+
+ fog_volume->shape = p_shape;
+ fog_volume->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
+}
+
+void RendererStorageRD::fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) {
+ FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
+ ERR_FAIL_COND(!fog_volume);
+
+ fog_volume->extents = p_extents;
+ fog_volume->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
+}
+
+void RendererStorageRD::fog_volume_set_material(RID p_fog_volume, RID p_material) {
+ FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
+ ERR_FAIL_COND(!fog_volume);
+ fog_volume->material = p_material;
+}
+
+RID RendererStorageRD::fog_volume_get_material(RID p_fog_volume) const {
+ FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
+ ERR_FAIL_COND_V(!fog_volume, RID());
+
+ return fog_volume->material;
+}
+
+RS::FogVolumeShape RendererStorageRD::fog_volume_get_shape(RID p_fog_volume) const {
+ FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
+ ERR_FAIL_COND_V(!fog_volume, RS::FOG_VOLUME_SHAPE_BOX);
+
+ return fog_volume->shape;
+}
+
+AABB RendererStorageRD::fog_volume_get_aabb(RID p_fog_volume) const {
+ FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
+ ERR_FAIL_COND_V(!fog_volume, AABB());
+
+ switch (fog_volume->shape) {
+ case RS::FOG_VOLUME_SHAPE_ELLIPSOID:
+ case RS::FOG_VOLUME_SHAPE_BOX: {
+ AABB aabb;
+ aabb.position = -fog_volume->extents;
+ aabb.size = fog_volume->extents * 2;
+ return aabb;
+ }
+ default: {
+ // Need some size otherwise will get culled
+ return AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2));
+ }
+ }
+
+ return AABB();
+}
+
+Vector3 RendererStorageRD::fog_volume_get_extents(RID p_fog_volume) const {
+ const FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
+ ERR_FAIL_COND_V(!fog_volume, Vector3());
+ return fog_volume->extents;
+}
+
/* VISIBILITY NOTIFIER */
RID RendererStorageRD::visibility_notifier_allocate() {
@@ -8081,6 +8322,9 @@ void RendererStorageRD::base_update_dependency(RID p_base, DependencyTracker *p_
} else if (particles_collision_owner.owns(p_base)) {
ParticlesCollision *pc = particles_collision_owner.get_or_null(p_base);
p_instance->update_dependency(&pc->dependency);
+ } else if (fog_volume_owner.owns(p_base)) {
+ FogVolume *fv = fog_volume_owner.get_or_null(p_base);
+ p_instance->update_dependency(&fv->dependency);
} else if (visibility_notifier_owner.owns(p_base)) {
VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_base);
p_instance->update_dependency(&vn->dependency);
@@ -8122,6 +8366,9 @@ RS::InstanceType RendererStorageRD::get_base_type(RID p_rid) const {
if (particles_collision_owner.owns(p_rid)) {
return RS::INSTANCE_PARTICLES_COLLISION;
}
+ if (fog_volume_owner.owns(p_rid)) {
+ return RS::INSTANCE_FOG_VOLUME;
+ }
if (visibility_notifier_owner.owns(p_rid)) {
return RS::INSTANCE_VISIBLITY_NOTIFIER;
}
@@ -9018,7 +9265,6 @@ void RendererStorageRD::_update_global_variables() {
ERR_CONTINUE(!material); //wtf
_material_queue_update(material, false, true);
- print_line("update material texture?");
}
global_variables.must_update_texture_materials = false;
@@ -9204,6 +9450,10 @@ bool RendererStorageRD::free(RID p_rid) {
visibility_notifier_owner.free(p_rid);
} else if (particles_collision_instance_owner.owns(p_rid)) {
particles_collision_instance_owner.free(p_rid);
+ } else if (fog_volume_owner.owns(p_rid)) {
+ FogVolume *fog_volume = fog_volume_owner.get_or_null(p_rid);
+ fog_volume->dependency.deleted_notify(p_rid);
+ fog_volume_owner.free(p_rid);
} else if (render_target_owner.owns(p_rid)) {
RenderTarget *rt = render_target_owner.get_or_null(p_rid);
@@ -9500,6 +9750,18 @@ RendererStorageRD::RendererStorageRD() {
{
Vector<Vector<uint8_t>> vpv;
vpv.push_back(pv);
+ default_rd_textures[DEFAULT_RD_TEXTURE_3D_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
+ }
+ for (int i = 0; i < 64; i++) {
+ pv.set(i * 4 + 0, 255);
+ pv.set(i * 4 + 1, 255);
+ pv.set(i * 4 + 2, 255);
+ pv.set(i * 4 + 3, 255);
+ }
+
+ {
+ Vector<Vector<uint8_t>> vpv;
+ vpv.push_back(pv);
default_rd_textures[DEFAULT_RD_TEXTURE_3D_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
}
}
@@ -9615,6 +9877,9 @@ RendererStorageRD::RendererStorageRD() {
}
}
+ //custom sampler
+ sampler_rd_configure_custom(0.0f);
+
//default rd buffers
{
Vector<uint8_t> buffer;
@@ -9767,7 +10032,7 @@ RendererStorageRD::RendererStorageRD() {
actions.renames["RESTART"] = "restart";
actions.renames["CUSTOM"] = "PARTICLE.custom";
actions.renames["TRANSFORM"] = "PARTICLE.xform";
- actions.renames["TIME"] = "FRAME.time";
+ actions.renames["TIME"] = "frame_history.data[0].time";
actions.renames["PI"] = _MKSTR(Math_PI);
actions.renames["TAU"] = _MKSTR(Math_TAU);
actions.renames["E"] = _MKSTR(Math_E);
@@ -9945,6 +10210,15 @@ RendererStorageRD::~RendererStorageRD() {
}
}
+ //custom samplers
+ for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
+ for (int j = 0; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
+ if (custom_rd_samplers[i][j].is_valid()) {
+ RD::get_singleton()->free(custom_rd_samplers[i][j]);
+ }
+ }
+ }
+
//def buffers
for (int i = 0; i < DEFAULT_RD_BUFFER_MAX; i++) {
RD::get_singleton()->free(mesh_default_rd_buffers[i]);
@@ -9970,6 +10244,6 @@ RendererStorageRD::~RendererStorageRD() {
if (effects) {
memdelete(effects);
- effects = NULL;
+ effects = nullptr;
}
}
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h
index d56afcc448..9a64480c3e 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.h
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.h
@@ -129,12 +129,13 @@ public:
SHADER_TYPE_3D,
SHADER_TYPE_PARTICLES,
SHADER_TYPE_SKY,
+ SHADER_TYPE_FOG,
SHADER_TYPE_MAX
};
struct ShaderData {
virtual void set_code(const String &p_Code) = 0;
- virtual void set_default_texture_param(const StringName &p_name, RID p_texture) = 0;
+ virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) = 0;
virtual void get_param_list(List<PropertyInfo> *p_param_list) const = 0;
virtual void get_instance_param_list(List<InstanceShaderParam> *p_param_list) const = 0;
@@ -151,7 +152,7 @@ public:
struct MaterialData {
void update_uniform_buffer(const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Map<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color);
- void update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, RID> &p_default_textures, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color);
+ void update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, Map<int, RID>> &p_default_textures, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color);
virtual void set_render_priority(int p_priority) = 0;
virtual void set_next_pass(RID p_pass) = 0;
@@ -159,7 +160,7 @@ public:
virtual ~MaterialData();
//to be used internally by update_parameters, in the most common configuration of material parameters
- bool update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, RID> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier = RD::BARRIER_MASK_ALL);
+ bool update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, Map<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier = RD::BARRIER_MASK_ALL);
void free_parameters_uniform_set(RID p_uniform_set);
private:
@@ -188,6 +189,7 @@ public:
DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK,
DEFAULT_RD_TEXTURE_CUBEMAP_WHITE,
DEFAULT_RD_TEXTURE_3D_WHITE,
+ DEFAULT_RD_TEXTURE_3D_BLACK,
DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE,
DEFAULT_RD_TEXTURE_2D_UINT,
DEFAULT_RD_TEXTURE_MAX
@@ -318,6 +320,7 @@ private:
RID default_rd_textures[DEFAULT_RD_TEXTURE_MAX];
RID default_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
+ RID custom_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
RID default_rd_storage_buffer;
/* DECAL ATLAS */
@@ -372,7 +375,7 @@ private:
ShaderData *data;
String code;
ShaderType type;
- Map<StringName, RID> default_texture_parameter;
+ Map<StringName, Map<int, RID>> default_texture_parameter;
Set<Material *> owners;
};
@@ -881,14 +884,14 @@ private:
String path;
String code;
- Map<StringName, RID> default_texture_params;
+ Map<StringName, Map<int, RID>> default_texture_params;
RID pipeline;
bool uses_time;
virtual void set_code(const String &p_Code);
- virtual void set_default_texture_param(const StringName &p_name, RID p_texture);
+ virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
@@ -957,6 +960,19 @@ private:
mutable RID_Owner<ParticlesCollisionInstance> particles_collision_instance_owner;
+ /* FOG VOLUMES */
+
+ struct FogVolume {
+ RID material;
+ Vector3 extents = Vector3(1, 1, 1);
+
+ RS::FogVolumeShape shape = RS::FOG_VOLUME_SHAPE_BOX;
+
+ Dependency dependency;
+ };
+
+ mutable RID_Owner<FogVolume, true> fog_volume_owner;
+
/* visibility_notifier */
struct VisibilityNotifier {
@@ -1284,7 +1300,7 @@ private:
void _update_global_variables();
/* EFFECTS */
- EffectsRD *effects = NULL;
+ EffectsRD *effects = nullptr;
public:
virtual bool can_create_resources_async() const;
@@ -1376,6 +1392,13 @@ public:
_FORCE_INLINE_ RID sampler_rd_get_default(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) {
return default_rd_samplers[p_filter][p_repeat];
}
+ _FORCE_INLINE_ RID sampler_rd_get_custom(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) {
+ return custom_rd_samplers[p_filter][p_repeat];
+ }
+
+ void sampler_rd_configure_custom(float mipmap_bias);
+
+ void sampler_rd_set_default(float p_mipmap_bias);
/* CANVAS TEXTURE API */
@@ -1399,8 +1422,8 @@ public:
String shader_get_code(RID p_shader) const;
void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const;
- void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture);
- RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const;
+ void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index);
+ RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const;
Variant shader_get_param_default(RID p_shader, const StringName &p_param) const;
void shader_set_data_request_function(ShaderType p_shader_type, ShaderDataRequestFunction p_function);
@@ -2259,6 +2282,21 @@ public:
virtual bool particles_collision_is_heightfield(RID p_particles_collision) const;
RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const;
+ /* FOG VOLUMES */
+
+ virtual RID fog_volume_allocate();
+ virtual void fog_volume_initialize(RID p_rid);
+
+ virtual void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape);
+ virtual void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents);
+ virtual void fog_volume_set_material(RID p_fog_volume, RID p_material);
+ virtual RS::FogVolumeShape fog_volume_get_shape(RID p_fog_volume) const;
+ virtual RID fog_volume_get_material(RID p_fog_volume) const;
+ virtual AABB fog_volume_get_aabb(RID p_fog_volume) const;
+ virtual Vector3 fog_volume_get_extents(RID p_fog_volume) const;
+
+ /* VISIBILITY NOTIFIER */
+
virtual RID visibility_notifier_allocate();
virtual void visibility_notifier_initialize(RID p_notifier);
virtual void visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb);
diff --git a/servers/rendering/renderer_rd/shader_compiler_rd.cpp b/servers/rendering/renderer_rd/shader_compiler_rd.cpp
index 4c26941dae..b02b3d2723 100644
--- a/servers/rendering/renderer_rd/shader_compiler_rd.cpp
+++ b/servers/rendering/renderer_rd/shader_compiler_rd.cpp
@@ -227,6 +227,13 @@ static String _prestr(SL::DataPrecision p_pres, bool p_force_highp = false) {
return "";
}
+static String _constr(bool p_is_const) {
+ if (p_is_const) {
+ return "const ";
+ }
+ return "";
+}
+
static String _qualstr(SL::ArgumentQualifier p_qual) {
switch (p_qual) {
case SL::ARGUMENT_QUALIFIER_IN:
@@ -417,9 +424,7 @@ void ShaderCompilerRD::_dump_function_deps(const SL::ShaderNode *p_node, const S
if (i > 0) {
header += ", ";
}
- if (fnode->arguments[i].is_const) {
- header += "const ";
- }
+ header += _constr(fnode->arguments[i].is_const);
if (fnode->arguments[i].type == SL::TYPE_STRUCT) {
header += _qualstr(fnode->arguments[i].qualifier) + _mkid(fnode->arguments[i].type_str) + " " + _mkid(fnode->arguments[i].name);
} else {
@@ -656,6 +661,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
uniform_sizes.write[uniform.order] = _get_datatype_size(ShaderLanguage::TYPE_UINT);
uniform_alignments.write[uniform.order] = _get_datatype_alignment(ShaderLanguage::TYPE_UINT);
} else {
+ // The following code enforces a 16-byte alignment of uniform arrays.
if (uniform.array_size > 0) {
int size = _get_datatype_size(uniform.type) * uniform.array_size;
int m = (16 * uniform.array_size);
@@ -663,10 +669,11 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
size += m - (size % m);
}
uniform_sizes.write[uniform.order] = size;
+ uniform_alignments.write[uniform.order] = 16;
} else {
uniform_sizes.write[uniform.order] = _get_datatype_size(uniform.type);
+ uniform_alignments.write[uniform.order] = _get_datatype_alignment(uniform.type);
}
- uniform_alignments.write[uniform.order] = _get_datatype_alignment(uniform.type);
}
}
@@ -791,7 +798,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
for (int i = 0; i < pnode->vconstants.size(); i++) {
const SL::ShaderNode::Constant &cnode = pnode->vconstants[i];
String gcode;
- gcode += "const ";
+ gcode += _constr(true);
gcode += _prestr(cnode.precision, ShaderLanguage::is_float_type(cnode.type));
if (cnode.type == SL::TYPE_STRUCT) {
gcode += _mkid(cnode.type_str);
@@ -875,9 +882,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
SL::VariableDeclarationNode *vdnode = (SL::VariableDeclarationNode *)p_node;
String declaration;
- if (vdnode->is_const) {
- declaration += "const ";
- }
+ declaration += _constr(vdnode->is_const);
if (vdnode->datatype == SL::TYPE_STRUCT) {
declaration += _mkid(vdnode->struct_name);
} else {
@@ -997,9 +1002,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
case SL::Node::TYPE_ARRAY_DECLARATION: {
SL::ArrayDeclarationNode *adnode = (SL::ArrayDeclarationNode *)p_node;
String declaration;
- if (adnode->is_const) {
- declaration += "const ";
- }
+ declaration += _constr(adnode->is_const);
if (adnode->datatype == SL::TYPE_STRUCT) {
declaration += _mkid(adnode->struct_name);
} else {
@@ -1315,6 +1318,9 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
code += ")";
} break;
+ case SL::OP_EMPTY: {
+ // Semicolon (or empty statement) - ignored.
+ } break;
default: {
if (p_use_scope) {
@@ -1421,7 +1427,7 @@ Error ShaderCompilerRD::compile(RS::ShaderMode p_mode, const String &p_code, Ide
}
}
- _err_print_error(nullptr, p_path.utf8().get_data(), parser.get_error_line(), parser.get_error_text().utf8().get_data(), ERR_HANDLER_SHADER);
+ _err_print_error(nullptr, p_path.utf8().get_data(), parser.get_error_line(), parser.get_error_text().utf8().get_data(), false, ERR_HANDLER_SHADER);
return err;
}
@@ -1463,6 +1469,7 @@ void ShaderCompilerRD::initialize(DefaultIdentifierActions p_actions) {
texture_functions.insert("textureLod");
texture_functions.insert("textureProjLod");
texture_functions.insert("textureGrad");
+ texture_functions.insert("textureGather");
texture_functions.insert("textureSize");
texture_functions.insert("texelFetch");
}
diff --git a/servers/rendering/renderer_rd/shader_rd.cpp b/servers/rendering/renderer_rd/shader_rd.cpp
index b9a8947fa2..2568090918 100644
--- a/servers/rendering/renderer_rd/shader_rd.cpp
+++ b/servers/rendering/renderer_rd/shader_rd.cpp
@@ -177,6 +177,9 @@ void ShaderRD::_build_variant_code(StringBuilder &builder, uint32_t p_variant, c
for (const KeyValue<StringName, CharString> &E : p_version->code_sections) {
builder.append(String("#define ") + String(E.key) + "_CODE_USED\n");
}
+#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+ builder.append("#define MOLTENVK_USED\n");
+#endif
} break;
case StageTemplate::Chunk::TYPE_MATERIAL_UNIFORMS: {
builder.append(p_version->uniforms.get_data()); //uniforms (same for vertex and fragment)
diff --git a/servers/rendering/renderer_rd/shaders/canvas.glsl b/servers/rendering/renderer_rd/shaders/canvas.glsl
index 2911e8b731..65a621b203 100644
--- a/servers/rendering/renderer_rd/shaders/canvas.glsl
+++ b/servers/rendering/renderer_rd/shaders/canvas.glsl
@@ -91,7 +91,6 @@ void main() {
uint instancing = draw_data.flags & FLAGS_INSTANCING_MASK;
#ifdef USE_ATTRIBUTES
-
if (instancing > 1) {
// trails
@@ -128,37 +127,37 @@ void main() {
vertex = new_vertex;
color *= pcolor;
-
} else
#endif // USE_ATTRIBUTES
+ {
+ if (instancing == 1) {
+ uint stride = 2;
+ {
+ if (bool(draw_data.flags & FLAGS_INSTANCING_HAS_COLORS)) {
+ stride += 1;
+ }
+ if (bool(draw_data.flags & FLAGS_INSTANCING_HAS_CUSTOM_DATA)) {
+ stride += 1;
+ }
+ }
+
+ uint offset = stride * gl_InstanceIndex;
+
+ mat4 matrix = mat4(transforms.data[offset + 0], transforms.data[offset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));
+ offset += 2;
- if (instancing == 1) {
- uint stride = 2;
- {
if (bool(draw_data.flags & FLAGS_INSTANCING_HAS_COLORS)) {
- stride += 1;
+ color *= transforms.data[offset];
+ offset += 1;
}
+
if (bool(draw_data.flags & FLAGS_INSTANCING_HAS_CUSTOM_DATA)) {
- stride += 1;
+ instance_custom = transforms.data[offset];
}
- }
-
- uint offset = stride * gl_InstanceIndex;
- mat4 matrix = mat4(transforms.data[offset + 0], transforms.data[offset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));
- offset += 2;
-
- if (bool(draw_data.flags & FLAGS_INSTANCING_HAS_COLORS)) {
- color *= transforms.data[offset];
- offset += 1;
- }
-
- if (bool(draw_data.flags & FLAGS_INSTANCING_HAS_CUSTOM_DATA)) {
- instance_custom = transforms.data[offset];
+ matrix = transpose(matrix);
+ world_matrix = world_matrix * matrix;
}
-
- matrix = transpose(matrix);
- world_matrix = world_matrix * matrix;
}
#if !defined(USE_ATTRIBUTES) && !defined(USE_PRIMITIVE)
diff --git a/servers/rendering/renderer_rd/shaders/fsr_upscale.glsl b/servers/rendering/renderer_rd/shaders/fsr_upscale.glsl
new file mode 100644
index 0000000000..4e2ba84033
--- /dev/null
+++ b/servers/rendering/renderer_rd/shaders/fsr_upscale.glsl
@@ -0,0 +1,173 @@
+/*************************************************************************/
+/* fsr_upscale.glsl */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#[compute]
+
+#version 450
+
+#VERSION_DEFINES
+
+#define A_GPU
+#define A_GLSL
+
+#ifdef MODE_FSR_UPSCALE_NORMAL
+
+#define A_HALF
+
+#endif
+
+#include "thirdparty/amd-fsr/ffx_a.h"
+
+layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
+
+layout(rgba16f, set = 1, binding = 0) uniform restrict writeonly image2D fsr_image;
+layout(set = 0, binding = 0) uniform sampler2D source_image;
+
+#define FSR_UPSCALE_PASS_TYPE_EASU 0
+#define FSR_UPSCALE_PASS_TYPE_RCAS 1
+
+layout(push_constant, binding = 1, std430) uniform Params {
+ float resolution_width;
+ float resolution_height;
+ float upscaled_width;
+ float upscaled_height;
+ float sharpness;
+ int pass;
+}
+params;
+
+AU4 Const0, Const1, Const2, Const3;
+
+#ifdef MODE_FSR_UPSCALE_FALLBACK
+
+#define FSR_EASU_F
+AF4 FsrEasuRF(AF2 p) {
+ AF4 res = textureGather(source_image, p, 0);
+ return res;
+}
+AF4 FsrEasuGF(AF2 p) {
+ AF4 res = textureGather(source_image, p, 1);
+ return res;
+}
+AF4 FsrEasuBF(AF2 p) {
+ AF4 res = textureGather(source_image, p, 2);
+ return res;
+}
+
+#define FSR_RCAS_F
+AF4 FsrRcasLoadF(ASU2 p) {
+ return AF4(texelFetch(source_image, ASU2(p), 0));
+}
+void FsrRcasInputF(inout AF1 r, inout AF1 g, inout AF1 b) {}
+
+#else
+
+#define FSR_EASU_H
+AH4 FsrEasuRH(AF2 p) {
+ AH4 res = AH4(textureGather(source_image, p, 0));
+ return res;
+}
+AH4 FsrEasuGH(AF2 p) {
+ AH4 res = AH4(textureGather(source_image, p, 1));
+ return res;
+}
+AH4 FsrEasuBH(AF2 p) {
+ AH4 res = AH4(textureGather(source_image, p, 2));
+ return res;
+}
+
+#define FSR_RCAS_H
+AH4 FsrRcasLoadH(ASW2 p) {
+ return AH4(texelFetch(source_image, ASU2(p), 0));
+}
+void FsrRcasInputH(inout AH1 r, inout AH1 g, inout AH1 b) {}
+
+#endif
+
+#include "thirdparty/amd-fsr/ffx_fsr1.h"
+
+void fsr_easu_pass(AU2 pos) {
+#ifdef MODE_FSR_UPSCALE_NORMAL
+
+ AH3 Gamma2Color = AH3(0, 0, 0);
+ FsrEasuH(Gamma2Color, pos, Const0, Const1, Const2, Const3);
+ imageStore(fsr_image, ASU2(pos), AH4(Gamma2Color, 1));
+
+#else
+
+ AF3 Gamma2Color = AF3(0, 0, 0);
+ FsrEasuF(Gamma2Color, pos, Const0, Const1, Const2, Const3);
+ imageStore(fsr_image, ASU2(pos), AF4(Gamma2Color, 1));
+
+#endif
+}
+
+void fsr_rcas_pass(AU2 pos) {
+#ifdef MODE_FSR_UPSCALE_NORMAL
+
+ AH3 Gamma2Color = AH3(0, 0, 0);
+ FsrRcasH(Gamma2Color.r, Gamma2Color.g, Gamma2Color.b, pos, Const0);
+ imageStore(fsr_image, ASU2(pos), AH4(Gamma2Color, 1));
+
+#else
+
+ AF3 Gamma2Color = AF3(0, 0, 0);
+ FsrRcasF(Gamma2Color.r, Gamma2Color.g, Gamma2Color.b, pos, Const0);
+ imageStore(fsr_image, ASU2(pos), AF4(Gamma2Color, 1));
+
+#endif
+}
+
+void fsr_pass(AU2 pos) {
+ if (params.pass == FSR_UPSCALE_PASS_TYPE_EASU) {
+ fsr_easu_pass(pos);
+ } else if (params.pass == FSR_UPSCALE_PASS_TYPE_RCAS) {
+ fsr_rcas_pass(pos);
+ }
+}
+
+void main() {
+ // Clang does not like unused functions. If ffx_a.h is included in the binary, clang will throw a fit and not compile so we must configure FSR in this shader
+ if (params.pass == FSR_UPSCALE_PASS_TYPE_EASU) {
+ FsrEasuCon(Const0, Const1, Const2, Const3, params.resolution_width, params.resolution_height, params.resolution_width, params.resolution_height, params.upscaled_width, params.upscaled_height);
+ } else if (params.pass == FSR_UPSCALE_PASS_TYPE_RCAS) {
+ FsrRcasCon(Const0, params.sharpness);
+ }
+
+ AU2 gxy = ARmp8x8(gl_LocalInvocationID.x) + AU2(gl_WorkGroupID.x << 4u, gl_WorkGroupID.y << 4u);
+
+ fsr_pass(gxy);
+ gxy.x += 8u;
+ fsr_pass(gxy);
+ gxy.y += 8u;
+ fsr_pass(gxy);
+ gxy.x -= 8u;
+ fsr_pass(gxy);
+}
diff --git a/servers/rendering/renderer_rd/shaders/particles.glsl b/servers/rendering/renderer_rd/shaders/particles.glsl
index 9f8410fd8a..328becbc20 100644
--- a/servers/rendering/renderer_rd/shaders/particles.glsl
+++ b/servers/rendering/renderer_rd/shaders/particles.glsl
@@ -567,11 +567,11 @@ void main() {
depth = particle_size - s;
const float EPSILON = 0.001;
normal = mat3(FRAME.colliders[i].transform) *
- normalize(
- vec3(
- texture(sampler3D(sdf_vec_textures[FRAME.colliders[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos + vec3(EPSILON, 0.0, 0.0)).r - texture(sampler3D(sdf_vec_textures[FRAME.colliders[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos - vec3(EPSILON, 0.0, 0.0)).r,
- texture(sampler3D(sdf_vec_textures[FRAME.colliders[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos + vec3(0.0, EPSILON, 0.0)).r - texture(sampler3D(sdf_vec_textures[FRAME.colliders[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos - vec3(0.0, EPSILON, 0.0)).r,
- texture(sampler3D(sdf_vec_textures[FRAME.colliders[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos + vec3(0.0, 0.0, EPSILON)).r - texture(sampler3D(sdf_vec_textures[FRAME.colliders[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos - vec3(0.0, 0.0, EPSILON)).r));
+ normalize(
+ vec3(
+ texture(sampler3D(sdf_vec_textures[FRAME.colliders[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos + vec3(EPSILON, 0.0, 0.0)).r - texture(sampler3D(sdf_vec_textures[FRAME.colliders[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos - vec3(EPSILON, 0.0, 0.0)).r,
+ texture(sampler3D(sdf_vec_textures[FRAME.colliders[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos + vec3(0.0, EPSILON, 0.0)).r - texture(sampler3D(sdf_vec_textures[FRAME.colliders[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos - vec3(0.0, EPSILON, 0.0)).r,
+ texture(sampler3D(sdf_vec_textures[FRAME.colliders[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos + vec3(0.0, 0.0, EPSILON)).r - texture(sampler3D(sdf_vec_textures[FRAME.colliders[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos - vec3(0.0, 0.0, EPSILON)).r));
}
} break;
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_aa_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_aa_inc.glsl
index 99714b4504..97c913d489 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_aa_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_aa_inc.glsl
@@ -2,7 +2,7 @@
float hash_2d(vec2 p) {
return fract(1.0e4 * sin(17.0 * p.x + 0.1 * p.y) *
- (0.1 + abs(sin(13.0 * p.y + p.x))));
+ (0.1 + abs(sin(13.0 * p.y + p.x))));
}
float hash_3d(vec3 p) {
@@ -29,8 +29,7 @@ float compute_alpha_hash_threshold(vec3 pos, float hash_scale) {
vec3 cases = vec3(a_interp * a_interp / (2.0 * min_lerp * (1.0 - min_lerp)),
(a_interp - 0.5 * min_lerp) / (1.0 - min_lerp),
- 1.0 - ((1.0 - a_interp) * (1.0 - a_interp) /
- (2.0 * min_lerp * (1.0 - min_lerp))));
+ 1.0 - ((1.0 - a_interp) * (1.0 - a_interp) / (2.0 * min_lerp * (1.0 - min_lerp))));
float alpha_hash_threshold =
(lerp_factor < (1.0 - min_lerp)) ? ((lerp_factor < min_lerp) ? cases.x : cases.y) : cases.z;
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
index f0fb31a457..e4628b2d5a 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
@@ -6,6 +6,8 @@
#include "scene_forward_clustered_inc.glsl"
+#define SHADER_IS_SRGB false
+
/* INPUT ATTRIBS */
layout(location = 0) in vec3 vertex_attrib;
@@ -95,7 +97,7 @@ layout(location = 8) out float dp_clip;
#endif
-layout(location = 9) out flat uint instance_index;
+layout(location = 9) out flat uint instance_index_interp;
invariant gl_Position;
@@ -107,13 +109,15 @@ void main() {
color_interp = color_attrib;
#endif
- instance_index = draw_call.instance_index;
+ uint instance_index = draw_call.instance_index;
bool is_multimesh = bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH);
if (!is_multimesh) {
instance_index += gl_InstanceIndex;
}
+ instance_index_interp = instance_index;
+
mat4 world_matrix = instances.data[instance_index].transform;
mat3 world_normal_matrix;
@@ -356,6 +360,8 @@ void main() {
#VERSION_DEFINES
+#define SHADER_IS_SRGB false
+
/* Specialization Constants (Toggles) */
layout(constant_id = 0) const bool sc_use_forward_gi = false;
@@ -410,7 +416,7 @@ layout(location = 8) in float dp_clip;
#endif
-layout(location = 9) in flat uint instance_index;
+layout(location = 9) in flat uint instance_index_interp;
//defines to keep compatibility with vertex
@@ -526,12 +532,12 @@ vec4 fog_process(vec3 vertex) {
float fog_amount = 1.0 - exp(min(0.0, -length(vertex) * scene_data.fog_density));
- if (abs(scene_data.fog_height_density) > 0.001) {
+ if (abs(scene_data.fog_height_density) >= 0.0001) {
float y = (scene_data.camera_matrix * vec4(vertex, 1.0)).y;
- float y_dist = scene_data.fog_height - y;
+ float y_dist = y - scene_data.fog_height;
- float vfog_amount = clamp(exp(y_dist * scene_data.fog_height_density), 0.0, 1.0);
+ float vfog_amount = 1.0 - exp(min(0.0, y_dist * scene_data.fog_height_density));
fog_amount = max(vfog_amount, fog_amount);
}
@@ -564,6 +570,8 @@ void main() {
discard;
#endif
+ uint instance_index = instance_index_interp;
+
//lay out everything, whathever is unused is optimized away anyway
vec3 vertex = vertex_interp;
vec3 view = -normalize(vertex_interp);
@@ -593,7 +601,7 @@ void main() {
float ao = 1.0;
float ao_light_affect = 0.0;
- float alpha = 1.0;
+ float alpha = float(instances.data[instance_index].flags >> INSTANCE_FLAGS_FADE_SHIFT) / float(255.0);
#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
vec3 binormal = normalize(binormal_interp);
@@ -687,7 +695,7 @@ void main() {
#endif // ALPHA_ANTIALIASING_EDGE_USED
#ifdef USE_OPAQUE_PREPASS
- if (alpha < opaque_prepass_threshold) {
+ if (alpha < scene_data.opaque_prepass_threshold) {
discard;
}
#endif // USE_OPAQUE_PREPASS
@@ -964,15 +972,15 @@ void main() {
const float c4 = 0.886227;
const float c5 = 0.247708;
ambient_light += (c1 * lightmap_captures.data[index].sh[8].rgb * (wnormal.x * wnormal.x - wnormal.y * wnormal.y) +
- c3 * lightmap_captures.data[index].sh[6].rgb * wnormal.z * wnormal.z +
- c4 * lightmap_captures.data[index].sh[0].rgb -
- c5 * lightmap_captures.data[index].sh[6].rgb +
- 2.0 * c1 * lightmap_captures.data[index].sh[4].rgb * wnormal.x * wnormal.y +
- 2.0 * c1 * lightmap_captures.data[index].sh[7].rgb * wnormal.x * wnormal.z +
- 2.0 * c1 * lightmap_captures.data[index].sh[5].rgb * wnormal.y * wnormal.z +
- 2.0 * c2 * lightmap_captures.data[index].sh[3].rgb * wnormal.x +
- 2.0 * c2 * lightmap_captures.data[index].sh[1].rgb * wnormal.y +
- 2.0 * c2 * lightmap_captures.data[index].sh[2].rgb * wnormal.z);
+ c3 * lightmap_captures.data[index].sh[6].rgb * wnormal.z * wnormal.z +
+ c4 * lightmap_captures.data[index].sh[0].rgb -
+ c5 * lightmap_captures.data[index].sh[6].rgb +
+ 2.0 * c1 * lightmap_captures.data[index].sh[4].rgb * wnormal.x * wnormal.y +
+ 2.0 * c1 * lightmap_captures.data[index].sh[7].rgb * wnormal.x * wnormal.z +
+ 2.0 * c1 * lightmap_captures.data[index].sh[5].rgb * wnormal.y * wnormal.z +
+ 2.0 * c2 * lightmap_captures.data[index].sh[3].rgb * wnormal.x +
+ 2.0 * c2 * lightmap_captures.data[index].sh[1].rgb * wnormal.y +
+ 2.0 * c2 * lightmap_captures.data[index].sh[2].rgb * wnormal.z);
} else if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP)) { // has actual lightmap
bool uses_sh = bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_SH_LIGHTMAP);
@@ -1249,9 +1257,10 @@ void main() {
// LIGHTING
#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
- { //directional light
+ { // Directional light.
- // Do shadow and lighting in two passes to reduce register pressure
+ // Do shadow and lighting in two passes to reduce register pressure.
+#ifndef SHADOWS_DISABLED
uint shadow0 = 0;
uint shadow1 = 0;
@@ -1270,21 +1279,21 @@ void main() {
float shadow = 1.0;
- //version with soft shadows, more expensive
if (directional_lights.data[i].shadow_enabled) {
- if (sc_use_directional_soft_shadows && directional_lights.data[i].softshadow_angle > 0) {
- float depth_z = -vertex.z;
-
- vec3 shadow_color = vec3(0.0);
- vec3 light_dir = directional_lights.data[i].direction;
+ float depth_z = -vertex.z;
+ vec3 light_dir = directional_lights.data[i].direction;
+ vec3 base_normal_bias = normalize(normal_interp) * (1.0 - max(0.0, dot(light_dir, -normalize(normal_interp))));
-#define BIAS_FUNC(m_var, m_idx) \
- m_var.xyz += light_dir * directional_lights.data[i].shadow_bias[m_idx]; \
- vec3 normal_bias = normalize(normal_interp) * (1.0 - max(0.0, dot(light_dir, -normalize(normal_interp)))) * directional_lights.data[i].shadow_normal_bias[m_idx]; \
- normal_bias -= light_dir * dot(light_dir, normal_bias); \
+#define BIAS_FUNC(m_var, m_idx) \
+ m_var.xyz += light_dir * directional_lights.data[i].shadow_bias[m_idx]; \
+ vec3 normal_bias = base_normal_bias * directional_lights.data[i].shadow_normal_bias[m_idx]; \
+ normal_bias -= light_dir * dot(light_dir, normal_bias); \
m_var.xyz += normal_bias;
- uint blend_index = 0;
+ //version with soft shadows, more expensive
+ if (sc_use_directional_soft_shadows && directional_lights.data[i].softshadow_angle > 0) {
+ uint blend_count = 0;
+ const uint blend_max = directional_lights.data[i].blend_splits ? 2 : 1;
if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
vec4 v = vec4(vertex, 1.0);
@@ -1299,10 +1308,10 @@ void main() {
float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
vec2 tex_scale = directional_lights.data[i].uv_scale1 * test_radius;
shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
- blend_index++;
+ blend_count++;
}
- if (blend_index < 2 && depth_z < directional_lights.data[i].shadow_split_offsets.y) {
+ if (blend_count < blend_max && depth_z < directional_lights.data[i].shadow_split_offsets.y) {
vec4 v = vec4(vertex, 1.0);
BIAS_FUNC(v, 1)
@@ -1316,7 +1325,7 @@ void main() {
vec2 tex_scale = directional_lights.data[i].uv_scale2 * test_radius;
float s = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
- if (blend_index == 0) {
+ if (blend_count == 0) {
shadow = s;
} else {
//blend
@@ -1324,10 +1333,10 @@ void main() {
shadow = mix(shadow, s, blend);
}
- blend_index++;
+ blend_count++;
}
- if (blend_index < 2 && depth_z < directional_lights.data[i].shadow_split_offsets.z) {
+ if (blend_count < blend_max && depth_z < directional_lights.data[i].shadow_split_offsets.z) {
vec4 v = vec4(vertex, 1.0);
BIAS_FUNC(v, 2)
@@ -1341,7 +1350,7 @@ void main() {
vec2 tex_scale = directional_lights.data[i].uv_scale3 * test_radius;
float s = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
- if (blend_index == 0) {
+ if (blend_count == 0) {
shadow = s;
} else {
//blend
@@ -1349,10 +1358,10 @@ void main() {
shadow = mix(shadow, s, blend);
}
- blend_index++;
+ blend_count++;
}
- if (blend_index < 2) {
+ if (blend_count < blend_max) {
vec4 v = vec4(vertex, 1.0);
BIAS_FUNC(v, 3)
@@ -1366,7 +1375,7 @@ void main() {
vec2 tex_scale = directional_lights.data[i].uv_scale4 * test_radius;
float s = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
- if (blend_index == 0) {
+ if (blend_count == 0) {
shadow = s;
} else {
//blend
@@ -1375,21 +1384,9 @@ void main() {
}
}
-#undef BIAS_FUNC
} else { //no soft shadows
- float depth_z = -vertex.z;
-
vec4 pssm_coord;
- vec3 light_dir = directional_lights.data[i].direction;
- vec3 base_normal_bias = normalize(normal_interp) * (1.0 - max(0.0, dot(light_dir, -normalize(normal_interp))));
-
-#define BIAS_FUNC(m_var, m_idx) \
- m_var.xyz += light_dir * directional_lights.data[i].shadow_bias[m_idx]; \
- vec3 normal_bias = base_normal_bias * directional_lights.data[i].shadow_normal_bias[m_idx]; \
- normal_bias -= light_dir * dot(light_dir, normal_bias); \
- m_var.xyz += normal_bias;
-
if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
vec4 v = vec4(vertex, 1.0);
@@ -1448,11 +1445,11 @@ void main() {
float shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
shadow = mix(shadow, shadow2, pssm_blend);
}
+ }
- shadow = mix(shadow, 1.0, smoothstep(directional_lights.data[i].fade_from, directional_lights.data[i].fade_to, vertex.z)); //done with negative values for performance
+ shadow = mix(shadow, 1.0, smoothstep(directional_lights.data[i].fade_from, directional_lights.data[i].fade_to, vertex.z)); //done with negative values for performance
#undef BIAS_FUNC
- }
} // shadows
if (i < 4) {
@@ -1461,6 +1458,7 @@ void main() {
shadow1 |= uint(clamp(shadow * 255.0, 0.0, 255.0)) << ((i - 4) * 8);
}
}
+#endif // SHADOWS_DISABLED
for (uint i = 0; i < 8; i++) {
if (i >= scene_data.directional_light_count) {
@@ -1523,18 +1521,19 @@ void main() {
#endif
float shadow = 1.0;
-
+#ifndef SHADOWS_DISABLED
if (i < 4) {
shadow = float(shadow0 >> (i * 8) & 0xFF) / 255.0;
} else {
shadow = float(shadow1 >> ((i - 4) * 8) & 0xFF) / 255.0;
}
+#endif
blur_shadow(shadow);
float size_A = sc_use_light_soft_shadows ? directional_lights.data[i].size : 0.0;
- light_compute(normal, directional_lights.data[i].direction, normalize(view), size_A, directional_lights.data[i].color * directional_lights.data[i].energy, shadow, f0, orms, 1.0,
+ light_compute(normal, directional_lights.data[i].direction, normalize(view), size_A, directional_lights.data[i].color * directional_lights.data[i].energy, shadow, f0, orms, 1.0, albedo, alpha,
#ifdef LIGHT_BACKLIGHT_USED
backlight,
#endif
@@ -1545,7 +1544,7 @@ void main() {
transmittance_z,
#endif
#ifdef LIGHT_RIM_USED
- rim, rim_tint, albedo,
+ rim, rim_tint,
#endif
#ifdef LIGHT_CLEARCOAT_USED
clearcoat, clearcoat_gloss,
@@ -1553,9 +1552,6 @@ void main() {
#ifdef LIGHT_ANISOTROPY_USED
binormal, tangent, anisotropy,
#endif
-#ifdef USE_SHADOW_TO_OPACITY
- alpha,
-#endif
diffuse_light,
specular_light);
}
@@ -1608,7 +1604,7 @@ void main() {
shadow = blur_shadow(shadow);
- light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow,
+ light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha,
#ifdef LIGHT_BACKLIGHT_USED
backlight,
#endif
@@ -1620,7 +1616,6 @@ void main() {
#ifdef LIGHT_RIM_USED
rim,
rim_tint,
- albedo,
#endif
#ifdef LIGHT_CLEARCOAT_USED
clearcoat, clearcoat_gloss,
@@ -1628,9 +1623,6 @@ void main() {
#ifdef LIGHT_ANISOTROPY_USED
tangent, binormal, anisotropy,
#endif
-#ifdef USE_SHADOW_TO_OPACITY
- alpha,
-#endif
diffuse_light, specular_light);
}
}
@@ -1684,7 +1676,7 @@ void main() {
shadow = blur_shadow(shadow);
- light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow,
+ light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha,
#ifdef LIGHT_BACKLIGHT_USED
backlight,
#endif
@@ -1696,7 +1688,6 @@ void main() {
#ifdef LIGHT_RIM_USED
rim,
rim_tint,
- albedo,
#endif
#ifdef LIGHT_CLEARCOAT_USED
clearcoat, clearcoat_gloss,
@@ -1704,9 +1695,6 @@ void main() {
#ifdef LIGHT_ANISOTROPY_USED
tangent, binormal, anisotropy,
#endif
-#ifdef USE_SHADOW_TO_OPACITY
- alpha,
-#endif
diffuse_light, specular_light);
}
}
@@ -1723,7 +1711,7 @@ void main() {
#ifdef USE_OPAQUE_PREPASS
- if (alpha < opaque_prepass_threshold) {
+ if (alpha < scene_data.opaque_prepass_threshold) {
discard;
}
@@ -1769,7 +1757,11 @@ void main() {
}
}
+#ifdef MOLTENVK_USED
+ imageStore(geom_facing_grid, grid_pos, uvec4(imageLoad(geom_facing_grid, grid_pos).r | facing_bits)); //store facing bits
+#else
imageAtomicOr(geom_facing_grid, grid_pos, facing_bits); //store facing bits
+#endif
if (length(emission) > 0.001) {
float lumas[6];
@@ -1909,7 +1901,6 @@ void main() {
// Draw "fixed" fog before volumetric fog to ensure volumetric fog can appear in front of the sky.
frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a);
- ;
#endif //MODE_MULTIPLE_RENDER_TARGETS
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 b943d81784..be29cf4f58 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl
@@ -68,6 +68,7 @@ layout(set = 0, binding = 4) uniform sampler light_projector_sampler;
#define INSTANCE_FLAGS_MULTIMESH_HAS_COLOR (1 << 14)
#define INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA (1 << 15)
#define INSTANCE_FLAGS_PARTICLE_TRAIL_SHIFT 16
+#define INSTANCE_FLAGS_FADE_SHIFT 24
//3 bits of stride
#define INSTANCE_FLAGS_PARTICLE_TRAIL_MASK 0xFF
@@ -207,7 +208,8 @@ layout(set = 1, binding = 0, std140) uniform SceneData {
float roughness_limiter_amount;
float roughness_limiter_limit;
- uvec2 roughness_limiter_pad;
+ float opaque_prepass_threshold;
+ uint roughness_limiter_pad;
mat4 sdf_to_bounds;
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 4d466342f8..d22f936a35 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
@@ -73,7 +73,7 @@ vec3 F0(float metallic, float specular, vec3 albedo) {
return mix(vec3(dielectric), albedo, vec3(metallic));
}
-void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float attenuation, vec3 f0, uint orms, float specular_amount,
+void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float attenuation, vec3 f0, uint orms, float specular_amount, vec3 albedo, inout float alpha,
#ifdef LIGHT_BACKLIGHT_USED
vec3 backlight,
#endif
@@ -84,7 +84,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte
float transmittance_z,
#endif
#ifdef LIGHT_RIM_USED
- float rim, float rim_tint, vec3 rim_color,
+ float rim, float rim_tint,
#endif
#ifdef LIGHT_CLEARCOAT_USED
float clearcoat, float clearcoat_gloss,
@@ -92,9 +92,6 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte
#ifdef LIGHT_ANISOTROPY_USED
vec3 B, vec3 T, float anisotropy,
#endif
-#ifdef USE_SHADOW_TO_OPACITY
- inout float alpha,
-#endif
inout vec3 diffuse_light, inout vec3 specular_light) {
vec4 orms_unpacked = unpackUnorm4x8(orms);
@@ -171,7 +168,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte
#if defined(LIGHT_RIM_USED)
float rim_light = pow(max(0.0, 1.0 - cNdotV), max(0.0, (1.0 - roughness) * 16.0));
- diffuse_light += rim_light * rim * mix(vec3(1.0), rim_color, rim_tint) * light_color;
+ diffuse_light += rim_light * rim * mix(vec3(1.0), albedo, rim_tint) * light_color;
#endif
#ifdef LIGHT_TRANSMITTANCE_USED
@@ -182,11 +179,11 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte
float d = scale * abs(transmittance_z);
float dd = -d * d;
vec3 profile = vec3(0.233, 0.455, 0.649) * exp(dd / 0.0064) +
- vec3(0.1, 0.336, 0.344) * exp(dd / 0.0484) +
- vec3(0.118, 0.198, 0.0) * exp(dd / 0.187) +
- vec3(0.113, 0.007, 0.007) * exp(dd / 0.567) +
- vec3(0.358, 0.004, 0.0) * exp(dd / 1.99) +
- vec3(0.078, 0.0, 0.0) * exp(dd / 7.41);
+ vec3(0.1, 0.336, 0.344) * exp(dd / 0.0484) +
+ vec3(0.118, 0.198, 0.0) * exp(dd / 0.187) +
+ vec3(0.113, 0.007, 0.007) * exp(dd / 0.567) +
+ vec3(0.358, 0.004, 0.0) * exp(dd / 1.99) +
+ vec3(0.078, 0.0, 0.0) * exp(dd / 7.41);
diffuse_light += profile * transmittance_color.a * light_color * clamp(transmittance_boost - NdotL, 0.0, 1.0) * (1.0 / M_PI);
#else
@@ -287,7 +284,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte
#endif //defined(LIGHT_CODE_USED)
}
-#ifndef USE_NO_SHADOWS
+#ifndef SHADOWS_DISABLED
// Interleaved Gradient Noise
// https://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare
@@ -301,7 +298,7 @@ float sample_directional_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, ve
float depth = coord.z;
//if only one sample is taken, take it from the center
- if (sc_directional_soft_shadow_samples == 1) {
+ if (sc_directional_soft_shadow_samples == 0) {
return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
}
@@ -327,7 +324,7 @@ float sample_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec3 coord) {
float depth = coord.z;
//if only one sample is taken, take it from the center
- if (sc_soft_shadow_samples == 1) {
+ if (sc_soft_shadow_samples == 0) {
return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
}
@@ -350,7 +347,7 @@ float sample_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec3 coord) {
float sample_omni_pcf_shadow(texture2D shadow, float blur_scale, vec2 coord, vec4 uv_rect, vec2 flip_offset, float depth) {
//if only one sample is taken, take it from the center
- if (sc_soft_shadow_samples == 1) {
+ if (sc_soft_shadow_samples == 0) {
vec2 pos = coord * 0.5 + 0.5;
pos = uv_rect.xy + pos * uv_rect.zw;
return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
@@ -433,7 +430,7 @@ float sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex
}
}
-#endif //USE_NO_SHADOWS
+#endif // SHADOWS_DISABLED
float get_omni_attenuation(float distance, float inv_range, float decay) {
float nd = distance * inv_range;
@@ -445,7 +442,7 @@ float get_omni_attenuation(float distance, float inv_range, float decay) {
}
float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {
-#ifndef USE_NO_SHADOWS
+#ifndef SHADOWS_DISABLED
if (omni_lights.data[idx].shadow_enabled) {
// there is a shadowmap
vec2 texel_size = scene_data.shadow_atlas_pixel_size;
@@ -577,7 +574,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {
return 1.0;
}
-void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 f0, uint orms, float shadow,
+void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 f0, uint orms, float shadow, vec3 albedo, inout float alpha,
#ifdef LIGHT_BACKLIGHT_USED
vec3 backlight,
#endif
@@ -587,7 +584,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
float transmittance_boost,
#endif
#ifdef LIGHT_RIM_USED
- float rim, float rim_tint, vec3 rim_color,
+ float rim, float rim_tint,
#endif
#ifdef LIGHT_CLEARCOAT_USED
float clearcoat, float clearcoat_gloss,
@@ -595,9 +592,6 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
#ifdef LIGHT_ANISOTROPY_USED
vec3 binormal, vec3 tangent, float anisotropy,
#endif
-#ifdef USE_SHADOW_TO_OPACITY
- inout float alpha,
-#endif
inout vec3 diffuse_light, inout vec3 specular_light) {
vec3 light_rel_vec = omni_lights.data[idx].position - vertex;
float light_length = length(light_rel_vec);
@@ -703,7 +697,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
light_attenuation *= shadow;
- light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, light_attenuation, f0, orms, omni_lights.data[idx].specular_amount,
+ light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, light_attenuation, f0, orms, omni_lights.data[idx].specular_amount, albedo, alpha,
#ifdef LIGHT_BACKLIGHT_USED
backlight,
#endif
@@ -714,7 +708,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
transmittance_z,
#endif
#ifdef LIGHT_RIM_USED
- rim * omni_attenuation, rim_tint, rim_color,
+ rim * omni_attenuation, rim_tint,
#endif
#ifdef LIGHT_CLEARCOAT_USED
clearcoat, clearcoat_gloss,
@@ -722,15 +716,12 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
#ifdef LIGHT_ANISOTROPY_USED
binormal, tangent, anisotropy,
#endif
-#ifdef USE_SHADOW_TO_OPACITY
- alpha,
-#endif
diffuse_light,
specular_light);
}
float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) {
-#ifndef USE_NO_SHADOWS
+#ifndef SHADOWS_DISABLED
if (spot_lights.data[idx].shadow_enabled) {
vec3 light_rel_vec = spot_lights.data[idx].position - vertex;
float light_length = length(light_rel_vec);
@@ -806,7 +797,7 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) {
return shadow;
}
-#endif //USE_NO_SHADOWS
+#endif // SHADOWS_DISABLED
return 1.0;
}
@@ -823,7 +814,7 @@ vec2 normal_to_panorama(vec3 n) {
return panorama_coords;
}
-void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 f0, uint orms, float shadow,
+void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 f0, uint orms, float shadow, vec3 albedo, inout float alpha,
#ifdef LIGHT_BACKLIGHT_USED
vec3 backlight,
#endif
@@ -833,7 +824,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
float transmittance_boost,
#endif
#ifdef LIGHT_RIM_USED
- float rim, float rim_tint, vec3 rim_color,
+ float rim, float rim_tint,
#endif
#ifdef LIGHT_CLEARCOAT_USED
float clearcoat, float clearcoat_gloss,
@@ -841,9 +832,6 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
#ifdef LIGHT_ANISOTROPY_USED
vec3 binormal, vec3 tangent, float anisotropy,
#endif
-#ifdef USE_SHADOW_TO_OPACITY
- inout float alpha,
-#endif
inout vec3 diffuse_light,
inout vec3 specular_light) {
vec3 light_rel_vec = spot_lights.data[idx].position - vertex;
@@ -910,7 +898,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
}
light_attenuation *= shadow;
- light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, light_attenuation, f0, orms, spot_lights.data[idx].specular_amount,
+ light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, light_attenuation, f0, orms, spot_lights.data[idx].specular_amount, albedo, alpha,
#ifdef LIGHT_BACKLIGHT_USED
backlight,
#endif
@@ -921,7 +909,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
transmittance_z,
#endif
#ifdef LIGHT_RIM_USED
- rim * spot_attenuation, rim_tint, rim_color,
+ rim * spot_attenuation, rim_tint,
#endif
#ifdef LIGHT_CLEARCOAT_USED
clearcoat, clearcoat_gloss,
@@ -929,9 +917,6 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
#ifdef LIGHT_ANISOTROPY_USED
binormal, tangent, anisotropy,
#endif
-#ifdef USE_SHADOW_TO_OPACITY
- alpha,
-#endif
diffuse_light, specular_light);
}
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
index 750ec5f00a..e92fbecfd0 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
@@ -7,6 +7,8 @@
/* Include our forward mobile UBOs definitions etc. */
#include "scene_forward_mobile_inc.glsl"
+#define SHADER_IS_SRGB false
+
/* INPUT ATTRIBS */
layout(location = 0) in vec3 vertex_attrib;
@@ -370,6 +372,8 @@ void main() {
#VERSION_DEFINES
+#define SHADER_IS_SRGB false
+
/* Specialization Constants */
#if !defined(MODE_RENDER_DEPTH)
@@ -552,12 +556,12 @@ vec4 fog_process(vec3 vertex) {
float fog_amount = 1.0 - exp(min(0.0, -length(vertex) * scene_data.fog_density));
- if (abs(scene_data.fog_height_density) > 0.001) {
+ if (abs(scene_data.fog_height_density) >= 0.0001) {
float y = (scene_data.camera_matrix * vec4(vertex, 1.0)).y;
- float y_dist = scene_data.fog_height - y;
+ float y_dist = y - scene_data.fog_height;
- float vfog_amount = clamp(exp(y_dist * scene_data.fog_height_density), 0.0, 1.0);
+ float vfog_amount = 1.0 - exp(min(0.0, y_dist * scene_data.fog_height_density));
fog_amount = max(vfog_amount, fog_amount);
}
@@ -701,7 +705,7 @@ void main() {
#endif // ALPHA_ANTIALIASING_EDGE_USED
#ifdef USE_OPAQUE_PREPASS
- if (alpha < opaque_prepass_threshold) {
+ if (alpha < scene_data.opaque_prepass_threshold) {
discard;
}
#endif // USE_OPAQUE_PREPASS
@@ -930,15 +934,15 @@ void main() {
const float c4 = 0.886227;
const float c5 = 0.247708;
ambient_light += (c1 * lightmap_captures.data[index].sh[8].rgb * (wnormal.x * wnormal.x - wnormal.y * wnormal.y) +
- c3 * lightmap_captures.data[index].sh[6].rgb * wnormal.z * wnormal.z +
- c4 * lightmap_captures.data[index].sh[0].rgb -
- c5 * lightmap_captures.data[index].sh[6].rgb +
- 2.0 * c1 * lightmap_captures.data[index].sh[4].rgb * wnormal.x * wnormal.y +
- 2.0 * c1 * lightmap_captures.data[index].sh[7].rgb * wnormal.x * wnormal.z +
- 2.0 * c1 * lightmap_captures.data[index].sh[5].rgb * wnormal.y * wnormal.z +
- 2.0 * c2 * lightmap_captures.data[index].sh[3].rgb * wnormal.x +
- 2.0 * c2 * lightmap_captures.data[index].sh[1].rgb * wnormal.y +
- 2.0 * c2 * lightmap_captures.data[index].sh[2].rgb * wnormal.z);
+ c3 * lightmap_captures.data[index].sh[6].rgb * wnormal.z * wnormal.z +
+ c4 * lightmap_captures.data[index].sh[0].rgb -
+ c5 * lightmap_captures.data[index].sh[6].rgb +
+ 2.0 * c1 * lightmap_captures.data[index].sh[4].rgb * wnormal.x * wnormal.y +
+ 2.0 * c1 * lightmap_captures.data[index].sh[7].rgb * wnormal.x * wnormal.z +
+ 2.0 * c1 * lightmap_captures.data[index].sh[5].rgb * wnormal.y * wnormal.z +
+ 2.0 * c2 * lightmap_captures.data[index].sh[3].rgb * wnormal.x +
+ 2.0 * c2 * lightmap_captures.data[index].sh[1].rgb * wnormal.y +
+ 2.0 * c2 * lightmap_captures.data[index].sh[2].rgb * wnormal.z);
} else if (bool(draw_call.flags & INSTANCE_FLAGS_USE_LIGHTMAP)) { // has actual lightmap
bool uses_sh = bool(draw_call.flags & INSTANCE_FLAGS_USE_SH_LIGHTMAP);
@@ -1046,7 +1050,7 @@ void main() {
#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
if (!sc_disable_directional_lights) { //directional light
-
+#ifndef SHADOWS_DISABLED
// Do shadow and lighting in two passes to reduce register pressure
uint shadow0 = 0;
uint shadow1 = 0;
@@ -1322,6 +1326,8 @@ void main() {
}
}
+#endif // SHADOWS_DISABLED
+
for (uint i = 0; i < 8; i++) {
if (i >= scene_data.directional_light_count) {
break;
@@ -1334,16 +1340,16 @@ void main() {
// We're not doing light transmittence
float shadow = 1.0;
-
+#ifndef SHADOWS_DISABLED
if (i < 4) {
shadow = float(shadow0 >> (i * 8) & 0xFF) / 255.0;
} else {
shadow = float(shadow1 >> ((i - 4) * 8) & 0xFF) / 255.0;
}
-
+#endif
blur_shadow(shadow);
- light_compute(normal, directional_lights.data[i].direction, normalize(view), 0.0, directional_lights.data[i].color * directional_lights.data[i].energy, shadow, f0, orms, 1.0,
+ light_compute(normal, directional_lights.data[i].direction, normalize(view), 0.0, directional_lights.data[i].color * directional_lights.data[i].energy, shadow, f0, orms, 1.0, albedo, alpha,
#ifdef LIGHT_BACKLIGHT_USED
backlight,
#endif
@@ -1356,7 +1362,7 @@ void main() {
#endif
*/
#ifdef LIGHT_RIM_USED
- rim, rim_tint, albedo,
+ rim, rim_tint,
#endif
#ifdef LIGHT_CLEARCOAT_USED
clearcoat, clearcoat_gloss,
@@ -1367,9 +1373,6 @@ void main() {
#ifdef USE_SOFT_SHADOW
directional_lights.data[i].size,
#endif
-#ifdef USE_SHADOW_TO_OPACITY
- alpha,
-#endif
diffuse_light,
specular_light);
}
@@ -1393,7 +1396,7 @@ void main() {
shadow = blur_shadow(shadow);
- light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow,
+ light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha,
#ifdef LIGHT_BACKLIGHT_USED
backlight,
#endif
@@ -1407,7 +1410,6 @@ void main() {
#ifdef LIGHT_RIM_USED
rim,
rim_tint,
- albedo,
#endif
#ifdef LIGHT_CLEARCOAT_USED
clearcoat, clearcoat_gloss,
@@ -1415,9 +1417,6 @@ void main() {
#ifdef LIGHT_ANISOTROPY_USED
tangent, binormal, anisotropy,
#endif
-#ifdef USE_SHADOW_TO_OPACITY
- alpha,
-#endif
diffuse_light, specular_light);
}
} //omni lights
@@ -1441,7 +1440,7 @@ void main() {
shadow = blur_shadow(shadow);
- light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow,
+ light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha,
#ifdef LIGHT_BACKLIGHT_USED
backlight,
#endif
@@ -1455,7 +1454,6 @@ void main() {
#ifdef LIGHT_RIM_USED
rim,
rim_tint,
- albedo,
#endif
#ifdef LIGHT_CLEARCOAT_USED
clearcoat, clearcoat_gloss,
@@ -1463,9 +1461,6 @@ void main() {
#ifdef LIGHT_ANISOTROPY_USED
tangent, binormal, anisotropy,
#endif
-#ifdef USE_SHADOW_TO_OPACITY
- alpha,
-#endif
diffuse_light, specular_light);
}
} //spot lights
@@ -1481,7 +1476,7 @@ void main() {
#ifdef USE_OPAQUE_PREPASS
- if (alpha < opaque_prepass_threshold) {
+ if (alpha < scene_data.opaque_prepass_threshold) {
discard;
}
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 eb8fb49598..a9a4fce82a 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl
@@ -168,7 +168,8 @@ layout(set = 1, binding = 0, std140) uniform SceneData {
mediump float roughness_limiter_amount;
mediump float roughness_limiter_limit;
- uvec2 roughness_limiter_pad;
+ mediump float opaque_prepass_threshold;
+ uint roughness_limiter_pad;
bool fog_enabled;
highp float fog_density;
diff --git a/servers/rendering/renderer_rd/shaders/tonemap.glsl b/servers/rendering/renderer_rd/shaders/tonemap.glsl
index 1ce3e04421..948c6e1e39 100644
--- a/servers/rendering/renderer_rd/shaders/tonemap.glsl
+++ b/servers/rendering/renderer_rd/shaders/tonemap.glsl
@@ -140,7 +140,7 @@ vec4 texture2D_bicubic(sampler2D tex, vec2 uv, int p_lod) {
vec2 p3 = (vec2(iuv.x + h1x, iuv.y + h1y) - vec2(0.5f)) * pixel_size;
return (g0(fuv.y) * (g0x * textureLod(tex, p0, lod) + g1x * textureLod(tex, p1, lod))) +
- (g1(fuv.y) * (g0x * textureLod(tex, p2, lod) + g1x * textureLod(tex, p3, lod)));
+ (g1(fuv.y) * (g0x * textureLod(tex, p2, lod) + g1x * textureLod(tex, p3, lod)));
}
#define GLOW_TEXTURE_SAMPLE(m_tex, m_uv, m_lod) texture2D_bicubic(m_tex, m_uv, m_lod)
@@ -341,14 +341,14 @@ vec3 do_fxaa(vec3 color, float exposure, vec2 uv_interp) {
dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));
float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) *
- (0.25 * FXAA_REDUCE_MUL),
+ (0.25 * FXAA_REDUCE_MUL),
FXAA_REDUCE_MIN);
float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce);
dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX),
max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),
dir * rcpDirMin)) *
- params.pixel_size;
+ params.pixel_size;
#ifdef MULTIVIEW
vec3 rgbA = 0.5 * exposure * (textureLod(source_color, vec3(uv_interp + dir * (1.0 / 3.0 - 0.5), ViewIndex), 0.0).xyz + textureLod(source_color, vec3(uv_interp + dir * (2.0 / 3.0 - 0.5), ViewIndex), 0.0).xyz) * params.luminance_multiplier;
diff --git a/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl b/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl
index f2010222e5..181d3b272f 100644
--- a/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl
+++ b/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl
@@ -4,219 +4,103 @@
#VERSION_DEFINES
-/* Do not use subgroups here, seems there is not much advantage and causes glitches
-#if defined(has_GL_KHR_shader_subgroup_ballot) && defined(has_GL_KHR_shader_subgroup_arithmetic)
-#extension GL_KHR_shader_subgroup_ballot: enable
-#extension GL_KHR_shader_subgroup_arithmetic: enable
-
-#define USE_SUBGROUPS
-#endif
-*/
-
-#if defined(MODE_FOG) || defined(MODE_FILTER)
-
-layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
-
-#endif
-
-#if defined(MODE_DENSITY)
-
layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in;
-#endif
+#define SAMPLER_NEAREST_CLAMP 0
+#define SAMPLER_LINEAR_CLAMP 1
+#define SAMPLER_NEAREST_WITH_MIPMAPS_CLAMP 2
+#define SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP 3
+#define SAMPLER_NEAREST_WITH_MIPMAPS_ANISOTROPIC_CLAMP 4
+#define SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_CLAMP 5
+#define SAMPLER_NEAREST_REPEAT 6
+#define SAMPLER_LINEAR_REPEAT 7
+#define SAMPLER_NEAREST_WITH_MIPMAPS_REPEAT 8
+#define SAMPLER_LINEAR_WITH_MIPMAPS_REPEAT 9
+#define SAMPLER_NEAREST_WITH_MIPMAPS_ANISOTROPIC_REPEAT 10
+#define SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_REPEAT 11
+
+#define DENSITY_SCALE 1024.0
#include "cluster_data_inc.glsl"
#include "light_data_inc.glsl"
#define M_PI 3.14159265359
-layout(set = 0, binding = 1) uniform texture2D shadow_atlas;
-layout(set = 0, binding = 2) uniform texture2D directional_shadow_atlas;
-
-layout(set = 0, binding = 3, std430) restrict readonly buffer OmniLights {
- LightData data[];
-}
-omni_lights;
-
-layout(set = 0, binding = 4, std430) restrict readonly buffer SpotLights {
- LightData data[];
-}
-spot_lights;
+layout(set = 0, binding = 1) uniform sampler material_samplers[12];
-layout(set = 0, binding = 5, std140) uniform DirectionalLights {
- DirectionalLightData data[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS];
+layout(set = 0, binding = 2, std430) restrict readonly buffer GlobalVariableData {
+ vec4 data[];
}
-directional_lights;
-
-layout(set = 0, binding = 6, std430) buffer restrict readonly ClusterBuffer {
- uint data[];
-}
-cluster_buffer;
-
-layout(set = 0, binding = 7) uniform sampler linear_sampler;
-
-#ifdef MODE_DENSITY
-layout(rgba16f, set = 0, binding = 8) uniform restrict writeonly image3D density_map;
-layout(rgba16f, set = 0, binding = 9) uniform restrict readonly image3D fog_map; //unused
-#endif
-
-#ifdef MODE_FOG
-layout(rgba16f, set = 0, binding = 8) uniform restrict readonly image3D density_map;
-layout(rgba16f, set = 0, binding = 9) uniform restrict writeonly image3D fog_map;
-#endif
-
-#ifdef MODE_FILTER
-layout(rgba16f, set = 0, binding = 8) uniform restrict readonly image3D source_map;
-layout(rgba16f, set = 0, binding = 9) uniform restrict writeonly image3D dest_map;
-#endif
-
-layout(set = 0, binding = 10) uniform sampler shadow_sampler;
-
-#define MAX_VOXEL_GI_INSTANCES 8
-
-struct VoxelGIData {
- mat4 xform;
- vec3 bounds;
- float dynamic_range;
+global_variables;
- float bias;
- float normal_bias;
- bool blend_ambient;
- uint texture_slot;
-
- float anisotropy_strength;
- float ambient_occlusion;
- float ambient_occlusion_size;
- uint mipmaps;
-};
-
-layout(set = 0, binding = 11, std140) uniform VoxelGIs {
- VoxelGIData data[MAX_VOXEL_GI_INSTANCES];
-}
-voxel_gi_instances;
-
-layout(set = 0, binding = 12) uniform texture3D voxel_gi_textures[MAX_VOXEL_GI_INSTANCES];
-
-layout(set = 0, binding = 13) uniform sampler linear_sampler_with_mipmaps;
-
-#ifdef ENABLE_SDFGI
-
-// SDFGI Integration on set 1
-#define SDFGI_MAX_CASCADES 8
-
-struct SDFVoxelGICascadeData {
+layout(push_constant, binding = 0, std430) uniform Params {
vec3 position;
- float to_probe;
- ivec3 probe_world_offset;
- float to_cell; // 1/bounds * grid_size
-};
-
-layout(set = 1, binding = 0, std140) uniform SDFGI {
- vec3 grid_size;
- uint max_cascades;
-
- bool use_occlusion;
- int probe_axis_size;
- float probe_to_uvw;
- float normal_bias;
+ float pad;
- vec3 lightprobe_tex_pixel_size;
- float energy;
+ vec3 extents;
+ float pad2;
- vec3 lightprobe_uv_offset;
- float y_mult;
+ ivec3 corner;
+ uint shape;
- vec3 occlusion_clamp;
- uint pad3;
-
- vec3 occlusion_renormalize;
- uint pad4;
-
- vec3 cascade_probe_size;
- uint pad5;
-
- SDFVoxelGICascadeData cascades[SDFGI_MAX_CASCADES];
+ mat4 transform;
}
-sdfgi;
-
-layout(set = 1, binding = 1) uniform texture2DArray sdfgi_ambient_texture;
-
-layout(set = 1, binding = 2) uniform texture3D sdfgi_occlusion_texture;
+params;
-#endif //SDFGI
+#ifdef MOLTENVK_USED
+layout(set = 1, binding = 1) volatile buffer emissive_only_map_buffer {
+ uint emissive_only_map[];
+};
+#else
+layout(r32ui, set = 1, binding = 1) uniform volatile uimage3D emissive_only_map;
+#endif
-layout(set = 0, binding = 14, std140) uniform Params {
+layout(set = 1, binding = 2, std140) uniform SceneParams {
vec2 fog_frustum_size_begin;
vec2 fog_frustum_size_end;
float fog_frustum_end;
- float z_near;
- float z_far;
- int filter_axis;
+ float z_near; //
+ float z_far; //
+ float time;
ivec3 fog_volume_size;
- uint directional_light_count;
-
- vec3 light_color;
- float base_density;
-
- float detail_spread;
- float gi_inject;
- uint max_voxel_gi_instances;
- uint cluster_type_size;
+ uint directional_light_count; //
- vec2 screen_size;
- uint cluster_shift;
- uint cluster_width;
-
- uint max_cluster_element_count_div_32;
bool use_temporal_reprojection;
uint temporal_frame;
+ float detail_spread;
float temporal_blend;
- mat3x4 cam_rotation;
mat4 to_prev_view;
+ mat4 transform;
}
-params;
-
-layout(set = 0, binding = 15) uniform texture3D prev_density_texture;
+scene_params;
-float get_depth_at_pos(float cell_depth_size, int z) {
- float d = float(z) * cell_depth_size + cell_depth_size * 0.5; //center of voxels
- d = pow(d, params.detail_spread);
- return params.fog_frustum_end * d;
-}
-
-vec3 hash3f(uvec3 x) {
- x = ((x >> 16) ^ x) * 0x45d9f3b;
- x = ((x >> 16) ^ x) * 0x45d9f3b;
- x = (x >> 16) ^ x;
- return vec3(x & 0xFFFFF) / vec3(float(0xFFFFF));
-}
-
-float get_omni_attenuation(float distance, float inv_range, float decay) {
- float nd = distance * inv_range;
- nd *= nd;
- nd *= nd; // nd^4
- nd = max(1.0 - nd, 0.0);
- nd *= nd; // nd^2
- return nd * pow(max(distance, 0.0001), -decay);
-}
+#ifdef MOLTENVK_USED
+layout(set = 1, binding = 3) volatile buffer density_only_map_buffer {
+ uint density_only_map[];
+};
+layout(set = 1, binding = 4) volatile buffer light_only_map_buffer {
+ uint light_only_map[];
+};
+#else
+layout(r32ui, set = 1, binding = 3) uniform volatile uimage3D density_only_map;
+layout(r32ui, set = 1, binding = 4) uniform volatile uimage3D light_only_map;
+#endif
-void cluster_get_item_range(uint p_offset, out uint item_min, out uint item_max, out uint item_from, out uint item_to) {
- uint item_min_max = cluster_buffer.data[p_offset];
- item_min = item_min_max & 0xFFFF;
- item_max = item_min_max >> 16;
- ;
+#ifdef MATERIAL_UNIFORMS_USED
+layout(set = 2, binding = 0, std140) uniform MaterialUniforms{
+#MATERIAL_UNIFORMS
+} material;
+#endif
- 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
-}
+#GLOBALS
-uint cluster_get_range_clip_mask(uint i, uint z_min, uint z_max) {
- int local_min = clamp(int(z_min) - int(i) * 32, 0, 31);
- int mask_width = min(int(z_max) - int(z_min), 32 - local_min);
- return bitfieldInsert(uint(0), uint(0xFFFFFFFF), local_min, mask_width);
+float get_depth_at_pos(float cell_depth_size, int z) {
+ float d = float(z) * cell_depth_size + cell_depth_size * 0.5; //center of voxels
+ d = pow(d, scene_params.detail_spread);
+ return scene_params.fog_frustum_end * d;
}
#define TEMPORAL_FRAMES 16
@@ -240,464 +124,167 @@ const vec3 halton_map[TEMPORAL_FRAMES] = vec3[](
vec3(0.03125, 0.59259259, 0.32));
void main() {
- vec3 fog_cell_size = 1.0 / vec3(params.fog_volume_size);
+ vec3 fog_cell_size = 1.0 / vec3(scene_params.fog_volume_size);
-#ifdef MODE_DENSITY
-
- ivec3 pos = ivec3(gl_GlobalInvocationID.xyz);
- if (any(greaterThanEqual(pos, params.fog_volume_size))) {
+ ivec3 pos = ivec3(gl_GlobalInvocationID.xyz) + params.corner;
+ if (any(greaterThanEqual(pos, scene_params.fog_volume_size))) {
return; //do not compute
}
+#ifdef MOLTENVK_USED
+ uint lpos = pos.z * scene_params.fog_volume_size.x * scene_params.fog_volume_size.y + pos.y * scene_params.fog_volume_size.x + pos.x;
+#endif
vec3 posf = vec3(pos);
- //posf += mix(vec3(0.0),vec3(1.0),0.3) * hash3f(uvec3(pos)) * 2.0 - 1.0;
-
vec3 fog_unit_pos = posf * fog_cell_size + fog_cell_size * 0.5; //center of voxels
-
- uvec2 screen_pos = uvec2(fog_unit_pos.xy * params.screen_size);
- uvec2 cluster_pos = screen_pos >> params.cluster_shift;
- uint cluster_offset = (params.cluster_width * cluster_pos.y + cluster_pos.x) * (params.max_cluster_element_count_div_32 + 32);
- //positions in screen are too spread apart, no hopes for optimizing with subgroups
-
- fog_unit_pos.z = pow(fog_unit_pos.z, params.detail_spread);
+ fog_unit_pos.z = pow(fog_unit_pos.z, scene_params.detail_spread);
vec3 view_pos;
- view_pos.xy = (fog_unit_pos.xy * 2.0 - 1.0) * mix(params.fog_frustum_size_begin, params.fog_frustum_size_end, vec2(fog_unit_pos.z));
- view_pos.z = -params.fog_frustum_end * fog_unit_pos.z;
+ view_pos.xy = (fog_unit_pos.xy * 2.0 - 1.0) * mix(scene_params.fog_frustum_size_begin, scene_params.fog_frustum_size_end, vec2(fog_unit_pos.z));
+ view_pos.z = -scene_params.fog_frustum_end * fog_unit_pos.z;
view_pos.y = -view_pos.y;
- vec4 reprojected_density = vec4(0.0);
- float reproject_amount = 0.0;
-
- if (params.use_temporal_reprojection) {
- vec3 prev_view = (params.to_prev_view * vec4(view_pos, 1.0)).xyz;
+ if (scene_params.use_temporal_reprojection) {
+ vec3 prev_view = (scene_params.to_prev_view * vec4(view_pos, 1.0)).xyz;
//undo transform into prev view
prev_view.y = -prev_view.y;
//z back to unit size
- prev_view.z /= -params.fog_frustum_end;
+ prev_view.z /= -scene_params.fog_frustum_end;
//xy back to unit size
- prev_view.xy /= mix(params.fog_frustum_size_begin, params.fog_frustum_size_end, vec2(prev_view.z));
+ prev_view.xy /= mix(scene_params.fog_frustum_size_begin, scene_params.fog_frustum_size_end, vec2(prev_view.z));
prev_view.xy = prev_view.xy * 0.5 + 0.5;
//z back to unspread value
- prev_view.z = pow(prev_view.z, 1.0 / params.detail_spread);
+ prev_view.z = pow(prev_view.z, 1.0 / scene_params.detail_spread);
if (all(greaterThan(prev_view, vec3(0.0))) && all(lessThan(prev_view, vec3(1.0)))) {
//reprojectinon fits
-
- reprojected_density = textureLod(sampler3D(prev_density_texture, linear_sampler), prev_view, 0.0);
- reproject_amount = params.temporal_blend;
-
// Since we can reproject, now we must jitter the current view pos.
// This is done here because cells that can't reproject should not jitter.
- fog_unit_pos = posf * fog_cell_size + fog_cell_size * halton_map[params.temporal_frame]; //center of voxels, offset by halton table
-
- screen_pos = uvec2(fog_unit_pos.xy * params.screen_size);
- cluster_pos = screen_pos >> params.cluster_shift;
- cluster_offset = (params.cluster_width * cluster_pos.y + cluster_pos.x) * (params.max_cluster_element_count_div_32 + 32);
- //positions in screen are too spread apart, no hopes for optimizing with subgroups
+ fog_unit_pos = posf * fog_cell_size + fog_cell_size * halton_map[scene_params.temporal_frame]; //center of voxels, offset by halton table
+ fog_unit_pos.z = pow(fog_unit_pos.z, scene_params.detail_spread);
- fog_unit_pos.z = pow(fog_unit_pos.z, params.detail_spread);
-
- view_pos.xy = (fog_unit_pos.xy * 2.0 - 1.0) * mix(params.fog_frustum_size_begin, params.fog_frustum_size_end, vec2(fog_unit_pos.z));
- view_pos.z = -params.fog_frustum_end * fog_unit_pos.z;
+ view_pos.xy = (fog_unit_pos.xy * 2.0 - 1.0) * mix(scene_params.fog_frustum_size_begin, scene_params.fog_frustum_size_end, vec2(fog_unit_pos.z));
+ view_pos.z = -scene_params.fog_frustum_end * fog_unit_pos.z;
view_pos.y = -view_pos.y;
}
}
- uint cluster_z = uint(clamp((abs(view_pos.z) / params.z_far) * 32.0, 0.0, 31.0));
-
- vec3 total_light = params.light_color;
+ float density = 0.0;
+ vec3 emission = vec3(0.0);
+ vec3 albedo = vec3(0.0);
- float total_density = params.base_density;
float cell_depth_size = abs(view_pos.z - get_depth_at_pos(fog_cell_size.z, pos.z + 1));
- //compute directional lights
-
- for (uint i = 0; i < params.directional_light_count; i++) {
- vec3 shadow_attenuation = vec3(1.0);
-
- if (directional_lights.data[i].shadow_enabled) {
- float depth_z = -view_pos.z;
-
- vec4 pssm_coord;
- vec3 shadow_color = directional_lights.data[i].shadow_color1.rgb;
- vec3 light_dir = directional_lights.data[i].direction;
- vec4 v = vec4(view_pos, 1.0);
- float z_range;
-
- if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
- pssm_coord = (directional_lights.data[i].shadow_matrix1 * v);
- pssm_coord /= pssm_coord.w;
- z_range = directional_lights.data[i].shadow_z_range.x;
-
- } else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
- pssm_coord = (directional_lights.data[i].shadow_matrix2 * v);
- pssm_coord /= pssm_coord.w;
- z_range = directional_lights.data[i].shadow_z_range.y;
-
- } else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
- pssm_coord = (directional_lights.data[i].shadow_matrix3 * v);
- pssm_coord /= pssm_coord.w;
- z_range = directional_lights.data[i].shadow_z_range.z;
-
- } else {
- pssm_coord = (directional_lights.data[i].shadow_matrix4 * v);
- pssm_coord /= pssm_coord.w;
- z_range = directional_lights.data[i].shadow_z_range.w;
- }
-
- float depth = texture(sampler2D(directional_shadow_atlas, linear_sampler), pssm_coord.xy).r;
- float shadow = exp(min(0.0, (depth - pssm_coord.z)) * z_range * directional_lights.data[i].shadow_volumetric_fog_fade);
-
- /*
- //float shadow = textureProj(sampler2DShadow(directional_shadow_atlas,shadow_sampler),pssm_coord);
- float shadow = 0.0;
- for(float xi=-1;xi<=1;xi++) {
- for(float yi=-1;yi<=1;yi++) {
- vec2 ofs = vec2(xi,yi) * 1.5 * params.directional_shadow_pixel_size;
- shadow += textureProj(sampler2DShadow(directional_shadow_atlas,shadow_sampler),pssm_coord + vec4(ofs,0.0,0.0));
- }
-
- }
-
- shadow /= 3.0 * 3.0;
-*/
- shadow = mix(shadow, 1.0, smoothstep(directional_lights.data[i].fade_from, directional_lights.data[i].fade_to, view_pos.z)); //done with negative values for performance
-
- shadow_attenuation = mix(shadow_color, vec3(1.0), shadow);
- }
-
- total_light += shadow_attenuation * directional_lights.data[i].color * directional_lights.data[i].energy / M_PI;
+ vec4 world = scene_params.transform * vec4(view_pos, 1.0);
+ world.xyz /= world.w;
+
+ vec3 uvw = fog_unit_pos;
+
+ vec4 local_pos = params.transform * world;
+ local_pos.xyz /= local_pos.w;
+
+ float sdf = -1.0;
+ if (params.shape == 0) {
+ //Ellipsoid
+ // https://www.shadertoy.com/view/tdS3DG
+ float k0 = length(local_pos.xyz / params.extents);
+ float k1 = length(local_pos.xyz / (params.extents * params.extents));
+ sdf = k0 * (k0 - 1.0) / k1;
+ } else if (params.shape == 1) {
+ // Box
+ // https://iquilezles.org/www/articles/distfunctions/distfunctions.htm
+ vec3 q = abs(local_pos.xyz) - params.extents;
+ sdf = length(max(q, 0.0)) + min(max(q.x, max(q.y, q.z)), 0.0);
}
- //compute lights from cluster
-
- { //omni lights
-
- uint cluster_omni_offset = cluster_offset;
-
- uint item_min;
- uint item_max;
- uint item_from;
- uint item_to;
-
- cluster_get_item_range(cluster_omni_offset + params.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to);
-
-#ifdef USE_SUBGROUPS
- item_from = subgroupBroadcastFirst(subgroupMin(item_from));
- item_to = subgroupBroadcastFirst(subgroupMax(item_to));
+ float cull_mask = 1.0; //used to cull cells that do not contribute
+ if (params.shape <= 1) {
+#ifndef SDF_USED
+ cull_mask = 1.0 - smoothstep(-0.1, 0.0, sdf);
#endif
+ uvw = clamp((local_pos.xyz + params.extents) / (2.0 * params.extents), 0.0, 1.0);
+ }
- for (uint i = item_from; i < item_to; i++) {
- uint mask = cluster_buffer.data[cluster_omni_offset + i];
- mask &= cluster_get_range_clip_mask(i, item_min, item_max);
-#ifdef USE_SUBGROUPS
- uint merged_mask = subgroupBroadcastFirst(subgroupOr(mask));
+ if (cull_mask > 0.0) {
+ {
+#CODE : FOG
+ }
+
+#ifdef DENSITY_USED
+ density *= cull_mask;
+ if (abs(density) > 0.001) {
+ int final_density = int(density * DENSITY_SCALE);
+#ifdef MOLTENVK_USED
+ atomicAdd(density_only_map[lpos], uint(final_density));
#else
- uint merged_mask = mask;
+ imageAtomicAdd(density_only_map, pos, uint(final_density));
#endif
- while (merged_mask != 0) {
- uint bit = findMSB(merged_mask);
- merged_mask &= ~(1 << bit);
-#ifdef USE_SUBGROUPS
- if (((1 << bit) & mask) == 0) { //do not process if not originally here
- continue;
- }
+#ifdef EMISSION_USED
+ {
+ emission *= clamp(density, 0.0, 1.0);
+ emission = clamp(emission, vec3(0.0), vec3(4.0));
+ // Scale to fit into R11G11B10 with a range of 0-4
+ uvec3 emission_u = uvec3(emission.r * 511.0, emission.g * 511.0, emission.b * 255.0);
+ // R and G have 11 bits each and B has 10. Then pack them into a 32 bit uint
+ uint final_emission = emission_u.r << 21 | emission_u.g << 10 | emission_u.b;
+#ifdef MOLTENVK_USED
+ uint prev_emission = atomicAdd(emissive_only_map[lpos], final_emission);
+#else
+ uint prev_emission = imageAtomicAdd(emissive_only_map, pos, final_emission);
#endif
- uint light_index = 32 * i + bit;
-
- //if (!bool(omni_omni_lights.data[light_index].mask & draw_call.layer_mask)) {
- // continue; //not masked
- //}
-
- vec3 light_pos = omni_lights.data[light_index].position;
- float d = distance(omni_lights.data[light_index].position, view_pos);
- float shadow_attenuation = 1.0;
-
- if (d * omni_lights.data[light_index].inv_radius < 1.0) {
- float attenuation = get_omni_attenuation(d, omni_lights.data[light_index].inv_radius, omni_lights.data[light_index].attenuation);
-
- vec3 light = omni_lights.data[light_index].color / M_PI;
-
- if (omni_lights.data[light_index].shadow_enabled) {
- //has shadow
- vec4 v = vec4(view_pos, 1.0);
-
- vec4 splane = (omni_lights.data[light_index].shadow_matrix * v);
- float shadow_len = length(splane.xyz); //need to remember shadow len from here
- splane.xyz = normalize(splane.xyz);
- vec4 clamp_rect = omni_lights.data[light_index].atlas_rect;
+ // Adding can lead to colors overflowing, so validate
+ uvec3 prev_emission_u = uvec3(prev_emission >> 21, (prev_emission << 11) >> 21, prev_emission % 1024);
+ uint add_emission = final_emission + prev_emission;
+ uvec3 add_emission_u = uvec3(add_emission >> 21, (add_emission << 11) >> 21, add_emission % 1024);
- if (splane.z >= 0.0) {
- splane.z += 1.0;
+ bvec3 overflowing = lessThan(add_emission_u, prev_emission_u + emission_u);
- clamp_rect.y += clamp_rect.w;
-
- } else {
- splane.z = 1.0 - splane.z;
- }
-
- splane.xy /= splane.z;
-
- splane.xy = splane.xy * 0.5 + 0.5;
- splane.z = shadow_len * omni_lights.data[light_index].inv_radius;
- splane.xy = clamp_rect.xy + splane.xy * clamp_rect.zw;
- splane.w = 1.0; //needed? i think it should be 1 already
-
- float depth = texture(sampler2D(shadow_atlas, linear_sampler), splane.xy).r;
-
- shadow_attenuation = exp(min(0.0, (depth - splane.z)) / omni_lights.data[light_index].inv_radius * omni_lights.data[light_index].shadow_volumetric_fog_fade);
- }
- total_light += light * attenuation * shadow_attenuation;
+ if (any(overflowing)) {
+ uvec3 overflow_factor = mix(uvec3(0), uvec3(2047 << 21, 2047 << 10, 1023), overflowing);
+ uint force_max = overflow_factor.r | overflow_factor.g | overflow_factor.b;
+#ifdef MOLTENVK_USED
+ atomicOr(emissive_only_map[lpos], force_max);
+#else
+ imageAtomicOr(emissive_only_map, pos, force_max);
+#endif
}
}
- }
- }
-
- { //spot lights
-
- uint cluster_spot_offset = cluster_offset + params.cluster_type_size;
-
- uint item_min;
- uint item_max;
- uint item_from;
- uint item_to;
-
- cluster_get_item_range(cluster_spot_offset + params.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to);
-
-#ifdef USE_SUBGROUPS
- item_from = subgroupBroadcastFirst(subgroupMin(item_from));
- item_to = subgroupBroadcastFirst(subgroupMax(item_to));
#endif
-
- for (uint i = item_from; i < item_to; i++) {
- uint mask = cluster_buffer.data[cluster_spot_offset + i];
- mask &= cluster_get_range_clip_mask(i, item_min, item_max);
-#ifdef USE_SUBGROUPS
- uint merged_mask = subgroupBroadcastFirst(subgroupOr(mask));
+#ifdef ALBEDO_USED
+ {
+ vec3 scattering = albedo * clamp(density, 0.0, 1.0);
+ scattering = clamp(scattering, vec3(0.0), vec3(1.0));
+ uvec3 scattering_u = uvec3(scattering.r * 2047.0, scattering.g * 2047.0, scattering.b * 1023.0);
+ // R and G have 11 bits each and B has 10. Then pack them into a 32 bit uint
+ uint final_scattering = scattering_u.r << 21 | scattering_u.g << 10 | scattering_u.b;
+#ifdef MOLTENVK_USED
+ uint prev_scattering = atomicAdd(light_only_map[lpos], final_scattering);
#else
- uint merged_mask = mask;
-#endif
-
- while (merged_mask != 0) {
- uint bit = findMSB(merged_mask);
- merged_mask &= ~(1 << bit);
-#ifdef USE_SUBGROUPS
- if (((1 << bit) & mask) == 0) { //do not process if not originally here
- continue;
- }
+ uint prev_scattering = imageAtomicAdd(light_only_map, pos, final_scattering);
#endif
- //if (!bool(omni_lights.data[light_index].mask & draw_call.layer_mask)) {
- // continue; //not masked
- //}
-
- uint light_index = 32 * i + bit;
-
- vec3 light_pos = spot_lights.data[light_index].position;
- vec3 light_rel_vec = spot_lights.data[light_index].position - view_pos;
- float d = length(light_rel_vec);
- float shadow_attenuation = 1.0;
-
- if (d * spot_lights.data[light_index].inv_radius < 1.0) {
- float attenuation = get_omni_attenuation(d, spot_lights.data[light_index].inv_radius, spot_lights.data[light_index].attenuation);
-
- vec3 spot_dir = spot_lights.data[light_index].direction;
- float scos = max(dot(-normalize(light_rel_vec), spot_dir), spot_lights.data[light_index].cone_angle);
- float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_lights.data[light_index].cone_angle));
- attenuation *= 1.0 - pow(spot_rim, spot_lights.data[light_index].cone_attenuation);
-
- vec3 light = spot_lights.data[light_index].color / M_PI;
-
- if (spot_lights.data[light_index].shadow_enabled) {
- //has shadow
- vec4 v = vec4(view_pos, 1.0);
-
- vec4 splane = (spot_lights.data[light_index].shadow_matrix * v);
- splane /= splane.w;
-
- float depth = texture(sampler2D(shadow_atlas, linear_sampler), splane.xy).r;
-
- shadow_attenuation = exp(min(0.0, (depth - splane.z)) / spot_lights.data[light_index].inv_radius * spot_lights.data[light_index].shadow_volumetric_fog_fade);
- }
-
- total_light += light * attenuation * shadow_attenuation;
- }
- }
- }
- }
-
- vec3 world_pos = mat3(params.cam_rotation) * view_pos;
-
- for (uint i = 0; i < params.max_voxel_gi_instances; i++) {
- vec3 position = (voxel_gi_instances.data[i].xform * vec4(world_pos, 1.0)).xyz;
-
- //this causes corrupted pixels, i have no idea why..
- if (all(bvec2(all(greaterThanEqual(position, vec3(0.0))), all(lessThan(position, voxel_gi_instances.data[i].bounds))))) {
- position /= voxel_gi_instances.data[i].bounds;
-
- vec4 light = vec4(0.0);
- for (uint j = 0; j < voxel_gi_instances.data[i].mipmaps; j++) {
- vec4 slight = textureLod(sampler3D(voxel_gi_textures[i], linear_sampler_with_mipmaps), position, float(j));
- float a = (1.0 - light.a);
- light += a * slight;
- }
-
- light.rgb *= voxel_gi_instances.data[i].dynamic_range * params.gi_inject;
-
- total_light += light.rgb;
- }
- }
-
- //sdfgi
-#ifdef ENABLE_SDFGI
+ // Adding can lead to colors overflowing, so validate
+ uvec3 prev_scattering_u = uvec3(prev_scattering >> 21, (prev_scattering << 11) >> 21, prev_scattering % 1024);
+ uint add_scattering = final_scattering + prev_scattering;
+ uvec3 add_scattering_u = uvec3(add_scattering >> 21, (add_scattering << 11) >> 21, add_scattering % 1024);
- {
- float blend = -1.0;
- vec3 ambient_total = vec3(0.0);
+ bvec3 overflowing = lessThan(add_scattering_u, prev_scattering_u + scattering_u);
- for (uint i = 0; i < sdfgi.max_cascades; i++) {
- vec3 cascade_pos = (world_pos - sdfgi.cascades[i].position) * sdfgi.cascades[i].to_probe;
-
- if (any(lessThan(cascade_pos, vec3(0.0))) || any(greaterThanEqual(cascade_pos, sdfgi.cascade_probe_size))) {
- continue; //skip cascade
- }
-
- vec3 base_pos = floor(cascade_pos);
- ivec3 probe_base_pos = ivec3(base_pos);
-
- vec4 ambient_accum = vec4(0.0);
-
- ivec3 tex_pos = ivec3(probe_base_pos.xy, int(i));
- tex_pos.x += probe_base_pos.z * sdfgi.probe_axis_size;
-
- for (uint j = 0; j < 8; j++) {
- ivec3 offset = (ivec3(j) >> ivec3(0, 1, 2)) & ivec3(1, 1, 1);
- ivec3 probe_posi = probe_base_pos;
- probe_posi += offset;
-
- // Compute weight
-
- vec3 probe_pos = vec3(probe_posi);
- vec3 probe_to_pos = cascade_pos - probe_pos;
-
- vec3 trilinear = vec3(1.0) - abs(probe_to_pos);
- float weight = trilinear.x * trilinear.y * trilinear.z;
-
- // Compute lightprobe occlusion
-
- if (sdfgi.use_occlusion) {
- ivec3 occ_indexv = abs((sdfgi.cascades[i].probe_world_offset + probe_posi) & ivec3(1, 1, 1)) * ivec3(1, 2, 4);
- vec4 occ_mask = mix(vec4(0.0), vec4(1.0), equal(ivec4(occ_indexv.x | occ_indexv.y), ivec4(0, 1, 2, 3)));
-
- vec3 occ_pos = clamp(cascade_pos, probe_pos - sdfgi.occlusion_clamp, probe_pos + sdfgi.occlusion_clamp) * sdfgi.probe_to_uvw;
- occ_pos.z += float(i);
- if (occ_indexv.z != 0) { //z bit is on, means index is >=4, so make it switch to the other half of textures
- occ_pos.x += 1.0;
- }
-
- occ_pos *= sdfgi.occlusion_renormalize;
- float occlusion = dot(textureLod(sampler3D(sdfgi_occlusion_texture, linear_sampler), occ_pos, 0.0), occ_mask);
-
- weight *= max(occlusion, 0.01);
+ if (any(overflowing)) {
+ uvec3 overflow_factor = mix(uvec3(0), uvec3(2047 << 21, 2047 << 10, 1023), overflowing);
+ uint force_max = overflow_factor.r | overflow_factor.g | overflow_factor.b;
+#ifdef MOLTENVK_USED
+ atomicOr(light_only_map[lpos], force_max);
+#else
+ imageAtomicOr(light_only_map, pos, force_max);
+#endif
}
-
- // Compute ambient texture position
-
- ivec3 uvw = tex_pos;
- uvw.xy += offset.xy;
- uvw.x += offset.z * sdfgi.probe_axis_size;
-
- vec3 ambient = texelFetch(sampler2DArray(sdfgi_ambient_texture, linear_sampler), uvw, 0).rgb;
-
- ambient_accum.rgb += ambient * weight;
- ambient_accum.a += weight;
- }
-
- if (ambient_accum.a > 0) {
- ambient_accum.rgb /= ambient_accum.a;
}
- ambient_total = ambient_accum.rgb;
- break;
+#endif // ALBEDO_USED
}
-
- total_light += ambient_total * params.gi_inject;
+#endif // DENSITY_USED
}
-
-#endif
-
- vec4 final_density = vec4(total_light, total_density);
-
- final_density = mix(final_density, reprojected_density, reproject_amount);
-
- imageStore(density_map, pos, final_density);
-#endif
-
-#ifdef MODE_FOG
-
- ivec3 pos = ivec3(gl_GlobalInvocationID.xy, 0);
-
- if (any(greaterThanEqual(pos, params.fog_volume_size))) {
- return; //do not compute
- }
-
- vec4 fog_accum = vec4(0.0);
- float prev_z = 0.0;
-
- float t = 1.0;
-
- for (int i = 0; i < params.fog_volume_size.z; i++) {
- //compute fog position
- ivec3 fog_pos = pos + ivec3(0, 0, i);
- //get fog value
- vec4 fog = imageLoad(density_map, fog_pos);
-
- //get depth at cell pos
- float z = get_depth_at_pos(fog_cell_size.z, i);
- //get distance from previous pos
- float d = abs(prev_z - z);
- //compute exinction based on beer's
- float extinction = t * exp(-d * fog.a);
- //compute alpha based on different of extinctions
- float alpha = t - extinction;
- //update extinction
- t = extinction;
-
- fog_accum += vec4(fog.rgb * alpha, alpha);
- prev_z = z;
-
- vec4 fog_value;
-
- if (fog_accum.a > 0.0) {
- fog_value = vec4(fog_accum.rgb / fog_accum.a, 1.0 - t);
- } else {
- fog_value = vec4(0.0);
- }
-
- imageStore(fog_map, fog_pos, fog_value);
- }
-
-#endif
-
-#ifdef MODE_FILTER
-
- ivec3 pos = ivec3(gl_GlobalInvocationID.xyz);
-
- const float gauss[7] = float[](0.071303, 0.131514, 0.189879, 0.214607, 0.189879, 0.131514, 0.071303);
-
- const ivec3 filter_dir[3] = ivec3[](ivec3(1, 0, 0), ivec3(0, 1, 0), ivec3(0, 0, 1));
- ivec3 offset = filter_dir[params.filter_axis];
-
- vec4 accum = vec4(0.0);
- for (int i = -3; i <= 3; i++) {
- accum += imageLoad(source_map, clamp(pos + offset * i, ivec3(0), params.fog_volume_size - ivec3(1))) * gauss[i + 3];
- }
-
- imageStore(dest_map, pos, accum);
-
-#endif
}
diff --git a/servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl b/servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl
new file mode 100644
index 0000000000..747f88960c
--- /dev/null
+++ b/servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl
@@ -0,0 +1,776 @@
+#[compute]
+
+#version 450
+
+#VERSION_DEFINES
+
+/* Do not use subgroups here, seems there is not much advantage and causes glitches
+#if defined(has_GL_KHR_shader_subgroup_ballot) && defined(has_GL_KHR_shader_subgroup_arithmetic)
+#extension GL_KHR_shader_subgroup_ballot: enable
+#extension GL_KHR_shader_subgroup_arithmetic: enable
+
+#define USE_SUBGROUPS
+#endif
+*/
+
+#ifdef MODE_DENSITY
+layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in;
+#else
+layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
+#endif
+
+#include "cluster_data_inc.glsl"
+#include "light_data_inc.glsl"
+
+#define M_PI 3.14159265359
+
+#define DENSITY_SCALE 1024.0
+
+layout(set = 0, binding = 1) uniform texture2D shadow_atlas;
+layout(set = 0, binding = 2) uniform texture2D directional_shadow_atlas;
+
+layout(set = 0, binding = 3, std430) restrict readonly buffer OmniLights {
+ LightData data[];
+}
+omni_lights;
+
+layout(set = 0, binding = 4, std430) restrict readonly buffer SpotLights {
+ LightData data[];
+}
+spot_lights;
+
+layout(set = 0, binding = 5, std140) uniform DirectionalLights {
+ DirectionalLightData data[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS];
+}
+directional_lights;
+
+layout(set = 0, binding = 6, std430) buffer restrict readonly ClusterBuffer {
+ uint data[];
+}
+cluster_buffer;
+
+layout(set = 0, binding = 7) uniform sampler linear_sampler;
+
+#ifdef MODE_DENSITY
+layout(rgba16f, set = 0, binding = 8) uniform restrict writeonly image3D density_map;
+layout(rgba16f, set = 0, binding = 9) uniform restrict readonly image3D fog_map; //unused
+#endif
+
+#ifdef MODE_FOG
+layout(rgba16f, set = 0, binding = 8) uniform restrict readonly image3D density_map;
+layout(rgba16f, set = 0, binding = 9) uniform restrict writeonly image3D fog_map;
+#endif
+
+#ifdef MODE_COPY
+layout(rgba16f, set = 0, binding = 8) uniform restrict readonly image3D source_map;
+layout(rgba16f, set = 0, binding = 9) uniform restrict writeonly image3D dest_map;
+#endif
+
+#ifdef MODE_FILTER
+layout(rgba16f, set = 0, binding = 8) uniform restrict readonly image3D source_map;
+layout(rgba16f, set = 0, binding = 9) uniform restrict writeonly image3D dest_map;
+#endif
+
+layout(set = 0, binding = 10) uniform sampler shadow_sampler;
+
+#define MAX_VOXEL_GI_INSTANCES 8
+
+struct VoxelGIData {
+ mat4 xform;
+ vec3 bounds;
+ float dynamic_range;
+
+ float bias;
+ float normal_bias;
+ bool blend_ambient;
+ uint texture_slot;
+
+ float anisotropy_strength;
+ float ambient_occlusion;
+ float ambient_occlusion_size;
+ uint mipmaps;
+};
+
+layout(set = 0, binding = 11, std140) uniform VoxelGIs {
+ VoxelGIData data[MAX_VOXEL_GI_INSTANCES];
+}
+voxel_gi_instances;
+
+layout(set = 0, binding = 12) uniform texture3D voxel_gi_textures[MAX_VOXEL_GI_INSTANCES];
+
+layout(set = 0, binding = 13) uniform sampler linear_sampler_with_mipmaps;
+
+#ifdef ENABLE_SDFGI
+
+// SDFGI Integration on set 1
+#define SDFGI_MAX_CASCADES 8
+
+struct SDFVoxelGICascadeData {
+ vec3 position;
+ float to_probe;
+ ivec3 probe_world_offset;
+ float to_cell; // 1/bounds * grid_size
+};
+
+layout(set = 1, binding = 0, std140) uniform SDFGI {
+ vec3 grid_size;
+ uint max_cascades;
+
+ bool use_occlusion;
+ int probe_axis_size;
+ float probe_to_uvw;
+ float normal_bias;
+
+ vec3 lightprobe_tex_pixel_size;
+ float energy;
+
+ vec3 lightprobe_uv_offset;
+ float y_mult;
+
+ vec3 occlusion_clamp;
+ uint pad3;
+
+ vec3 occlusion_renormalize;
+ uint pad4;
+
+ vec3 cascade_probe_size;
+ uint pad5;
+
+ SDFVoxelGICascadeData cascades[SDFGI_MAX_CASCADES];
+}
+sdfgi;
+
+layout(set = 1, binding = 1) uniform texture2DArray sdfgi_ambient_texture;
+
+layout(set = 1, binding = 2) uniform texture3D sdfgi_occlusion_texture;
+
+#endif //SDFGI
+
+layout(set = 0, binding = 14, std140) uniform Params {
+ vec2 fog_frustum_size_begin;
+ vec2 fog_frustum_size_end;
+
+ float fog_frustum_end;
+ float ambient_inject;
+ float z_far;
+ int filter_axis;
+
+ vec3 ambient_color;
+ float sky_contribution;
+
+ ivec3 fog_volume_size;
+ uint directional_light_count;
+
+ vec3 base_emission;
+ float base_density;
+
+ vec3 base_scattering;
+ float phase_g;
+
+ float detail_spread;
+ float gi_inject;
+ uint max_voxel_gi_instances;
+ uint cluster_type_size;
+
+ vec2 screen_size;
+ uint cluster_shift;
+ uint cluster_width;
+
+ uint max_cluster_element_count_div_32;
+ bool use_temporal_reprojection;
+ uint temporal_frame;
+ float temporal_blend;
+
+ mat3x4 cam_rotation;
+ mat4 to_prev_view;
+
+ mat3 radiance_inverse_xform;
+}
+params;
+#ifndef MODE_COPY
+layout(set = 0, binding = 15) uniform texture3D prev_density_texture;
+
+#ifdef MOLTENVK_USED
+layout(set = 0, binding = 16) buffer density_only_map_buffer {
+ uint density_only_map[];
+};
+layout(set = 0, binding = 17) buffer light_only_map_buffer {
+ uint light_only_map[];
+};
+layout(set = 0, binding = 18) buffer emissive_only_map_buffer {
+ uint emissive_only_map[];
+};
+#else
+layout(r32ui, set = 0, binding = 16) uniform uimage3D density_only_map;
+layout(r32ui, set = 0, binding = 17) uniform uimage3D light_only_map;
+layout(r32ui, set = 0, binding = 18) uniform uimage3D emissive_only_map;
+#endif
+
+#ifdef USE_RADIANCE_CUBEMAP_ARRAY
+layout(set = 0, binding = 19) uniform textureCubeArray sky_texture;
+#else
+layout(set = 0, binding = 19) uniform textureCube sky_texture;
+#endif
+#endif // MODE_COPY
+
+float get_depth_at_pos(float cell_depth_size, int z) {
+ float d = float(z) * cell_depth_size + cell_depth_size * 0.5; //center of voxels
+ d = pow(d, params.detail_spread);
+ return params.fog_frustum_end * d;
+}
+
+vec3 hash3f(uvec3 x) {
+ x = ((x >> 16) ^ x) * 0x45d9f3b;
+ x = ((x >> 16) ^ x) * 0x45d9f3b;
+ x = (x >> 16) ^ x;
+ return vec3(x & 0xFFFFF) / vec3(float(0xFFFFF));
+}
+
+float get_omni_attenuation(float dist, float inv_range, float decay) {
+ float nd = dist * inv_range;
+ nd *= nd;
+ nd *= nd; // nd^4
+ nd = max(1.0 - nd, 0.0);
+ nd *= nd; // nd^2
+ return nd * pow(max(dist, 0.0001), -decay);
+}
+
+void cluster_get_item_range(uint p_offset, out uint item_min, out uint item_max, out uint item_from, out uint item_to) {
+ uint item_min_max = cluster_buffer.data[p_offset];
+ item_min = item_min_max & 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
+}
+
+uint cluster_get_range_clip_mask(uint i, uint z_min, uint z_max) {
+ int local_min = clamp(int(z_min) - int(i) * 32, 0, 31);
+ int mask_width = min(int(z_max) - int(z_min), 32 - local_min);
+ return bitfieldInsert(uint(0), uint(0xFFFFFFFF), local_min, mask_width);
+}
+
+float henyey_greenstein(float cos_theta, float g) {
+ const float k = 0.0795774715459; // 1 / (4 * PI)
+ return k * (1.0 - g * g) / (pow(1.0 + g * g - 2.0 * g * cos_theta, 1.5));
+}
+
+#define TEMPORAL_FRAMES 16
+
+const vec3 halton_map[TEMPORAL_FRAMES] = vec3[](
+ vec3(0.5, 0.33333333, 0.2),
+ vec3(0.25, 0.66666667, 0.4),
+ vec3(0.75, 0.11111111, 0.6),
+ vec3(0.125, 0.44444444, 0.8),
+ vec3(0.625, 0.77777778, 0.04),
+ vec3(0.375, 0.22222222, 0.24),
+ vec3(0.875, 0.55555556, 0.44),
+ vec3(0.0625, 0.88888889, 0.64),
+ vec3(0.5625, 0.03703704, 0.84),
+ vec3(0.3125, 0.37037037, 0.08),
+ vec3(0.8125, 0.7037037, 0.28),
+ vec3(0.1875, 0.14814815, 0.48),
+ vec3(0.6875, 0.48148148, 0.68),
+ vec3(0.4375, 0.81481481, 0.88),
+ vec3(0.9375, 0.25925926, 0.12),
+ vec3(0.03125, 0.59259259, 0.32));
+
+void main() {
+ vec3 fog_cell_size = 1.0 / vec3(params.fog_volume_size);
+
+#ifdef MODE_DENSITY
+
+ ivec3 pos = ivec3(gl_GlobalInvocationID.xyz);
+ if (any(greaterThanEqual(pos, params.fog_volume_size))) {
+ return; //do not compute
+ }
+#ifdef MOLTENVK_USED
+ uint lpos = pos.z * params.fog_volume_size.x * params.fog_volume_size.y + pos.y * params.fog_volume_size.x + pos.x;
+#endif
+
+ vec3 posf = vec3(pos);
+
+ //posf += mix(vec3(0.0),vec3(1.0),0.3) * hash3f(uvec3(pos)) * 2.0 - 1.0;
+
+ vec3 fog_unit_pos = posf * fog_cell_size + fog_cell_size * 0.5; //center of voxels
+
+ uvec2 screen_pos = uvec2(fog_unit_pos.xy * params.screen_size);
+ uvec2 cluster_pos = screen_pos >> params.cluster_shift;
+ uint cluster_offset = (params.cluster_width * cluster_pos.y + cluster_pos.x) * (params.max_cluster_element_count_div_32 + 32);
+ //positions in screen are too spread apart, no hopes for optimizing with subgroups
+
+ fog_unit_pos.z = pow(fog_unit_pos.z, params.detail_spread);
+
+ vec3 view_pos;
+ view_pos.xy = (fog_unit_pos.xy * 2.0 - 1.0) * mix(params.fog_frustum_size_begin, params.fog_frustum_size_end, vec2(fog_unit_pos.z));
+ view_pos.z = -params.fog_frustum_end * fog_unit_pos.z;
+ view_pos.y = -view_pos.y;
+
+ vec4 reprojected_density = vec4(0.0);
+ float reproject_amount = 0.0;
+
+ if (params.use_temporal_reprojection) {
+ vec3 prev_view = (params.to_prev_view * vec4(view_pos, 1.0)).xyz;
+ //undo transform into prev view
+ prev_view.y = -prev_view.y;
+ //z back to unit size
+ prev_view.z /= -params.fog_frustum_end;
+ //xy back to unit size
+ prev_view.xy /= mix(params.fog_frustum_size_begin, params.fog_frustum_size_end, vec2(prev_view.z));
+ prev_view.xy = prev_view.xy * 0.5 + 0.5;
+ //z back to unspread value
+ prev_view.z = pow(prev_view.z, 1.0 / params.detail_spread);
+
+ if (all(greaterThan(prev_view, vec3(0.0))) && all(lessThan(prev_view, vec3(1.0)))) {
+ //reprojectinon fits
+
+ reprojected_density = textureLod(sampler3D(prev_density_texture, linear_sampler), prev_view, 0.0);
+ reproject_amount = params.temporal_blend;
+
+ // Since we can reproject, now we must jitter the current view pos.
+ // This is done here because cells that can't reproject should not jitter.
+
+ fog_unit_pos = posf * fog_cell_size + fog_cell_size * halton_map[params.temporal_frame]; //center of voxels, offset by halton table
+
+ screen_pos = uvec2(fog_unit_pos.xy * params.screen_size);
+ cluster_pos = screen_pos >> params.cluster_shift;
+ cluster_offset = (params.cluster_width * cluster_pos.y + cluster_pos.x) * (params.max_cluster_element_count_div_32 + 32);
+ //positions in screen are too spread apart, no hopes for optimizing with subgroups
+
+ fog_unit_pos.z = pow(fog_unit_pos.z, params.detail_spread);
+
+ view_pos.xy = (fog_unit_pos.xy * 2.0 - 1.0) * mix(params.fog_frustum_size_begin, params.fog_frustum_size_end, vec2(fog_unit_pos.z));
+ view_pos.z = -params.fog_frustum_end * fog_unit_pos.z;
+ view_pos.y = -view_pos.y;
+ }
+ }
+
+ uint cluster_z = uint(clamp((abs(view_pos.z) / params.z_far) * 32.0, 0.0, 31.0));
+
+ vec3 total_light = vec3(0.0);
+
+ float total_density = params.base_density;
+#ifdef MOLTENVK_USED
+ uint local_density = density_only_map[lpos];
+#else
+ uint local_density = imageLoad(density_only_map, pos).x;
+#endif
+
+ total_density += float(int(local_density)) / DENSITY_SCALE;
+ total_density = max(0.0, total_density);
+
+#ifdef MOLTENVK_USED
+ uint scattering_u = light_only_map[lpos];
+#else
+ uint scattering_u = imageLoad(light_only_map, pos).x;
+#endif
+ vec3 scattering = vec3(scattering_u >> 21, (scattering_u << 11) >> 21, scattering_u % 1024) / vec3(2047.0, 2047.0, 1023.0);
+ scattering += params.base_scattering * params.base_density;
+
+#ifdef MOLTENVK_USED
+ uint emission_u = emissive_only_map[lpos];
+#else
+ uint emission_u = imageLoad(emissive_only_map, pos).x;
+#endif
+ vec3 emission = vec3(emission_u >> 21, (emission_u << 11) >> 21, emission_u % 1024) / vec3(511.0, 511.0, 255.0);
+ emission += params.base_emission * params.base_density;
+
+ float cell_depth_size = abs(view_pos.z - get_depth_at_pos(fog_cell_size.z, pos.z + 1));
+ //compute directional lights
+
+ if (total_density > 0.001) {
+ for (uint i = 0; i < params.directional_light_count; i++) {
+ vec3 shadow_attenuation = vec3(1.0);
+
+ if (directional_lights.data[i].shadow_enabled) {
+ float depth_z = -view_pos.z;
+
+ vec4 pssm_coord;
+ vec3 shadow_color = directional_lights.data[i].shadow_color1.rgb;
+ vec3 light_dir = directional_lights.data[i].direction;
+ vec4 v = vec4(view_pos, 1.0);
+ float z_range;
+
+ if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
+ pssm_coord = (directional_lights.data[i].shadow_matrix1 * v);
+ pssm_coord /= pssm_coord.w;
+ z_range = directional_lights.data[i].shadow_z_range.x;
+
+ } else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
+ pssm_coord = (directional_lights.data[i].shadow_matrix2 * v);
+ pssm_coord /= pssm_coord.w;
+ z_range = directional_lights.data[i].shadow_z_range.y;
+
+ } else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
+ pssm_coord = (directional_lights.data[i].shadow_matrix3 * v);
+ pssm_coord /= pssm_coord.w;
+ z_range = directional_lights.data[i].shadow_z_range.z;
+
+ } else {
+ pssm_coord = (directional_lights.data[i].shadow_matrix4 * v);
+ pssm_coord /= pssm_coord.w;
+ z_range = directional_lights.data[i].shadow_z_range.w;
+ }
+
+ float depth = texture(sampler2D(directional_shadow_atlas, linear_sampler), pssm_coord.xy).r;
+ float shadow = exp(min(0.0, (depth - pssm_coord.z)) * z_range * directional_lights.data[i].shadow_volumetric_fog_fade);
+
+ shadow = mix(shadow, 1.0, smoothstep(directional_lights.data[i].fade_from, directional_lights.data[i].fade_to, view_pos.z)); //done with negative values for performance
+
+ shadow_attenuation = mix(shadow_color, vec3(1.0), shadow);
+ }
+
+ total_light += shadow_attenuation * directional_lights.data[i].color * directional_lights.data[i].energy * henyey_greenstein(dot(normalize(view_pos), normalize(directional_lights.data[i].direction)), params.phase_g);
+ }
+
+ // Compute light from sky
+ if (params.ambient_inject > 0.0) {
+ vec3 isotropic = vec3(0.0);
+ vec3 anisotropic = vec3(0.0);
+ if (params.sky_contribution > 0.0) {
+ float mip_bias = 2.0 + total_density * (MAX_SKY_LOD - 2.0); // Not physically based, but looks nice
+ vec3 scatter_direction = (params.radiance_inverse_xform * normalize(view_pos)) * sign(params.phase_g);
+#ifdef USE_RADIANCE_CUBEMAP_ARRAY
+ isotropic = texture(samplerCubeArray(sky_texture, linear_sampler_with_mipmaps), vec4(0.0, 1.0, 0.0, mip_bias)).rgb;
+ anisotropic = texture(samplerCubeArray(sky_texture, linear_sampler_with_mipmaps), vec4(scatter_direction, mip_bias)).rgb;
+#else
+ isotropic = textureLod(samplerCube(sky_texture, linear_sampler_with_mipmaps), vec3(0.0, 1.0, 0.0), mip_bias).rgb;
+ anisotropic = textureLod(samplerCube(sky_texture, linear_sampler_with_mipmaps), vec3(scatter_direction), mip_bias).rgb;
+#endif //USE_RADIANCE_CUBEMAP_ARRAY
+ }
+
+ total_light += mix(params.ambient_color, mix(isotropic, anisotropic, abs(params.phase_g)), params.sky_contribution) * params.ambient_inject;
+ }
+
+ //compute lights from cluster
+
+ { //omni lights
+
+ uint cluster_omni_offset = cluster_offset;
+
+ uint item_min;
+ uint item_max;
+ uint item_from;
+ uint item_to;
+
+ cluster_get_item_range(cluster_omni_offset + params.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to);
+
+#ifdef USE_SUBGROUPS
+ item_from = subgroupBroadcastFirst(subgroupMin(item_from));
+ item_to = subgroupBroadcastFirst(subgroupMax(item_to));
+#endif
+
+ for (uint i = item_from; i < item_to; i++) {
+ uint mask = cluster_buffer.data[cluster_omni_offset + i];
+ mask &= cluster_get_range_clip_mask(i, item_min, item_max);
+#ifdef USE_SUBGROUPS
+ uint merged_mask = subgroupBroadcastFirst(subgroupOr(mask));
+#else
+ uint merged_mask = mask;
+#endif
+
+ while (merged_mask != 0) {
+ uint bit = findMSB(merged_mask);
+ merged_mask &= ~(1 << bit);
+#ifdef USE_SUBGROUPS
+ if (((1 << bit) & mask) == 0) { //do not process if not originally here
+ continue;
+ }
+#endif
+ uint light_index = 32 * i + bit;
+
+ //if (!bool(omni_omni_lights.data[light_index].mask & draw_call.layer_mask)) {
+ // continue; //not masked
+ //}
+
+ vec3 light_pos = omni_lights.data[light_index].position;
+ float d = distance(omni_lights.data[light_index].position, view_pos);
+ float shadow_attenuation = 1.0;
+
+ if (d * omni_lights.data[light_index].inv_radius < 1.0) {
+ float attenuation = get_omni_attenuation(d, omni_lights.data[light_index].inv_radius, omni_lights.data[light_index].attenuation);
+
+ vec3 light = omni_lights.data[light_index].color;
+
+ if (omni_lights.data[light_index].shadow_enabled) {
+ //has shadow
+ vec4 uv_rect = omni_lights.data[light_index].atlas_rect;
+ vec2 flip_offset = omni_lights.data[light_index].direction.xy;
+
+ vec3 local_vert = (omni_lights.data[light_index].shadow_matrix * vec4(view_pos, 1.0)).xyz;
+
+ float shadow_len = length(local_vert); //need to remember shadow len from here
+ vec3 shadow_sample = normalize(local_vert);
+
+ if (shadow_sample.z >= 0.0) {
+ uv_rect.xy += flip_offset;
+ }
+
+ shadow_sample.z = 1.0 + abs(shadow_sample.z);
+ vec3 pos = vec3(shadow_sample.xy / shadow_sample.z, shadow_len - omni_lights.data[light_index].shadow_bias);
+ pos.z *= omni_lights.data[light_index].inv_radius;
+
+ pos.xy = pos.xy * 0.5 + 0.5;
+ pos.xy = uv_rect.xy + pos.xy * uv_rect.zw;
+
+ float depth = texture(sampler2D(shadow_atlas, linear_sampler), pos.xy).r;
+
+ shadow_attenuation = exp(min(0.0, (depth - pos.z)) / omni_lights.data[light_index].inv_radius * omni_lights.data[light_index].shadow_volumetric_fog_fade);
+ }
+ total_light += light * attenuation * shadow_attenuation * henyey_greenstein(dot(normalize(light_pos - view_pos), normalize(view_pos)), params.phase_g);
+ }
+ }
+ }
+ }
+
+ { //spot lights
+
+ uint cluster_spot_offset = cluster_offset + params.cluster_type_size;
+
+ uint item_min;
+ uint item_max;
+ uint item_from;
+ uint item_to;
+
+ cluster_get_item_range(cluster_spot_offset + params.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to);
+
+#ifdef USE_SUBGROUPS
+ item_from = subgroupBroadcastFirst(subgroupMin(item_from));
+ item_to = subgroupBroadcastFirst(subgroupMax(item_to));
+#endif
+
+ for (uint i = item_from; i < item_to; i++) {
+ uint mask = cluster_buffer.data[cluster_spot_offset + i];
+ mask &= cluster_get_range_clip_mask(i, item_min, item_max);
+#ifdef USE_SUBGROUPS
+ uint merged_mask = subgroupBroadcastFirst(subgroupOr(mask));
+#else
+ uint merged_mask = mask;
+#endif
+
+ while (merged_mask != 0) {
+ uint bit = findMSB(merged_mask);
+ merged_mask &= ~(1 << bit);
+#ifdef USE_SUBGROUPS
+ if (((1 << bit) & mask) == 0) { //do not process if not originally here
+ continue;
+ }
+#endif
+
+ //if (!bool(omni_lights.data[light_index].mask & draw_call.layer_mask)) {
+ // continue; //not masked
+ //}
+
+ uint light_index = 32 * i + bit;
+
+ vec3 light_pos = spot_lights.data[light_index].position;
+ vec3 light_rel_vec = spot_lights.data[light_index].position - view_pos;
+ float d = length(light_rel_vec);
+ float shadow_attenuation = 1.0;
+
+ if (d * spot_lights.data[light_index].inv_radius < 1.0) {
+ float attenuation = get_omni_attenuation(d, spot_lights.data[light_index].inv_radius, spot_lights.data[light_index].attenuation);
+
+ vec3 spot_dir = spot_lights.data[light_index].direction;
+ float scos = max(dot(-normalize(light_rel_vec), spot_dir), spot_lights.data[light_index].cone_angle);
+ float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_lights.data[light_index].cone_angle));
+ attenuation *= 1.0 - pow(spot_rim, spot_lights.data[light_index].cone_attenuation);
+
+ vec3 light = spot_lights.data[light_index].color;
+
+ if (spot_lights.data[light_index].shadow_enabled) {
+ //has shadow
+ vec4 v = vec4(view_pos, 1.0);
+
+ vec4 splane = (spot_lights.data[light_index].shadow_matrix * v);
+ splane /= splane.w;
+
+ float depth = texture(sampler2D(shadow_atlas, linear_sampler), splane.xy).r;
+
+ shadow_attenuation = exp(min(0.0, (depth - splane.z)) / spot_lights.data[light_index].inv_radius * spot_lights.data[light_index].shadow_volumetric_fog_fade);
+ }
+
+ total_light += light * attenuation * shadow_attenuation * henyey_greenstein(dot(normalize(light_rel_vec), normalize(view_pos)), params.phase_g);
+ }
+ }
+ }
+ }
+
+ vec3 world_pos = mat3(params.cam_rotation) * view_pos;
+
+ for (uint i = 0; i < params.max_voxel_gi_instances; i++) {
+ vec3 position = (voxel_gi_instances.data[i].xform * vec4(world_pos, 1.0)).xyz;
+
+ //this causes corrupted pixels, i have no idea why..
+ if (all(bvec2(all(greaterThanEqual(position, vec3(0.0))), all(lessThan(position, voxel_gi_instances.data[i].bounds))))) {
+ position /= voxel_gi_instances.data[i].bounds;
+
+ vec4 light = vec4(0.0);
+ for (uint j = 0; j < voxel_gi_instances.data[i].mipmaps; j++) {
+ vec4 slight = textureLod(sampler3D(voxel_gi_textures[i], linear_sampler_with_mipmaps), position, float(j));
+ float a = (1.0 - light.a);
+ light += a * slight;
+ }
+
+ light.rgb *= voxel_gi_instances.data[i].dynamic_range * params.gi_inject;
+
+ total_light += light.rgb;
+ }
+ }
+
+ //sdfgi
+#ifdef ENABLE_SDFGI
+
+ {
+ float blend = -1.0;
+ vec3 ambient_total = vec3(0.0);
+
+ for (uint i = 0; i < sdfgi.max_cascades; i++) {
+ vec3 cascade_pos = (world_pos - sdfgi.cascades[i].position) * sdfgi.cascades[i].to_probe;
+
+ if (any(lessThan(cascade_pos, vec3(0.0))) || any(greaterThanEqual(cascade_pos, sdfgi.cascade_probe_size))) {
+ continue; //skip cascade
+ }
+
+ vec3 base_pos = floor(cascade_pos);
+ ivec3 probe_base_pos = ivec3(base_pos);
+
+ vec4 ambient_accum = vec4(0.0);
+
+ ivec3 tex_pos = ivec3(probe_base_pos.xy, int(i));
+ tex_pos.x += probe_base_pos.z * sdfgi.probe_axis_size;
+
+ for (uint j = 0; j < 8; j++) {
+ ivec3 offset = (ivec3(j) >> ivec3(0, 1, 2)) & ivec3(1, 1, 1);
+ ivec3 probe_posi = probe_base_pos;
+ probe_posi += offset;
+
+ // Compute weight
+
+ vec3 probe_pos = vec3(probe_posi);
+ vec3 probe_to_pos = cascade_pos - probe_pos;
+
+ vec3 trilinear = vec3(1.0) - abs(probe_to_pos);
+ float weight = trilinear.x * trilinear.y * trilinear.z;
+
+ // Compute lightprobe occlusion
+
+ if (sdfgi.use_occlusion) {
+ ivec3 occ_indexv = abs((sdfgi.cascades[i].probe_world_offset + probe_posi) & ivec3(1, 1, 1)) * ivec3(1, 2, 4);
+ vec4 occ_mask = mix(vec4(0.0), vec4(1.0), equal(ivec4(occ_indexv.x | occ_indexv.y), ivec4(0, 1, 2, 3)));
+
+ vec3 occ_pos = clamp(cascade_pos, probe_pos - sdfgi.occlusion_clamp, probe_pos + sdfgi.occlusion_clamp) * sdfgi.probe_to_uvw;
+ occ_pos.z += float(i);
+ if (occ_indexv.z != 0) { //z bit is on, means index is >=4, so make it switch to the other half of textures
+ occ_pos.x += 1.0;
+ }
+
+ occ_pos *= sdfgi.occlusion_renormalize;
+ float occlusion = dot(textureLod(sampler3D(sdfgi_occlusion_texture, linear_sampler), occ_pos, 0.0), occ_mask);
+
+ weight *= max(occlusion, 0.01);
+ }
+
+ // Compute ambient texture position
+
+ ivec3 uvw = tex_pos;
+ uvw.xy += offset.xy;
+ uvw.x += offset.z * sdfgi.probe_axis_size;
+
+ vec3 ambient = texelFetch(sampler2DArray(sdfgi_ambient_texture, linear_sampler), uvw, 0).rgb;
+
+ ambient_accum.rgb += ambient * weight;
+ ambient_accum.a += weight;
+ }
+
+ if (ambient_accum.a > 0) {
+ ambient_accum.rgb /= ambient_accum.a;
+ }
+ ambient_total = ambient_accum.rgb;
+ break;
+ }
+
+ total_light += ambient_total * params.gi_inject;
+ }
+
+#endif
+ }
+
+ vec4 final_density = vec4(total_light * scattering + emission, total_density);
+
+ final_density = mix(final_density, reprojected_density, reproject_amount);
+
+ imageStore(density_map, pos, final_density);
+#ifdef MOLTENVK_USED
+ density_only_map[lpos] = 0;
+ light_only_map[lpos] = 0;
+ emissive_only_map[lpos] = 0;
+#else
+ imageStore(density_only_map, pos, uvec4(0));
+ imageStore(light_only_map, pos, uvec4(0));
+ imageStore(emissive_only_map, pos, uvec4(0));
+#endif
+#endif
+
+#ifdef MODE_FOG
+
+ ivec3 pos = ivec3(gl_GlobalInvocationID.xy, 0);
+
+ if (any(greaterThanEqual(pos, params.fog_volume_size))) {
+ return; //do not compute
+ }
+
+ vec4 fog_accum = vec4(0.0, 0.0, 0.0, 1.0);
+ float prev_z = 0.0;
+
+ for (int i = 0; i < params.fog_volume_size.z; i++) {
+ //compute fog position
+ ivec3 fog_pos = pos + ivec3(0, 0, i);
+ //get fog value
+ vec4 fog = imageLoad(density_map, fog_pos);
+
+ //get depth at cell pos
+ float z = get_depth_at_pos(fog_cell_size.z, i);
+ //get distance from previous pos
+ float d = abs(prev_z - z);
+ //compute transmittance using beer's law
+ float transmittance = exp(-d * fog.a);
+
+ fog_accum.rgb += ((fog.rgb - fog.rgb * transmittance) / max(fog.a, 0.00001)) * fog_accum.a;
+ fog_accum.a *= transmittance;
+
+ prev_z = z;
+
+ imageStore(fog_map, fog_pos, vec4(fog_accum.rgb, 1.0 - fog_accum.a));
+ }
+
+#endif
+
+#ifdef MODE_FILTER
+
+ ivec3 pos = ivec3(gl_GlobalInvocationID.xyz);
+
+ const float gauss[7] = float[](0.071303, 0.131514, 0.189879, 0.214607, 0.189879, 0.131514, 0.071303);
+
+ const ivec3 filter_dir[3] = ivec3[](ivec3(1, 0, 0), ivec3(0, 1, 0), ivec3(0, 0, 1));
+ ivec3 offset = filter_dir[params.filter_axis];
+
+ vec4 accum = vec4(0.0);
+ for (int i = -3; i <= 3; i++) {
+ accum += imageLoad(source_map, clamp(pos + offset * i, ivec3(0), params.fog_volume_size - ivec3(1))) * gauss[i + 3];
+ }
+
+ imageStore(dest_map, pos, accum);
+
+#endif
+#ifdef MODE_COPY
+ ivec3 pos = ivec3(gl_GlobalInvocationID.xyz);
+ if (any(greaterThanEqual(pos, params.fog_volume_size))) {
+ return; //do not compute
+ }
+
+ imageStore(dest_map, pos, imageLoad(source_map, pos));
+
+#endif
+}
diff --git a/servers/rendering/renderer_scene.h b/servers/rendering/renderer_scene.h
index 5961f59b6f..02c845581c 100644
--- a/servers/rendering/renderer_scene.h
+++ b/servers/rendering/renderer_scene.h
@@ -76,6 +76,7 @@ public:
virtual void instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight) = 0;
virtual void instance_set_surface_override_material(RID p_instance, int p_surface, RID p_material) = 0;
virtual void instance_set_visible(RID p_instance, bool p_visible) = 0;
+ virtual void instance_geometry_set_transparency(RID p_instance, float p_transparency) = 0;
virtual void instance_set_custom_aabb(RID p_instance, AABB p_aabb) = 0;
@@ -84,6 +85,8 @@ public:
virtual void instance_set_extra_visibility_margin(RID p_instance, real_t p_margin) = 0;
virtual void instance_set_visibility_parent(RID p_instance, RID p_parent_instance) = 0;
+ virtual void instance_set_ignore_culling(RID p_instance, bool p_enabled) = 0;
+
// don't use these in a game!
virtual Vector<ObjectID> instances_cull_aabb(const AABB &p_aabb, RID p_scenario = RID()) const = 0;
virtual Vector<ObjectID> instances_cull_ray(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario = RID()) const = 0;
@@ -93,10 +96,9 @@ public:
virtual void instance_geometry_set_cast_shadows_setting(RID p_instance, RS::ShadowCastingSetting p_shadow_casting_setting) = 0;
virtual void instance_geometry_set_material_override(RID p_instance, RID p_material) = 0;
- virtual void instance_geometry_set_visibility_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin) = 0;
+ virtual void instance_geometry_set_visibility_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin, RS::VisibilityRangeFadeMode p_fade_mode) = 0;
virtual void instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_slice_index) = 0;
virtual void instance_geometry_set_lod_bias(RID p_instance, float p_lod_bias) = 0;
-
virtual void instance_geometry_set_shader_parameter(RID p_instance, const StringName &p_parameter, const Variant &p_value) = 0;
virtual void instance_geometry_get_shader_parameter_list(RID p_instance, List<PropertyInfo> *p_parameters) const = 0;
virtual Variant instance_geometry_get_shader_parameter(RID p_instance, const StringName &p_parameter) const = 0;
@@ -132,7 +134,7 @@ public:
virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) = 0;
virtual void environment_glow_set_use_high_quality(bool p_enable) = 0;
- virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount) = 0;
+ virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) = 0;
virtual void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) = 0;
virtual void environment_set_volumetric_fog_filter_active(bool p_enable) = 0;
@@ -189,7 +191,7 @@ public:
virtual RID render_buffers_create() = 0;
- virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) = 0;
+ virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) = 0;
virtual void gi_set_use_half_resolution(bool p_enable) = 0;
diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp
index 558516ac7c..5b834db178 100644
--- a/servers/rendering/renderer_scene_cull.cpp
+++ b/servers/rendering/renderer_scene_cull.cpp
@@ -540,6 +540,10 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(instance->base_data);
RSG::storage->free(collision->instance);
} break;
+ case RS::INSTANCE_FOG_VOLUME: {
+ InstanceFogVolumeData *volume = static_cast<InstanceFogVolumeData *>(instance->base_data);
+ scene_render->free(volume->instance);
+ } break;
case RS::INSTANCE_VISIBLITY_NOTIFIER: {
//none
} break;
@@ -640,10 +644,17 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
scene_render->geometry_instance_set_use_dynamic_gi(geom->geometry_instance, instance->dynamic_gi);
scene_render->geometry_instance_set_cast_double_sided_shadows(geom->geometry_instance, instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED);
scene_render->geometry_instance_set_use_lightmap(geom->geometry_instance, RID(), instance->lightmap_uv_scale, instance->lightmap_slice_index);
+ scene_render->geometry_instance_set_transparency(geom->geometry_instance, instance->transparency);
if (instance->lightmap_sh.size() == 9) {
scene_render->geometry_instance_set_lightmap_capture(geom->geometry_instance, instance->lightmap_sh.ptr());
}
+ for (Set<Instance *>::Element *E = instance->visibility_dependencies.front(); E; E = E->next()) {
+ Instance *dep_instance = E->get();
+ ERR_CONTINUE(dep_instance->array_index == -1);
+ ERR_CONTINUE(dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index != -1);
+ dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index = instance->array_index;
+ }
} break;
case RS::INSTANCE_PARTICLES_COLLISION: {
InstanceParticlesCollisionData *collision = memnew(InstanceParticlesCollisionData);
@@ -651,6 +662,12 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
RSG::storage->particles_collision_instance_set_active(collision->instance, instance->visible);
instance->base_data = collision;
} break;
+ case RS::INSTANCE_FOG_VOLUME: {
+ InstanceFogVolumeData *volume = memnew(InstanceFogVolumeData);
+ volume->instance = scene_render->fog_volume_instance_create(p_base);
+ scene_render->fog_volume_instance_set_active(volume->instance, instance->visible);
+ instance->base_data = volume;
+ } break;
case RS::INSTANCE_VISIBLITY_NOTIFIER: {
InstanceVisibilityNotifierData *vnd = memnew(InstanceVisibilityNotifierData);
vnd->base = p_base;
@@ -819,6 +836,18 @@ void RendererSceneCull::instance_set_layer_mask(RID p_instance, uint32_t p_mask)
}
}
+void RendererSceneCull::instance_geometry_set_transparency(RID p_instance, float p_transparency) {
+ Instance *instance = instance_owner.get_or_null(p_instance);
+ ERR_FAIL_COND(!instance);
+
+ instance->transparency = p_transparency;
+
+ if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
+ scene_render->geometry_instance_set_transparency(geom->geometry_instance, p_transparency);
+ }
+}
+
void RendererSceneCull::instance_set_transform(RID p_instance, const Transform3D &p_transform) {
Instance *instance = instance_owner.get_or_null(p_instance);
ERR_FAIL_COND(!instance);
@@ -914,6 +943,11 @@ void RendererSceneCull::instance_set_visible(RID p_instance, bool p_visible) {
RSG::storage->particles_collision_instance_set_active(collision->instance, p_visible);
}
+ if (instance->base_type == RS::INSTANCE_FOG_VOLUME) {
+ InstanceFogVolumeData *volume = static_cast<InstanceFogVolumeData *>(instance->base_data);
+ scene_render->fog_volume_instance_set_active(volume->instance, p_visible);
+ }
+
if (instance->base_type == RS::INSTANCE_OCCLUDER) {
if (instance->scenario) {
RendererSceneOcclusionCull::get_singleton()->scenario_set_instance(instance->scenario->self, p_instance, instance->base, instance->transform, p_visible);
@@ -983,6 +1017,21 @@ void RendererSceneCull::instance_set_extra_visibility_margin(RID p_instance, rea
_instance_queue_update(instance, true, false);
}
+void RendererSceneCull::instance_set_ignore_culling(RID p_instance, bool p_enabled) {
+ Instance *instance = instance_owner.get_or_null(p_instance);
+ ERR_FAIL_COND(!instance);
+ instance->ignore_all_culling = p_enabled;
+
+ if (instance->scenario && instance->array_index >= 0) {
+ InstanceData &idata = instance->scenario->instance_data[instance->array_index];
+ if (instance->ignore_all_culling) {
+ idata.flags |= InstanceData::FLAG_IGNORE_ALL_CULLING;
+ } else {
+ idata.flags &= ~uint32_t(InstanceData::FLAG_IGNORE_ALL_CULLING);
+ }
+ }
+}
+
Vector<ObjectID> RendererSceneCull::instances_cull_aabb(const AABB &p_aabb, RID p_scenario) const {
Vector<ObjectID> instances;
Scenario *scenario = scenario_owner.get_or_null(p_scenario);
@@ -1139,7 +1188,7 @@ void RendererSceneCull::instance_geometry_set_cast_shadows_setting(RID p_instanc
if (instance->scenario && instance->array_index >= 0) {
InstanceData &idata = instance->scenario->instance_data[instance->array_index];
- if (instance->cast_shadows != RS::SHADOW_CASTING_SETTING_SHADOWS_ONLY) {
+ if (instance->cast_shadows != RS::SHADOW_CASTING_SETTING_OFF) {
idata.flags |= InstanceData::FLAG_CAST_SHADOWS;
} else {
idata.flags &= ~uint32_t(InstanceData::FLAG_CAST_SHADOWS);
@@ -1173,7 +1222,7 @@ void RendererSceneCull::instance_geometry_set_material_override(RID p_instance,
}
}
-void RendererSceneCull::instance_geometry_set_visibility_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin) {
+void RendererSceneCull::instance_geometry_set_visibility_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin, RS::VisibilityRangeFadeMode p_fade_mode) {
Instance *instance = instance_owner.get_or_null(p_instance);
ERR_FAIL_COND(!instance);
@@ -1181,6 +1230,7 @@ void RendererSceneCull::instance_geometry_set_visibility_range(RID p_instance, f
instance->visibility_range_end = p_max;
instance->visibility_range_begin_margin = p_min_margin;
instance->visibility_range_end_margin = p_max_margin;
+ instance->visibility_range_fade_mode = p_fade_mode;
_update_instance_visibility_dependencies(instance);
@@ -1190,6 +1240,7 @@ void RendererSceneCull::instance_geometry_set_visibility_range(RID p_instance, f
vd.range_end = instance->visibility_range_end;
vd.range_begin_margin = instance->visibility_range_begin_margin;
vd.range_end_margin = instance->visibility_range_end_margin;
+ vd.fade_mode = p_fade_mode;
}
}
@@ -1199,53 +1250,48 @@ void RendererSceneCull::instance_set_visibility_parent(RID p_instance, RID p_par
Instance *old_parent = instance->visibility_parent;
if (old_parent) {
- if ((1 << old_parent->base_type) & RS::INSTANCE_GEOMETRY_MASK && old_parent->base_data) {
- InstanceGeometryData *old_parent_geom = static_cast<InstanceGeometryData *>(old_parent->base_data);
- old_parent_geom->visibility_dependencies.erase(instance);
- _update_instance_visibility_depth(old_parent);
- }
+ old_parent->visibility_dependencies.erase(instance);
instance->visibility_parent = nullptr;
+ _update_instance_visibility_depth(old_parent);
}
Instance *parent = instance_owner.get_or_null(p_parent_instance);
ERR_FAIL_COND(p_parent_instance.is_valid() && !parent);
if (parent) {
- if ((1 << parent->base_type) & RS::INSTANCE_GEOMETRY_MASK && parent->base_data) {
- InstanceGeometryData *parent_geom = static_cast<InstanceGeometryData *>(parent->base_data);
- parent_geom->visibility_dependencies.insert(instance);
- _update_instance_visibility_depth(parent);
- }
+ parent->visibility_dependencies.insert(instance);
instance->visibility_parent = parent;
+
+ bool cycle_detected = _update_instance_visibility_depth(parent);
+ if (cycle_detected) {
+ ERR_PRINT("Cycle detected in the visibility dependencies tree. The latest change to visibility_parent will have no effect.");
+ parent->visibility_dependencies.erase(instance);
+ instance->visibility_parent = nullptr;
+ }
}
_update_instance_visibility_dependencies(instance);
}
-void RendererSceneCull::_update_instance_visibility_depth(Instance *p_instance) {
+bool RendererSceneCull::_update_instance_visibility_depth(Instance *p_instance) {
bool cycle_detected = false;
Set<Instance *> traversed_nodes;
{
Instance *instance = p_instance;
- while (instance && ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) && instance->base_data) {
- InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
- if (!geom->visibility_dependencies.is_empty()) {
+ while (instance) {
+ if (!instance->visibility_dependencies.is_empty()) {
uint32_t depth = 0;
- for (Set<Instance *>::Element *E = geom->visibility_dependencies.front(); E; E = E->next()) {
- if (((1 << E->get()->base_type) & RS::INSTANCE_GEOMETRY_MASK) == 0 || !E->get()->base_data) {
- continue;
- }
- InstanceGeometryData *child_geom = static_cast<InstanceGeometryData *>(E->get()->base_data);
- depth = MAX(depth, child_geom->visibility_dependencies_depth);
+ for (Set<Instance *>::Element *E = instance->visibility_dependencies.front(); E; E = E->next()) {
+ depth = MAX(depth, E->get()->visibility_dependencies_depth);
}
- geom->visibility_dependencies_depth = depth + 1;
+ instance->visibility_dependencies_depth = depth + 1;
} else {
- geom->visibility_dependencies_depth = 0;
+ instance->visibility_dependencies_depth = 0;
}
if (instance->scenario && instance->visibility_index != -1) {
- instance->scenario->instance_visibility.move(instance->visibility_index, geom->visibility_dependencies_depth);
+ instance->scenario->instance_visibility.move(instance->visibility_index, instance->visibility_dependencies_depth);
}
traversed_nodes.insert(instance);
@@ -1258,17 +1304,7 @@ void RendererSceneCull::_update_instance_visibility_depth(Instance *p_instance)
}
}
- if (cycle_detected) {
- ERR_PRINT("Cycle detected in the visibility dependencies tree.");
- for (Set<Instance *>::Element *E = traversed_nodes.front(); E; E = E->next()) {
- Instance *instance = E->get();
- InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
- geom->visibility_dependencies_depth = 0;
- if (instance->scenario && instance->visibility_index != -1) {
- instance->scenario->instance_visibility.move(instance->visibility_index, geom->visibility_dependencies_depth);
- }
- }
- }
+ return cycle_detected;
}
void RendererSceneCull::_update_instance_visibility_dependencies(Instance *p_instance) {
@@ -1277,7 +1313,7 @@ void RendererSceneCull::_update_instance_visibility_dependencies(Instance *p_ins
bool needs_visibility_cull = has_visibility_range && is_geometry_instance && p_instance->array_index != -1;
if (!needs_visibility_cull && p_instance->visibility_index != -1) {
- p_instance->scenario->instance_visibility.remove(p_instance->visibility_index);
+ p_instance->scenario->instance_visibility.remove_at(p_instance->visibility_index);
p_instance->visibility_index = -1;
} else if (needs_visibility_cull && p_instance->visibility_index == -1) {
InstanceVisibilityData vd;
@@ -1288,25 +1324,42 @@ void RendererSceneCull::_update_instance_visibility_dependencies(Instance *p_ins
vd.range_end_margin = p_instance->visibility_range_end_margin;
vd.position = p_instance->transformed_aabb.get_center();
vd.array_index = p_instance->array_index;
+ vd.fade_mode = p_instance->visibility_range_fade_mode;
- InstanceGeometryData *geom_data = static_cast<InstanceGeometryData *>(p_instance->base_data);
- p_instance->scenario->instance_visibility.insert(vd, geom_data->visibility_dependencies_depth);
+ p_instance->scenario->instance_visibility.insert(vd, p_instance->visibility_dependencies_depth);
}
if (p_instance->scenario && p_instance->array_index != -1) {
- p_instance->scenario->instance_data[p_instance->array_index].visibility_index = p_instance->visibility_index;
+ InstanceData &idata = p_instance->scenario->instance_data[p_instance->array_index];
+ idata.visibility_index = p_instance->visibility_index;
+
+ if (is_geometry_instance) {
+ if (has_visibility_range && p_instance->visibility_range_fade_mode == RS::VISIBILITY_RANGE_FADE_SELF) {
+ bool begin_enabled = p_instance->visibility_range_begin > 0.0f;
+ float begin_min = p_instance->visibility_range_begin - p_instance->visibility_range_begin_margin;
+ float begin_max = p_instance->visibility_range_begin + p_instance->visibility_range_begin_margin;
+ bool end_enabled = p_instance->visibility_range_end > 0.0f;
+ float end_min = p_instance->visibility_range_end - p_instance->visibility_range_end_margin;
+ float end_max = p_instance->visibility_range_end + p_instance->visibility_range_end_margin;
+ scene_render->geometry_instance_set_fade_range(idata.instance_geometry, begin_enabled, begin_min, begin_max, end_enabled, end_min, end_max);
+ } else {
+ scene_render->geometry_instance_set_fade_range(idata.instance_geometry, false, 0.0f, 0.0f, false, 0.0f, 0.0f);
+ }
+ }
- InstanceGeometryData *geom_data = static_cast<InstanceGeometryData *>(p_instance->base_data);
- if ((has_visibility_range || p_instance->visibility_parent) && (p_instance->visibility_index == -1 || (geom_data && geom_data->visibility_dependencies_depth == 0))) {
- p_instance->scenario->instance_data[p_instance->array_index].flags |= InstanceData::FLAG_VISIBILITY_DEPENDENCY_NEEDS_CHECK;
+ if ((has_visibility_range || p_instance->visibility_parent) && (p_instance->visibility_index == -1 || p_instance->visibility_dependencies_depth == 0)) {
+ idata.flags |= InstanceData::FLAG_VISIBILITY_DEPENDENCY_NEEDS_CHECK;
} else {
- p_instance->scenario->instance_data[p_instance->array_index].flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_NEEDS_CHECK;
+ idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_NEEDS_CHECK;
}
if (p_instance->visibility_parent) {
- p_instance->scenario->instance_data[p_instance->array_index].parent_array_index = p_instance->visibility_parent->array_index;
+ idata.parent_array_index = p_instance->visibility_parent->array_index;
} else {
- p_instance->scenario->instance_data[p_instance->array_index].parent_array_index = -1;
+ idata.parent_array_index = -1;
+ if (is_geometry_instance) {
+ scene_render->geometry_instance_set_parent_fade_alpha(idata.instance_geometry, 1.0f);
+ }
}
}
}
@@ -1471,6 +1524,9 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
heightfield_particle_colliders_update_list.insert(p_instance);
}
RSG::storage->particles_collision_instance_set_transform(collision->instance, p_instance->transform);
+ } else if (p_instance->base_type == RS::INSTANCE_FOG_VOLUME) {
+ InstanceFogVolumeData *volume = static_cast<InstanceFogVolumeData *>(p_instance->base_data);
+ scene_render->fog_volume_instance_set_transform(volume->instance, p_instance->transform);
} else if (p_instance->base_type == RS::INSTANCE_OCCLUDER) {
if (p_instance->scenario) {
RendererSceneOcclusionCull::get_singleton()->scenario_set_instance(p_instance->scenario->self, p_instance->self, p_instance->base, p_instance->transform, p_instance->visible);
@@ -1559,19 +1615,19 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
idata.parent_array_index = p_instance->visibility_parent ? p_instance->visibility_parent->array_index : -1;
idata.visibility_index = p_instance->visibility_index;
+ for (Set<Instance *>::Element *E = p_instance->visibility_dependencies.front(); E; E = E->next()) {
+ Instance *dep_instance = E->get();
+ if (dep_instance->array_index != -1) {
+ dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index = p_instance->array_index;
+ }
+ }
+
switch (p_instance->base_type) {
case RS::INSTANCE_MESH:
case RS::INSTANCE_MULTIMESH:
case RS::INSTANCE_PARTICLES: {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);
idata.instance_geometry = geom->geometry_instance;
-
- for (Set<Instance *>::Element *E = geom->visibility_dependencies.front(); E; E = E->next()) {
- Instance *dep_instance = E->get();
- if (dep_instance->array_index != -1) {
- dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index = p_instance->array_index;
- }
- }
} break;
case RS::INSTANCE_LIGHT: {
InstanceLightData *light_data = static_cast<InstanceLightData *>(p_instance->base_data);
@@ -1592,6 +1648,9 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
case RS::INSTANCE_VOXEL_GI: {
idata.instance_data_rid = static_cast<InstanceVoxelGIData *>(p_instance->base_data)->probe_instance.get_id();
} break;
+ case RS::INSTANCE_FOG_VOLUME: {
+ idata.instance_data_rid = static_cast<InstanceFogVolumeData *>(p_instance->base_data)->instance.get_id();
+ } break;
case RS::INSTANCE_VISIBLITY_NOTIFIER: {
idata.visibility_notifier = static_cast<InstanceVisibilityNotifierData *>(p_instance->base_data);
} break;
@@ -1603,7 +1662,7 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
//always dirty when added
idata.flags |= InstanceData::FLAG_REFLECTION_PROBE_DIRTY;
}
- if (p_instance->cast_shadows != RS::SHADOW_CASTING_SETTING_SHADOWS_ONLY) {
+ if (p_instance->cast_shadows != RS::SHADOW_CASTING_SETTING_OFF) {
idata.flags |= InstanceData::FLAG_CAST_SHADOWS;
}
if (p_instance->cast_shadows == RS::SHADOW_CASTING_SETTING_SHADOWS_ONLY) {
@@ -1622,6 +1681,9 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
if (p_instance->ignore_occlusion_culling) {
idata.flags |= InstanceData::FLAG_IGNORE_OCCLUSION_CULLING;
}
+ if (p_instance->ignore_all_culling) {
+ idata.flags |= InstanceData::FLAG_IGNORE_ALL_CULLING;
+ }
p_instance->scenario->instance_data.push_back(idata);
p_instance->scenario->instance_aabbs.push_back(InstanceBounds(p_instance->transformed_aabb));
@@ -1721,13 +1783,10 @@ void RendererSceneCull::_unpair_instance(Instance *p_instance) {
swapped_instance->scenario->instance_visibility[swapped_instance->visibility_index].array_index = swapped_instance->array_index;
}
- if ((1 << swapped_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
- InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(swapped_instance->base_data);
- for (Set<Instance *>::Element *E = geom->visibility_dependencies.front(); E; E = E->next()) {
- Instance *dep_instance = E->get();
- if (dep_instance != p_instance && dep_instance->array_index != -1) {
- dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index = swapped_instance->array_index;
- }
+ for (Set<Instance *>::Element *E = swapped_instance->visibility_dependencies.front(); E; E = E->next()) {
+ Instance *dep_instance = E->get();
+ if (dep_instance != p_instance && dep_instance->array_index != -1) {
+ dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index = swapped_instance->array_index;
}
}
}
@@ -1746,11 +1805,14 @@ void RendererSceneCull::_unpair_instance(Instance *p_instance) {
scene_render->geometry_instance_pair_reflection_probe_instances(geom->geometry_instance, nullptr, 0);
scene_render->geometry_instance_pair_decal_instances(geom->geometry_instance, nullptr, 0);
scene_render->geometry_instance_pair_voxel_gi_instances(geom->geometry_instance, nullptr, 0);
+ }
- for (Set<Instance *>::Element *E = geom->visibility_dependencies.front(); E; E = E->next()) {
- Instance *dep_instance = E->get();
- if (dep_instance->array_index != -1) {
- dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index = -1;
+ for (Set<Instance *>::Element *E = p_instance->visibility_dependencies.front(); E; E = E->next()) {
+ Instance *dep_instance = E->get();
+ if (dep_instance->array_index != -1) {
+ dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index = -1;
+ if ((1 << dep_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
+ scene_render->geometry_instance_set_parent_fade_alpha(dep_instance->scenario->instance_data[dep_instance->array_index].instance_geometry, 1.0f);
}
}
}
@@ -1796,6 +1858,9 @@ void RendererSceneCull::_update_instance_aabb(Instance *p_instance) {
new_aabb = RSG::storage->particles_collision_get_aabb(p_instance->base);
} break;
+ case RenderingServer::INSTANCE_FOG_VOLUME: {
+ new_aabb = RSG::storage->fog_volume_get_aabb(p_instance->base);
+ } break;
case RenderingServer::INSTANCE_VISIBLITY_NOTIFIER: {
new_aabb = RSG::storage->visibility_notifier_get_aabb(p_instance->base);
} break;
@@ -2076,7 +2141,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
// This trick here is what stabilizes the shadow (make potential jaggies to not move)
// at the cost of some wasted resolution. Still, the quality increase is very well worth it.
- const real_t unit = radius * 2.0 / texture_size;
+ const real_t unit = (radius + soft_shadow_expand) * 2.0 / texture_size;
x_max_cam = Math::snapped(x_vec.dot(center) + radius + soft_shadow_expand, unit);
x_min_cam = Math::snapped(x_vec.dot(center) - radius - soft_shadow_expand, unit);
y_max_cam = Math::snapped(y_vec.dot(center) + radius + soft_shadow_expand, unit);
@@ -2453,34 +2518,49 @@ void RendererSceneCull::_visibility_cull(const VisibilityCullData &cull_data, ui
if (idata.parent_array_index >= 0) {
uint32_t parent_flags = scenario->instance_data[idata.parent_array_index].flags;
- if ((parent_flags & InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN) || (parent_flags & InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE) == 0) {
+
+ if ((parent_flags & InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN) || !(parent_flags & (InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE | InstanceData::FLAG_VISIBILITY_DEPENDENCY_FADE_CHILDREN))) {
idata.flags |= InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN;
idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE;
+ idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_FADE_CHILDREN;
continue;
}
}
- int range_check = _visibility_range_check(vd, cull_data.camera_position, cull_data.viewport_mask);
+ int range_check = _visibility_range_check<true>(vd, cull_data.camera_position, cull_data.viewport_mask);
if (range_check == -1) {
idata.flags |= InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN;
idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE;
+ idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_FADE_CHILDREN;
} else if (range_check == 1) {
idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN;
idata.flags |= InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE;
+ idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_FADE_CHILDREN;
} else {
idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN;
idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE;
+ if (range_check == 2) {
+ idata.flags |= InstanceData::FLAG_VISIBILITY_DEPENDENCY_FADE_CHILDREN;
+ } else {
+ idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_FADE_CHILDREN;
+ }
}
}
}
+template <bool p_fade_check>
int RendererSceneCull::_visibility_range_check(InstanceVisibilityData &r_vis_data, const Vector3 &p_camera_pos, uint64_t p_viewport_mask) {
float dist = p_camera_pos.distance_to(r_vis_data.position);
+ const RS::VisibilityRangeFadeMode &fade_mode = r_vis_data.fade_mode;
- bool in_range_last_frame = p_viewport_mask & r_vis_data.viewport_state;
- float begin_offset = in_range_last_frame ? -r_vis_data.range_begin_margin : r_vis_data.range_begin_margin;
- float end_offset = in_range_last_frame ? r_vis_data.range_end_margin : -r_vis_data.range_end_margin;
+ float begin_offset = -r_vis_data.range_begin_margin;
+ float end_offset = r_vis_data.range_end_margin;
+
+ if (fade_mode == RS::VISIBILITY_RANGE_FADE_DISABLED && !(p_viewport_mask & r_vis_data.viewport_state)) {
+ begin_offset = -begin_offset;
+ end_offset = -end_offset;
+ }
if (r_vis_data.range_end > 0.0f && dist > r_vis_data.range_end + end_offset) {
r_vis_data.viewport_state &= ~p_viewport_mask;
@@ -2490,10 +2570,34 @@ int RendererSceneCull::_visibility_range_check(InstanceVisibilityData &r_vis_dat
return 1;
} else {
r_vis_data.viewport_state |= p_viewport_mask;
+ if (p_fade_check) {
+ if (fade_mode != RS::VISIBILITY_RANGE_FADE_DISABLED) {
+ r_vis_data.children_fade_alpha = 1.0f;
+ if (r_vis_data.range_end > 0.0f && dist > r_vis_data.range_end - end_offset) {
+ if (fade_mode == RS::VISIBILITY_RANGE_FADE_DEPENDENCIES) {
+ r_vis_data.children_fade_alpha = MIN(1.0f, (dist - (r_vis_data.range_end - end_offset)) / (2.0f * r_vis_data.range_end_margin));
+ }
+ return 2;
+ } else if (r_vis_data.range_begin > 0.0f && dist < r_vis_data.range_begin - begin_offset) {
+ if (fade_mode == RS::VISIBILITY_RANGE_FADE_DEPENDENCIES) {
+ r_vis_data.children_fade_alpha = MIN(1.0f, 1.0 - (dist - (r_vis_data.range_begin + begin_offset)) / (2.0f * r_vis_data.range_begin_margin));
+ }
+ return 2;
+ }
+ }
+ }
return 0;
}
}
+bool RendererSceneCull::_visibility_parent_check(const CullData &p_cull_data, const InstanceData &p_instance_data) {
+ if (p_instance_data.parent_array_index == -1) {
+ return true;
+ }
+ const uint32_t &parent_flags = p_cull_data.scenario->instance_data[p_instance_data.parent_array_index].flags;
+ return ((parent_flags & InstanceData::FLAG_VISIBILITY_DEPENDENCY_NEEDS_CHECK) == InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE) || (parent_flags & InstanceData::FLAG_VISIBILITY_DEPENDENCY_FADE_CHILDREN);
+}
+
void RendererSceneCull::_scene_cull_threaded(uint32_t p_thread, CullData *cull_data) {
uint32_t cull_total = cull_data->scenario->instance_data.size();
uint32_t total_threads = RendererThreadPool::singleton->thread_work_pool.get_thread_count();
@@ -2519,19 +2623,19 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
bool mesh_visible = false;
InstanceData &idata = cull_data.scenario->instance_data[i];
- uint32_t visibility_flags = idata.flags & (InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE | InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN);
+ uint32_t visibility_flags = idata.flags & (InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE | InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN | InstanceData::FLAG_VISIBILITY_DEPENDENCY_FADE_CHILDREN);
int32_t visibility_check = -1;
#define HIDDEN_BY_VISIBILITY_CHECKS (visibility_flags == InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE || visibility_flags == InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN)
#define LAYER_CHECK (cull_data.visible_layers & idata.layer_mask)
#define IN_FRUSTUM(f) (cull_data.scenario->instance_aabbs[i].in_frustum(f))
-#define VIS_RANGE_CHECK ((idata.visibility_index == -1) || _visibility_range_check(cull_data.scenario->instance_visibility[idata.visibility_index], cull_data.cam_transform.origin, cull_data.visibility_viewport_mask) == 0)
-#define VIS_PARENT_CHECK ((idata.parent_array_index == -1) || ((cull_data.scenario->instance_data[idata.parent_array_index].flags & InstanceData::FLAG_VISIBILITY_DEPENDENCY_NEEDS_CHECK) == InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE))
+#define VIS_RANGE_CHECK ((idata.visibility_index == -1) || _visibility_range_check<false>(cull_data.scenario->instance_visibility[idata.visibility_index], cull_data.cam_transform.origin, cull_data.visibility_viewport_mask) == 0)
+#define VIS_PARENT_CHECK (_visibility_parent_check(cull_data, idata))
#define VIS_CHECK (visibility_check < 0 ? (visibility_check = (visibility_flags != InstanceData::FLAG_VISIBILITY_DEPENDENCY_NEEDS_CHECK || (VIS_RANGE_CHECK && VIS_PARENT_CHECK))) : visibility_check)
#define OCCLUSION_CULLED (cull_data.occlusion_buffer != nullptr && (cull_data.scenario->instance_data[i].flags & InstanceData::FLAG_IGNORE_OCCLUSION_CULLING) == 0 && cull_data.occlusion_buffer->is_occluded(cull_data.scenario->instance_aabbs[i].bounds, cull_data.cam_transform.origin, inv_cam_transform, *cull_data.camera_matrix, z_near))
if (!HIDDEN_BY_VISIBILITY_CHECKS) {
- if (LAYER_CHECK && IN_FRUSTUM(cull_data.cull->frustum) && VIS_CHECK && !OCCLUSION_CULLED) {
+ if ((LAYER_CHECK && IN_FRUSTUM(cull_data.cull->frustum) && VIS_CHECK && !OCCLUSION_CULLED) || (cull_data.scenario->instance_data[i].flags & InstanceData::FLAG_IGNORE_ALL_CULLING)) {
uint32_t base_type = idata.flags & InstanceData::FLAG_BASE_TYPE_MASK;
if (base_type == RS::INSTANCE_LIGHT) {
cull_result.lights.push_back(idata.instance);
@@ -2574,6 +2678,8 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
} else if (base_type == RS::INSTANCE_LIGHTMAP) {
cull_result.lightmaps.push_back(RID::from_uint64(idata.instance_data_rid));
+ } else if (base_type == RS::INSTANCE_FOG_VOLUME) {
+ cull_result.fog_volumes.push_back(RID::from_uint64(idata.instance_data_rid));
} else if (base_type == RS::INSTANCE_VISIBLITY_NOTIFIER) {
InstanceVisibilityNotifierData *vnd = idata.visibility_notifier;
if (!vnd->list_element.in_list()) {
@@ -2607,6 +2713,16 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
}
}
+ if (idata.parent_array_index != -1) {
+ float fade = 1.0f;
+ const uint32_t &parent_flags = cull_data.scenario->instance_data[idata.parent_array_index].flags;
+ if (parent_flags & InstanceData::FLAG_VISIBILITY_DEPENDENCY_FADE_CHILDREN) {
+ const int32_t &parent_idx = cull_data.scenario->instance_data[idata.parent_array_index].visibility_index;
+ fade = cull_data.scenario->instance_visibility[parent_idx].children_fade_alpha;
+ }
+ scene_render->geometry_instance_set_parent_fade_alpha(idata.instance_geometry, fade);
+ }
+
if (geometry_instance_pair_mask & (1 << RS::INSTANCE_LIGHT) && (idata.flags & InstanceData::FLAG_GEOM_LIGHTING_DIRTY)) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
uint32_t idx = 0;
@@ -2952,7 +3068,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
Transform3D cam_xf = p_camera_data->main_transform;
float zn = p_camera_data->main_projection.get_z_near();
- Plane p(cam_xf.origin + cam_xf.basis.get_axis(2) * -zn, -cam_xf.basis.get_axis(2)); //camera near plane
+ Plane p(-cam_xf.basis.get_axis(2), cam_xf.origin + cam_xf.basis.get_axis(2) * -zn); //camera near plane
// near plane half width and height
Vector2 vp_half_extents = p_camera_data->main_projection.get_viewport_half_extents();
@@ -3088,7 +3204,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
}
RENDER_TIMESTAMP("Render Scene ");
- scene_render->render_scene(p_render_buffers, p_camera_data, scene_cull_result.geometry_instances, scene_cull_result.light_instances, scene_cull_result.reflections, scene_cull_result.voxel_gi_instances, scene_cull_result.decals, scene_cull_result.lightmaps, p_environment, camera_effects, p_shadow_atlas, occluders_tex, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass, p_screen_lod_threshold, render_shadow_data, max_shadows_used, render_sdfgi_data, cull.sdfgi.region_count, &sdfgi_update_data, r_render_info);
+ scene_render->render_scene(p_render_buffers, p_camera_data, scene_cull_result.geometry_instances, scene_cull_result.light_instances, scene_cull_result.reflections, scene_cull_result.voxel_gi_instances, scene_cull_result.decals, scene_cull_result.lightmaps, scene_cull_result.fog_volumes, p_environment, camera_effects, p_shadow_atlas, occluders_tex, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass, p_screen_lod_threshold, render_shadow_data, max_shadows_used, render_sdfgi_data, cull.sdfgi.region_count, &sdfgi_update_data, r_render_info);
for (uint32_t i = 0; i < max_shadows_used; i++) {
render_shadow_data[i].instances.clear();
@@ -3138,7 +3254,7 @@ void RendererSceneCull::render_empty_scene(RID p_render_buffers, RID p_scenario,
RendererSceneRender::CameraData camera_data;
camera_data.set_camera(Transform3D(), CameraMatrix(), true, false);
- scene_render->render_scene(p_render_buffers, &camera_data, PagedArray<RendererSceneRender::GeometryInstance *>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), RID(), RID(), p_shadow_atlas, RID(), scenario->reflection_atlas, RID(), 0, 0, nullptr, 0, nullptr, 0, nullptr);
+ scene_render->render_scene(p_render_buffers, &camera_data, PagedArray<RendererSceneRender::GeometryInstance *>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), RID(), RID(), p_shadow_atlas, RID(), scenario->reflection_atlas, RID(), 0, 0, nullptr, 0, nullptr, 0, nullptr);
#endif
}
@@ -3742,6 +3858,10 @@ void RendererSceneCull::update() {
}
bool RendererSceneCull::free(RID p_rid) {
+ if (p_rid.is_null()) {
+ return true;
+ }
+
if (scene_render->free(p_rid)) {
return true;
}
diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h
index 905d0eb558..e51a1fc02e 100644
--- a/servers/rendering/renderer_scene_cull.h
+++ b/servers/rendering/renderer_scene_cull.h
@@ -267,7 +267,9 @@ public:
FLAG_VISIBILITY_DEPENDENCY_NEEDS_CHECK = (3 << 20), // 2 bits, overlaps with the other vis. dependency flags
FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE = (1 << 20),
FLAG_VISIBILITY_DEPENDENCY_HIDDEN = (1 << 21),
- FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY = (1 << 22),
+ FLAG_VISIBILITY_DEPENDENCY_FADE_CHILDREN = (1 << 22),
+ FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY = (1 << 23),
+ FLAG_IGNORE_ALL_CULLING = (1 << 24),
};
uint32_t flags = 0;
@@ -286,12 +288,14 @@ public:
struct InstanceVisibilityData {
uint64_t viewport_state = 0;
int32_t array_index = -1;
+ RS::VisibilityRangeFadeMode fade_mode = RS::VISIBILITY_RANGE_FADE_DISABLED;
Vector3 position;
Instance *instance = nullptr;
float range_begin = 0.0f;
float range_end = 0.0f;
float range_begin_margin = 0.0f;
float range_end_margin = 0.0f;
+ float children_fade_alpha = 1.0f;
};
class VisibilityArray : public BinSortedArray<InstanceVisibilityData> {
@@ -394,6 +398,7 @@ public:
float lod_bias;
bool ignore_occlusion_culling;
+ bool ignore_all_culling;
Vector<RID> materials;
@@ -434,14 +439,18 @@ public:
RID self;
//scenario stuff
DynamicBVH::ID indexer_id;
- int32_t array_index;
+ int32_t array_index = -1;
int32_t visibility_index = -1;
- float visibility_range_begin;
- float visibility_range_end;
- float visibility_range_begin_margin;
- float visibility_range_end_margin;
+ float visibility_range_begin = 0.0f;
+ float visibility_range_end = 0.0f;
+ float visibility_range_begin_margin = 0.0f;
+ float visibility_range_end_margin = 0.0f;
+ RS::VisibilityRangeFadeMode visibility_range_fade_mode = RS::VISIBILITY_RANGE_FADE_DISABLED;
Instance *visibility_parent = nullptr;
- Scenario *scenario;
+ Set<Instance *> visibility_dependencies;
+ uint32_t visibility_dependencies_depth = 0;
+ float transparency = 0.0f;
+ Scenario *scenario = nullptr;
SelfList<Instance> scenario_item;
//aabb stuff
@@ -529,6 +538,7 @@ public:
lightmap_cull_index = 0;
lod_bias = 1.0;
ignore_occlusion_culling = false;
+ ignore_all_culling = false;
scenario = nullptr;
@@ -583,8 +593,6 @@ public:
Set<Instance *> reflection_probes;
Set<Instance *> voxel_gi_instances;
Set<Instance *> lightmap_captures;
- Set<Instance *> visibility_dependencies;
- uint32_t visibility_dependencies_depth = 0;
InstanceGeometryData() {
can_cast_shadows = true;
@@ -624,6 +632,11 @@ public:
RID instance;
};
+ struct InstanceFogVolumeData : public InstanceBaseData {
+ RID instance;
+ bool is_global;
+ };
+
struct InstanceVisibilityNotifierData : public InstanceBaseData {
bool just_visible = false;
uint64_t visible_in_frame = 0;
@@ -788,6 +801,7 @@ public:
PagedArray<RID> decals;
PagedArray<RID> voxel_gi_instances;
PagedArray<RID> mesh_instances;
+ PagedArray<RID> fog_volumes;
struct DirectionalShadow {
PagedArray<RendererSceneRender::GeometryInstance *> cascade_geometry_instances[RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES];
@@ -805,6 +819,7 @@ public:
decals.clear();
voxel_gi_instances.clear();
mesh_instances.clear();
+ fog_volumes.clear();
for (int i = 0; i < RendererSceneRender::MAX_DIRECTIONAL_LIGHTS; i++) {
for (int j = 0; j < RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES; j++) {
directional_shadows[i].cascade_geometry_instances[j].clear();
@@ -829,6 +844,7 @@ public:
decals.reset();
voxel_gi_instances.reset();
mesh_instances.reset();
+ fog_volumes.reset();
for (int i = 0; i < RendererSceneRender::MAX_DIRECTIONAL_LIGHTS; i++) {
for (int j = 0; j < RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES; j++) {
directional_shadows[i].cascade_geometry_instances[j].reset();
@@ -853,6 +869,7 @@ public:
decals.merge_unordered(p_cull_result.decals);
voxel_gi_instances.merge_unordered(p_cull_result.voxel_gi_instances);
mesh_instances.merge_unordered(p_cull_result.mesh_instances);
+ fog_volumes.merge_unordered(p_cull_result.fog_volumes);
for (int i = 0; i < RendererSceneRender::MAX_DIRECTIONAL_LIGHTS; i++) {
for (int j = 0; j < RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES; j++) {
@@ -878,6 +895,7 @@ public:
decals.set_page_pool(p_rid_pool);
voxel_gi_instances.set_page_pool(p_rid_pool);
mesh_instances.set_page_pool(p_rid_pool);
+ fog_volumes.set_page_pool(p_rid_pool);
for (int i = 0; i < RendererSceneRender::MAX_DIRECTIONAL_LIGHTS; i++) {
for (int j = 0; j < RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES; j++) {
directional_shadows[i].cascade_geometry_instances[j].set_page_pool(p_geometry_instance_pool);
@@ -920,6 +938,7 @@ public:
virtual void instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight);
virtual void instance_set_surface_override_material(RID p_instance, int p_surface, RID p_material);
virtual void instance_set_visible(RID p_instance, bool p_visible);
+ virtual void instance_geometry_set_transparency(RID p_instance, float p_transparency);
virtual void instance_set_custom_aabb(RID p_instance, AABB p_aabb);
@@ -929,7 +948,9 @@ public:
virtual void instance_set_visibility_parent(RID p_instance, RID p_parent_instance);
- void _update_instance_visibility_depth(Instance *p_instance);
+ virtual void instance_set_ignore_culling(RID p_instance, bool p_enabled);
+
+ bool _update_instance_visibility_depth(Instance *p_instance);
void _update_instance_visibility_dependencies(Instance *p_instance);
// don't use these in a game!
@@ -941,7 +962,7 @@ public:
virtual void instance_geometry_set_cast_shadows_setting(RID p_instance, RS::ShadowCastingSetting p_shadow_casting_setting);
virtual void instance_geometry_set_material_override(RID p_instance, RID p_material);
- virtual void instance_geometry_set_visibility_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin);
+ virtual void instance_geometry_set_visibility_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin, RS::VisibilityRangeFadeMode p_fade_mode);
virtual void instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_slice_index);
virtual void instance_geometry_set_lod_bias(RID p_instance, float p_lod_bias);
@@ -1013,7 +1034,7 @@ public:
void _visibility_cull_threaded(uint32_t p_thread, VisibilityCullData *cull_data);
void _visibility_cull(const VisibilityCullData &cull_data, uint64_t p_from, uint64_t p_to);
- _FORCE_INLINE_ void _visibility_cull(const VisibilityCullData &cull_data, uint64_t p_idx);
+ template <bool p_fade_check>
_FORCE_INLINE_ int _visibility_range_check(InstanceVisibilityData &r_vis_data, const Vector3 &p_camera_pos, uint64_t p_viewport_mask);
struct CullData {
@@ -1030,6 +1051,7 @@ public:
void _scene_cull_threaded(uint32_t p_thread, CullData *cull_data);
void _scene_cull(CullData &cull_data, InstanceCullResult &cull_result, uint64_t p_from, uint64_t p_to);
+ _FORCE_INLINE_ bool _visibility_parent_check(const CullData &p_cull_data, const InstanceData &p_instance_data);
bool _render_reflection_probe_step(Instance *p_instance, int p_step);
void _render_scene(const RendererSceneRender::CameraData *p_camera_data, RID p_render_buffers, RID p_environment, RID p_force_camera_effects, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, bool p_using_shadows = true, RenderInfo *r_render_info = nullptr);
@@ -1095,7 +1117,7 @@ public:
PASS7(environment_set_adjustment, RID, bool, float, float, float, bool, RID)
PASS9(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float)
- PASS10(environment_set_volumetric_fog, RID, bool, float, const Color &, float, float, float, float, bool, float)
+ PASS13(environment_set_volumetric_fog, RID, bool, float, const Color &, const Color &, float, float, float, float, float, bool, float, float)
PASS2(environment_set_volumetric_fog_volume_size, int, int)
PASS1(environment_set_volumetric_fog_filter_active, bool)
@@ -1133,7 +1155,7 @@ public:
/* Render Buffers */
PASS0R(RID, render_buffers_create)
- PASS8(render_buffers_configure, RID, RID, int, int, RS::ViewportMSAA, RS::ViewportScreenSpaceAA, bool, uint32_t)
+ PASS12(render_buffers_configure, RID, RID, int, int, int, int, float, float, RS::ViewportMSAA, RS::ViewportScreenSpaceAA, bool, uint32_t)
PASS1(gi_set_use_half_resolution, bool)
/* Shadow Atlas */
diff --git a/servers/rendering/renderer_scene_render.cpp b/servers/rendering/renderer_scene_render.cpp
index 3a230ac89d..38d1218dee 100644
--- a/servers/rendering/renderer_scene_render.cpp
+++ b/servers/rendering/renderer_scene_render.cpp
@@ -68,7 +68,7 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count
main_transform.basis.set(x, y, z);
// 3. create a horizon plane with one of the eyes and the up vector as normal.
- Plane horizon(p_transforms[0].origin, y);
+ Plane horizon(y, p_transforms[0].origin);
// 4. Intersect horizon, left and right to obtain the combined camera origin.
ERR_FAIL_COND_MSG(
@@ -79,7 +79,7 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count
// 5. figure out far plane, this could use some improvement, we may have our far plane too close like this, not sure if this matters
Vector3 far_center = (planes[0][CameraMatrix::PLANE_FAR].center() + planes[1][CameraMatrix::PLANE_FAR].center()) * 0.5;
- Plane far(far_center, -z);
+ Plane far(-z, far_center);
/////////////////////////////////////////////////////////////////////////////
// Figure out our top/bottom planes
@@ -137,9 +137,9 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count
Plane near;
Vector3 neg_z = -z;
if (neg_z.dot(p_transforms[1].origin) < neg_z.dot(p_transforms[0].origin)) {
- near = Plane(p_transforms[0].origin, neg_z);
+ near = Plane(neg_z, p_transforms[0].origin);
} else {
- near = Plane(p_transforms[1].origin, neg_z);
+ near = Plane(neg_z, p_transforms[1].origin);
}
// 13. Intersect near plane with bottm/left planes, to obtain min_vec then top/right to obtain max_vec
diff --git a/servers/rendering/renderer_scene_render.h b/servers/rendering/renderer_scene_render.h
index 60ba355c03..0d71ea22da 100644
--- a/servers/rendering/renderer_scene_render.h
+++ b/servers/rendering/renderer_scene_render.h
@@ -56,6 +56,9 @@ public:
virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) = 0;
virtual void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) = 0;
virtual void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) = 0;
+ virtual void geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) = 0;
+ virtual void geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) = 0;
+ virtual void geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) = 0;
virtual void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) = 0;
virtual void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) = 0;
virtual void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) = 0;
@@ -123,7 +126,7 @@ public:
virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) = 0;
virtual void environment_glow_set_use_high_quality(bool p_enable) = 0;
- virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount) = 0;
+ virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) = 0;
virtual void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) = 0;
virtual void environment_set_volumetric_fog_filter_active(bool p_enable) = 0;
@@ -173,6 +176,12 @@ public:
return true;
}
+ virtual RID fog_volume_instance_create(RID p_fog_volume) = 0;
+ virtual void fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) = 0;
+ virtual void fog_volume_instance_set_active(RID p_fog_volume_instance, bool p_active) = 0;
+ virtual RID fog_volume_instance_get_volume(RID p_fog_volume_instance) const = 0;
+ virtual Vector3 fog_volume_instance_get_position(RID p_fog_volume_instance) const = 0;
+
virtual RID reflection_atlas_create() = 0;
virtual void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) = 0;
virtual int reflection_atlas_get_size(RID p_ref_atlas) const = 0;
@@ -237,7 +246,7 @@ public:
void set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const CameraMatrix *p_projections, bool p_is_ortogonal, bool p_vaspect);
};
- virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) = 0;
+ virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) = 0;
virtual void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
virtual void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) = 0;
@@ -247,7 +256,7 @@ public:
virtual void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) = 0;
virtual RID render_buffers_create() = 0;
- virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) = 0;
+ virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) = 0;
virtual void gi_set_use_half_resolution(bool p_enable) = 0;
virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_limit) = 0;
diff --git a/servers/rendering/renderer_storage.h b/servers/rendering/renderer_storage.h
index 2304394501..8926bf24aa 100644
--- a/servers/rendering/renderer_storage.h
+++ b/servers/rendering/renderer_storage.h
@@ -183,8 +183,8 @@ public:
virtual String shader_get_code(RID p_shader) const = 0;
virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const = 0;
- virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) = 0;
- virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const = 0;
+ virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) = 0;
+ virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const = 0;
virtual Variant shader_get_param_default(RID p_material, const StringName &p_param) const = 0;
virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const = 0;
@@ -535,6 +535,19 @@ public:
virtual bool particles_collision_is_heightfield(RID p_particles_collision) const = 0;
virtual RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const = 0;
+ /* FOG VOLUMES */
+
+ virtual RID fog_volume_allocate() = 0;
+ virtual void fog_volume_initialize(RID p_rid) = 0;
+
+ virtual void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) = 0;
+ virtual void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) = 0;
+ virtual void fog_volume_set_material(RID p_fog_volume, RID p_material) = 0;
+ virtual AABB fog_volume_get_aabb(RID p_fog_volume) const = 0;
+ virtual RS::FogVolumeShape fog_volume_get_shape(RID p_fog_volume) const = 0;
+
+ /* VISIBILITY NOTIFIER */
+
virtual RID visibility_notifier_allocate() = 0;
virtual void visibility_notifier_initialize(RID p_notifier) = 0;
virtual void visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) = 0;
diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp
index b67b1cd806..eddf5bf53d 100644
--- a/servers/rendering/renderer_viewport.cpp
+++ b/servers/rendering/renderer_viewport.cpp
@@ -77,18 +77,69 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
RSG::scene->free(p_viewport->render_buffers);
p_viewport->render_buffers = RID();
} else {
- float scale_3d = p_viewport->scale_3d;
- if (Engine::get_singleton()->is_editor_hint()) {
- // Ignore the 3D viewport render scaling inside of the editor.
- // The Half Resolution 3D editor viewport option should be used instead.
- scale_3d = 1.0;
+ float scaling_3d_scale = p_viewport->scaling_3d_scale;
+
+ RS::ViewportScaling3DMode scaling_3d_mode = p_viewport->scaling_3d_mode;
+ bool scaling_enabled = true;
+
+ if ((scaling_3d_mode == RS::VIEWPORT_SCALING_3D_MODE_FSR) && (scaling_3d_scale > 1.0)) {
+ // FSR is not design for downsampling.
+ // Throw a warning and fallback to VIEWPORT_SCALING_3D_MODE_BILINEAR
+ WARN_PRINT_ONCE("FSR 3D resolution scaling does not support supersampling. Falling back to bilinear scaling.");
+ scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_BILINEAR;
+ }
+
+ if ((scaling_3d_mode == RS::VIEWPORT_SCALING_3D_MODE_FSR) && !p_viewport->fsr_enabled) {
+ // FSR is not actually available.
+ // Throw a warning and fallback to disable scaling
+ WARN_PRINT_ONCE("FSR 3D resolution scaling is not available. Disabling 3D resolution scaling.");
+ scaling_enabled = false;
+ }
+
+ if (scaling_3d_scale == 1.0) {
+ scaling_enabled = false;
}
- // Clamp 3D rendering resolution to reasonable values supported on most hardware.
- // This prevents freezing the engine or outright crashing on lower-end GPUs.
- const int width = CLAMP(p_viewport->size.width * scale_3d, 1, 16384);
- const int height = CLAMP(p_viewport->size.height * scale_3d, 1, 16384);
- RSG::scene->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, width, height, p_viewport->msaa, p_viewport->screen_space_aa, p_viewport->use_debanding, p_viewport->get_view_count());
+ int width;
+ int height;
+ int render_width;
+ int render_height;
+
+ if (scaling_enabled) {
+ switch (scaling_3d_mode) {
+ case RS::VIEWPORT_SCALING_3D_MODE_BILINEAR:
+ // Clamp 3D rendering resolution to reasonable values supported on most hardware.
+ // This prevents freezing the engine or outright crashing on lower-end GPUs.
+ width = CLAMP(p_viewport->size.width * scaling_3d_scale, 1, 16384);
+ height = CLAMP(p_viewport->size.height * scaling_3d_scale, 1, 16384);
+ render_width = width;
+ render_height = height;
+ break;
+ case RS::VIEWPORT_SCALING_3D_MODE_FSR:
+ width = p_viewport->size.width;
+ height = p_viewport->size.height;
+ render_width = MAX(width * scaling_3d_scale, 1.0); // width / (width * scaling)
+ render_height = MAX(height * scaling_3d_scale, 1.0);
+ break;
+ default:
+ // This is an unknown mode.
+ WARN_PRINT_ONCE(vformat("Unknown scaling mode: %d. Disabling 3D resolution scaling.", scaling_3d_mode));
+ width = p_viewport->size.width;
+ height = p_viewport->size.height;
+ render_width = width;
+ render_height = height;
+ break;
+ }
+ } else {
+ width = p_viewport->size.width;
+ height = p_viewport->size.height;
+ render_width = width;
+ render_height = height;
+ }
+
+ p_viewport->internal_size = Size2(render_width, render_height);
+
+ RSG::scene->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, render_width, render_height, width, height, p_viewport->fsr_sharpness, p_viewport->fsr_mipmap_bias, p_viewport->msaa, p_viewport->screen_space_aa, p_viewport->use_debanding, p_viewport->get_view_count());
}
}
}
@@ -117,7 +168,7 @@ void RendererViewport::_draw_3d(Viewport *p_viewport) {
}
float screen_lod_threshold = p_viewport->lod_threshold / float(p_viewport->size.width);
- RSG::scene->render_camera(p_viewport->render_buffers, p_viewport->camera, p_viewport->scenario, p_viewport->self, p_viewport->size, screen_lod_threshold, p_viewport->shadow_atlas, xr_interface, &p_viewport->render_info);
+ RSG::scene->render_camera(p_viewport->render_buffers, p_viewport->camera, p_viewport->scenario, p_viewport->self, p_viewport->internal_size, screen_lod_threshold, p_viewport->shadow_atlas, xr_interface, &p_viewport->render_info);
RENDER_TIMESTAMP("<End Rendering 3D Scene");
}
@@ -129,6 +180,11 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
timestamp_vp_map[rt_id] = p_viewport->self;
}
+ if (OS::get_singleton()->get_current_rendering_driver_name() == "opengl3") {
+ // This is currently needed for GLES to keep the current window being rendered to up to date
+ DisplayServer::get_singleton()->gl_window_make_current(p_viewport->viewport_to_screen);
+ }
+
/* Camera should always be BEFORE any other 3D */
bool scenario_draw_canvas_bg = false; //draw canvas, or some layer of it, as BG for 3D instead of in front
@@ -495,9 +551,6 @@ void RendererViewport::draw_viewports() {
if (XRServer::get_singleton() != nullptr) {
xr_interface = XRServer::get_singleton()->get_primary_interface();
-
- // process all our active interfaces
- XRServer::get_singleton()->_process();
}
if (Engine::get_singleton()->is_editor_hint()) {
@@ -569,7 +622,7 @@ void RendererViewport::draw_viewports() {
// override our size, make sure it matches our required size and is created as a stereo target
vp->size = xr_interface->get_render_target_size();
uint32_t view_count = xr_interface->get_view_count();
- RSG::storage->render_target_set_size(vp->render_target, vp->size.x, vp->size.y, view_count);
+ RSG::storage->render_target_set_size(vp->render_target, vp->internal_size.x, vp->internal_size.y, view_count);
// check for an external texture destination (disabled for now, not yet supported)
// RSG::storage->render_target_set_external_texture(vp->render_target, xr_interface->get_external_texture_for_eye(leftOrMono));
@@ -660,6 +713,8 @@ void RendererViewport::viewport_initialize(RID p_rid) {
viewport->render_target = RSG::storage->render_target_create();
viewport->shadow_atlas = RSG::scene->shadow_atlas_create();
viewport->viewport_render_direct_to_screen = false;
+
+ viewport->fsr_enabled = !RSG::rasterizer->is_low_end() && !viewport->disable_3d;
}
void RendererViewport::viewport_set_use_xr(RID p_viewport, bool p_use_xr) {
@@ -674,18 +729,42 @@ void RendererViewport::viewport_set_use_xr(RID p_viewport, bool p_use_xr) {
_configure_3d_render_buffers(viewport);
}
-void RendererViewport::viewport_set_scale_3d(RID p_viewport, float p_scale_3d) {
+void RendererViewport::viewport_set_scaling_3d_mode(RID p_viewport, RS::ViewportScaling3DMode p_mode) {
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
+ ERR_FAIL_COND(!viewport);
+
+ viewport->scaling_3d_mode = p_mode;
+ _configure_3d_render_buffers(viewport);
+}
+
+void RendererViewport::viewport_set_fsr_sharpness(RID p_viewport, float p_sharpness) {
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
+ ERR_FAIL_COND(!viewport);
+
+ viewport->fsr_sharpness = p_sharpness;
+ _configure_3d_render_buffers(viewport);
+}
+
+void RendererViewport::viewport_set_fsr_mipmap_bias(RID p_viewport, float p_mipmap_bias) {
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
+ ERR_FAIL_COND(!viewport);
+
+ viewport->fsr_mipmap_bias = p_mipmap_bias;
+ _configure_3d_render_buffers(viewport);
+}
+
+void RendererViewport::viewport_set_scaling_3d_scale(RID p_viewport, float p_scaling_3d_scale) {
Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
// Clamp to reasonable values that are actually useful.
// Values above 2.0 don't serve a practical purpose since the viewport
// isn't displayed with mipmaps.
- if (viewport->scale_3d == CLAMP(p_scale_3d, 0.1, 2.0)) {
+ if (viewport->scaling_3d_scale == CLAMP(p_scaling_3d_scale, 0.1, 2.0)) {
return;
}
- viewport->scale_3d = CLAMP(p_scale_3d, 0.1, 2.0);
+ viewport->scaling_3d_scale = CLAMP(p_scaling_3d_scale, 0.1, 2.0);
_configure_3d_render_buffers(viewport);
}
@@ -711,6 +790,7 @@ void RendererViewport::viewport_set_size(RID p_viewport, int p_width, int p_heig
ERR_FAIL_COND(!viewport);
viewport->size = Size2(p_width, p_height);
+
uint32_t view_count = viewport->get_view_count();
RSG::storage->render_target_set_size(viewport->render_target, p_width, p_height, view_count);
_configure_3d_render_buffers(viewport);
@@ -750,7 +830,7 @@ void RendererViewport::viewport_attach_to_screen(RID p_viewport, const Rect2 &p_
ERR_FAIL_COND(!viewport);
if (p_screen != DisplayServer::INVALID_WINDOW_ID) {
- // If using GLES2 we can optimize this operation by rendering directly to system_fbo
+ // If using OpenGL we can optimize this operation by rendering directly to system_fbo
// instead of rendering to fbo and copying to system_fbo after
if (RSG::rasterizer->is_low_end() && viewport->viewport_render_direct_to_screen) {
RSG::storage->render_target_set_size(viewport->render_target, p_rect.size.x, p_rect.size.y, viewport->get_view_count());
@@ -763,7 +843,7 @@ void RendererViewport::viewport_attach_to_screen(RID p_viewport, const Rect2 &p_
// if render_direct_to_screen was used, reset size and position
if (RSG::rasterizer->is_low_end() && viewport->viewport_render_direct_to_screen) {
RSG::storage->render_target_set_position(viewport->render_target, 0, 0);
- RSG::storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y, viewport->get_view_count());
+ RSG::storage->render_target_set_size(viewport->render_target, viewport->internal_size.x, viewport->internal_size.y, viewport->get_view_count());
}
viewport->viewport_to_screen_rect = Rect2();
@@ -1012,6 +1092,7 @@ void RendererViewport::viewport_set_lod_threshold(RID p_viewport, float p_pixels
}
int RendererViewport::viewport_get_render_info(RID p_viewport, RS::ViewportRenderInfoType p_type, RS::ViewportRenderInfo p_info) {
+ ERR_FAIL_INDEX_V(p_type, RS::VIEWPORT_RENDER_INFO_TYPE_MAX, -1);
ERR_FAIL_INDEX_V(p_info, RS::VIEWPORT_RENDER_INFO_MAX, -1);
Viewport *viewport = viewport_owner.get_or_null(p_viewport);
diff --git a/servers/rendering/renderer_viewport.h b/servers/rendering/renderer_viewport.h
index f6e6cc8e84..5bb4dbbc6f 100644
--- a/servers/rendering/renderer_viewport.h
+++ b/servers/rendering/renderer_viewport.h
@@ -49,12 +49,16 @@ public:
bool use_xr; /* use xr interface to override camera positioning and projection matrices and control output */
- float scale_3d = 1.0;
-
+ Size2i internal_size;
Size2i size;
RID camera;
RID scenario;
+ RS::ViewportScaling3DMode scaling_3d_mode;
+ float scaling_3d_scale = 1.0;
+ float fsr_sharpness = 0.2f;
+ float fsr_mipmap_bias = 0.0f;
+ bool fsr_enabled;
RS::ViewportUpdateMode update_mode;
RID render_target;
RID render_target_texture;
@@ -207,7 +211,6 @@ public:
void viewport_initialize(RID p_rid);
void viewport_set_use_xr(RID p_viewport, bool p_use_xr);
- void viewport_set_scale_3d(RID p_viewport, float p_scale_3d);
void viewport_set_size(RID p_viewport, int p_width, int p_height);
@@ -216,6 +219,12 @@ public:
void viewport_set_active(RID p_viewport, bool p_active);
void viewport_set_parent_viewport(RID p_viewport, RID p_parent_viewport);
+
+ void viewport_set_scaling_3d_mode(RID p_viewport, RS::ViewportScaling3DMode p_mode);
+ void viewport_set_scaling_3d_scale(RID p_viewport, float p_scaling_3d_scale);
+ void viewport_set_fsr_sharpness(RID p_viewport, float p_sharpness);
+ void viewport_set_fsr_mipmap_bias(RID p_viewport, float p_mipmap_bias);
+
void viewport_set_update_mode(RID p_viewport, RS::ViewportUpdateMode p_mode);
void viewport_set_vflip(RID p_viewport, bool p_enable);
diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp
index dcbc5f5c8e..5602bb197b 100644
--- a/servers/rendering/rendering_device.cpp
+++ b/servers/rendering/rendering_device.cpp
@@ -185,9 +185,13 @@ Ref<RDShaderSPIRV> RenderingDevice::_shader_compile_spirv_from_source(const Ref<
String error;
ShaderStage stage = ShaderStage(i);
- Vector<uint8_t> spirv = shader_compile_spirv_from_source(stage, p_source->get_stage_source(stage), p_source->get_language(), &error, p_allow_cache);
- bytecode->set_stage_bytecode(stage, spirv);
- bytecode->set_stage_compile_error(stage, error);
+ String source = p_source->get_stage_source(stage);
+
+ if (!source.is_empty()) {
+ Vector<uint8_t> spirv = shader_compile_spirv_from_source(stage, source, p_source->get_language(), &error, p_allow_cache);
+ bytecode->set_stage_bytecode(stage, spirv);
+ bytecode->set_stage_compile_error(stage, error);
+ }
}
return bytecode;
}
diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h
index 5eb8f1cead..563a80c12c 100644
--- a/servers/rendering/rendering_device.h
+++ b/servers/rendering/rendering_device.h
@@ -120,6 +120,7 @@ public:
// features
bool supports_multiview = false; // If true this device supports multiview options
+ bool supports_fsr_half_float = false; // If true this device supports FSR scaling 3D in half float mode, otherwise use the fallback mode
};
typedef String (*ShaderSPIRVGetCacheKeyFunction)(const Capabilities *p_capabilities);
diff --git a/servers/rendering/rendering_device_binds.h b/servers/rendering/rendering_device_binds.h
index da614877c4..2cf7821668 100644
--- a/servers/rendering/rendering_device_binds.h
+++ b/servers/rendering/rendering_device_binds.h
@@ -427,7 +427,7 @@ protected:
ClassDB::bind_method(D_METHOD("_set_versions", "versions"), &RDShaderFile::_set_versions);
ClassDB::bind_method(D_METHOD("_get_versions"), &RDShaderFile::_get_versions);
- ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "_versions", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_versions", "_get_versions");
+ ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "_versions", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_versions", "_get_versions");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "base_error"), "set_base_error", "get_base_error");
}
};
diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp
index 107c9f8040..2ce9a20b6b 100644
--- a/servers/rendering/rendering_server_default.cpp
+++ b/servers/rendering/rendering_server_default.cpp
@@ -64,14 +64,8 @@ void RenderingServerDefault::_free(RID p_rid) {
/* EVENT QUEUING */
-void RenderingServerDefault::request_frame_drawn_callback(Object *p_where, const StringName &p_method, const Variant &p_userdata) {
- ERR_FAIL_NULL(p_where);
- FrameDrawnCallbacks fdc;
- fdc.object = p_where->get_instance_id();
- fdc.method = p_method;
- fdc.param = p_userdata;
-
- frame_drawn_callbacks.push_back(fdc);
+void RenderingServerDefault::request_frame_drawn_callback(const Callable &p_callable) {
+ frame_drawn_callbacks.push_back(p_callable);
}
void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
@@ -103,15 +97,13 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
RSG::scene->update_visibility_notifiers();
while (frame_drawn_callbacks.front()) {
- Object *obj = ObjectDB::get_instance(frame_drawn_callbacks.front()->get().object);
- if (obj) {
- Callable::CallError ce;
- const Variant *v = &frame_drawn_callbacks.front()->get().param;
- obj->call(frame_drawn_callbacks.front()->get().method, &v, 1, ce);
- if (ce.error != Callable::CallError::CALL_OK) {
- String err = Variant::get_call_error_text(obj, frame_drawn_callbacks.front()->get().method, &v, 1, ce);
- ERR_PRINT("Error calling frame drawn function: " + err);
- }
+ Callable c = frame_drawn_callbacks.front()->get();
+ Variant result;
+ Callable::CallError ce;
+ c.call(nullptr, 0, result, ce);
+ if (ce.error != Callable::CallError::CALL_OK) {
+ String err = Variant::get_callable_error_text(c, nullptr, 0, ce);
+ ERR_PRINT("Error calling frame drawn function: " + err);
}
frame_drawn_callbacks.pop_front();
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index 911d4c463b..b50631bb21 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -58,13 +58,7 @@ class RenderingServerDefault : public RenderingServer {
static int changes;
RID test_cube;
- struct FrameDrawnCallbacks {
- ObjectID object;
- StringName method;
- Variant param;
- };
-
- List<FrameDrawnCallbacks> frame_drawn_callbacks;
+ List<Callable> frame_drawn_callbacks;
static void _changes_changed() {}
@@ -229,8 +223,8 @@ public:
FUNC2SC(shader_get_param_list, RID, List<PropertyInfo> *)
- FUNC3(shader_set_default_texture_param, RID, const StringName &, RID)
- FUNC2RC(RID, shader_get_default_texture_param, RID, const StringName &)
+ FUNC4(shader_set_default_texture_param, RID, const StringName &, RID, int)
+ FUNC3RC(RID, shader_get_default_texture_param, RID, const StringName &, int)
FUNC2RC(Variant, shader_get_param_default, RID, const StringName &)
FUNC1RC(ShaderNativeSourceCode, shader_get_native_source_code, RID)
@@ -487,6 +481,14 @@ public:
FUNC1(particles_collision_height_field_update, RID)
FUNC2(particles_collision_set_height_field_resolution, RID, ParticlesCollisionHeightfieldResolution)
+ /* FOG VOLUME */
+
+ FUNCRIDSPLIT(fog_volume)
+
+ FUNC2(fog_volume_set_shape, RID, FogVolumeShape)
+ FUNC2(fog_volume_set_extents, RID, const Vector3 &)
+ FUNC2(fog_volume_set_material, RID, RID)
+
/* VISIBILITY_NOTIFIER */
FUNCRIDSPLIT(visibility_notifier)
@@ -526,7 +528,6 @@ public:
FUNCRIDSPLIT(viewport)
FUNC2(viewport_set_use_xr, RID, bool)
- FUNC2(viewport_set_scale_3d, RID, float)
FUNC3(viewport_set_size, RID, int, int)
FUNC2(viewport_set_active, RID, bool)
@@ -537,6 +538,11 @@ public:
FUNC3(viewport_attach_to_screen, RID, const Rect2 &, int)
FUNC2(viewport_set_render_direct_to_screen, RID, bool)
+ FUNC2(viewport_set_scaling_3d_mode, RID, ViewportScaling3DMode)
+ FUNC2(viewport_set_scaling_3d_scale, RID, float)
+ FUNC2(viewport_set_fsr_sharpness, RID, float)
+ FUNC2(viewport_set_fsr_mipmap_bias, RID, float)
+
FUNC2(viewport_set_update_mode, RID, ViewportUpdateMode)
FUNC1RC(RID, viewport_get_texture, RID)
@@ -629,7 +635,7 @@ public:
FUNC7(environment_set_adjustment, RID, bool, float, float, float, bool, RID)
FUNC9(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float)
- FUNC10(environment_set_volumetric_fog, RID, bool, float, const Color &, float, float, float, float, bool, float)
+ FUNC13(environment_set_volumetric_fog, RID, bool, float, const Color &, const Color &, float, float, float, float, float, bool, float, float)
FUNC2(environment_set_volumetric_fog_volume_size, int, int)
FUNC1(environment_set_volumetric_fog_filter_active, bool)
@@ -693,6 +699,8 @@ public:
FUNC2(instance_set_extra_visibility_margin, RID, real_t)
FUNC2(instance_set_visibility_parent, RID, RID)
+ FUNC2(instance_set_ignore_culling, RID, bool)
+
// don't use these in a game!
FUNC2RC(Vector<ObjectID>, instances_cull_aabb, const AABB &, RID)
FUNC3RC(Vector<ObjectID>, instances_cull_ray, const Vector3 &, const Vector3 &, RID)
@@ -702,10 +710,10 @@ public:
FUNC2(instance_geometry_set_cast_shadows_setting, RID, ShadowCastingSetting)
FUNC2(instance_geometry_set_material_override, RID, RID)
- FUNC5(instance_geometry_set_visibility_range, RID, float, float, float, float)
+ FUNC6(instance_geometry_set_visibility_range, RID, float, float, float, float, VisibilityRangeFadeMode)
FUNC4(instance_geometry_set_lightmap, RID, RID, const Rect2 &, int)
FUNC2(instance_geometry_set_lod_bias, RID, float)
-
+ FUNC2(instance_geometry_set_transparency, RID, float)
FUNC3(instance_geometry_set_shader_parameter, RID, const StringName &, const Variant &)
FUNC2RC(Variant, instance_geometry_get_shader_parameter, RID, const StringName &)
FUNC2RC(Variant, instance_geometry_get_shader_parameter_default_value, RID, const StringName &)
@@ -870,7 +878,7 @@ public:
/* EVENT QUEUING */
- virtual void request_frame_drawn_callback(Object *p_where, const StringName &p_method, const Variant &p_userdata) override;
+ virtual void request_frame_drawn_callback(const Callable &p_callable) override;
virtual void draw(bool p_swap_buffers, double frame_step) override;
virtual void sync() override;
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index 81a9e00d7c..f5e91d0423 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -88,7 +88,8 @@ String ShaderLanguage::get_operator_text(Operator p_op) {
"--",
"()",
"construct",
- "index" };
+ "index",
+ "empty" };
return op_names[p_op];
}
@@ -474,6 +475,10 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
case ':':
return _make_token(TK_COLON);
case '^':
+ if (GETCHAR(0) == '=') {
+ char_idx++;
+ return _make_token(TK_OP_ASSIGN_BIT_XOR);
+ }
return _make_token(TK_OP_BIT_XOR);
case '~':
return _make_token(TK_OP_BIT_INVERT);
@@ -2456,6 +2461,23 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
{ "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
+ // textureGather
+
+ { "textureGather", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureGather", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureGather", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureGather", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true },
+ { "textureGather", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true },
+ { "textureGather", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true },
+ { "textureGather", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureGather", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureGather", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureGather", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true },
+ { "textureGather", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true },
+ { "textureGather", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true },
+ { "textureGather", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureGather", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true },
+
// dFdx
{ "dFdx", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
@@ -2576,6 +2598,20 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "findMSB", TYPE_UVEC3, { TYPE_UVEC3, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
{ "findMSB", TYPE_UVEC4, { TYPE_UVEC4, TYPE_VOID }, { "value" }, TAG_GLOBAL, true },
+ // umulExtended
+
+ { "umulExtended", TYPE_VOID, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "y", "msb", "lsb" }, TAG_GLOBAL, true },
+ { "umulExtended", TYPE_VOID, { TYPE_UVEC2, TYPE_UVEC2, TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "x", "y", "msb", "lsb" }, TAG_GLOBAL, true },
+ { "umulExtended", TYPE_VOID, { TYPE_UVEC3, TYPE_UVEC3, TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "x", "y", "msb", "lsb" }, TAG_GLOBAL, true },
+ { "umulExtended", TYPE_VOID, { TYPE_UVEC4, TYPE_UVEC4, TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "x", "y", "msb", "lsb" }, TAG_GLOBAL, true },
+
+ // imulExtended
+
+ { "imulExtended", TYPE_VOID, { TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_VOID }, { "x", "y", "msb", "lsb" }, TAG_GLOBAL, true },
+ { "imulExtended", TYPE_VOID, { TYPE_IVEC2, TYPE_IVEC2, TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, { "x", "y", "msb", "lsb" }, TAG_GLOBAL, true },
+ { "imulExtended", TYPE_VOID, { TYPE_IVEC3, TYPE_IVEC3, TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, { "x", "y", "msb", "lsb" }, TAG_GLOBAL, true },
+ { "imulExtended", TYPE_VOID, { TYPE_IVEC4, TYPE_IVEC4, TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "x", "y", "msb", "lsb" }, TAG_GLOBAL, true },
+
// uaddCarry
{ "uaddCarry", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "y", "carry" }, TAG_GLOBAL, true },
@@ -2590,15 +2626,37 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "usubBorrow", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "x", "y", "borrow" }, TAG_GLOBAL, true },
{ "usubBorrow", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "x", "y", "borrow" }, TAG_GLOBAL, true },
+ // ldexp
+
+ { "ldexp", TYPE_FLOAT, { TYPE_FLOAT, TYPE_INT, TYPE_VOID }, { "x", "exp" }, TAG_GLOBAL, true },
+ { "ldexp", TYPE_VEC2, { TYPE_VEC2, TYPE_IVEC2, TYPE_VOID }, { "x", "exp" }, TAG_GLOBAL, true },
+ { "ldexp", TYPE_VEC3, { TYPE_VEC3, TYPE_IVEC3, TYPE_VOID }, { "x", "exp" }, TAG_GLOBAL, true },
+ { "ldexp", TYPE_VEC4, { TYPE_VEC4, TYPE_IVEC4, TYPE_VOID }, { "x", "exp" }, TAG_GLOBAL, true },
+
+ // frexp
+
+ { "frexp", TYPE_FLOAT, { TYPE_FLOAT, TYPE_INT, TYPE_VOID }, { "x", "exp" }, TAG_GLOBAL, true },
+ { "frexp", TYPE_VEC2, { TYPE_VEC2, TYPE_IVEC2, TYPE_VOID }, { "x", "exp" }, TAG_GLOBAL, true },
+ { "frexp", TYPE_VEC3, { TYPE_VEC3, TYPE_IVEC3, TYPE_VOID }, { "x", "exp" }, TAG_GLOBAL, true },
+ { "frexp", TYPE_VEC4, { TYPE_VEC4, TYPE_IVEC4, TYPE_VOID }, { "x", "exp" }, TAG_GLOBAL, true },
+
{ nullptr, TYPE_VOID, { TYPE_VOID }, { "" }, TAG_GLOBAL, false }
};
const ShaderLanguage::BuiltinFuncOutArgs ShaderLanguage::builtin_func_out_args[] = {
- //constructors
- { "modf", 1 },
- { "uaddCarry", 2 },
- { "usubBorrow", 2 },
- { nullptr, 0 }
+ { "modf", { 1, -1 } },
+ { "umulExtended", { 2, 3 } },
+ { "imulExtended", { 2, 3 } },
+ { "uaddCarry", { 2, -1 } },
+ { "usubBorrow", { 2, -1 } },
+ { "ldexp", { 1, -1 } },
+ { "frexp", { 1, -1 } },
+ { nullptr, { 0, -1 } }
+};
+
+const ShaderLanguage::BuiltinFuncConstArgs ShaderLanguage::builtin_func_const_args[] = {
+ { "textureGather", 2, 0, 3 },
+ { nullptr, 0, 0, 0 }
};
bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionInfo &p_function_info, OperatorNode *p_func, DataType *r_ret_type, StringName *r_ret_type_str) {
@@ -2692,100 +2750,153 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
}
if (!fail) {
- //make sure its not an out argument used in the wrong way
- int outarg_idx = 0;
- while (builtin_func_out_args[outarg_idx].name) {
- if (String(name) == builtin_func_out_args[outarg_idx].name) {
- int arg_idx = builtin_func_out_args[outarg_idx].argument;
-
- if (arg_idx < argcount) {
- if (p_func->arguments[arg_idx + 1]->type != Node::TYPE_VARIABLE && p_func->arguments[arg_idx + 1]->type != Node::TYPE_MEMBER && p_func->arguments[arg_idx + 1]->type != Node::TYPE_ARRAY) {
- _set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' is not a variable, array or member.");
- return false;
+ {
+ int constarg_idx = 0;
+ while (builtin_func_const_args[constarg_idx].name) {
+ if (String(name) == builtin_func_const_args[constarg_idx].name) {
+ int arg = builtin_func_const_args[constarg_idx].arg + 1;
+ if (p_func->arguments.size() <= arg) {
+ break;
}
- if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_ARRAY) {
- ArrayNode *mn = static_cast<ArrayNode *>(p_func->arguments[arg_idx + 1]);
- if (mn->is_const) {
- fail = true;
- }
- } else if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_MEMBER) {
- MemberNode *mn = static_cast<MemberNode *>(p_func->arguments[arg_idx + 1]);
- if (mn->basetype_const) {
- fail = true;
+ int min = builtin_func_const_args[constarg_idx].min;
+ int max = builtin_func_const_args[constarg_idx].max;
+
+ bool error = false;
+ if (p_func->arguments[arg]->type == Node::TYPE_VARIABLE) {
+ const VariableNode *vn = (VariableNode *)p_func->arguments[arg];
+
+ bool is_const = false;
+ ConstantNode::Value value;
+ value.sint = -1;
+
+ _find_identifier(p_block, false, p_function_info, vn->name, nullptr, nullptr, &is_const, nullptr, nullptr, &value);
+ if (!is_const || value.sint < min || value.sint > max) {
+ error = true;
}
- } else { // TYPE_VARIABLE
- VariableNode *vn = static_cast<VariableNode *>(p_func->arguments[arg_idx + 1]);
- if (vn->is_const) {
- fail = true;
- } else {
- StringName varname = vn->name;
- if (shader->uniforms.has(varname)) {
- fail = true;
- } else {
- if (shader->varyings.has(varname)) {
- _set_error(vformat("Varyings cannot be passed for '%s' parameter!", "out"));
- return false;
- }
- if (p_function_info.built_ins.has(varname)) {
- BuiltInInfo info = p_function_info.built_ins[varname];
- if (info.constant) {
- fail = true;
- }
+ } else {
+ if (p_func->arguments[arg]->type == Node::TYPE_CONSTANT) {
+ ConstantNode *cn = (ConstantNode *)p_func->arguments[arg];
+
+ if (cn->get_datatype() == TYPE_INT && cn->values.size() == 1) {
+ int value = cn->values[0].sint;
+
+ if (value < min || value > max) {
+ error = true;
}
+ } else {
+ error = true;
}
+ } else {
+ error = true;
}
}
- if (fail) {
- _set_error(vformat("Constant value cannot be passed for '%s' parameter!", "out"));
+ if (error) {
+ _set_error(vformat("Expected integer constant within %s..%s range.", min, max));
return false;
}
+ }
+ constarg_idx++;
+ }
+ }
- StringName var_name;
- if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_ARRAY) {
- var_name = static_cast<const ArrayNode *>(p_func->arguments[arg_idx + 1])->name;
- } else if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_MEMBER) {
- Node *n = static_cast<const MemberNode *>(p_func->arguments[arg_idx + 1])->owner;
- while (n->type == Node::TYPE_MEMBER) {
- n = static_cast<const MemberNode *>(n)->owner;
- }
- if (n->type != Node::TYPE_VARIABLE && n->type != Node::TYPE_ARRAY) {
+ //make sure its not an out argument used in the wrong way
+ int outarg_idx = 0;
+ while (builtin_func_out_args[outarg_idx].name) {
+ if (String(name) == builtin_func_out_args[outarg_idx].name) {
+ for (int arg = 0; arg < BuiltinFuncOutArgs::MAX_ARGS; arg++) {
+ int arg_idx = builtin_func_out_args[outarg_idx].arguments[arg];
+ if (arg_idx == -1) {
+ break;
+ }
+ if (arg_idx < argcount) {
+ if (p_func->arguments[arg_idx + 1]->type != Node::TYPE_VARIABLE && p_func->arguments[arg_idx + 1]->type != Node::TYPE_MEMBER && p_func->arguments[arg_idx + 1]->type != Node::TYPE_ARRAY) {
_set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' is not a variable, array or member.");
return false;
}
- if (n->type == Node::TYPE_VARIABLE) {
- var_name = static_cast<const VariableNode *>(n)->name;
- } else { // TYPE_ARRAY
- var_name = static_cast<const ArrayNode *>(n)->name;
+
+ if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_ARRAY) {
+ ArrayNode *mn = static_cast<ArrayNode *>(p_func->arguments[arg_idx + 1]);
+ if (mn->is_const) {
+ fail = true;
+ }
+ } else if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_MEMBER) {
+ MemberNode *mn = static_cast<MemberNode *>(p_func->arguments[arg_idx + 1]);
+ if (mn->basetype_const) {
+ fail = true;
+ }
+ } else { // TYPE_VARIABLE
+ VariableNode *vn = static_cast<VariableNode *>(p_func->arguments[arg_idx + 1]);
+ if (vn->is_const) {
+ fail = true;
+ } else {
+ StringName varname = vn->name;
+ if (shader->uniforms.has(varname)) {
+ fail = true;
+ } else {
+ if (shader->varyings.has(varname)) {
+ _set_error(vformat("Varyings cannot be passed for '%s' parameter!", "out"));
+ return false;
+ }
+ if (p_function_info.built_ins.has(varname)) {
+ BuiltInInfo info = p_function_info.built_ins[varname];
+ if (info.constant) {
+ fail = true;
+ }
+ }
+ }
+ }
+ }
+ if (fail) {
+ _set_error(vformat("Constant value cannot be passed for '%s' parameter!", "out"));
+ return false;
}
- } else { // TYPE_VARIABLE
- var_name = static_cast<const VariableNode *>(p_func->arguments[arg_idx + 1])->name;
- }
- const BlockNode *b = p_block;
- bool valid = false;
- while (b) {
- if (b->variables.has(var_name) || p_function_info.built_ins.has(var_name)) {
- valid = true;
- break;
+
+ StringName var_name;
+ if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_ARRAY) {
+ var_name = static_cast<const ArrayNode *>(p_func->arguments[arg_idx + 1])->name;
+ } else if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_MEMBER) {
+ Node *n = static_cast<const MemberNode *>(p_func->arguments[arg_idx + 1])->owner;
+ while (n->type == Node::TYPE_MEMBER) {
+ n = static_cast<const MemberNode *>(n)->owner;
+ }
+ if (n->type != Node::TYPE_VARIABLE && n->type != Node::TYPE_ARRAY) {
+ _set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' is not a variable, array or member.");
+ return false;
+ }
+ if (n->type == Node::TYPE_VARIABLE) {
+ var_name = static_cast<const VariableNode *>(n)->name;
+ } else { // TYPE_ARRAY
+ var_name = static_cast<const ArrayNode *>(n)->name;
+ }
+ } else { // TYPE_VARIABLE
+ var_name = static_cast<const VariableNode *>(p_func->arguments[arg_idx + 1])->name;
}
- if (b->parent_function) {
- for (int i = 0; i < b->parent_function->arguments.size(); i++) {
- if (b->parent_function->arguments[i].name == var_name) {
- valid = true;
- break;
+ const BlockNode *b = p_block;
+ bool valid = false;
+ while (b) {
+ if (b->variables.has(var_name) || p_function_info.built_ins.has(var_name)) {
+ valid = true;
+ break;
+ }
+ if (b->parent_function) {
+ for (int i = 0; i < b->parent_function->arguments.size(); i++) {
+ if (b->parent_function->arguments[i].name == var_name) {
+ valid = true;
+ break;
+ }
}
}
+ b = b->parent_block;
}
- b = b->parent_block;
- }
- if (!valid) {
- _set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' can only take a local variable, array or member.");
- return false;
+ if (!valid) {
+ _set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' can only take a local variable, array or member.");
+ return false;
+ }
}
}
}
-
outarg_idx++;
}
//implicitly convert values if possible
@@ -3190,16 +3301,16 @@ bool ShaderLanguage::is_float_type(DataType p_type) {
}
bool ShaderLanguage::is_sampler_type(DataType p_type) {
return p_type == TYPE_SAMPLER2D ||
- p_type == TYPE_ISAMPLER2D ||
- p_type == TYPE_USAMPLER2D ||
- p_type == TYPE_SAMPLER2DARRAY ||
- p_type == TYPE_ISAMPLER2DARRAY ||
- p_type == TYPE_USAMPLER2DARRAY ||
- p_type == TYPE_SAMPLER3D ||
- p_type == TYPE_ISAMPLER3D ||
- p_type == TYPE_USAMPLER3D ||
- p_type == TYPE_SAMPLERCUBE ||
- p_type == TYPE_SAMPLERCUBEARRAY;
+ p_type == TYPE_ISAMPLER2D ||
+ p_type == TYPE_USAMPLER2D ||
+ p_type == TYPE_SAMPLER2DARRAY ||
+ p_type == TYPE_ISAMPLER2DARRAY ||
+ p_type == TYPE_USAMPLER2DARRAY ||
+ p_type == TYPE_SAMPLER3D ||
+ p_type == TYPE_ISAMPLER3D ||
+ p_type == TYPE_USAMPLER3D ||
+ p_type == TYPE_SAMPLERCUBE ||
+ p_type == TYPE_SAMPLERCUBEARRAY;
}
Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::ConstantNode::Value> &p_value, DataType p_type, int p_array_size, ShaderLanguage::ShaderNode::Uniform::Hint p_hint) {
@@ -3767,16 +3878,16 @@ void ShaderLanguage::get_keyword_list(List<String> *r_keywords) {
bool ShaderLanguage::is_control_flow_keyword(String p_keyword) {
return p_keyword == "break" ||
- p_keyword == "case" ||
- p_keyword == "continue" ||
- p_keyword == "default" ||
- p_keyword == "do" ||
- p_keyword == "else" ||
- p_keyword == "for" ||
- p_keyword == "if" ||
- p_keyword == "return" ||
- p_keyword == "switch" ||
- p_keyword == "while";
+ p_keyword == "case" ||
+ p_keyword == "continue" ||
+ p_keyword == "default" ||
+ p_keyword == "do" ||
+ p_keyword == "else" ||
+ p_keyword == "for" ||
+ p_keyword == "if" ||
+ p_keyword == "return" ||
+ p_keyword == "switch" ||
+ p_keyword == "while";
}
void ShaderLanguage::get_builtin_funcs(List<String> *r_keywords) {
@@ -4187,7 +4298,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_array_size(BlockNode *p_block, cons
return n;
}
-Error ShaderLanguage::_parse_global_array_size(int &r_array_size) {
+Error ShaderLanguage::_parse_global_array_size(int &r_array_size, const FunctionInfo &p_function_info) {
if (r_array_size > 0) {
_set_error("Array size is already defined!");
return ERR_PARSE_ERROR;
@@ -4199,7 +4310,7 @@ Error ShaderLanguage::_parse_global_array_size(int &r_array_size) {
if (tk.type != TK_INT_CONSTANT || ((int)tk.constant) <= 0) {
_set_tkpos(pos);
- Node *n = _parse_array_size(nullptr, FunctionInfo(), array_size);
+ Node *n = _parse_array_size(nullptr, p_function_info, array_size);
if (!n) {
return ERR_PARSE_ERROR;
}
@@ -4814,7 +4925,9 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
bool error = false;
Node *n = func->arguments[argidx];
if (n->type == Node::TYPE_CONSTANT || n->type == Node::TYPE_OPERATOR) {
- error = true;
+ if (!call_function->arguments[i].is_const) {
+ error = true;
+ }
} else if (n->type == Node::TYPE_ARRAY) {
ArrayNode *an = static_cast<ArrayNode *>(n);
if (an->call_expression != nullptr || an->is_const) {
@@ -5100,9 +5213,21 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
expression.push_back(e);
continue;
} else {
- _set_error("Expected expression, found: " + get_token_text(tk));
- return nullptr;
- //nothing
+ if (tk.type != TK_SEMICOLON) {
+ _set_error("Expected expression, found: " + get_token_text(tk));
+ return nullptr;
+ } else {
+#if DEBUG_ENABLED
+ if (check_warnings && HAS_WARNING(ShaderWarning::FORMATTING_ERROR_FLAG)) {
+ _add_line_warning(ShaderWarning::FORMATTING_ERROR, "Empty statement. Remove ';' to fix this warning.");
+ }
+#endif // DEBUG_ENABLED
+ _set_tkpos(prepos);
+
+ OperatorNode *func = alloc_node<OperatorNode>();
+ func->op = OP_EMPTY;
+ expr = func;
+ }
}
ERR_FAIL_COND_V(!expr, nullptr);
@@ -5965,7 +6090,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
_set_error("Invalid arguments to unary operator '" + get_operator_text(op->op) + "' :" + at);
return nullptr;
}
- expression.remove(i + 1);
+ expression.remove_at(i + 1);
}
} else if (is_ternary) {
@@ -6005,7 +6130,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
for (int i = 0; i < 4; i++) {
- expression.remove(next_op);
+ expression.remove_at(next_op);
}
} else {
@@ -6066,8 +6191,8 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
return nullptr;
}
- expression.remove(next_op);
- expression.remove(next_op);
+ expression.remove_at(next_op);
+ expression.remove_at(next_op);
}
}
@@ -6278,7 +6403,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
ArrayDeclarationNode::Declaration adecl;
if (tk.type != TK_IDENTIFIER && tk.type != TK_BRACKET_OPEN) {
- _set_error("Expected identifier or '[' after type.");
+ _set_error("Expected identifier or '[' after datatype.");
return ERR_PARSE_ERROR;
}
@@ -7082,11 +7207,6 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
//check return type
BlockNode *b = p_block;
- if (b && b->parent_function && p_function_info.main_function) {
- _set_error(vformat("Using 'return' in '%s' processor function results in undefined behavior!", b->parent_function->name));
- return ERR_PARSE_ERROR;
- }
-
while (b && !b->parent_function) {
b = b->parent_block;
}
@@ -7096,6 +7216,11 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
return ERR_BUG;
}
+ if (b && b->parent_function && p_function_info.main_function) {
+ _set_error(vformat("Using 'return' in '%s' processor function results in undefined behavior!", b->parent_function->name));
+ return ERR_PARSE_ERROR;
+ }
+
String return_struct_name = String(b->parent_function->return_struct_name);
String array_size_string;
@@ -7338,6 +7463,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
ShaderNode::Uniform::Scope uniform_scope = ShaderNode::Uniform::SCOPE_LOCAL;
stages = &p_functions;
+ const FunctionInfo &constants = p_functions.has("constants") ? p_functions["constants"] : FunctionInfo();
while (tk.type != TK_EOF) {
switch (tk.type) {
@@ -7381,7 +7507,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
if (tk.type == TK_IDENTIFIER) {
st.name = tk.text;
- if (shader->structs.has(st.name)) {
+ if (shader->constants.has(st.name) || shader->structs.has(st.name)) {
_set_error("Redefinition of '" + String(st.name) + "'");
return ERR_PARSE_ERROR;
}
@@ -7453,7 +7579,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
int array_size = 0;
if (tk.type == TK_BRACKET_OPEN) {
- Error error = _parse_global_array_size(array_size);
+ Error error = _parse_global_array_size(array_size, constants);
if (error != OK) {
return error;
}
@@ -7480,7 +7606,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) {
- Error error = _parse_global_array_size(member->array_size);
+ Error error = _parse_global_array_size(member->array_size, constants);
if (error != OK) {
return error;
}
@@ -7539,7 +7665,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
bool uniform = tk.type == TK_UNIFORM;
if (!uniform) {
- if (shader_type_identifier == "particles" || shader_type_identifier == "sky") {
+ if (shader_type_identifier == "particles" || shader_type_identifier == "sky" || shader_type_identifier == "fog") {
_set_error(vformat("Varyings cannot be used in '%s' shaders!", shader_type_identifier));
return ERR_PARSE_ERROR;
}
@@ -7607,7 +7733,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
if (tk.type == TK_BRACKET_OPEN) {
- Error error = _parse_global_array_size(array_size);
+ Error error = _parse_global_array_size(array_size, constants);
if (error != OK) {
return error;
}
@@ -7622,7 +7748,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
prev_pos = _get_tkpos();
name = tk.text;
- if (_find_identifier(nullptr, false, FunctionInfo(), name)) {
+ if (_find_identifier(nullptr, false, constants, name)) {
_set_error("Redefinition of '" + String(name) + "'");
return ERR_PARSE_ERROR;
}
@@ -7655,7 +7781,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) {
- Error error = _parse_global_array_size(uniform2.array_size);
+ Error error = _parse_global_array_size(uniform2.array_size, constants);
if (error != OK) {
return error;
}
@@ -7909,7 +8035,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return ERR_PARSE_ERROR;
}
- Node *expr = _parse_and_reduce_expression(nullptr, FunctionInfo());
+ Node *expr = _parse_and_reduce_expression(nullptr, constants);
if (!expr) {
return ERR_PARSE_ERROR;
}
@@ -8005,7 +8131,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
DataPrecision precision = PRECISION_DEFAULT;
DataType type;
StringName name;
- int return_array_size = 0;
+ int array_size = 0;
if (tk.type == TK_CONST) {
is_constant = true;
@@ -8044,13 +8170,19 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
prev_pos = _get_tkpos();
tk = _get_token();
+ bool unknown_size = false;
+
if (tk.type == TK_BRACKET_OPEN) {
+ if (is_constant && RenderingServer::get_singleton()->is_low_end()) {
+ _set_error("Global const arrays are only supported on high-end platform!");
+ return ERR_PARSE_ERROR;
+ }
bool error = false;
tk = _get_token();
if (tk.type == TK_INT_CONSTANT) {
- return_array_size = (int)tk.constant;
- if (return_array_size > 0) {
+ array_size = (int)tk.constant;
+ if (array_size > 0) {
tk = _get_token();
if (tk.type != TK_BRACKET_CLOSE) {
_set_error("Expected ']'");
@@ -8059,11 +8191,13 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
} else {
error = true;
}
+ } else if (tk.type == TK_BRACKET_CLOSE) {
+ unknown_size = true;
} else {
error = true;
}
if (error) {
- _set_error("Expected integer constant > 0");
+ _set_error("Expected integer constant > 0 or ']'");
return ERR_PARSE_ERROR;
}
@@ -8075,16 +8209,15 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
_get_completable_identifier(nullptr, COMPLETION_MAIN_FUNCTION, name);
if (name == StringName()) {
- _set_error("Expected function name after datatype");
- return ERR_PARSE_ERROR;
- }
-
- if (_find_identifier(nullptr, false, FunctionInfo(), name)) {
- _set_error("Redefinition of '" + String(name) + "'");
+ if (is_constant) {
+ _set_error("Expected identifier or '[' after datatype.");
+ } else {
+ _set_error("Expected function name after datatype.");
+ }
return ERR_PARSE_ERROR;
}
- if (has_builtin(p_functions, name)) {
+ if (shader->structs.has(name) || _find_identifier(nullptr, false, constants, name) || has_builtin(p_functions, name)) {
_set_error("Redefinition of '" + String(name) + "'");
return ERR_PARSE_ERROR;
}
@@ -8097,7 +8230,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
//variable
-
+ bool first = true;
while (true) {
ShaderNode::Constant constant;
constant.name = name;
@@ -8105,16 +8238,18 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
constant.type_str = struct_name;
constant.precision = precision;
constant.initializer = nullptr;
- constant.array_size = 0;
-
- bool unknown_size = false;
+ constant.array_size = (first ? array_size : 0);
+ first = false;
if (tk.type == TK_BRACKET_OPEN) {
if (RenderingServer::get_singleton()->is_low_end()) {
- _set_error("Global const arrays are supported only on high-end platform!");
+ _set_error("Global const arrays are only supported on high-end platform!");
+ return ERR_PARSE_ERROR;
+ }
+ if (constant.array_size > 0 || unknown_size) {
+ _set_error("Array size is already defined!");
return ERR_PARSE_ERROR;
}
-
tk = _get_token();
if (tk.type == TK_BRACKET_CLOSE) {
unknown_size = true;
@@ -8192,7 +8327,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
} else {
_set_tkpos(prev_pos);
- Node *n = _parse_and_reduce_expression(nullptr, FunctionInfo());
+ Node *n = _parse_and_reduce_expression(nullptr, constants);
if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) {
_set_error("Expected single integer constant > 0");
return ERR_PARSE_ERROR;
@@ -8273,7 +8408,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
if (tk.type == TK_PARENTHESIS_OPEN || curly) { // initialization
while (true) {
- Node *n = _parse_and_reduce_expression(nullptr, FunctionInfo());
+ Node *n = _parse_and_reduce_expression(nullptr, constants);
if (!n) {
return ERR_PARSE_ERROR;
}
@@ -8328,7 +8463,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
constant.initializer = static_cast<ConstantNode *>(expr);
} else {
//variable created with assignment! must parse an expression
- Node *expr = _parse_and_reduce_expression(nullptr, FunctionInfo());
+ Node *expr = _parse_and_reduce_expression(nullptr, constants);
if (!expr) {
return ERR_PARSE_ERROR;
}
@@ -8344,7 +8479,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
constant.initializer = static_cast<ConstantNode *>(expr);
- if (!_compare_datatypes(type, struct_name, 0, expr->get_datatype(), expr->get_datatype_name(), 0)) {
+ if (!_compare_datatypes(type, struct_name, 0, expr->get_datatype(), expr->get_datatype_name(), expr->get_array_size())) {
return ERR_PARSE_ERROR;
}
}
@@ -8375,7 +8510,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
name = tk.text;
- if (_find_identifier(nullptr, false, FunctionInfo(), name)) {
+ if (_find_identifier(nullptr, false, constants, name)) {
_set_error("Redefinition of '" + String(name) + "'");
return ERR_PARSE_ERROR;
}
@@ -8409,6 +8544,12 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
}
+ if (p_functions.has("constants")) { // Adds global constants: 'PI', 'TAU', 'E'
+ for (const KeyValue<StringName, BuiltInInfo> &E : p_functions["constants"].built_ins) {
+ builtins.built_ins.insert(E.key, E.value);
+ }
+ }
+
ShaderNode::Function function;
function.callable = !p_functions.has(name);
@@ -8424,7 +8565,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
func_node->return_type = type;
func_node->return_struct_name = struct_name;
func_node->return_precision = precision;
- func_node->return_array_size = return_array_size;
+ func_node->return_array_size = array_size;
if (p_functions.has(name)) {
func_node->can_discard = p_functions[name].can_discard;
@@ -8478,7 +8619,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
StringName param_struct_name;
DataPrecision pprecision = PRECISION_DEFAULT;
bool use_precision = false;
- int array_size = 0;
+ int arg_array_size = 0;
if (is_token_precision(tk.type)) {
pprecision = get_token_precision(tk.type);
@@ -8529,9 +8670,9 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
if (tk.type == TK_INT_CONSTANT) {
- array_size = (int)tk.constant;
+ arg_array_size = (int)tk.constant;
- if (array_size > 0) {
+ if (arg_array_size > 0) {
tk = _get_token();
if (tk.type != TK_BRACKET_CLOSE) {
_set_error("Expected ']'");
@@ -8583,7 +8724,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) {
- if (array_size > 0) {
+ if (arg_array_size > 0) {
_set_error("Array size is already defined!");
return ERR_PARSE_ERROR;
}
@@ -8591,9 +8732,9 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
if (tk.type == TK_INT_CONSTANT) {
- array_size = (int)tk.constant;
+ arg_array_size = (int)tk.constant;
- if (array_size > 0) {
+ if (arg_array_size > 0) {
tk = _get_token();
if (tk.type != TK_BRACKET_CLOSE) {
_set_error("Expected ']'");
@@ -8613,7 +8754,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
}
- arg.array_size = array_size;
+ arg.array_size = arg_array_size;
func_node->arguments.push_back(arg);
if (tk.type == TK_COMMA) {
@@ -8959,6 +9100,16 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
}
}
+ if (p_functions.has("constants")) {
+ for (const KeyValue<StringName, BuiltInInfo> &E : p_functions["constants"].built_ins) {
+ ScriptCodeCompletionOption::Kind kind = ScriptCodeCompletionOption::KIND_MEMBER;
+ if (E.value.constant) {
+ kind = ScriptCodeCompletionOption::KIND_CONSTANT;
+ }
+ matches.insert(E.key, kind);
+ }
+ }
+
if (skip_function != StringName() && p_functions.has(skip_function)) {
for (const KeyValue<StringName, BuiltInInfo> &E : p_functions[skip_function].built_ins) {
ScriptCodeCompletionOption::Kind kind = ScriptCodeCompletionOption::KIND_MEMBER;
@@ -9157,10 +9308,16 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
}
int idx2 = 0;
- int out_arg = -1;
+ Set<int> out_args;
while (builtin_func_out_args[idx2].name != nullptr) {
if (builtin_func_out_args[idx2].name == builtin_func_defs[idx].name) {
- out_arg = builtin_func_out_args[idx2].argument;
+ for (int i = 0; i < BuiltinFuncOutArgs::MAX_ARGS; i++) {
+ int arg = builtin_func_out_args[idx2].arguments[i];
+ if (arg == -1) {
+ break;
+ }
+ out_args.insert(arg);
+ }
break;
}
idx2++;
@@ -9197,7 +9354,7 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
calltip += char32_t(0xFFFF);
}
- if (out_arg >= 0 && i == out_arg) {
+ if (out_args.has(i)) {
calltip += "out ";
}
@@ -9258,15 +9415,6 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
limit = 4;
} break;
- case TYPE_MAT2:
- limit = 2;
- break;
- case TYPE_MAT3:
- limit = 3;
- break;
- case TYPE_MAT4:
- limit = 4;
- break;
default: {
}
}
diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h
index 4740da0c37..3de89a89a5 100644
--- a/servers/rendering/shader_language.h
+++ b/servers/rendering/shader_language.h
@@ -287,6 +287,7 @@ public:
OP_CONSTRUCT,
OP_STRUCT,
OP_INDEX,
+ OP_EMPTY,
OP_MAX
};
@@ -949,8 +950,16 @@ private:
};
struct BuiltinFuncOutArgs { //arguments used as out in built in functions
+ enum { MAX_ARGS = 2 };
const char *name;
- int argument;
+ const int arguments[MAX_ARGS];
+ };
+
+ struct BuiltinFuncConstArgs {
+ const char *name;
+ int arg;
+ int min;
+ int max;
};
CompletionType completion_type;
@@ -966,6 +975,7 @@ private:
bool _get_completable_identifier(BlockNode *p_block, CompletionType p_type, StringName &identifier);
static const BuiltinFuncDef builtin_func_defs[];
static const BuiltinFuncOutArgs builtin_func_out_args[];
+ static const BuiltinFuncConstArgs builtin_func_const_args[];
Error _validate_datatype(DataType p_type);
bool _compare_datatypes(DataType p_datatype_a, String p_datatype_name_a, int p_array_size_a, DataType p_datatype_b, String p_datatype_name_b, int p_array_size_b);
@@ -980,7 +990,7 @@ private:
bool _check_node_constness(const Node *p_node) const;
Node *_parse_array_size(BlockNode *p_block, const FunctionInfo &p_function_info, int &r_array_size);
- Error _parse_global_array_size(int &r_array_size);
+ Error _parse_global_array_size(int &r_array_size, const FunctionInfo &p_function_info);
Error _parse_local_array_size(BlockNode *p_block, const FunctionInfo &p_function_info, ArrayDeclarationNode *p_node, ArrayDeclarationNode::Declaration *p_decl, int &r_array_size, bool &r_is_unknown_size);
Node *_parse_expression(BlockNode *p_block, const FunctionInfo &p_function_info);
diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp
index 0bfcccef28..359196e096 100644
--- a/servers/rendering/shader_types.cpp
+++ b/servers/rendering/shader_types.cpp
@@ -59,9 +59,9 @@ ShaderTypes::ShaderTypes() {
/*************** SPATIAL ***********************/
shader_modes[RS::SHADER_SPATIAL].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
- shader_modes[RS::SHADER_SPATIAL].functions["global"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT);
- shader_modes[RS::SHADER_SPATIAL].functions["global"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT);
- shader_modes[RS::SHADER_SPATIAL].functions["global"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_SPATIAL].functions["constants"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_SPATIAL].functions["constants"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_SPATIAL].functions["constants"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VERTEX"] = ShaderLanguage::TYPE_VEC3;
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["NORMAL"] = ShaderLanguage::TYPE_VEC3;
@@ -241,9 +241,9 @@ ShaderTypes::ShaderTypes() {
/************ CANVAS ITEM **************************/
shader_modes[RS::SHADER_CANVAS_ITEM].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
- shader_modes[RS::SHADER_CANVAS_ITEM].functions["global"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT);
- shader_modes[RS::SHADER_CANVAS_ITEM].functions["global"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT);
- shader_modes[RS::SHADER_CANVAS_ITEM].functions["global"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_CANVAS_ITEM].functions["constants"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_CANVAS_ITEM].functions["constants"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_CANVAS_ITEM].functions["constants"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["VERTEX"] = ShaderLanguage::TYPE_VEC2;
shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["UV"] = ShaderLanguage::TYPE_VEC2;
@@ -334,9 +334,9 @@ ShaderTypes::ShaderTypes() {
/************ PARTICLES **************************/
shader_modes[RS::SHADER_PARTICLES].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
- shader_modes[RS::SHADER_PARTICLES].functions["global"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT);
- shader_modes[RS::SHADER_PARTICLES].functions["global"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT);
- shader_modes[RS::SHADER_PARTICLES].functions["global"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_PARTICLES].functions["constants"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_PARTICLES].functions["constants"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_PARTICLES].functions["constants"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4;
shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["VELOCITY"] = ShaderLanguage::TYPE_VEC3;
@@ -367,7 +367,7 @@ ShaderTypes::ShaderTypes() {
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);
shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["NUMBER"] = constt(ShaderLanguage::TYPE_UINT);
- shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["INDEX"] = constt(ShaderLanguage::TYPE_INT);
+ shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["INDEX"] = constt(ShaderLanguage::TYPE_UINT);
shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["EMISSION_TRANSFORM"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["RANDOM_SEED"] = constt(ShaderLanguage::TYPE_UINT);
shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["FLAG_EMIT_POSITION"] = constt(ShaderLanguage::TYPE_UINT);
@@ -400,9 +400,9 @@ ShaderTypes::ShaderTypes() {
/************ SKY **************************/
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
- shader_modes[RS::SHADER_SKY].functions["global"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT);
- shader_modes[RS::SHADER_SKY].functions["global"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT);
- shader_modes[RS::SHADER_SKY].functions["global"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_SKY].functions["constants"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_SKY].functions["constants"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_SKY].functions["constants"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["POSITION"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["RADIANCE"] = constt(ShaderLanguage::TYPE_SAMPLERCUBE);
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["AT_HALF_RES_PASS"] = constt(ShaderLanguage::TYPE_BOOL);
@@ -443,10 +443,29 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SKY].modes.push_back("use_quarter_res_pass");
shader_modes[RS::SHADER_SKY].modes.push_back("disable_fog");
+ /************ FOG **************************/
+
+ shader_modes[RS::SHADER_FOG].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_FOG].functions["constants"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_FOG].functions["constants"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_FOG].functions["constants"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT);
+
+ shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["WORLD_POSITION"] = constt(ShaderLanguage::TYPE_VEC3);
+ shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["OBJECT_POSITION"] = constt(ShaderLanguage::TYPE_VEC3);
+ shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["UVW"] = constt(ShaderLanguage::TYPE_VEC3);
+ shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["EXTENTS"] = constt(ShaderLanguage::TYPE_VEC3);
+ shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["TRANSFORM"] = constt(ShaderLanguage::TYPE_MAT4);
+ shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["SDF"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["ALBEDO"] = ShaderLanguage::TYPE_VEC3;
+ shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["DENSITY"] = ShaderLanguage::TYPE_FLOAT;
+ shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["EMISSION"] = ShaderLanguage::TYPE_VEC3;
+ shader_modes[RS::SHADER_FOG].functions["fog"].main_function = true;
+
shader_types_list.push_back("spatial");
shader_types_list.push_back("canvas_item");
shader_types_list.push_back("particles");
shader_types_list.push_back("sky");
+ shader_types_list.push_back("fog");
for (int i = 0; i < shader_types_list.size(); i++) {
shader_types.insert(shader_types_list[i]);
diff --git a/servers/rendering/shader_warnings.cpp b/servers/rendering/shader_warnings.cpp
index 0b8476478c..bffae484a8 100644
--- a/servers/rendering/shader_warnings.cpp
+++ b/servers/rendering/shader_warnings.cpp
@@ -61,6 +61,8 @@ String ShaderWarning::get_message() const {
return vformat("The varying '%s' is declared but never used.", subject);
case UNUSED_LOCAL_VARIABLE:
return vformat("The local variable '%s' is declared but never used.", subject);
+ case FORMATTING_ERROR:
+ return subject;
default:
break;
}
@@ -82,6 +84,7 @@ String ShaderWarning::get_name_from_code(Code p_code) {
"UNUSED_UNIFORM",
"UNUSED_VARYING",
"UNUSED_LOCAL_VARIABLE",
+ "FORMATTING_ERROR",
};
static_assert((sizeof(names) / sizeof(*names)) == WARNING_MAX, "Amount of warning types don't match the amount of warning names.");
@@ -110,6 +113,7 @@ static void init_code_to_flags_map() {
code_to_flags_map->insert(ShaderWarning::UNUSED_UNIFORM, ShaderWarning::UNUSED_UNIFORM_FLAG);
code_to_flags_map->insert(ShaderWarning::UNUSED_VARYING, ShaderWarning::UNUSED_VARYING_FLAG);
code_to_flags_map->insert(ShaderWarning::UNUSED_LOCAL_VARIABLE, ShaderWarning::UNUSED_LOCAL_VARIABLE_FLAG);
+ code_to_flags_map->insert(ShaderWarning::FORMATTING_ERROR, ShaderWarning::FORMATTING_ERROR_FLAG);
}
ShaderWarning::CodeFlags ShaderWarning::get_flags_from_codemap(const Map<Code, bool> &p_map) {
diff --git a/servers/rendering/shader_warnings.h b/servers/rendering/shader_warnings.h
index db872d8fb1..18915fffd8 100644
--- a/servers/rendering/shader_warnings.h
+++ b/servers/rendering/shader_warnings.h
@@ -47,6 +47,7 @@ public:
UNUSED_UNIFORM,
UNUSED_VARYING,
UNUSED_LOCAL_VARIABLE,
+ FORMATTING_ERROR,
WARNING_MAX,
};
@@ -59,6 +60,7 @@ public:
UNUSED_UNIFORM_FLAG = 16U,
UNUSED_VARYING_FLAG = 32U,
UNUSED_LOCAL_VARIABLE_FLAG = 64U,
+ FORMATTING_ERROR_FLAG = 128U,
};
private: