summaryrefslogtreecommitdiff
path: root/servers/rendering
diff options
context:
space:
mode:
Diffstat (limited to 'servers/rendering')
-rw-r--r--servers/rendering/rasterizer.cpp9
-rw-r--r--servers/rendering/rasterizer.h247
-rw-r--r--servers/rendering/rasterizer_rd/light_cluster_builder.cpp9
-rw-r--r--servers/rendering/rasterizer_rd/light_cluster_builder.h47
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp140
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h13
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp801
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_effects_rd.h299
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_rd.cpp16
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_rd.h7
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp1171
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h149
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp775
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_scene_rd.h200
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp2164
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_storage_rd.h401
-rw-r--r--servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.cpp14
-rw-r--r--servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h10
-rw-r--r--servers/rendering/rasterizer_rd/shader_compiler_rd.cpp509
-rw-r--r--servers/rendering/rasterizer_rd/shader_compiler_rd.h11
-rw-r--r--servers/rendering/rasterizer_rd/shader_rd.cpp25
-rw-r--r--servers/rendering/rasterizer_rd/shader_rd.h1
-rw-r--r--servers/rendering/rasterizer_rd/shaders/SCsub10
-rw-r--r--servers/rendering/rasterizer_rd/shaders/blur.glsl294
-rw-r--r--servers/rendering/rasterizer_rd/shaders/blur_inc.glsl35
-rw-r--r--servers/rendering/rasterizer_rd/shaders/bokeh_dof.glsl9
-rw-r--r--servers/rendering/rasterizer_rd/shaders/canvas.glsl19
-rw-r--r--servers/rendering/rasterizer_rd/shaders/canvas_occlusion.glsl11
-rw-r--r--servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl5
-rw-r--r--servers/rendering/rasterizer_rd/shaders/copy.glsl258
-rw-r--r--servers/rendering/rasterizer_rd/shaders/copy_to_fb.glsl99
-rw-r--r--servers/rendering/rasterizer_rd/shaders/cube_to_dp.glsl69
-rw-r--r--servers/rendering/rasterizer_rd/shaders/cubemap_downsampler.glsl9
-rw-r--r--servers/rendering/rasterizer_rd/shaders/cubemap_filter.glsl4
-rw-r--r--servers/rendering/rasterizer_rd/shaders/cubemap_roughness.glsl7
-rw-r--r--servers/rendering/rasterizer_rd/shaders/giprobe.glsl22
-rw-r--r--servers/rendering/rasterizer_rd/shaders/giprobe_debug.glsl83
-rw-r--r--servers/rendering/rasterizer_rd/shaders/giprobe_sdf.glsl12
-rw-r--r--servers/rendering/rasterizer_rd/shaders/giprobe_write.glsl20
-rw-r--r--servers/rendering/rasterizer_rd/shaders/luminance_reduce.glsl7
-rw-r--r--servers/rendering/rasterizer_rd/shaders/roughness_limiter.glsl9
-rw-r--r--servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl1108
-rw-r--r--servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl143
-rw-r--r--servers/rendering/rasterizer_rd/shaders/screen_space_reflection.glsl252
-rw-r--r--servers/rendering/rasterizer_rd/shaders/screen_space_reflection_filter.glsl154
-rw-r--r--servers/rendering/rasterizer_rd/shaders/screen_space_reflection_scale.glsl87
-rw-r--r--servers/rendering/rasterizer_rd/shaders/sky.glsl35
-rw-r--r--servers/rendering/rasterizer_rd/shaders/specular_merge.glsl53
-rw-r--r--servers/rendering/rasterizer_rd/shaders/ssao.glsl7
-rw-r--r--servers/rendering/rasterizer_rd/shaders/ssao_blur.glsl8
-rw-r--r--servers/rendering/rasterizer_rd/shaders/ssao_minify.glsl5
-rw-r--r--servers/rendering/rasterizer_rd/shaders/subsurface_scattering.glsl189
-rw-r--r--servers/rendering/rasterizer_rd/shaders/tonemap.glsl69
-rw-r--r--servers/rendering/rendering_device.cpp748
-rw-r--r--servers/rendering/rendering_device.h105
-rw-r--r--servers/rendering/rendering_device_binds.cpp205
-rw-r--r--servers/rendering/rendering_device_binds.h629
-rw-r--r--servers/rendering/rendering_server_canvas.cpp249
-rw-r--r--servers/rendering/rendering_server_canvas.h19
-rw-r--r--servers/rendering/rendering_server_globals.cpp14
-rw-r--r--servers/rendering/rendering_server_raster.cpp63
-rw-r--r--servers/rendering/rendering_server_raster.h99
-rw-r--r--servers/rendering/rendering_server_scene.cpp1155
-rw-r--r--servers/rendering/rendering_server_scene.h84
-rw-r--r--servers/rendering/rendering_server_viewport.cpp204
-rw-r--r--servers/rendering/rendering_server_viewport.h50
-rw-r--r--servers/rendering/rendering_server_wrap_mt.cpp46
-rw-r--r--servers/rendering/rendering_server_wrap_mt.h85
-rw-r--r--servers/rendering/shader_language.cpp1261
-rw-r--r--servers/rendering/shader_language.h219
-rw-r--r--servers/rendering/shader_types.cpp19
-rw-r--r--servers/rendering/shader_types.h2
72 files changed, 11302 insertions, 4064 deletions
diff --git a/servers/rendering/rasterizer.cpp b/servers/rendering/rasterizer.cpp
index a3f93a3f8c..566a14b655 100644
--- a/servers/rendering/rasterizer.cpp
+++ b/servers/rendering/rasterizer.cpp
@@ -33,13 +33,14 @@
#include "core/os/os.h"
#include "core/print_string.h"
-Rasterizer *(*Rasterizer::_create_func)() = NULL;
+Rasterizer *(*Rasterizer::_create_func)() = nullptr;
void RasterizerScene::InstanceDependency::instance_notify_changed(bool p_aabb, bool p_dependencies) {
for (Map<InstanceBase *, uint32_t>::Element *E = instances.front(); E; E = E->next()) {
E->key()->dependency_changed(p_aabb, p_dependencies);
}
}
+
void RasterizerScene::InstanceDependency::instance_notify_deleted(RID p_deleted) {
for (Map<InstanceBase *, uint32_t>::Element *E = instances.front(); E; E = E->next()) {
E->key()->dependency_deleted(p_deleted);
@@ -63,15 +64,13 @@ RasterizerScene::InstanceDependency::~InstanceDependency() {
}
Rasterizer *Rasterizer::create() {
-
return _create_func();
}
-RasterizerCanvas *RasterizerCanvas::singleton = NULL;
+RasterizerCanvas *RasterizerCanvas::singleton = nullptr;
-RasterizerStorage *RasterizerStorage::base_singleton = NULL;
+RasterizerStorage *RasterizerStorage::base_singleton = nullptr;
RasterizerStorage::RasterizerStorage() {
-
base_singleton = this;
}
diff --git a/servers/rendering/rasterizer.h b/servers/rendering/rasterizer.h
index eb33db04fc..026725bf01 100644
--- a/servers/rendering/rasterizer.h
+++ b/servers/rendering/rasterizer.h
@@ -38,7 +38,6 @@
#include "core/self_list.h"
class RasterizerScene {
-
public:
/* SHADOW ATLAS API */
@@ -57,6 +56,7 @@ public:
virtual void sky_set_radiance_size(RID p_sky, int p_radiance_size) = 0;
virtual void sky_set_mode(RID p_sky, RS::SkyMode p_samples) = 0;
virtual void sky_set_material(RID p_sky, RID p_material) = 0;
+ virtual Ref<Image> sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) = 0;
/* ENVIRONMENT API */
@@ -79,7 +79,9 @@ public:
virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) = 0;
virtual void environment_set_fog(RID p_env, bool p_enable, float p_begin, float p_end, RID p_gradient_texture) = 0;
- virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance, bool p_roughness) = 0;
+ virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) = 0;
+ virtual void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) = 0;
+
virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_bias, float p_light_affect, float p_ao_channel_affect, RS::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) = 0;
virtual void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size) = 0;
@@ -92,6 +94,8 @@ public:
virtual void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_end, float p_depth_curve, bool p_transmit, float p_transmit_curve) = 0;
virtual void environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve) = 0;
+ virtual Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) = 0;
+
virtual bool is_environment(RID p_env) const = 0;
virtual RS::EnvironmentBG environment_get_background(RID p_env) const = 0;
virtual int environment_get_canvas_max_layer(RID p_env) const = 0;
@@ -104,10 +108,12 @@ public:
virtual void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) = 0;
virtual void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) = 0;
+ virtual void shadows_quality_set(RS::ShadowQuality p_quality) = 0;
+ virtual void directional_shadow_quality_set(RS::ShadowQuality p_quality) = 0;
+
struct InstanceBase;
struct InstanceDependency {
-
void instance_notify_changed(bool p_aabb, bool p_dependencies);
void instance_notify_deleted(RID p_deleted);
@@ -119,7 +125,6 @@ public:
};
struct InstanceBase {
-
RS::InstanceType base_type;
RID base;
@@ -157,15 +162,28 @@ public:
SelfList<InstanceBase> dependency_item;
- InstanceBase *lightmap_capture;
- RID lightmap;
- Vector<Color> lightmap_capture_data; //in a array (12 values) to avoid wasting space if unused. Alpha is unused, but needed to send to shader
+ InstanceBase *lightmap;
+ Rect2 lightmap_uv_scale;
+ int lightmap_slice_index;
+ uint32_t lightmap_cull_index;
+ Vector<Color> lightmap_sh; //spherical harmonic
AABB aabb;
AABB transformed_aabb;
- virtual void dependency_deleted(RID p_dependency) = 0;
- virtual void dependency_changed(bool p_aabb, bool p_dependencies) = 0;
+ struct InstanceShaderParameter {
+ int32_t index = -1;
+ Variant value;
+ Variant default_value;
+ PropertyInfo info;
+ };
+
+ Map<StringName, InstanceShaderParameter> instance_shader_parameters;
+ bool instance_allocated_shader_parameters = false;
+ int32_t instance_allocated_shader_parameters_offset = -1;
+
+ virtual void dependency_deleted(RID p_dependency) {}
+ virtual void dependency_changed(bool p_aabb, bool p_dependencies) {}
Set<InstanceDependency *> dependencies;
@@ -208,7 +226,6 @@ public:
InstanceBase() :
dependency_item(this) {
-
base_type = RS::INSTANCE_NONE;
cast_shadows = RS::SHADOW_CASTING_SETTING_ON;
receive_shadows = true;
@@ -219,7 +236,9 @@ public:
baked_light = false;
dynamic_gi = false;
redraw_if_visible = false;
- lightmap_capture = NULL;
+ lightmap_slice_index = 0;
+ lightmap = nullptr;
+ lightmap_cull_index = 0;
}
virtual ~InstanceBase() {
@@ -229,9 +248,11 @@ public:
virtual RID light_instance_create(RID p_light) = 0;
virtual void light_instance_set_transform(RID p_light_instance, const Transform &p_transform) = 0;
- virtual void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale = 1.0) = 0;
+ virtual void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &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()) = 0;
virtual void light_instance_mark_visible(RID p_light_instance) = 0;
- virtual bool light_instances_can_render_shadow_cube() const { return true; }
+ virtual bool light_instances_can_render_shadow_cube() const {
+ return true;
+ }
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;
@@ -244,12 +265,15 @@ public:
virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) = 0;
virtual bool reflection_probe_instance_postprocess_step(RID p_instance) = 0;
+ virtual RID decal_instance_create(RID p_decal) = 0;
+ virtual void decal_instance_set_transform(RID p_decal, const Transform &p_transform) = 0;
+
virtual RID gi_probe_instance_create(RID p_gi_probe) = 0;
virtual void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) = 0;
virtual bool gi_probe_needs_update(RID p_probe) const = 0;
virtual void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, int p_dynamic_object_count, InstanceBase **p_dynamic_objects) = 0;
- virtual void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) = 0;
+ virtual void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) = 0;
virtual void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) = 0;
virtual void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) = 0;
@@ -259,11 +283,16 @@ 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) = 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) = 0;
virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_curve) = 0;
virtual bool screen_space_roughness_limiter_is_active() const = 0;
+ virtual void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) = 0;
+ virtual void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) = 0;
+
+ virtual TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) = 0;
+
virtual bool free(RID p_rid) = 0;
virtual void update() = 0;
@@ -271,7 +300,6 @@ public:
};
class RasterizerStorage {
-
Color default_clear_color;
public:
@@ -289,7 +317,7 @@ public:
//these two APIs can be used together or in combination with the others.
virtual RID texture_2d_placeholder_create() = 0;
- virtual RID texture_2d_layered_placeholder_create() = 0;
+ virtual RID texture_2d_layered_placeholder_create(RenderingServer::TextureLayeredType p_layered_type) = 0;
virtual RID texture_3d_placeholder_create() = 0;
virtual Ref<Image> texture_2d_get(RID p_texture) const = 0;
@@ -316,6 +344,9 @@ public:
virtual Size2 texture_size_with_proxy(RID p_proxy) = 0;
+ virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) = 0;
+ virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) = 0;
+
/* SHADER API */
virtual RID shader_create() = 0;
@@ -343,6 +374,14 @@ public:
virtual bool material_is_animated(RID p_material) = 0;
virtual bool material_casts_shadows(RID p_material) = 0;
+ struct InstanceShaderParam {
+ PropertyInfo info;
+ int index;
+ Variant default_value;
+ };
+
+ virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) = 0;
+
virtual void material_update_dependency(RID p_material, RasterizerScene::InstanceBase *p_instance) = 0;
/* MESH API */
@@ -496,6 +535,21 @@ public:
virtual void base_update_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) = 0;
virtual void skeleton_update_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) = 0;
+ /* DECAL API */
+
+ virtual RID decal_create() = 0;
+ virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents) = 0;
+ virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) = 0;
+ virtual void decal_set_emission_energy(RID p_decal, float p_energy) = 0;
+ virtual void decal_set_albedo_mix(RID p_decal, float p_mix) = 0;
+ virtual void decal_set_modulate(RID p_decal, const Color &p_modulate) = 0;
+ virtual void decal_set_cull_mask(RID p_decal, uint32_t p_layers) = 0;
+ virtual void decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) = 0;
+ virtual void decal_set_fade(RID p_decal, float p_above, float p_below) = 0;
+ virtual void decal_set_normal_fade(RID p_decal, float p_fade) = 0;
+
+ virtual AABB decal_get_aabb(RID p_decal) const = 0;
+
/* GI PROBE API */
virtual RID gi_probe_create() = 0;
@@ -545,29 +599,21 @@ public:
/* LIGHTMAP CAPTURE */
- struct LightmapCaptureOctree {
-
- enum {
- CHILD_EMPTY = 0xFFFFFFFF
- };
-
- uint16_t light[6][3]; //anisotropic light
- float alpha;
- uint32_t children[8];
- };
-
- virtual RID lightmap_capture_create() = 0;
- virtual void lightmap_capture_set_bounds(RID p_capture, const AABB &p_bounds) = 0;
- virtual AABB lightmap_capture_get_bounds(RID p_capture) const = 0;
- virtual void lightmap_capture_set_octree(RID p_capture, const Vector<uint8_t> &p_octree) = 0;
- virtual Vector<uint8_t> lightmap_capture_get_octree(RID p_capture) const = 0;
- virtual void lightmap_capture_set_octree_cell_transform(RID p_capture, const Transform &p_xform) = 0;
- virtual Transform lightmap_capture_get_octree_cell_transform(RID p_capture) const = 0;
- virtual void lightmap_capture_set_octree_cell_subdiv(RID p_capture, int p_subdiv) = 0;
- virtual int lightmap_capture_get_octree_cell_subdiv(RID p_capture) const = 0;
- virtual void lightmap_capture_set_energy(RID p_capture, float p_energy) = 0;
- virtual float lightmap_capture_get_energy(RID p_capture) const = 0;
- virtual const Vector<LightmapCaptureOctree> *lightmap_capture_get_octree_ptr(RID p_capture) const = 0;
+ virtual RID lightmap_create() = 0;
+
+ virtual void lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) = 0;
+ virtual void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) = 0;
+ virtual void lightmap_set_probe_interior(RID p_lightmap, bool p_interior) = 0;
+ virtual void lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) = 0;
+ virtual PackedVector3Array lightmap_get_probe_capture_points(RID p_lightmap) const = 0;
+ virtual PackedColorArray lightmap_get_probe_capture_sh(RID p_lightmap) const = 0;
+ virtual PackedInt32Array lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const = 0;
+ virtual PackedInt32Array lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const = 0;
+ virtual AABB lightmap_get_aabb(RID p_lightmap) const = 0;
+ virtual void lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) = 0;
+ virtual bool lightmap_is_interior(RID p_lightmap) const = 0;
+ virtual void lightmap_set_probe_capture_update_speed(float p_speed) = 0;
+ virtual float lightmap_get_probe_capture_update_speed() const = 0;
/* PARTICLES */
@@ -606,6 +652,24 @@ public:
virtual int particles_get_draw_passes(RID p_particles) const = 0;
virtual RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const = 0;
+ /* GLOBAL VARIABLES */
+
+ virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) = 0;
+ virtual void global_variable_remove(const StringName &p_name) = 0;
+ virtual Vector<StringName> global_variable_get_list() const = 0;
+
+ virtual void global_variable_set(const StringName &p_name, const Variant &p_value) = 0;
+ virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) = 0;
+ virtual Variant global_variable_get(const StringName &p_name) const = 0;
+ virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const = 0;
+
+ virtual void global_variables_load_settings(bool p_load_textures = true) = 0;
+ virtual void global_variables_clear() = 0;
+
+ virtual int32_t global_variables_instance_allocate(RID p_instance) = 0;
+ virtual void global_variables_instance_free(RID p_instance) = 0;
+ virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) = 0;
+
/* RENDER TARGET */
enum RenderTargetFlags {
@@ -655,14 +719,16 @@ public:
Color get_default_clear_color() const {
return default_clear_color;
}
-#define TIMESTAMP_BEGIN() \
- { \
- if (RSG::storage->capturing_timestamps) RSG::storage->capture_timestamps_begin(); \
+#define TIMESTAMP_BEGIN() \
+ { \
+ if (RSG::storage->capturing_timestamps) \
+ RSG::storage->capture_timestamps_begin(); \
}
-#define RENDER_TIMESTAMP(m_text) \
- { \
- if (RSG::storage->capturing_timestamps) RSG::storage->capture_timestamp(m_text); \
+#define RENDER_TIMESTAMP(m_text) \
+ { \
+ if (RSG::storage->capturing_timestamps) \
+ RSG::storage->capture_timestamp(m_text); \
}
bool capturing_timestamps = false;
@@ -694,7 +760,6 @@ public:
};
struct Light {
-
bool enabled;
Color color;
Transform2D xform;
@@ -749,12 +814,12 @@ public:
item_mask = 1;
scale = 1.0;
energy = 1.0;
- item_shadow_mask = -1;
+ item_shadow_mask = 1;
mode = RS::CANVAS_LIGHT_MODE_ADD;
- // texture_cache = NULL;
- next_ptr = NULL;
- mask_next_ptr = NULL;
- filter_next_ptr = NULL;
+ // texture_cache = nullptr;
+ next_ptr = nullptr;
+ mask_next_ptr = nullptr;
+ filter_next_ptr = nullptr;
use_shadow = false;
shadow_buffer_size = 2048;
shadow_filter = RS::CANVAS_LIGHT_FILTER_NONE;
@@ -773,7 +838,6 @@ public:
struct Item;
struct TextureBinding {
-
TextureBindingID binding_id;
_FORCE_INLINE_ void create(RS::CanvasItemTextureFilter p_item_filter, RS::CanvasItemTextureRepeat p_item_repeat, RID p_texture, RID p_normalmap, RID p_specular, RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat, RID p_multimesh) {
@@ -791,7 +855,9 @@ public:
_FORCE_INLINE_ TextureBinding() { binding_id = 0; }
_FORCE_INLINE_ ~TextureBinding() {
- if (binding_id) singleton->free_texture_binding(binding_id);
+ if (binding_id) {
+ singleton->free_texture_binding(binding_id);
+ }
}
};
@@ -801,7 +867,6 @@ public:
//also easier to wrap to avoid mistakes
struct Polygon {
-
PolygonID polygon_id;
Rect2 rect_cache;
@@ -820,14 +885,15 @@ public:
_FORCE_INLINE_ Polygon() { polygon_id = 0; }
_FORCE_INLINE_ ~Polygon() {
- if (polygon_id) singleton->free_polygon(polygon_id);
+ if (polygon_id) {
+ singleton->free_polygon(polygon_id);
+ }
}
};
//item
struct Item {
-
//commands are allocated in blocks of 4k to improve performance
//and cache coherence.
//blocks always grow but never shrink.
@@ -841,7 +907,6 @@ public:
};
struct Command {
-
enum Type {
TYPE_RECT,
@@ -861,7 +926,6 @@ public:
};
struct CommandRect : public Command {
-
Rect2 rect;
Color modulate;
Rect2 source;
@@ -877,7 +941,6 @@ public:
};
struct CommandNinePatch : public Command {
-
Rect2 rect;
Rect2 source;
float margin[4];
@@ -894,7 +957,6 @@ public:
};
struct CommandPolygon : public Command {
-
RS::PrimitiveType primitive;
Polygon polygon;
Color specular_shininess;
@@ -905,7 +967,6 @@ public:
};
struct CommandPrimitive : public Command {
-
uint32_t point_count;
Vector2 points[4];
Vector2 uvs[4];
@@ -918,7 +979,6 @@ public:
};
struct CommandMesh : public Command {
-
RID mesh;
Transform2D transform;
Color modulate;
@@ -928,7 +988,6 @@ public:
};
struct CommandMultiMesh : public Command {
-
RID multimesh;
Color specular_shininess;
TextureBinding texture_binding;
@@ -936,7 +995,6 @@ public:
};
struct CommandParticles : public Command {
-
RID particles;
Color specular_shininess;
TextureBinding texture_binding;
@@ -944,13 +1002,11 @@ public:
};
struct CommandTransform : public Command {
-
Transform2D xform;
CommandTransform() { type = TYPE_TRANSFORM; }
};
struct CommandClipIgnore : public Command {
-
bool ignore;
CommandClipIgnore() {
type = TYPE_CLIP_IGNORE;
@@ -1000,13 +1056,13 @@ public:
Rect2 global_rect_cache;
const Rect2 &get_rect() const {
- if (custom_rect || (!rect_dirty && !update_when_visible))
+ if (custom_rect || (!rect_dirty && !update_when_visible)) {
return rect;
+ }
//must update rect
- if (commands == NULL) {
-
+ if (commands == nullptr) {
rect = Rect2();
rect_dirty = false;
return rect;
@@ -1019,29 +1075,24 @@ public:
const Item::Command *c = commands;
while (c) {
-
Rect2 r;
switch (c->type) {
case Item::Command::TYPE_RECT: {
-
const Item::CommandRect *crect = static_cast<const Item::CommandRect *>(c);
r = crect->rect;
} break;
case Item::Command::TYPE_NINEPATCH: {
-
const Item::CommandNinePatch *style = static_cast<const Item::CommandNinePatch *>(c);
r = style->rect;
} break;
case Item::Command::TYPE_POLYGON: {
-
const Item::CommandPolygon *polygon = static_cast<const Item::CommandPolygon *>(c);
r = polygon->polygon.rect_cache;
} break;
case Item::Command::TYPE_PRIMITIVE: {
-
const Item::CommandPrimitive *primitive = static_cast<const Item::CommandPrimitive *>(c);
for (uint32_t j = 0; j < primitive->point_count; j++) {
if (j == 0) {
@@ -1052,7 +1103,6 @@ public:
}
} break;
case Item::Command::TYPE_MESH: {
-
const Item::CommandMesh *mesh = static_cast<const Item::CommandMesh *>(c);
AABB aabb = RasterizerStorage::base_singleton->mesh_get_aabb(mesh->mesh, RID());
@@ -1060,7 +1110,6 @@ public:
} break;
case Item::Command::TYPE_MULTIMESH: {
-
const Item::CommandMultiMesh *multimesh = static_cast<const Item::CommandMultiMesh *>(c);
AABB aabb = RasterizerStorage::base_singleton->multimesh_get_aabb(multimesh->multimesh);
@@ -1068,7 +1117,6 @@ public:
} break;
case Item::Command::TYPE_PARTICLES: {
-
const Item::CommandParticles *particles_cmd = static_cast<const Item::CommandParticles *>(c);
if (particles_cmd->particles.is_valid()) {
AABB aabb = RasterizerStorage::base_singleton->particles_get_aabb(particles_cmd->particles);
@@ -1077,7 +1125,6 @@ public:
} break;
case Item::Command::TYPE_TRANSFORM: {
-
const Item::CommandTransform *transform = static_cast<const Item::CommandTransform *>(c);
xf = transform->xform;
found_xform = true;
@@ -1115,12 +1162,12 @@ public:
template <class T>
T *alloc_command() {
T *command;
- if (commands == NULL) {
+ if (commands == nullptr) {
// As the most common use case of canvas items is to
// use only one command, the first is done with it's
// own allocation. The rest of them use blocks.
command = memnew(T);
- command->next = NULL;
+ command->next = nullptr;
commands = command;
last_command = command;
} else {
@@ -1147,7 +1194,7 @@ public:
//allocate block and add to the linked list
void *memory = c->memory + c->usage;
command = memnew_placement(memory, T);
- command->next = NULL;
+ command->next = nullptr;
last_command->next = command;
last_command = command;
c->usage += sizeof(T);
@@ -1160,7 +1207,6 @@ public:
}
struct CustomData {
-
virtual ~CustomData() {}
};
@@ -1172,7 +1218,7 @@ public:
Command *n = c->next;
if (c == commands) {
memdelete(commands);
- commands = NULL;
+ commands = nullptr;
} else {
c->~Command();
}
@@ -1186,43 +1232,45 @@ public:
}
}
- last_command = NULL;
- commands = NULL;
+ last_command = nullptr;
+ commands = nullptr;
current_block = 0;
clip = false;
rect_dirty = true;
- final_clip_owner = NULL;
- material_owner = NULL;
+ final_clip_owner = nullptr;
+ material_owner = nullptr;
light_masked = false;
}
Item() {
- commands = NULL;
- last_command = NULL;
+ commands = nullptr;
+ last_command = nullptr;
current_block = 0;
light_mask = 1;
- vp_render = NULL;
- next = NULL;
- final_clip_owner = NULL;
+ vp_render = nullptr;
+ next = nullptr;
+ final_clip_owner = nullptr;
clip = false;
final_modulate = Color(1, 1, 1, 1);
visible = true;
rect_dirty = true;
custom_rect = false;
behind = false;
- material_owner = NULL;
- copy_back_buffer = NULL;
+ material_owner = nullptr;
+ copy_back_buffer = nullptr;
distance_field = false;
light_masked = false;
update_when_visible = false;
z_final = 0;
- custom_data = NULL;
+ custom_data = nullptr;
}
virtual ~Item() {
clear();
for (int i = 0; i < blocks.size(); i++) {
memfree(blocks[i].memory);
}
- if (copy_back_buffer) memdelete(copy_back_buffer);
+ if (copy_back_buffer) {
+ memdelete(copy_back_buffer);
+ }
if (custom_data) {
memdelete(custom_data);
}
@@ -1233,7 +1281,6 @@ public:
virtual void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) = 0;
struct LightOccluderInstance {
-
bool enabled;
RID canvas;
RID polygon;
@@ -1248,7 +1295,7 @@ public:
LightOccluderInstance() {
enabled = true;
- next = NULL;
+ next = nullptr;
light_mask = 1;
cull_cache = RS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED;
}
@@ -1299,6 +1346,8 @@ public:
virtual void end_frame(bool p_swap_buffers) = 0;
virtual void finalize() = 0;
+ virtual uint64_t get_frame_number() const = 0;
+ virtual float get_frame_delta_time() const = 0;
virtual bool is_low_end() const = 0;
diff --git a/servers/rendering/rasterizer_rd/light_cluster_builder.cpp b/servers/rendering/rasterizer_rd/light_cluster_builder.cpp
index 943ef1c7fa..efb48e6df7 100644
--- a/servers/rendering/rasterizer_rd/light_cluster_builder.cpp
+++ b/servers/rendering/rasterizer_rd/light_cluster_builder.cpp
@@ -39,12 +39,12 @@ void LightClusterBuilder::begin(const Transform &p_view_transform, const CameraM
//reset counts
light_count = 0;
refprobe_count = 0;
+ decal_count = 0;
item_count = 0;
sort_id_count = 0;
}
void LightClusterBuilder::bake_cluster() {
-
float slice_depth = (z_near - z_far) / depth;
uint8_t *cluster_dataw = cluster_data.ptrw();
@@ -55,7 +55,6 @@ void LightClusterBuilder::bake_cluster() {
/* Step 1, create cell positions and count them */
for (uint32_t i = 0; i < item_count; i++) {
-
const Item &item = items[i];
int from_slice = Math::floor((z_near - (item.aabb.position.z + item.aabb.size.z)) / slice_depth);
@@ -69,7 +68,6 @@ void LightClusterBuilder::bake_cluster() {
to_slice = MIN((int)depth - 1, to_slice);
for (int j = from_slice; j <= to_slice; j++) {
-
Vector3 min = item.aabb.position;
Vector3 max = item.aabb.position + item.aabb.size;
@@ -125,7 +123,6 @@ void LightClusterBuilder::bake_cluster() {
sort_id_max = nearest_power_of_2_templated(sort_id_max + 1);
sort_ids = (SortID *)memrealloc(sort_ids, sizeof(SortID) * sort_id_max);
if (ids.size()) {
-
ids.resize(sort_id_max);
RD::get_singleton()->free(items_buffer);
items_buffer = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t) * sort_id_max);
@@ -177,7 +174,6 @@ void LightClusterBuilder::bake_cluster() {
}
void LightClusterBuilder::setup(uint32_t p_width, uint32_t p_height, uint32_t p_depth) {
-
if (width == p_width && height == p_height && depth == p_depth) {
return;
}
@@ -207,6 +203,7 @@ void LightClusterBuilder::setup(uint32_t p_width, uint32_t p_height, uint32_t p_
RID LightClusterBuilder::get_cluster_texture() const {
return cluster_texture;
}
+
RID LightClusterBuilder::get_cluster_indices_buffer() const {
return items_buffer;
}
@@ -230,8 +227,8 @@ LightClusterBuilder::LightClusterBuilder() {
items_buffer = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t) * 1024);
item_max = 1024;
}
-LightClusterBuilder::~LightClusterBuilder() {
+LightClusterBuilder::~LightClusterBuilder() {
if (cluster_data.size()) {
RD::get_singleton()->free(cluster_texture);
}
diff --git a/servers/rendering/rasterizer_rd/light_cluster_builder.h b/servers/rendering/rasterizer_rd/light_cluster_builder.h
index 3411ed07a0..b1da083dad 100644
--- a/servers/rendering/rasterizer_rd/light_cluster_builder.h
+++ b/servers/rendering/rasterizer_rd/light_cluster_builder.h
@@ -170,17 +170,14 @@ public:
_add_item(aabb, ITEM_TYPE_OMNI_LIGHT, light_count);
} break;
case LIGHT_TYPE_SPOT: {
- Vector3 v(0, 0, -1);
- v.rotated(Vector3(0, 1, 0), Math::deg2rad(ld.spot_aperture)); //rotate in x-z
- v.normalize();
- v *= ld.radius;
- v.y = v.x;
+ float r = ld.radius;
+ real_t len = Math::tan(Math::deg2rad(ld.spot_aperture)) * r;
aabb.position = xform.origin;
- aabb.expand_to(xform.xform(v));
- aabb.expand_to(xform.xform(Vector3(-v.x, v.y, v.z)));
- aabb.expand_to(xform.xform(Vector3(-v.x, -v.y, v.z)));
- aabb.expand_to(xform.xform(Vector3(v.x, -v.y, v.z)));
+ aabb.expand_to(xform.xform(Vector3(len, len, -r)));
+ aabb.expand_to(xform.xform(Vector3(-len, len, -r)));
+ aabb.expand_to(xform.xform(Vector3(-len, -len, -r)));
+ aabb.expand_to(xform.xform(Vector3(len, -len, -r)));
_add_item(aabb, ITEM_TYPE_SPOT_LIGHT, light_count);
} break;
}
@@ -189,29 +186,30 @@ public:
}
_FORCE_INLINE_ void add_reflection_probe(const Transform &p_transform, const Vector3 &p_half_extents) {
-
if (unlikely(refprobe_count == refprobe_max)) {
refprobe_max = nearest_power_of_2_templated(refprobe_max + 1);
refprobes = (OrientedBoxData *)memrealloc(refprobes, sizeof(OrientedBoxData) * refprobe_max);
}
+ Transform xform = view_xform * p_transform;
+
OrientedBoxData &rp = refprobes[refprobe_count];
- Vector3 origin = p_transform.origin;
+ Vector3 origin = xform.origin;
rp.position[0] = origin.x;
rp.position[1] = origin.y;
rp.position[2] = origin.z;
- Vector3 x_axis = p_transform.basis.get_axis(0) * p_half_extents.x;
+ Vector3 x_axis = xform.basis.get_axis(0) * p_half_extents.x;
rp.x_axis[0] = x_axis.x;
rp.x_axis[1] = x_axis.y;
rp.x_axis[2] = x_axis.z;
- Vector3 y_axis = p_transform.basis.get_axis(1) * p_half_extents.y;
+ Vector3 y_axis = xform.basis.get_axis(1) * p_half_extents.y;
rp.y_axis[0] = y_axis.x;
rp.y_axis[1] = y_axis.y;
rp.y_axis[2] = y_axis.z;
- Vector3 z_axis = p_transform.basis.get_axis(2) * p_half_extents.z;
+ Vector3 z_axis = xform.basis.get_axis(2) * p_half_extents.z;
rp.z_axis[0] = z_axis.x;
rp.z_axis[1] = z_axis.y;
rp.z_axis[2] = z_axis.z;
@@ -232,35 +230,36 @@ public:
refprobe_count++;
}
- _FORCE_INLINE_ void add_decal(const Transform &p_transform, const Vector2 &p_half_extents, float p_depth) {
-
+ _FORCE_INLINE_ void add_decal(const Transform &p_transform, const Vector3 &p_half_extents) {
if (unlikely(decal_count == decal_max)) {
decal_max = nearest_power_of_2_templated(decal_max + 1);
decals = (OrientedBoxData *)memrealloc(decals, sizeof(OrientedBoxData) * decal_max);
}
- OrientedBoxData &dc = decals[decal_count];
+ Transform xform = view_xform * p_transform;
- Vector3 z_axis = -p_transform.basis.get_axis(2) * p_depth * 0.5;
- dc.z_axis[0] = z_axis.x;
- dc.z_axis[1] = z_axis.y;
- dc.z_axis[2] = z_axis.z;
+ OrientedBoxData &dc = decals[decal_count];
- Vector3 origin = p_transform.origin - z_axis;
+ Vector3 origin = xform.origin;
dc.position[0] = origin.x;
dc.position[1] = origin.y;
dc.position[2] = origin.z;
- Vector3 x_axis = p_transform.basis.get_axis(0) * p_half_extents.x;
+ Vector3 x_axis = xform.basis.get_axis(0) * p_half_extents.x;
dc.x_axis[0] = x_axis.x;
dc.x_axis[1] = x_axis.y;
dc.x_axis[2] = x_axis.z;
- Vector3 y_axis = p_transform.basis.get_axis(1) * p_half_extents.y;
+ Vector3 y_axis = xform.basis.get_axis(1) * p_half_extents.y;
dc.y_axis[0] = y_axis.x;
dc.y_axis[1] = y_axis.y;
dc.y_axis[2] = y_axis.z;
+ Vector3 z_axis = xform.basis.get_axis(2) * p_half_extents.z;
+ dc.z_axis[0] = z_axis.x;
+ dc.z_axis[1] = z_axis.y;
+ dc.z_axis[2] = z_axis.z;
+
AABB aabb;
aabb.position = origin + x_axis + y_axis + z_axis;
diff --git a/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp
index 8d52ffd7b9..4c477ca5f4 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp
+++ b/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp
@@ -34,7 +34,6 @@
#include "rasterizer_rd.h"
void RasterizerCanvasRD::_update_transform_2d_to_mat4(const Transform2D &p_transform, float *p_mat4) {
-
p_mat4[0] = p_transform.elements[0][0];
p_mat4[1] = p_transform.elements[0][1];
p_mat4[2] = 0;
@@ -54,7 +53,6 @@ void RasterizerCanvasRD::_update_transform_2d_to_mat4(const Transform2D &p_trans
}
void RasterizerCanvasRD::_update_transform_2d_to_mat2x4(const Transform2D &p_transform, float *p_mat2x4) {
-
p_mat2x4[0] = p_transform.elements[0][0];
p_mat2x4[1] = p_transform.elements[1][0];
p_mat2x4[2] = 0;
@@ -67,7 +65,6 @@ void RasterizerCanvasRD::_update_transform_2d_to_mat2x4(const Transform2D &p_tra
}
void RasterizerCanvasRD::_update_transform_2d_to_mat2x3(const Transform2D &p_transform, float *p_mat2x3) {
-
p_mat2x3[0] = p_transform.elements[0][0];
p_mat2x3[1] = p_transform.elements[0][1];
p_mat2x3[2] = p_transform.elements[1][0];
@@ -77,7 +74,6 @@ void RasterizerCanvasRD::_update_transform_2d_to_mat2x3(const Transform2D &p_tra
}
void RasterizerCanvasRD::_update_transform_to_mat4(const Transform &p_transform, float *p_mat4) {
-
p_mat4[0] = p_transform.basis.elements[0][0];
p_mat4[1] = p_transform.basis.elements[1][0];
p_mat4[2] = p_transform.basis.elements[2][0];
@@ -97,7 +93,6 @@ void RasterizerCanvasRD::_update_transform_to_mat4(const Transform &p_transform,
}
void RasterizerCanvasRD::_update_specular_shininess(const Color &p_transform, uint32_t *r_ss) {
-
*r_ss = uint32_t(CLAMP(p_transform.a * 255.0, 0, 255)) << 24;
*r_ss |= uint32_t(CLAMP(p_transform.b * 255.0, 0, 255)) << 16;
*r_ss |= uint32_t(CLAMP(p_transform.g * 255.0, 0, 255)) << 8;
@@ -105,7 +100,6 @@ void RasterizerCanvasRD::_update_specular_shininess(const Color &p_transform, ui
}
RID RasterizerCanvasRD::_create_texture_binding(RID p_texture, RID p_normalmap, RID p_specular, RenderingServer::CanvasItemTextureFilter p_filter, RenderingServer::CanvasItemTextureRepeat p_repeat, RID p_multimesh) {
-
Vector<RD::Uniform> uniform_set;
{ // COLOR TEXTURE
@@ -169,7 +163,6 @@ RID RasterizerCanvasRD::_create_texture_binding(RID p_texture, RID p_normalmap,
}
RasterizerCanvas::TextureBindingID RasterizerCanvasRD::request_texture_binding(RID p_texture, RID p_normalmap, RID p_specular, RenderingServer::CanvasItemTextureFilter p_filter, RenderingServer::CanvasItemTextureRepeat p_repeat, RID p_multimesh) {
-
if (p_filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT) {
p_filter = default_samplers.default_filter;
}
@@ -221,7 +214,6 @@ RasterizerCanvas::TextureBindingID RasterizerCanvasRD::request_texture_binding(R
}
void RasterizerCanvasRD::free_texture_binding(TextureBindingID p_binding) {
-
TextureBinding **binding_ptr = bindings.texture_bindings.getptr(p_binding);
ERR_FAIL_COND(!binding_ptr);
TextureBinding *binding = *binding_ptr;
@@ -233,7 +225,6 @@ void RasterizerCanvasRD::free_texture_binding(TextureBindingID p_binding) {
}
void RasterizerCanvasRD::_dispose_bindings() {
-
while (bindings.to_dispose_list.first()) {
TextureBinding *binding = bindings.to_dispose_list.first()->self();
if (binding->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(binding->uniform_set)) {
@@ -248,7 +239,6 @@ void RasterizerCanvasRD::_dispose_bindings() {
}
RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, const Vector<int> &p_bones, const Vector<float> &p_weights) {
-
// Care must be taken to generate array formats
// in ways where they could be reused, so we will
// put single-occuring elements first, and repeated
@@ -273,7 +263,7 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int
Vector<uint8_t> polygon_buffer;
polygon_buffer.resize(buffer_size * sizeof(float));
- Vector<RD::VertexDescription> descriptions;
+ Vector<RD::VertexAttribute> descriptions;
descriptions.resize(4);
Vector<RID> buffers;
buffers.resize(4);
@@ -284,7 +274,7 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int
uint32_t *uptr = (uint32_t *)r;
uint32_t base_offset = 0;
{ //vertices
- RD::VertexDescription vd;
+ RD::VertexAttribute vd;
vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
vd.offset = base_offset * sizeof(float);
vd.location = RS::ARRAY_VERTEX;
@@ -304,7 +294,7 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int
//colors
if ((uint32_t)p_colors.size() == vertex_count || p_colors.size() == 1) {
- RD::VertexDescription vd;
+ RD::VertexAttribute vd;
vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
vd.offset = base_offset * sizeof(float);
vd.location = RS::ARRAY_COLOR;
@@ -332,7 +322,7 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int
}
base_offset += 4;
} else {
- RD::VertexDescription vd;
+ RD::VertexAttribute vd;
vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
vd.offset = 0;
vd.location = RS::ARRAY_COLOR;
@@ -344,7 +334,7 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int
//uvs
if ((uint32_t)p_uvs.size() == vertex_count) {
- RD::VertexDescription vd;
+ RD::VertexAttribute vd;
vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
vd.offset = base_offset * sizeof(float);
vd.location = RS::ARRAY_TEX_UV;
@@ -360,7 +350,7 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int
}
base_offset += 2;
} else {
- RD::VertexDescription vd;
+ RD::VertexAttribute vd;
vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
vd.offset = 0;
vd.location = RS::ARRAY_TEX_UV;
@@ -372,7 +362,7 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int
//bones
if ((uint32_t)p_indices.size() == vertex_count * 4 && (uint32_t)p_weights.size() == vertex_count * 4) {
- RD::VertexDescription vd;
+ RD::VertexAttribute vd;
vd.format = RD::DATA_FORMAT_R32G32B32A32_UINT;
vd.offset = base_offset * sizeof(float);
vd.location = RS::ARRAY_BONES;
@@ -384,7 +374,6 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int
const float *weight_ptr = p_weights.ptr();
for (uint32_t i = 0; i < vertex_count; i++) {
-
uint16_t *bone16w = (uint16_t *)&uptr[base_offset + i * stride];
uint16_t *weight16w = (uint16_t *)&uptr[base_offset + i * stride + 2];
@@ -401,7 +390,7 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int
base_offset += 4;
} else {
- RD::VertexDescription vd;
+ RD::VertexAttribute vd;
vd.format = RD::DATA_FORMAT_R32G32B32A32_UINT;
vd.offset = 0;
vd.location = RS::ARRAY_BONES;
@@ -450,7 +439,6 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int
}
void RasterizerCanvasRD::free_polygon(PolygonID p_polygon) {
-
PolygonBuffers *pb_ptr = polygon_buffers.polygons.getptr(p_polygon);
ERR_FAIL_COND(!pb_ptr);
@@ -470,7 +458,6 @@ void RasterizerCanvasRD::free_polygon(PolygonID p_polygon) {
}
Size2i RasterizerCanvasRD::_bind_texture_binding(TextureBindingID p_binding, RD::DrawListID p_draw_list, uint32_t &flags) {
-
TextureBinding **texture_binding_ptr = bindings.texture_bindings.getptr(p_binding);
ERR_FAIL_COND_V(!texture_binding_ptr, Size2i());
TextureBinding *texture_binding = *texture_binding_ptr;
@@ -498,7 +485,6 @@ Size2i RasterizerCanvasRD::_bind_texture_binding(TextureBindingID p_binding, RD:
////////////////////
void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_item, RD::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, Light *p_lights, PipelineVariants *p_pipeline_variants) {
-
//create an empty push constant
PushConstant push_constant;
@@ -541,13 +527,10 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_
PipelineLightMode light_mode;
{
-
Light *light = p_lights;
while (light) {
-
if (light->render_index_cache >= 0 && p_item->light_mask & light->item_mask && p_item->z_final >= light->z_min && p_item->z_final <= light->z_max && p_item->global_rect_cache.intersects_transformed(light->xform_cache, light->rect_cache)) {
-
uint32_t light_index = light->render_index_cache;
push_constant.lights[light_count >> 2] |= light_index << ((light_count & 3) * 8);
@@ -575,7 +558,6 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_
}
{
-
RID &canvas_item_state = light_count ? state_data->state_uniform_set_with_light : state_data->state_uniform_set;
bool invalid_uniform = canvas_item_state.is_valid() && !RD::get_singleton()->uniform_set_is_valid(canvas_item_state);
@@ -618,6 +600,14 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_
}
}
+ {
+ RD::Uniform u;
+ u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 7;
+ u.ids.push_back(storage->global_variables_get_storage_buffer());
+ uniforms.push_back(u);
+ }
+
//validate and update lighs if they are being used
if (light_count > 0) {
@@ -632,7 +622,6 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_
}
{
-
RD::Uniform u_lights;
u_lights.type = RD::UNIFORM_TYPE_TEXTURE;
u_lights.binding = 4;
@@ -644,7 +633,6 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_
//lights
for (uint32_t i = 0; i < state.max_lights_per_item; i++) {
if (i < light_count) {
-
CanvasLight *cl = canvas_light_owner.getornull(light_cache[i]->light_internal);
ERR_CONTINUE(!cl);
@@ -703,7 +691,6 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_
switch (c->type) {
case Item::Command::TYPE_RECT: {
-
const Item::CommandRect *rect = static_cast<const Item::CommandRect *>(c);
//bind pipeline
@@ -803,7 +790,6 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_
} break;
case Item::Command::TYPE_NINEPATCH: {
-
const Item::CommandNinePatch *np = static_cast<const Item::CommandNinePatch *>(c);
//bind pipeline
@@ -831,12 +817,10 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_
Rect2 dst_rect(np->rect.position.x, np->rect.position.y, np->rect.size.x, np->rect.size.y);
if (texpixel_size == Size2()) {
-
texpixel_size = Size2(1, 1);
src_rect = Rect2(0, 0, 1, 1);
} else {
-
if (np->source != Rect2()) {
src_rect = Rect2(np->source.position.x * texpixel_size.width, np->source.position.y * texpixel_size.height, np->source.size.x * texpixel_size.width, np->source.size.y * texpixel_size.height);
texpixel_size = Size2(1.0 / np->source.size.width, 1.0 / np->source.size.height);
@@ -881,7 +865,6 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_
} break;
case Item::Command::TYPE_POLYGON: {
-
const Item::CommandPolygon *polygon = static_cast<const Item::CommandPolygon *>(c);
PolygonBuffers *pb = polygon_buffers.polygons.getptr(polygon->polygon.polygon_id);
@@ -937,7 +920,6 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_
} break;
case Item::Command::TYPE_PRIMITIVE: {
-
const Item::CommandPrimitive *primitive = static_cast<const Item::CommandPrimitive *>(c);
//bind pipeline
@@ -1220,7 +1202,7 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_
glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 5));
glVertexAttribDivisor(10, 1);
glEnableVertexAttribArray(11); //color
- glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, NULL);
+ glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, nullptr);
glVertexAttribDivisor(11, 1);
glEnableVertexAttribArray(12); //custom
glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 2));
@@ -1262,7 +1244,7 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_
glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 5));
glVertexAttribDivisor(10, 1);
glEnableVertexAttribArray(11); //color
- glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, NULL);
+ glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, nullptr);
glVertexAttribDivisor(11, 1);
glEnableVertexAttribArray(12); //custom
glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 2));
@@ -1283,23 +1265,18 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_
} break;
#endif
case Item::Command::TYPE_TRANSFORM: {
-
const Item::CommandTransform *transform = static_cast<const Item::CommandTransform *>(c);
_update_transform_2d_to_mat2x3(base_transform * transform->xform, push_constant.world);
} break;
case Item::Command::TYPE_CLIP_IGNORE: {
-
const Item::CommandClipIgnore *ci = static_cast<const Item::CommandClipIgnore *>(c);
if (current_clip) {
-
if (ci->ignore != reclip) {
-
if (ci->ignore) {
RD::get_singleton()->draw_list_disable_scissor(p_draw_list);
reclip = true;
} else {
-
RD::get_singleton()->draw_list_enable_scissor(p_draw_list, current_clip->final_clip_rect);
reclip = false;
}
@@ -1314,13 +1291,12 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_
if (current_clip && reclip) {
//will make it re-enable clipping if needed afterwards
- current_clip = NULL;
+ current_clip = nullptr;
}
}
void RasterizerCanvasRD::_render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, RID p_screen_uniform_set) {
-
- Item *current_clip = NULL;
+ Item *current_clip = nullptr;
Transform2D canvas_transform_inverse = p_canvas_transform_inverse;
@@ -1349,33 +1325,27 @@ void RasterizerCanvasRD::_render_items(RID p_to_render_target, int p_item_count,
PipelineVariants *pipeline_variants = &shader.pipeline_variants;
for (int i = 0; i < p_item_count; i++) {
-
Item *ci = items[i];
if (current_clip != ci->final_clip_owner) {
-
current_clip = ci->final_clip_owner;
//setup clip
if (current_clip) {
-
RD::get_singleton()->draw_list_enable_scissor(draw_list, current_clip->final_clip_rect);
} else {
-
RD::get_singleton()->draw_list_disable_scissor(draw_list);
}
}
if (ci->material != prev_material) {
-
- MaterialData *material_data = NULL;
+ MaterialData *material_data = nullptr;
if (ci->material.is_valid()) {
material_data = (MaterialData *)storage->material_get_data(ci->material, RasterizerStorageRD::SHADER_TYPE_2D);
}
if (material_data) {
-
if (material_data->shader_data->version.is_valid() && material_data->shader_data->valid) {
pipeline_variants = &material_data->shader_data->pipeline_variants;
if (material_data->uniform_set.is_valid()) {
@@ -1398,7 +1368,6 @@ void RasterizerCanvasRD::_render_items(RID p_to_render_target, int p_item_count,
}
void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, const Transform2D &p_canvas_transform) {
-
int item_count = 0;
//setup canvas state uniforms if needed
@@ -1439,12 +1408,10 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite
//setup lights if exist
{
-
Light *l = p_light_list;
uint32_t index = 0;
while (l) {
-
if (index == state.max_lights_per_render) {
l->render_index_cache = -1;
l = l->next_ptr;
@@ -1505,7 +1472,6 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite
RID screen_uniform_set;
while (ci) {
-
if (ci->copy_back_buffer) {
backbuffer_copy = true;
@@ -1519,7 +1485,6 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite
if (ci->material.is_valid()) {
MaterialData *md = (MaterialData *)storage->material_get_data(ci->material, RasterizerStorageRD::SHADER_TYPE_2D);
if (md && md->shader_data->valid) {
-
if (md->shader_data->uses_screen_texture) {
if (!material_screen_texture_found) {
backbuffer_copy = true;
@@ -1531,8 +1496,8 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite
}
}
- if (md->last_frame != RasterizerRD::get_frame_number()) {
- md->last_frame = RasterizerRD::get_frame_number();
+ if (md->last_frame != RasterizerRD::singleton->get_frame_number()) {
+ md->last_frame = RasterizerRD::singleton->get_frame_number();
if (!RD::get_singleton()->uniform_set_is_valid(md->uniform_set)) {
// uniform set may be gone because a dependency was erased. In this case, it will happen
// if a texture is deleted, so just re-create it.
@@ -1566,7 +1531,6 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite
}
RID RasterizerCanvasRD::light_create() {
-
CanvasLight canvas_light;
canvas_light.shadow.size = 0;
return canvas_light_owner.make_rid(canvas_light);
@@ -1581,6 +1545,7 @@ void RasterizerCanvasRD::light_set_texture(RID p_rid, RID p_texture) {
cl->texture = p_texture;
}
+
void RasterizerCanvasRD::light_set_use_shadow(RID p_rid, bool p_enable, int p_resolution) {
CanvasLight *cl = canvas_light_owner.getornull(p_rid);
ERR_FAIL_COND(!cl);
@@ -1590,7 +1555,6 @@ void RasterizerCanvasRD::light_set_use_shadow(RID p_rid, bool p_enable, int p_re
}
if (cl->shadow.texture.is_valid()) {
-
RD::get_singleton()->free(cl->shadow.fb);
RD::get_singleton()->free(cl->shadow.depth);
RD::get_singleton()->free(cl->shadow.texture);
@@ -1600,7 +1564,6 @@ void RasterizerCanvasRD::light_set_use_shadow(RID p_rid, bool p_enable, int p_re
}
if (p_enable) {
-
Vector<RID> fb_textures;
{ //texture
@@ -1633,12 +1596,10 @@ void RasterizerCanvasRD::light_set_use_shadow(RID p_rid, bool p_enable, int p_re
}
void RasterizerCanvasRD::light_update_shadow(RID p_rid, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders) {
-
CanvasLight *cl = canvas_light_owner.getornull(p_rid);
ERR_FAIL_COND(cl->shadow.texture.is_null());
for (int i = 0; i < 4; i++) {
-
//make sure it remains orthogonal, makes easy to read angle later
//light.basis.scale(Vector3(to_light.elements[0].length(),to_light.elements[1].length(),1));
@@ -1683,11 +1644,9 @@ void RasterizerCanvasRD::light_update_shadow(RID p_rid, const Transform2D &p_lig
LightOccluderInstance *instance = p_occluders;
while (instance) {
-
OccluderPolygon *co = occluder_polygon_owner.getornull(instance->occluder);
if (!co || co->index_array.is_null() || !(p_light_mask & instance->light_mask)) {
-
instance = instance->next;
continue;
}
@@ -1709,7 +1668,6 @@ void RasterizerCanvasRD::light_update_shadow(RID p_rid, const Transform2D &p_lig
}
RID RasterizerCanvasRD::occluder_polygon_create() {
-
OccluderPolygon occluder;
occluder.point_count = 0;
occluder.cull_mode = RS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED;
@@ -1717,12 +1675,10 @@ RID RasterizerCanvasRD::occluder_polygon_create() {
}
void RasterizerCanvasRD::occluder_polygon_set_shape_as_lines(RID p_occluder, const Vector<Vector2> &p_lines) {
-
OccluderPolygon *oc = occluder_polygon_owner.getornull(p_occluder);
ERR_FAIL_COND(!oc);
if (oc->point_count != p_lines.size() && oc->vertex_array.is_valid()) {
-
RD::get_singleton()->free(oc->vertex_array);
RD::get_singleton()->free(oc->vertex_buffer);
RD::get_singleton()->free(oc->index_array);
@@ -1735,7 +1691,6 @@ void RasterizerCanvasRD::occluder_polygon_set_shape_as_lines(RID p_occluder, con
}
if (p_lines.size()) {
-
Vector<uint8_t> geometry;
Vector<uint8_t> indices;
int lc = p_lines.size();
@@ -1754,7 +1709,6 @@ void RasterizerCanvasRD::occluder_polygon_set_shape_as_lines(RID p_occluder, con
const int POLY_HEIGHT = 16384;
for (int i = 0; i < lc / 2; i++) {
-
vwptr[i * 12 + 0] = lr[i * 2 + 0].x;
vwptr[i * 12 + 1] = lr[i * 2 + 0].y;
vwptr[i * 12 + 2] = POLY_HEIGHT;
@@ -1805,6 +1759,7 @@ void RasterizerCanvasRD::occluder_polygon_set_shape_as_lines(RID p_occluder, con
}
}
}
+
void RasterizerCanvasRD::occluder_polygon_set_cull_mode(RID p_occluder, RS::CanvasOccluderPolygonCullMode p_mode) {
OccluderPolygon *oc = occluder_polygon_owner.getornull(p_occluder);
ERR_FAIL_COND(!oc);
@@ -1887,12 +1842,10 @@ void RasterizerCanvasRD::ShaderData::set_code(const String &p_code) {
switch (blend_mode) {
case BLEND_MODE_DISABLED: {
-
// nothing to do here, disabled by default
} break;
case BLEND_MODE_MIX: {
-
attachment.enable_blend = true;
attachment.alpha_blend_op = RD::BLEND_OP_ADD;
attachment.color_blend_op = RD::BLEND_OP_ADD;
@@ -1903,7 +1856,6 @@ void RasterizerCanvasRD::ShaderData::set_code(const String &p_code) {
} break;
case BLEND_MODE_ADD: {
-
attachment.enable_blend = true;
attachment.alpha_blend_op = RD::BLEND_OP_ADD;
attachment.color_blend_op = RD::BLEND_OP_ADD;
@@ -1914,7 +1866,6 @@ void RasterizerCanvasRD::ShaderData::set_code(const String &p_code) {
} break;
case BLEND_MODE_SUB: {
-
attachment.enable_blend = true;
attachment.alpha_blend_op = RD::BLEND_OP_SUBTRACT;
attachment.color_blend_op = RD::BLEND_OP_SUBTRACT;
@@ -2006,12 +1957,14 @@ void RasterizerCanvasRD::ShaderData::set_default_texture_param(const StringName
default_texture_params[p_name] = p_texture;
}
}
-void RasterizerCanvasRD::ShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
+void RasterizerCanvasRD::ShaderData::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_LOCAL) {
+ continue;
+ }
if (E->get().texture_order >= 0) {
order[E->get().texture_order + 100000] = E->key();
} else {
@@ -2020,13 +1973,27 @@ void RasterizerCanvasRD::ShaderData::get_param_list(List<PropertyInfo> *p_param_
}
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 RasterizerCanvasRD::ShaderData::get_instance_param_list(List<RasterizerStorage::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;
+ }
+
+ RasterizerStorage::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().hint);
+ p_param_list->push_back(p);
+ }
+}
+
bool RasterizerCanvasRD::ShaderData::is_param_texture(const StringName &p_param) const {
if (!uniforms.has(p_param)) {
return false;
@@ -2038,9 +2005,11 @@ bool RasterizerCanvasRD::ShaderData::is_param_texture(const StringName &p_param)
bool RasterizerCanvasRD::ShaderData::is_animated() const {
return false;
}
+
bool RasterizerCanvasRD::ShaderData::casts_shadows() const {
return false;
}
+
Variant RasterizerCanvasRD::ShaderData::get_default_parameter(const StringName &p_parameter) const {
if (uniforms.has(p_parameter)) {
ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter];
@@ -2069,8 +2038,8 @@ RasterizerStorageRD::ShaderData *RasterizerCanvasRD::_create_shader_func() {
ShaderData *shader_data = memnew(ShaderData);
return shader_data;
}
-void RasterizerCanvasRD::MaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
+void RasterizerCanvasRD::MaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
RasterizerCanvasRD *canvas_singleton = (RasterizerCanvasRD *)RasterizerCanvas::singleton;
if ((uint32_t)ubo_data.size() != shader_data->ubo_size) {
@@ -2095,7 +2064,6 @@ void RasterizerCanvasRD::MaterialData::update_parameters(const Map<StringName, V
//check whether buffer changed
if (p_uniform_dirty && ubo_data.size()) {
-
update_uniform_buffer(shader_data->uniforms, shader_data->ubo_offsets.ptr(), p_parameters, ubo_data.ptrw(), ubo_data.size(), false);
RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw());
}
@@ -2114,7 +2082,6 @@ void RasterizerCanvasRD::MaterialData::update_parameters(const Map<StringName, V
}
if (p_textures_dirty && tex_uniform_count) {
-
update_textures(p_parameters, shader_data->default_texture_params, shader_data->texture_uniforms, texture_cache.ptrw(), false);
}
@@ -2173,6 +2140,7 @@ void RasterizerCanvasRD::MaterialData::update_parameters(const Map<StringName, V
uniform_set = RD::get_singleton()->uniform_set_create(uniforms, canvas_singleton->shader.canvas_shader.version_get_shader(shader_data->version, 0), 1);
}
+
RasterizerCanvasRD::MaterialData::~MaterialData() {
if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
RD::get_singleton()->free(uniform_set);
@@ -2366,6 +2334,8 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) {
actions.default_repeat = ShaderLanguage::REPEAT_DISABLE;
actions.base_varying_index = 4;
+ actions.global_buffer_array_variable = "global_variables.data";
+
shader.compiler.initialize(actions);
}
@@ -2393,8 +2363,8 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) {
}
//pipelines
- Vector<RD::VertexDescription> vf;
- RD::VertexDescription vd;
+ Vector<RD::VertexAttribute> vf;
+ RD::VertexAttribute vd;
vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT;
vd.location = 0;
vd.offset = 0;
@@ -2484,7 +2454,6 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) {
}
bool RasterizerCanvasRD::free(RID p_rid) {
-
if (canvas_light_owner.owns(p_rid)) {
CanvasLight *cl = canvas_light_owner.getornull(p_rid);
ERR_FAIL_COND_V(!cl, false);
@@ -2501,7 +2470,6 @@ bool RasterizerCanvasRD::free(RID p_rid) {
}
RasterizerCanvasRD::~RasterizerCanvasRD() {
-
//canvas state
{
@@ -2517,14 +2485,12 @@ RasterizerCanvasRD::~RasterizerCanvasRD() {
//shadow rendering
{
-
shadow_render.shader.version_free(shadow_render.shader_version);
//this will also automatically clear all pipelines
RD::get_singleton()->free(state.shadow_sampler);
}
//bindings
{
-
free_texture_binding(bindings.default_empty);
//dispose pending
@@ -2532,7 +2498,7 @@ RasterizerCanvasRD::~RasterizerCanvasRD() {
//anything remains?
if (bindings.texture_bindings.size()) {
ERR_PRINT("Some texture bindings were not properly freed (leaked canvasitems?");
- const TextureBindingID *key = NULL;
+ const TextureBindingID *key = nullptr;
while ((key = bindings.texture_bindings.next(key))) {
TextureBinding *tb = bindings.texture_bindings[*key];
tb->reference_count = 1;
diff --git a/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h b/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h
index 0c151975bc..bfe4e61f47 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h
+++ b/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h
@@ -40,7 +40,6 @@
#include "servers/rendering/rendering_device.h"
class RasterizerCanvasRD : public RasterizerCanvas {
-
RasterizerStorageRD *storage;
enum ShaderVariant {
@@ -149,7 +148,6 @@ class RasterizerCanvasRD : public RasterizerCanvas {
} shader;
struct ShaderData : public RasterizerStorageRD::ShaderData {
-
enum BlendMode { //used internally
BLEND_MODE_MIX,
BLEND_MODE_ADD,
@@ -185,6 +183,8 @@ class RasterizerCanvasRD : public RasterizerCanvas {
virtual void set_code(const String &p_Code);
virtual void set_default_texture_param(const StringName &p_name, RID p_texture);
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
+ virtual void get_instance_param_list(List<RasterizerStorage::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;
@@ -311,7 +311,6 @@ class RasterizerCanvasRD : public RasterizerCanvas {
/******************/
struct CanvasLight {
-
RID texture;
struct {
int size;
@@ -331,7 +330,6 @@ class RasterizerCanvasRD : public RasterizerCanvas {
};
struct OccluderPolygon {
-
RS::CanvasOccluderPolygonCullMode cull_mode;
int point_count;
RID vertex_buffer;
@@ -369,7 +367,6 @@ class RasterizerCanvasRD : public RasterizerCanvas {
//state that does not vary across rendering all items
struct ItemStateData : public Item::CustomData {
-
struct LightCache {
uint64_t light_version;
Light *light;
@@ -380,10 +377,9 @@ class RasterizerCanvasRD : public RasterizerCanvas {
RID state_uniform_set_with_light;
RID state_uniform_set;
ItemStateData() {
-
for (int i = 0; i < DEFAULT_MAX_LIGHTS_PER_ITEM; i++) {
light_cache[i].light_version = 0;
- light_cache[i].light = NULL;
+ light_cache[i].light = nullptr;
}
light_cache_count = 0xFFFFFFFF;
}
@@ -399,7 +395,6 @@ class RasterizerCanvasRD : public RasterizerCanvas {
};
struct State {
-
//state buffer
struct Buffer {
float canvas_transform[16];
@@ -487,7 +482,7 @@ public:
void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, const Transform2D &p_canvas_transform);
- void canvas_debug_viewport_shadows(Light *p_lights_with_shadow){};
+ void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) {}
void draw_window_margins(int *p_margins, RID *p_margin_textures) {}
diff --git a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp
index 9ccc1f172e..303cb7ad42 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp
+++ b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp
@@ -50,8 +50,15 @@ static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_basis, float *p_ar
p_array[11] = 0;
}
-RID RasterizerEffectsRD::_get_uniform_set_from_image(RID p_image) {
+static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_array) {
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+ p_array[i * 4 + j] = p_mtx.matrix[i][j];
+ }
+ }
+}
+RID RasterizerEffectsRD::_get_uniform_set_from_image(RID p_image) {
if (image_to_uniform_set_cache.has(p_image)) {
RID uniform_set = image_to_uniform_set_cache[p_image];
if (RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
@@ -73,7 +80,6 @@ RID RasterizerEffectsRD::_get_uniform_set_from_image(RID p_image) {
}
RID RasterizerEffectsRD::_get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps) {
-
if (texture_to_uniform_set_cache.has(p_texture)) {
RID uniform_set = texture_to_uniform_set_cache[p_texture];
if (RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
@@ -89,7 +95,7 @@ RID RasterizerEffectsRD::_get_uniform_set_from_texture(RID p_texture, bool p_use
u.ids.push_back(p_texture);
uniforms.push_back(u);
//any thing with the same configuration (one texture in binding 0 for set 0), is good
- RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, blur.shader.version_get_shader(blur.shader_version, 0), 0);
+ RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, tonemap.shader.version_get_shader(tonemap.shader_version, 0), 0);
texture_to_uniform_set_cache[p_texture] = uniform_set;
@@ -97,7 +103,6 @@ RID RasterizerEffectsRD::_get_uniform_set_from_texture(RID p_texture, bool p_use
}
RID RasterizerEffectsRD::_get_compute_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps) {
-
if (texture_to_compute_uniform_set_cache.has(p_texture)) {
RID uniform_set = texture_to_compute_uniform_set_cache[p_texture];
if (RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
@@ -120,171 +125,558 @@ RID RasterizerEffectsRD::_get_compute_uniform_set_from_texture(RID p_texture, bo
return uniform_set;
}
-void RasterizerEffectsRD::copy_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, bool p_flip_y, bool p_force_luminance) {
+RID RasterizerEffectsRD::_get_compute_uniform_set_from_texture_pair(RID p_texture1, RID p_texture2, bool p_use_mipmaps) {
+ TexturePair tp;
+ tp.texture1 = p_texture1;
+ tp.texture2 = p_texture2;
+
+ if (texture_pair_to_compute_uniform_set_cache.has(tp)) {
+ RID uniform_set = texture_pair_to_compute_uniform_set_cache[tp];
+ if (RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
+ return uniform_set;
+ }
+ }
+
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
+ u.binding = 0;
+ u.ids.push_back(p_use_mipmaps ? default_mipmap_sampler : default_sampler);
+ u.ids.push_back(p_texture1);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
+ u.binding = 1;
+ u.ids.push_back(p_use_mipmaps ? default_mipmap_sampler : default_sampler);
+ u.ids.push_back(p_texture2);
+ uniforms.push_back(u);
+ }
+ //any thing with the same configuration (one texture in binding 0 for set 0), is good
+ RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssr_scale.shader.version_get_shader(ssr_scale.shader_version, 0), 1);
+
+ texture_pair_to_compute_uniform_set_cache[tp] = uniform_set;
+
+ return uniform_set;
+}
+
+RID RasterizerEffectsRD::_get_compute_uniform_set_from_image_pair(RID p_texture1, RID p_texture2) {
+ TexturePair tp;
+ tp.texture1 = p_texture1;
+ tp.texture2 = p_texture2;
+
+ if (image_pair_to_compute_uniform_set_cache.has(tp)) {
+ RID uniform_set = image_pair_to_compute_uniform_set_cache[tp];
+ if (RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
+ return uniform_set;
+ }
+ }
+
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 0;
+ u.ids.push_back(p_texture1);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 1;
+ u.ids.push_back(p_texture2);
+ uniforms.push_back(u);
+ }
+ //any thing with the same configuration (one texture in binding 0 for set 0), is good
+ RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssr_scale.shader.version_get_shader(ssr_scale.shader_version, 0), 3);
+
+ image_pair_to_compute_uniform_set_cache[tp] = uniform_set;
+
+ return uniform_set;
+}
+
+void RasterizerEffectsRD::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) {
+ zeromem(&copy_to_fb.push_constant, sizeof(CopyToFbPushConstant));
+
+ copy_to_fb.push_constant.use_section = true;
+ copy_to_fb.push_constant.section[0] = p_uv_rect.position.x;
+ copy_to_fb.push_constant.section[1] = p_uv_rect.position.y;
+ copy_to_fb.push_constant.section[2] = p_uv_rect.size.x;
+ copy_to_fb.push_constant.section[3] = p_uv_rect.size.y;
+
+ if (p_flip_y) {
+ copy_to_fb.push_constant.flip_y = true;
+ }
+
+ RD::DrawListID draw_list = p_draw_list;
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_to_fb.pipelines[p_panorama ? COPY_TO_FB_COPY_PANORAMA_TO_DP : COPY_TO_FB_COPY].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &copy_to_fb.push_constant, sizeof(CopyToFbPushConstant));
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+}
+
+void RasterizerEffectsRD::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_alpha_to_zero) {
+ zeromem(&copy_to_fb.push_constant, sizeof(CopyToFbPushConstant));
- zeromem(&blur.push_constant, sizeof(BlurPushConstant));
if (p_flip_y) {
- blur.push_constant.flags |= BLUR_FLAG_FLIP_Y;
+ copy_to_fb.push_constant.flip_y = true;
}
if (p_force_luminance) {
- blur.push_constant.flags |= BLUR_COPY_FORCE_LUMINANCE;
+ copy_to_fb.push_constant.force_luminance = true;
+ }
+ if (p_alpha_to_zero) {
+ copy_to_fb.push_constant.alpha_to_zero = true;
}
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, p_rect);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[BLUR_MODE_SIMPLY_COPY].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_to_fb.pipelines[COPY_TO_FB_COPY].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur.push_constant, sizeof(BlurPushConstant));
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &copy_to_fb.push_constant, sizeof(CopyToFbPushConstant));
RD::get_singleton()->draw_list_draw(draw_list, true);
RD::get_singleton()->draw_list_end();
}
-void RasterizerEffectsRD::region_copy(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_region) {
+void RasterizerEffectsRD::copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_all_source, bool p_8_bit_dst) {
+ zeromem(&copy.push_constant, sizeof(CopyPushConstant));
+ if (p_flip_y) {
+ copy.push_constant.flags |= COPY_FLAG_FLIP_Y;
+ }
- zeromem(&blur.push_constant, sizeof(BlurPushConstant));
+ if (p_force_luminance) {
+ copy.push_constant.flags |= COPY_FLAG_FORCE_LUMINANCE;
+ }
- if (p_region != Rect2()) {
- blur.push_constant.flags = BLUR_FLAG_USE_BLUR_SECTION;
- blur.push_constant.section[0] = p_region.position.x;
- blur.push_constant.section[1] = p_region.position.y;
- blur.push_constant.section[2] = p_region.size.width;
- blur.push_constant.section[3] = p_region.size.height;
+ if (p_all_source) {
+ copy.push_constant.flags |= COPY_FLAG_ALL_SOURCE;
}
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[BLUR_MODE_SIMPLY_COPY].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur.push_constant, sizeof(BlurPushConstant));
- RD::get_singleton()->draw_list_draw(draw_list, true);
- RD::get_singleton()->draw_list_end();
+ copy.push_constant.section[0] = 0;
+ copy.push_constant.section[1] = 0;
+ copy.push_constant.section[2] = p_rect.size.width;
+ copy.push_constant.section[3] = p_rect.size.height;
+ copy.push_constant.target[0] = p_rect.position.x;
+ copy.push_constant.target[1] = p_rect.position.y;
+
+ int32_t x_groups = (p_rect.size.width - 1) / 8 + 1;
+ int32_t y_groups = (p_rect.size.height - 1) / 8 + 1;
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[p_8_bit_dst ? COPY_MODE_SIMPLY_COPY_8BIT : COPY_MODE_SIMPLY_COPY]);
+ 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_dest_texture), 3);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
+ RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ RD::get_singleton()->compute_list_end();
}
-void RasterizerEffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, const Rect2 &p_region) {
+void RasterizerEffectsRD::copy_cubemap_to_panorama(RID p_source_cube, RID p_dest_panorama, const Size2i &p_panorama_size, float p_lod, bool p_is_array) {
+ zeromem(&copy.push_constant, sizeof(CopyPushConstant));
- zeromem(&blur.push_constant, sizeof(BlurPushConstant));
+ copy.push_constant.section[0] = 0;
+ copy.push_constant.section[1] = 0;
+ copy.push_constant.section[2] = p_panorama_size.width;
+ copy.push_constant.section[3] = p_panorama_size.height;
+ copy.push_constant.target[0] = 0;
+ copy.push_constant.target[1] = 0;
+ copy.push_constant.camera_z_far = p_lod;
- uint32_t base_flags = 0;
- if (p_region != Rect2()) {
- base_flags = BLUR_FLAG_USE_BLUR_SECTION;
- blur.push_constant.section[0] = p_region.position.x;
- blur.push_constant.section[1] = p_region.position.y;
- blur.push_constant.section[2] = p_region.size.width;
- blur.push_constant.section[3] = p_region.size.height;
+ int32_t x_groups = (p_panorama_size.width - 1) / 8 + 1;
+ int32_t y_groups = (p_panorama_size.height - 1) / 8 + 1;
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[p_is_array ? COPY_MODE_CUBE_ARRAY_TO_PANORAMA : COPY_MODE_CUBE_TO_PANORAMA]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_cube), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_panorama), 3);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
+ RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ RD::get_singleton()->compute_list_end();
+}
+
+void RasterizerEffectsRD::copy_depth_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, float p_z_near, float p_z_far) {
+ zeromem(&copy.push_constant, sizeof(CopyPushConstant));
+ if (p_flip_y) {
+ copy.push_constant.flags |= COPY_FLAG_FLIP_Y;
+ }
+
+ copy.push_constant.section[0] = 0;
+ copy.push_constant.section[1] = 0;
+ copy.push_constant.section[2] = p_rect.size.width;
+ copy.push_constant.section[3] = p_rect.size.height;
+ copy.push_constant.target[0] = p_rect.position.x;
+ copy.push_constant.target[1] = p_rect.position.y;
+ copy.push_constant.camera_z_far = p_z_far;
+ copy.push_constant.camera_z_near = p_z_near;
+
+ int32_t x_groups = (p_rect.size.width - 1) / 8 + 1;
+ int32_t y_groups = (p_rect.size.height - 1) / 8 + 1;
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[COPY_MODE_LINEARIZE_DEPTH]);
+ 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_dest_texture), 3);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
+ RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ RD::get_singleton()->compute_list_end();
+}
+
+void RasterizerEffectsRD::copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y) {
+ zeromem(&copy.push_constant, sizeof(CopyPushConstant));
+ if (p_flip_y) {
+ copy.push_constant.flags |= COPY_FLAG_FLIP_Y;
}
- blur.push_constant.pixel_size[0] = p_pixel_size.x;
- blur.push_constant.pixel_size[1] = p_pixel_size.y;
+ copy.push_constant.section[0] = 0;
+ copy.push_constant.section[1] = 0;
+ copy.push_constant.section[2] = p_rect.size.width;
+ copy.push_constant.section[3] = p_rect.size.height;
+ copy.push_constant.target[0] = p_rect.position.x;
+ copy.push_constant.target[1] = p_rect.position.y;
+ int32_t x_groups = (p_rect.size.width - 1) / 8 + 1;
+ int32_t y_groups = (p_rect.size.height - 1) / 8 + 1;
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[COPY_MODE_SIMPLY_COPY_DEPTH]);
+ 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_dest_texture), 3);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
+ RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ RD::get_singleton()->compute_list_end();
+}
+
+void RasterizerEffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_texture, RID p_back_texture, const Rect2i &p_region, bool p_8bit_dst) {
+ zeromem(&copy.push_constant, sizeof(CopyPushConstant));
+
+ uint32_t base_flags = 0;
+ copy.push_constant.section[0] = p_region.position.x;
+ copy.push_constant.section[1] = p_region.position.y;
+ copy.push_constant.section[2] = p_region.size.width;
+ copy.push_constant.section[3] = p_region.size.height;
+
+ int32_t x_groups = (p_region.size.width - 1) / 8 + 1;
+ int32_t y_groups = (p_region.size.height - 1) / 8 + 1;
//HORIZONTAL
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer_half, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[BLUR_MODE_GAUSSIAN_BLUR].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer_half)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
+ RD::DrawListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[p_8bit_dst ? COPY_MODE_GAUSSIAN_COPY_8BIT : COPY_MODE_GAUSSIAN_COPY]);
+ 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_back_texture), 0);
- blur.push_constant.flags = base_flags | BLUR_FLAG_HORIZONTAL;
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur.push_constant, sizeof(BlurPushConstant));
+ copy.push_constant.flags = base_flags | COPY_FLAG_HORIZONTAL;
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
- RD::get_singleton()->draw_list_draw(draw_list, true);
- RD::get_singleton()->draw_list_end();
+ RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
//VERTICAL
- draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[BLUR_MODE_GAUSSIAN_BLUR].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_rd_texture_half), 0);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_back_texture), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_texture), 0);
- blur.push_constant.flags = base_flags;
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur.push_constant, sizeof(BlurPushConstant));
+ copy.push_constant.flags = base_flags;
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
- RD::get_singleton()->draw_list_draw(draw_list, true);
- RD::get_singleton()->draw_list_end();
+ RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ RD::get_singleton()->compute_list_end();
}
-void RasterizerEffectsRD::gaussian_glow(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_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) {
-
- zeromem(&blur.push_constant, sizeof(BlurPushConstant));
+void RasterizerEffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_texture, RID p_back_texture, const Size2i &p_size, float p_strength, 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) {
+ zeromem(&copy.push_constant, sizeof(CopyPushConstant));
- BlurMode blur_mode = p_first_pass && p_auto_exposure.is_valid() ? BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE : BLUR_MODE_GAUSSIAN_GLOW;
+ CopyMode copy_mode = p_first_pass && p_auto_exposure.is_valid() ? COPY_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE : COPY_MODE_GAUSSIAN_GLOW;
uint32_t base_flags = 0;
- blur.push_constant.pixel_size[0] = p_pixel_size.x;
- blur.push_constant.pixel_size[1] = p_pixel_size.y;
+ int32_t x_groups = (p_size.width - 1) / 8 + 1;
+ int32_t y_groups = (p_size.height - 1) / 8 + 1;
+
+ copy.push_constant.section[2] = p_size.x;
+ copy.push_constant.section[3] = p_size.y;
+
+ 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_scale = p_hdr_bleed_scale;
+ copy.push_constant.glow_exposure = p_exposure;
+ copy.push_constant.glow_white = 0; //actually unused
+ copy.push_constant.glow_luminance_cap = p_luminance_cap;
- blur.push_constant.glow_strength = p_strength;
- blur.push_constant.glow_bloom = p_bloom;
- blur.push_constant.glow_hdr_threshold = p_hdr_bleed_treshold;
- blur.push_constant.glow_hdr_scale = p_hdr_bleed_scale;
- blur.push_constant.glow_exposure = p_exposure;
- blur.push_constant.glow_white = 0; //actually unused
- blur.push_constant.glow_luminance_cap = p_luminance_cap;
- blur.push_constant.glow_auto_exposure_grey = p_auto_exposure_grey; //unused also
+ copy.push_constant.glow_auto_exposure_grey = p_auto_exposure_grey; //unused also
//HORIZONTAL
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer_half, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer_half)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[copy_mode]);
+ 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_back_texture), 3);
if (p_auto_exposure.is_valid() && p_first_pass) {
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_auto_exposure), 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_auto_exposure), 1);
}
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
- blur.push_constant.flags = base_flags | BLUR_FLAG_HORIZONTAL | (p_first_pass ? BLUR_FLAG_GLOW_FIRST_PASS : 0);
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur.push_constant, sizeof(BlurPushConstant));
+ copy.push_constant.flags = base_flags | COPY_FLAG_HORIZONTAL | (p_first_pass ? COPY_FLAG_GLOW_FIRST_PASS : 0);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
- RD::get_singleton()->draw_list_draw(draw_list, true);
- RD::get_singleton()->draw_list_end();
+ RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
- blur_mode = BLUR_MODE_GAUSSIAN_GLOW;
+ copy_mode = COPY_MODE_GAUSSIAN_GLOW;
//VERTICAL
- draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_rd_texture_half), 0);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[copy_mode]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_back_texture), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_texture), 3);
- blur.push_constant.flags = base_flags;
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur.push_constant, sizeof(BlurPushConstant));
+ copy.push_constant.flags = base_flags;
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
- RD::get_singleton()->draw_list_draw(draw_list, true);
- RD::get_singleton()->draw_list_end();
+ RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ RD::get_singleton()->compute_list_end();
}
-void RasterizerEffectsRD::make_mipmap(RID p_source_rd_texture, RID p_dest_framebuffer, const Vector2 &p_pixel_size) {
+void RasterizerEffectsRD::screen_space_reflection(RID p_diffuse, RID p_normal, RenderingServer::EnvironmentSSRRoughnessQuality p_roughness_quality, RID p_roughness, RID p_blur_radius, RID p_blur_radius2, RID p_metallic, const Color &p_metallic_mask, RID p_depth, RID p_scale_depth, RID p_scale_normal, RID p_output, RID p_output_blur, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const CameraMatrix &p_camera) {
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+
+ int32_t x_groups = (p_screen_size.width - 1) / 8 + 1;
+ int32_t y_groups = (p_screen_size.height - 1) / 8 + 1;
- zeromem(&blur.push_constant, sizeof(BlurPushConstant));
+ { //scale color and depth to half
+ ssr_scale.push_constant.camera_z_far = p_camera.get_z_far();
+ ssr_scale.push_constant.camera_z_near = p_camera.get_z_near();
+ ssr_scale.push_constant.orthogonal = p_camera.is_orthogonal();
+ ssr_scale.push_constant.filter = false; //enabling causes arctifacts
+ ssr_scale.push_constant.screen_size[0] = p_screen_size.x;
+ ssr_scale.push_constant.screen_size[1] = p_screen_size.y;
- blur.push_constant.pixel_size[0] = p_pixel_size.x;
- blur.push_constant.pixel_size[1] = p_pixel_size.y;
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_scale.pipeline);
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_diffuse), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_pair(p_depth, p_normal), 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_output_blur), 2);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_scale_depth, p_scale_normal), 3);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssr_scale.push_constant, sizeof(ScreenSpaceReflectionScalePushConstant));
+
+ RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ }
+
+ {
+ ssr.push_constant.camera_z_far = p_camera.get_z_far();
+ ssr.push_constant.camera_z_near = p_camera.get_z_near();
+ ssr.push_constant.orthogonal = p_camera.is_orthogonal();
+ ssr.push_constant.screen_size[0] = p_screen_size.x;
+ ssr.push_constant.screen_size[1] = p_screen_size.y;
+ ssr.push_constant.curve_fade_in = p_fade_in;
+ ssr.push_constant.distance_fade = p_fade_out;
+ ssr.push_constant.num_steps = p_max_steps;
+ ssr.push_constant.depth_tolerance = p_tolerance;
+ ssr.push_constant.use_half_res = true;
+ ssr.push_constant.proj_info[0] = -2.0f / (p_screen_size.width * p_camera.matrix[0][0]);
+ ssr.push_constant.proj_info[1] = -2.0f / (p_screen_size.height * p_camera.matrix[1][1]);
+ ssr.push_constant.proj_info[2] = (1.0f - p_camera.matrix[0][2]) / p_camera.matrix[0][0];
+ ssr.push_constant.proj_info[3] = (1.0f + p_camera.matrix[1][2]) / p_camera.matrix[1][1];
+ ssr.push_constant.metallic_mask[0] = CLAMP(p_metallic_mask.r * 255.0, 0, 255);
+ ssr.push_constant.metallic_mask[1] = CLAMP(p_metallic_mask.g * 255.0, 0, 255);
+ ssr.push_constant.metallic_mask[2] = CLAMP(p_metallic_mask.b * 255.0, 0, 255);
+ ssr.push_constant.metallic_mask[3] = CLAMP(p_metallic_mask.a * 255.0, 0, 255);
+ store_camera(p_camera, ssr.push_constant.projection);
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr.pipelines[(p_roughness_quality != RS::ENV_SSR_ROUGNESS_QUALITY_DISABLED) ? SCREEN_SPACE_REFLECTION_ROUGH : SCREEN_SPACE_REFLECTION_NORMAL]);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssr.push_constant, sizeof(ScreenSpaceReflectionPushConstant));
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_output_blur, p_scale_depth), 0);
+
+ if (p_roughness_quality != RS::ENV_SSR_ROUGNESS_QUALITY_DISABLED) {
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_output, p_blur_radius), 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_pair(p_metallic, p_roughness), 3);
+ } else {
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_output), 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_metallic), 3);
+ }
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_scale_normal), 2);
+
+ RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ }
+
+ if (p_roughness_quality != RS::ENV_SSR_ROUGNESS_QUALITY_DISABLED) {
+ //blurr
+
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ ssr_filter.push_constant.orthogonal = p_camera.is_orthogonal();
+ ssr_filter.push_constant.edge_tolerance = Math::sin(Math::deg2rad(15.0));
+ ssr_filter.push_constant.proj_info[0] = -2.0f / (p_screen_size.width * p_camera.matrix[0][0]);
+ ssr_filter.push_constant.proj_info[1] = -2.0f / (p_screen_size.height * p_camera.matrix[1][1]);
+ ssr_filter.push_constant.proj_info[2] = (1.0f - p_camera.matrix[0][2]) / p_camera.matrix[0][0];
+ ssr_filter.push_constant.proj_info[3] = (1.0f + p_camera.matrix[1][2]) / p_camera.matrix[1][1];
+ ssr_filter.push_constant.vertical = 0;
+ if (p_roughness_quality == RS::ENV_SSR_ROUGNESS_QUALITY_LOW) {
+ ssr_filter.push_constant.steps = p_max_steps / 3;
+ ssr_filter.push_constant.increment = 3;
+ } else if (p_roughness_quality == RS::ENV_SSR_ROUGNESS_QUALITY_MEDIUM) {
+ ssr_filter.push_constant.steps = p_max_steps / 2;
+ ssr_filter.push_constant.increment = 2;
+ } else {
+ ssr_filter.push_constant.steps = p_max_steps;
+ ssr_filter.push_constant.increment = 1;
+ }
+
+ ssr_filter.push_constant.screen_size[0] = p_screen_size.width;
+ ssr_filter.push_constant.screen_size[1] = p_screen_size.height;
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_filter.pipelines[SCREEN_SPACE_REFLECTION_FILTER_HORIZONTAL]);
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_output, p_blur_radius), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_scale_normal), 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_output_blur, p_blur_radius2), 2);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_scale_depth), 3);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssr_filter.push_constant, sizeof(ScreenSpaceReflectionFilterPushConstant));
+
+ RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_filter.pipelines[SCREEN_SPACE_REFLECTION_FILTER_VERTICAL]);
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_output_blur, p_blur_radius2), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_scale_normal), 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_output), 2);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_scale_depth), 3);
+
+ ssr_filter.push_constant.vertical = 1;
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssr_filter.push_constant, sizeof(ScreenSpaceReflectionFilterPushConstant));
+
+ RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ }
+
+ RD::get_singleton()->compute_list_end();
+}
+
+void RasterizerEffectsRD::sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_depth, const CameraMatrix &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RenderingServer::SubSurfaceScatteringQuality p_quality) {
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+
+ int32_t x_groups = (p_screen_size.width - 1) / 8 + 1;
+ int32_t y_groups = (p_screen_size.height - 1) / 8 + 1;
+
+ Plane p = p_camera.xform4(Plane(1, 0, -1, 1));
+ p.normal /= p.d;
+ float unit_size = p.normal.x;
+
+ { //scale color and depth to half
+ sss.push_constant.camera_z_far = p_camera.get_z_far();
+ sss.push_constant.camera_z_near = p_camera.get_z_near();
+ sss.push_constant.orthogonal = p_camera.is_orthogonal();
+ sss.push_constant.unit_size = unit_size;
+ sss.push_constant.screen_size[0] = p_screen_size.x;
+ sss.push_constant.screen_size[1] = p_screen_size.y;
+ sss.push_constant.vertical = false;
+ sss.push_constant.scale = p_scale;
+ sss.push_constant.depth_scale = p_depth_scale;
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sss.pipelines[p_quality - 1]);
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_diffuse), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_diffuse2), 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth), 2);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &sss.push_constant, sizeof(SubSurfaceScatteringPushConstant));
+
+ RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_diffuse2), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_diffuse), 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth), 2);
+
+ sss.push_constant.vertical = true;
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &sss.push_constant, sizeof(SubSurfaceScatteringPushConstant));
+
+ RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+
+ RD::get_singleton()->compute_list_end();
+ }
+}
+
+void RasterizerEffectsRD::merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_base, RID p_reflection) {
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, Vector<Color>());
+
+ if (p_reflection.is_valid()) {
+ if (p_base.is_valid()) {
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, specular_merge.pipelines[SPECULAR_MERGE_SSR].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_base), 2);
+ } else {
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, specular_merge.pipelines[SPECULAR_MERGE_ADDITIVE_SSR].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
+ }
+
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_specular), 0);
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_reflection), 1);
+
+ } else {
+ if (p_base.is_valid()) {
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, specular_merge.pipelines[SPECULAR_MERGE_ADD].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_base), 2);
+ } else {
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, specular_merge.pipelines[SPECULAR_MERGE_ADDITIVE_ADD].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
+ }
+
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_specular), 0);
+ }
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[BLUR_MODE_MIPMAP].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur.push_constant, sizeof(BlurPushConstant));
RD::get_singleton()->draw_list_draw(draw_list, true);
RD::get_singleton()->draw_list_end();
}
-void RasterizerEffectsRD::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, float p_z_near, float p_z_far, float p_bias, bool p_dp_flip) {
+void RasterizerEffectsRD::make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size) {
+ zeromem(&copy.push_constant, sizeof(CopyPushConstant));
+
+ copy.push_constant.section[0] = 0;
+ copy.push_constant.section[1] = 0;
+ copy.push_constant.section[2] = p_size.width;
+ copy.push_constant.section[3] = p_size.height;
+
+ int32_t x_groups = (p_size.width - 1) / 8 + 1;
+ int32_t y_groups = (p_size.height - 1) / 8 + 1;
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[COPY_MODE_MIPMAP]);
+ 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_dest_texture), 3);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
+ RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ RD::get_singleton()->compute_list_end();
+}
+void RasterizerEffectsRD::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, float p_z_near, float p_z_far, float p_bias, bool p_dp_flip) {
CopyToDPPushConstant push_constant;
+ push_constant.screen_size[0] = p_rect.size.x;
+ push_constant.screen_size[1] = p_rect.size.y;
+ push_constant.dest_offset[0] = p_rect.position.x;
+ push_constant.dest_offset[1] = p_rect.position.y;
push_constant.bias = p_bias;
push_constant.z_far = p_z_far;
push_constant.z_near = p_z_near;
push_constant.z_flip = p_dp_flip;
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, p_rect);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy.pipelines[COPY_MODE_CUBE_TO_DP].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(CopyToDPPushConstant));
- RD::get_singleton()->draw_list_draw(draw_list, true);
- RD::get_singleton()->draw_list_end();
+ int32_t x_groups = (p_rect.size.width - 1) / 8 + 1;
+ int32_t y_groups = (p_rect.size.height - 1) / 8 + 1;
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, cube_to_dp.pipeline);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_texture), 1);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(CopyToDPPushConstant));
+ RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ RD::get_singleton()->compute_list_end();
}
void RasterizerEffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer, const TonemapSettings &p_settings) {
-
zeromem(&tonemap.push_constant, sizeof(TonemapPushConstant));
tonemap.push_constant.use_bcs = p_settings.use_bcs;
@@ -309,7 +701,11 @@ void RasterizerEffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer,
tonemap.push_constant.use_color_correction = p_settings.use_color_correction;
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dst_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ tonemap.push_constant.use_fxaa = p_settings.use_fxaa;
+ tonemap.push_constant.pixel_size[0] = 1.0 / p_settings.texture_size.x;
+ tonemap.push_constant.pixel_size[1] = 1.0 / p_settings.texture_size.y;
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dst_framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD);
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, tonemap.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dst_framebuffer)));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_color), 0);
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_settings.exposure_texture), 1);
@@ -323,7 +719,6 @@ void RasterizerEffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer,
}
void RasterizerEffectsRD::luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set) {
-
luminance_reduce.push_constant.source_size[0] = p_source_size.x;
luminance_reduce.push_constant.source_size[1] = p_source_size.y;
luminance_reduce.push_constant.max_luminance = p_max_luminance;
@@ -333,12 +728,10 @@ void RasterizerEffectsRD::luminance_reduction(RID p_source_texture, const Size2i
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
for (int i = 0; i < p_reduce.size(); i++) {
-
if (i == 0) {
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, luminance_reduce.pipelines[LUMINANCE_REDUCE_READ]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_texture), 0);
} else {
-
RD::get_singleton()->compute_list_add_barrier(compute_list); //needs barrier, wait until previous is done
if (i == p_reduce.size() - 1 && !p_set) {
@@ -368,7 +761,6 @@ void RasterizerEffectsRD::luminance_reduction(RID p_source_texture, const Size2i
}
void RasterizerEffectsRD::bokeh_dof(RID p_base_texture, RID p_depth_texture, const Size2i &p_base_texture_size, RID p_secondary_texture, RID p_halfsize_texture1, RID p_halfsize_texture2, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) {
-
bokeh.push_constant.blur_far_active = p_dof_far;
bokeh.push_constant.blur_far_begin = p_dof_far_begin;
bokeh.push_constant.blur_far_end = p_dof_far_begin + p_dof_far_size;
@@ -411,7 +803,6 @@ void RasterizerEffectsRD::bokeh_dof(RID p_base_texture, RID p_depth_texture, con
RD::get_singleton()->compute_list_add_barrier(compute_list);
if (p_bokeh_shape == RS::DOF_BOKEH_BOX || p_bokeh_shape == RS::DOF_BOKEH_HEXAGON) {
-
//second pass
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.pipelines[p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL]);
@@ -447,7 +838,6 @@ void RasterizerEffectsRD::bokeh_dof(RID p_base_texture, RID p_depth_texture, con
bokeh.push_constant.second_pass = true;
if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
-
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_halfsize_texture2), 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_halfsize_texture1), 1);
} else {
@@ -531,7 +921,6 @@ void RasterizerEffectsRD::bokeh_dof(RID p_base_texture, RID p_depth_texture, con
}
void RasterizerEffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, const Size2i &p_depth_buffer_size, RID p_depth_mipmaps_texture, const Vector<RID> &depth_mipmaps, RID p_ao1, bool p_half_size, RID p_ao2, RID p_upscale_buffer, float p_intensity, float p_radius, float p_bias, const CameraMatrix &p_projection, RS::EnvironmentSSAOQuality p_quality, RS::EnvironmentSSAOBlur p_blur, float p_edge_sharpness) {
-
//minify first
ssao.minify_push_constant.orthogonal = p_projection.is_orthogonal();
ssao.minify_push_constant.z_near = p_projection.get_z_near();
@@ -547,7 +936,6 @@ void RasterizerEffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer,
// Minify the depth buffer.
for (int i = 0; i < depth_mipmaps.size(); i++) {
-
if (i == 0) {
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_MINIFY_FIRST]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_buffer), 0);
@@ -631,7 +1019,6 @@ void RasterizerEffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer,
ssao.blur_push_constant.axis[1] = 0;
if (p_blur != RS::ENV_SSAO_BLUR_DISABLED) {
-
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[p_half_size ? SSAO_BLUR_PASS_HALF : SSAO_BLUR_PASS]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao1), 0);
if (p_half_size) {
@@ -687,7 +1074,6 @@ void RasterizerEffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer,
}
void RasterizerEffectsRD::roughness_limit(RID p_source_normal, RID p_roughness, const Size2i &p_size, float p_curve) {
-
roughness_limiter.push_constant.screen_size[0] = p_size.x;
roughness_limiter.push_constant.screen_size[1] = p_size.y;
roughness_limiter.push_constant.curve = p_curve;
@@ -708,7 +1094,6 @@ void RasterizerEffectsRD::roughness_limit(RID p_source_normal, RID p_roughness,
}
void RasterizerEffectsRD::cubemap_roughness(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) {
-
zeromem(&roughness.push_constant, sizeof(CubemapRoughnessPushConstant));
roughness.push_constant.face_id = p_face_id > 9 ? 0 : p_face_id;
@@ -734,7 +1119,6 @@ void RasterizerEffectsRD::cubemap_roughness(RID p_source_rd_texture, RID p_dest_
}
void RasterizerEffectsRD::cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, const Size2i &p_size) {
-
cubemap_downsampler.push_constant.face_size = p_size.x;
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
@@ -753,7 +1137,6 @@ void RasterizerEffectsRD::cubemap_downsample(RID p_source_cubemap, RID p_dest_cu
}
void RasterizerEffectsRD::cubemap_filter(RID p_source_cubemap, Vector<RID> p_dest_cubemap, bool p_use_array) {
-
Vector<RD::Uniform> uniforms;
for (int i = 0; i < p_dest_cubemap.size(); i++) {
RD::Uniform u;
@@ -783,7 +1166,6 @@ void RasterizerEffectsRD::cubemap_filter(RID p_source_cubemap, Vector<RID> p_des
}
void RasterizerEffectsRD::render_sky(RD::DrawListID p_list, float p_time, RID p_fb, RID p_samplers, RID p_lights, RenderPipelineVertexFormatCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, const CameraMatrix &p_camera, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position) {
-
SkyPushConstant sky_push_constant;
zeromem(&sky_push_constant, sizeof(SkyPushConstant));
@@ -806,7 +1188,9 @@ void RasterizerEffectsRD::render_sky(RD::DrawListID p_list, float p_time, RID p_
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, p_pipeline->get_render_pipeline(RD::INVALID_ID, fb_format));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_samplers, 0);
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_uniform_set, 1);
+ if (p_uniform_set.is_valid()) { //material may not have uniform set
+ 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, p_lights, 3);
@@ -818,32 +1202,41 @@ void RasterizerEffectsRD::render_sky(RD::DrawListID p_list, float p_time, RID p_
}
RasterizerEffectsRD::RasterizerEffectsRD() {
+ { // Initialize copy
+ Vector<String> copy_modes;
+ copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n");
+ copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n#define DST_IMAGE_8BIT\n");
+ copy_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n");
+ copy_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n#define GLOW_USE_AUTO_EXPOSURE\n");
+ copy_modes.push_back("\n#define MODE_SIMPLE_COPY\n");
+ copy_modes.push_back("\n#define MODE_SIMPLE_COPY\n#define DST_IMAGE_8BIT\n");
+ copy_modes.push_back("\n#define MODE_SIMPLE_COPY_DEPTH\n");
+ copy_modes.push_back("\n#define MODE_MIPMAP\n");
+ copy_modes.push_back("\n#define MODE_LINEARIZE_DEPTH_COPY\n");
+ copy_modes.push_back("\n#define MODE_CUBEMAP_TO_PANORAMA\n");
+ copy_modes.push_back("\n#define MODE_CUBEMAP_ARRAY_TO_PANORAMA\n");
+ copy.shader.initialize(copy_modes);
+ zeromem(&copy.push_constant, sizeof(CopyPushConstant));
+ copy.shader_version = copy.shader.version_create();
+
+ for (int i = 0; i < COPY_MODE_MAX; i++) {
+ copy.pipelines[i] = RD::get_singleton()->compute_pipeline_create(copy.shader.version_get_shader(copy.shader_version, i));
+ }
+ }
{
- // Initialize blur
- Vector<String> blur_modes;
- blur_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n");
- blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n");
- blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n#define GLOW_USE_AUTO_EXPOSURE\n");
- blur_modes.push_back("\n#define MODE_DOF_NEAR_BLUR\n#define DOF_QUALITY_LOW\n");
- blur_modes.push_back("\n#define MODE_DOF_NEAR_BLUR\n#define DOF_QUALITY_MEDIUM\n");
- blur_modes.push_back("\n#define MODE_DOF_NEAR_BLUR\n#define DOF_QUALITY_HIGH\n");
- blur_modes.push_back("\n#define MODE_DOF_NEAR_BLUR\n#define DOF_QUALITY_LOW\n#define DOF_NEAR_BLUR_MERGE\n");
- blur_modes.push_back("\n#define MODE_DOF_NEAR_BLUR\n#define DOF_QUALITY_MEDIUM\n#define DOF_NEAR_BLUR_MERGE\n");
- blur_modes.push_back("\n#define MODE_DOF_NEAR_BLUR\n#define DOF_QUALITY_HIGH\n#define DOF_NEAR_BLUR_MERGE\n");
- blur_modes.push_back("\n#define MODE_DOF_FAR_BLUR\n#define DOF_QUALITY_LOW\n");
- blur_modes.push_back("\n#define MODE_DOF_FAR_BLUR\n#define DOF_QUALITY_MEDIUM\n");
- blur_modes.push_back("\n#define MODE_DOF_FAR_BLUR\n#define DOF_QUALITY_HIGH\n");
- blur_modes.push_back("\n#define MODE_SSAO_MERGE\n");
- blur_modes.push_back("\n#define MODE_SIMPLE_COPY\n");
- blur_modes.push_back("\n#define MODE_MIPMAP\n");
-
- blur.shader.initialize(blur_modes);
- zeromem(&blur.push_constant, sizeof(BlurPushConstant));
- blur.shader_version = blur.shader.version_create();
-
- for (int i = 0; i < BLUR_MODE_MAX; i++) {
- blur.pipelines[i].setup(blur.shader.version_get_shader(blur.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
+ Vector<String> copy_modes;
+ copy_modes.push_back("\n");
+ copy_modes.push_back("\n#define MODE_PANORAMA_TO_DP\n");
+
+ copy_to_fb.shader.initialize(copy_modes);
+
+ copy_to_fb.shader_version = copy_to_fb.shader.version_create();
+
+ //use additive
+
+ for (int i = 0; i < COPY_TO_FB_MAX; i++) {
+ copy_to_fb.pipelines[i].setup(copy_to_fb.shader.version_get_shader(copy_to_fb.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
}
}
@@ -892,15 +1285,13 @@ RasterizerEffectsRD::RasterizerEffectsRD() {
{
// Initialize copier
Vector<String> copy_modes;
- copy_modes.push_back("\n#define MODE_CUBE_TO_DP\n");
+ copy_modes.push_back("\n");
- copy.shader.initialize(copy_modes);
+ cube_to_dp.shader.initialize(copy_modes);
- copy.shader_version = copy.shader.version_create();
+ cube_to_dp.shader_version = cube_to_dp.shader.version_create();
- for (int i = 0; i < COPY_MODE_MAX; i++) {
- copy.pipelines[i].setup(copy.shader.version_get_shader(copy.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
- }
+ cube_to_dp.pipeline = RD::get_singleton()->compute_pipeline_create(cube_to_dp.shader.version_get_shader(cube_to_dp.shader_version, 0));
}
{
@@ -970,6 +1361,7 @@ RasterizerEffectsRD::RasterizerEffectsRD() {
for (int i = SSAO_BLUR_PASS; i <= SSAO_BLUR_UPSCALE; i++) {
ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.blur_shader.version_get_shader(ssao.blur_shader_version, i - SSAO_BLUR_PASS));
+
pipeline++;
}
}
@@ -1035,6 +1427,96 @@ RasterizerEffectsRD::RasterizerEffectsRD() {
filter.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, filter.shader.version_get_shader(filter.shader_version, filter.use_high_quality ? 0 : 1), 1);
}
+ {
+ Vector<String> specular_modes;
+ specular_modes.push_back("\n#define MODE_MERGE\n");
+ specular_modes.push_back("\n#define MODE_MERGE\n#define MODE_SSR\n");
+ specular_modes.push_back("\n");
+ specular_modes.push_back("\n#define MODE_SSR\n");
+
+ specular_merge.shader.initialize(specular_modes);
+
+ specular_merge.shader_version = specular_merge.shader.version_create();
+
+ //use additive
+
+ RD::PipelineColorBlendState::Attachment ba;
+ ba.enable_blend = true;
+ ba.src_color_blend_factor = RD::BLEND_FACTOR_ONE;
+ ba.dst_color_blend_factor = RD::BLEND_FACTOR_ONE;
+ ba.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
+ ba.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
+ ba.color_blend_op = RD::BLEND_OP_ADD;
+ ba.alpha_blend_op = RD::BLEND_OP_ADD;
+
+ RD::PipelineColorBlendState blend_additive;
+ blend_additive.attachments.push_back(ba);
+
+ for (int i = 0; i < SPECULAR_MERGE_MAX; i++) {
+ RD::PipelineColorBlendState blend_state;
+ if (i == SPECULAR_MERGE_ADDITIVE_ADD || i == SPECULAR_MERGE_ADDITIVE_SSR) {
+ blend_state = blend_additive;
+ } else {
+ blend_state = RD::PipelineColorBlendState::create_disabled();
+ }
+ specular_merge.pipelines[i].setup(specular_merge.shader.version_get_shader(specular_merge.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0);
+ }
+ }
+
+ {
+ Vector<String> ssr_modes;
+ ssr_modes.push_back("\n");
+ ssr_modes.push_back("\n#define MODE_ROUGH\n");
+
+ ssr.shader.initialize(ssr_modes);
+
+ ssr.shader_version = ssr.shader.version_create();
+
+ for (int i = 0; i < SCREEN_SPACE_REFLECTION_MAX; i++) {
+ ssr.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssr.shader.version_get_shader(ssr.shader_version, i));
+ }
+ }
+
+ {
+ Vector<String> ssr_filter_modes;
+ ssr_filter_modes.push_back("\n");
+ ssr_filter_modes.push_back("\n#define VERTICAL_PASS\n");
+
+ ssr_filter.shader.initialize(ssr_filter_modes);
+
+ ssr_filter.shader_version = ssr_filter.shader.version_create();
+
+ for (int i = 0; i < SCREEN_SPACE_REFLECTION_FILTER_MAX; i++) {
+ ssr_filter.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssr_filter.shader.version_get_shader(ssr_filter.shader_version, i));
+ }
+ }
+
+ {
+ Vector<String> ssr_scale_modes;
+ ssr_scale_modes.push_back("\n");
+
+ ssr_scale.shader.initialize(ssr_scale_modes);
+
+ ssr_scale.shader_version = ssr_scale.shader.version_create();
+
+ ssr_scale.pipeline = RD::get_singleton()->compute_pipeline_create(ssr_scale.shader.version_get_shader(ssr_scale.shader_version, 0));
+ }
+
+ {
+ Vector<String> sss_modes;
+ sss_modes.push_back("\n#define USE_11_SAMPLES\n");
+ sss_modes.push_back("\n#define USE_17_SAMPLES\n");
+ sss_modes.push_back("\n#define USE_25_SAMPLES\n");
+
+ sss.shader.initialize(sss_modes);
+
+ sss.shader_version = sss.shader.version_create();
+
+ for (int i = 0; i < sss_modes.size(); i++) {
+ sss.pipelines[i] = RD::get_singleton()->compute_pipeline_create(sss.shader.version_get_shader(sss.shader_version, i));
+ }
+ }
+
RD::SamplerState sampler;
sampler.mag_filter = RD::SAMPLER_FILTER_LINEAR;
sampler.min_filter = RD::SAMPLER_FILTER_LINEAR;
@@ -1079,16 +1561,23 @@ RasterizerEffectsRD::~RasterizerEffectsRD() {
RD::get_singleton()->free(default_mipmap_sampler);
RD::get_singleton()->free(index_buffer); //array gets freed as dependency
RD::get_singleton()->free(filter.coefficient_buffer);
- blur.shader.version_free(blur.shader_version);
- roughness.shader.version_free(roughness.shader_version);
- tonemap.shader.version_free(tonemap.shader_version);
- luminance_reduce.shader.version_free(luminance_reduce.shader_version);
- copy.shader.version_free(copy.shader_version);
+
bokeh.shader.version_free(bokeh.shader_version);
- ssao.minify_shader.version_free(ssao.minify_shader_version);
- ssao.gather_shader.version_free(ssao.gather_shader_version);
- ssao.blur_shader.version_free(ssao.blur_shader_version);
- roughness_limiter.shader.version_free(roughness_limiter.shader_version);
+ copy.shader.version_free(copy.shader_version);
+ copy_to_fb.shader.version_free(copy_to_fb.shader_version);
+ cube_to_dp.shader.version_free(cube_to_dp.shader_version);
cubemap_downsampler.shader.version_free(cubemap_downsampler.shader_version);
filter.shader.version_free(filter.shader_version);
+ luminance_reduce.shader.version_free(luminance_reduce.shader_version);
+ roughness.shader.version_free(roughness.shader_version);
+ roughness_limiter.shader.version_free(roughness_limiter.shader_version);
+ specular_merge.shader.version_free(specular_merge.shader_version);
+ ssao.blur_shader.version_free(ssao.blur_shader_version);
+ ssao.gather_shader.version_free(ssao.gather_shader_version);
+ ssao.minify_shader.version_free(ssao.minify_shader_version);
+ ssr.shader.version_free(ssr.shader_version);
+ ssr_filter.shader.version_free(ssr_filter.shader_version);
+ ssr_scale.shader.version_free(ssr_scale.shader_version);
+ sss.shader.version_free(sss.shader_version);
+ tonemap.shader.version_free(tonemap.shader_version);
}
diff --git a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h
index 69da5dc6d4..8a55d2d13c 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h
+++ b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h
@@ -33,87 +33,109 @@
#include "core/math/camera_matrix.h"
#include "servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h"
-#include "servers/rendering/rasterizer_rd/shaders/blur.glsl.gen.h"
#include "servers/rendering/rasterizer_rd/shaders/bokeh_dof.glsl.gen.h"
#include "servers/rendering/rasterizer_rd/shaders/copy.glsl.gen.h"
+#include "servers/rendering/rasterizer_rd/shaders/copy_to_fb.glsl.gen.h"
+#include "servers/rendering/rasterizer_rd/shaders/cube_to_dp.glsl.gen.h"
#include "servers/rendering/rasterizer_rd/shaders/cubemap_downsampler.glsl.gen.h"
#include "servers/rendering/rasterizer_rd/shaders/cubemap_filter.glsl.gen.h"
#include "servers/rendering/rasterizer_rd/shaders/cubemap_roughness.glsl.gen.h"
#include "servers/rendering/rasterizer_rd/shaders/luminance_reduce.glsl.gen.h"
#include "servers/rendering/rasterizer_rd/shaders/roughness_limiter.glsl.gen.h"
+#include "servers/rendering/rasterizer_rd/shaders/screen_space_reflection.glsl.gen.h"
+#include "servers/rendering/rasterizer_rd/shaders/screen_space_reflection_filter.glsl.gen.h"
+#include "servers/rendering/rasterizer_rd/shaders/screen_space_reflection_scale.glsl.gen.h"
+#include "servers/rendering/rasterizer_rd/shaders/specular_merge.glsl.gen.h"
#include "servers/rendering/rasterizer_rd/shaders/ssao.glsl.gen.h"
#include "servers/rendering/rasterizer_rd/shaders/ssao_blur.glsl.gen.h"
#include "servers/rendering/rasterizer_rd/shaders/ssao_minify.glsl.gen.h"
+#include "servers/rendering/rasterizer_rd/shaders/subsurface_scattering.glsl.gen.h"
#include "servers/rendering/rasterizer_rd/shaders/tonemap.glsl.gen.h"
#include "servers/rendering_server.h"
class RasterizerEffectsRD {
-
- enum BlurMode {
- BLUR_MODE_GAUSSIAN_BLUR,
- BLUR_MODE_GAUSSIAN_GLOW,
- BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE,
- BLUR_MODE_DOF_NEAR_LOW,
- BLUR_MODE_DOF_NEAR_MEDIUM,
- BLUR_MODE_DOF_NEAR_HIGH,
- BLUR_MODE_DOF_NEAR_MERGE_LOW,
- BLUR_MODE_DOF_NEAR_MERGE_MEDIUM,
- BLUR_MODE_DOF_NEAR_MERGE_HIGH,
- BLUR_MODE_DOF_FAR_LOW,
- BLUR_MODE_DOF_FAR_MEDIUM,
- BLUR_MODE_DOF_FAR_HIGH,
- BLUR_MODE_SSAO_MERGE,
- BLUR_MODE_SIMPLY_COPY,
- BLUR_MODE_MIPMAP,
- BLUR_MODE_MAX,
+ enum CopyMode {
+ COPY_MODE_GAUSSIAN_COPY,
+ COPY_MODE_GAUSSIAN_COPY_8BIT,
+ COPY_MODE_GAUSSIAN_GLOW,
+ COPY_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE,
+ COPY_MODE_SIMPLY_COPY,
+ COPY_MODE_SIMPLY_COPY_8BIT,
+ COPY_MODE_SIMPLY_COPY_DEPTH,
+ COPY_MODE_MIPMAP,
+ COPY_MODE_LINEARIZE_DEPTH,
+ COPY_MODE_CUBE_TO_PANORAMA,
+ COPY_MODE_CUBE_ARRAY_TO_PANORAMA,
+ COPY_MODE_MAX,
};
enum {
- BLUR_FLAG_HORIZONTAL = (1 << 0),
- BLUR_FLAG_USE_BLUR_SECTION = (1 << 1),
- BLUR_FLAG_USE_ORTHOGONAL_PROJECTION = (1 << 2),
- BLUR_FLAG_DOF_NEAR_FIRST_TAP = (1 << 3),
- BLUR_FLAG_GLOW_FIRST_PASS = (1 << 4),
- BLUR_FLAG_FLIP_Y = (1 << 5),
- BLUR_COPY_FORCE_LUMINANCE = (1 << 6)
+ COPY_FLAG_HORIZONTAL = (1 << 0),
+ COPY_FLAG_USE_COPY_SECTION = (1 << 1),
+ COPY_FLAG_USE_ORTHOGONAL_PROJECTION = (1 << 2),
+ COPY_FLAG_DOF_NEAR_FIRST_TAP = (1 << 3),
+ COPY_FLAG_GLOW_FIRST_PASS = (1 << 4),
+ COPY_FLAG_FLIP_Y = (1 << 5),
+ COPY_FLAG_FORCE_LUMINANCE = (1 << 6),
+ COPY_FLAG_ALL_SOURCE = (1 << 7)
};
- struct BlurPushConstant {
- float section[4];
- float pixel_size[2];
+ struct CopyPushConstant {
+ int32_t section[4];
+ int32_t target[2];
uint32_t flags;
uint32_t pad;
- //glow
+ // Glow.
float glow_strength;
float glow_bloom;
float glow_hdr_threshold;
float glow_hdr_scale;
+
float glow_exposure;
float glow_white;
float glow_luminance_cap;
float glow_auto_exposure_grey;
- //dof
- float dof_begin;
- float dof_end;
- float dof_radius;
- float dof_pad;
-
- float dof_dir[2];
+ // DOF.
float camera_z_far;
float camera_z_near;
+ uint32_t pad2[2];
+ };
+
+ struct Copy {
+ CopyPushConstant push_constant;
+ CopyShaderRD shader;
+ RID shader_version;
+ RID pipelines[COPY_MODE_MAX];
+
+ } copy;
- float ssao_color[4];
+ enum CopyToFBMode {
+ COPY_TO_FB_COPY,
+ COPY_TO_FB_COPY_PANORAMA_TO_DP,
+ COPY_TO_FB_MAX,
+
+ };
+
+ struct CopyToFbPushConstant {
+ float section[4];
+ float pixel_size[2];
+ uint32_t flip_y;
+ uint32_t use_section;
+
+ uint32_t force_luminance;
+ uint32_t alpha_to_zero;
+ uint32_t pad[2];
};
- struct Blur {
- BlurPushConstant push_constant;
- BlurShaderRD shader;
+ struct CopyToFb {
+ CopyToFbPushConstant push_constant;
+ CopyToFbShaderRD shader;
RID shader_version;
- RenderPipelineVertexFormatCacheRD pipelines[BLUR_MODE_MAX];
+ RenderPipelineVertexFormatCacheRD pipelines[COPY_TO_FB_MAX];
- } blur;
+ } copy_to_fb;
struct CubemapRoughnessPushConstant {
uint32_t face_id;
@@ -125,7 +147,6 @@ class RasterizerEffectsRD {
};
struct CubemapRoughness {
-
CubemapRoughnessPushConstant push_constant;
CubemapRoughnessShaderRD shader;
RID shader_version;
@@ -156,10 +177,17 @@ class RasterizerEffectsRD {
float exposure;
float white;
float auto_exposure_grey;
+
+ float pixel_size[2];
+ uint32_t use_fxaa;
+ uint32_t pad;
};
+ /* tonemap actually writes to a framebuffer, which is
+ * better to do using the raster pipeline rather than
+ * comptute, as that framebuffer might be in different formats
+ */
struct Tonemap {
-
TonemapPushConstant push_constant;
TonemapShaderRD shader;
RID shader_version;
@@ -182,7 +210,6 @@ class RasterizerEffectsRD {
};
struct LuminanceReduce {
-
LuminanceReducePushConstant push_constant;
LuminanceReduceShaderRD shader;
RID shader_version;
@@ -190,23 +217,19 @@ class RasterizerEffectsRD {
} luminance_reduce;
struct CopyToDPPushConstant {
+ int32_t screen_size[2];
+ int32_t dest_offset[2];
float bias;
float z_far;
float z_near;
uint32_t z_flip;
};
- enum CopyMode {
- COPY_MODE_CUBE_TO_DP,
- COPY_MODE_MAX
- };
-
- struct Copy {
-
- CopyShaderRD shader;
+ struct CoptToDP {
+ CubeToDpShaderRD shader;
RID shader_version;
- RenderPipelineVertexFormatCacheRD pipelines[COPY_MODE_MAX];
- } copy;
+ RID pipeline;
+ } cube_to_dp;
struct BokehPushConstant {
uint32_t size[2];
@@ -243,7 +266,6 @@ class RasterizerEffectsRD {
};
struct Bokeh {
-
BokehPushConstant push_constant;
BokehDofShaderRD shader;
RID shader_version;
@@ -304,7 +326,6 @@ class RasterizerEffectsRD {
};
struct SSAO {
-
SSAOMinifyPushConstant minify_push_constant;
SsaoMinifyShaderRD minify_shader;
RID minify_shader_version;
@@ -327,7 +348,6 @@ class RasterizerEffectsRD {
};
struct RoughnessLimiter {
-
RoughnessLimiterPushConstant push_constant;
RoughnessLimiterShaderRD shader;
RID shader_version;
@@ -341,7 +361,6 @@ class RasterizerEffectsRD {
};
struct CubemapDownsampler {
-
CubemapDownsamplerPushConstant push_constant;
CubemapDownsamplerShaderRD shader;
RID shader_version;
@@ -358,7 +377,6 @@ class RasterizerEffectsRD {
};
struct CubemapFilter {
-
CubemapFilterShaderRD shader;
RID shader_version;
RID pipelines[FILTER_MODE_MAX];
@@ -378,6 +396,122 @@ class RasterizerEffectsRD {
float pad[3];
};
+ enum SpecularMergeMode {
+ SPECULAR_MERGE_ADD,
+ SPECULAR_MERGE_SSR,
+ SPECULAR_MERGE_ADDITIVE_ADD,
+ SPECULAR_MERGE_ADDITIVE_SSR,
+ SPECULAR_MERGE_MAX
+ };
+
+ /* Specular merge must be done using raster, rather than compute
+ * because it must continue the existing color buffer
+ */
+
+ struct SpecularMerge {
+ SpecularMergeShaderRD shader;
+ RID shader_version;
+ RenderPipelineVertexFormatCacheRD pipelines[SPECULAR_MERGE_MAX];
+
+ } specular_merge;
+
+ enum ScreenSpaceReflectionMode {
+ SCREEN_SPACE_REFLECTION_NORMAL,
+ SCREEN_SPACE_REFLECTION_ROUGH,
+ SCREEN_SPACE_REFLECTION_MAX,
+ };
+
+ struct ScreenSpaceReflectionPushConstant {
+ float proj_info[4];
+
+ int32_t screen_size[2];
+ float camera_z_near;
+ float camera_z_far;
+
+ int32_t num_steps;
+ float depth_tolerance;
+ float distance_fade;
+ float curve_fade_in;
+
+ uint32_t orthogonal;
+ float filter_mipmap_levels;
+ uint32_t use_half_res;
+ uint8_t metallic_mask[4];
+
+ float projection[16];
+ };
+
+ struct ScreenSpaceReflection {
+ ScreenSpaceReflectionPushConstant push_constant;
+ ScreenSpaceReflectionShaderRD shader;
+ RID shader_version;
+ RID pipelines[SCREEN_SPACE_REFLECTION_MAX];
+
+ } ssr;
+
+ struct ScreenSpaceReflectionFilterPushConstant {
+ float proj_info[4];
+
+ uint32_t orthogonal;
+ float edge_tolerance;
+ int32_t increment;
+ uint32_t pad;
+
+ int32_t screen_size[2];
+ uint32_t vertical;
+ uint32_t steps;
+ };
+ enum {
+ SCREEN_SPACE_REFLECTION_FILTER_HORIZONTAL,
+ SCREEN_SPACE_REFLECTION_FILTER_VERTICAL,
+ SCREEN_SPACE_REFLECTION_FILTER_MAX,
+ };
+
+ struct ScreenSpaceReflectionFilter {
+ ScreenSpaceReflectionFilterPushConstant push_constant;
+ ScreenSpaceReflectionFilterShaderRD shader;
+ RID shader_version;
+ RID pipelines[SCREEN_SPACE_REFLECTION_FILTER_MAX];
+ } ssr_filter;
+
+ struct ScreenSpaceReflectionScalePushConstant {
+ int32_t screen_size[2];
+ float camera_z_near;
+ float camera_z_far;
+
+ uint32_t orthogonal;
+ uint32_t filter;
+ uint32_t pad[2];
+ };
+
+ struct ScreenSpaceReflectionScale {
+ ScreenSpaceReflectionScalePushConstant push_constant;
+ ScreenSpaceReflectionScaleShaderRD shader;
+ RID shader_version;
+ RID pipeline;
+ } ssr_scale;
+
+ struct SubSurfaceScatteringPushConstant {
+ int32_t screen_size[2];
+ float camera_z_far;
+ float camera_z_near;
+
+ uint32_t vertical;
+ uint32_t orthogonal;
+ float unit_size;
+ float scale;
+
+ float depth_scale;
+ uint32_t pad[3];
+ };
+
+ struct SubSurfaceScattering {
+ SubSurfaceScatteringPushConstant push_constant;
+ SubsurfaceScatteringShaderRD shader;
+ RID shader_version;
+ RID pipelines[3]; //3 quality levels
+ } sss;
+
RID default_sampler;
RID default_mipmap_sampler;
RID index_buffer;
@@ -386,28 +520,46 @@ class RasterizerEffectsRD {
Map<RID, RID> texture_to_uniform_set_cache;
Map<RID, RID> image_to_uniform_set_cache;
+
+ struct TexturePair {
+ RID texture1;
+ RID texture2;
+ _FORCE_INLINE_ bool operator<(const TexturePair &p_pair) const {
+ if (texture1 == p_pair.texture1) {
+ return texture2 < p_pair.texture2;
+ } else {
+ return texture1 < p_pair.texture1;
+ }
+ }
+ };
+
Map<RID, RID> texture_to_compute_uniform_set_cache;
+ Map<TexturePair, RID> texture_pair_to_compute_uniform_set_cache;
+ Map<TexturePair, RID> image_pair_to_compute_uniform_set_cache;
RID _get_uniform_set_from_image(RID p_texture);
RID _get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps = false);
RID _get_compute_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps = false);
+ RID _get_compute_uniform_set_from_texture_pair(RID p_texture, RID p_texture2, bool p_use_mipmaps = false);
+ RID _get_compute_uniform_set_from_image_pair(RID p_texture, RID p_texture2);
public:
- //TODO must re-do most of the shaders in compute
-
- void region_copy(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_region);
- void copy_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, bool p_flip_y = false, bool p_force_luminance = false);
- void gaussian_blur(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, const Rect2 &p_region);
- void gaussian_glow(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_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 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);
+ 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);
+ void copy_cubemap_to_panorama(RID p_source_cube, RID p_dest_panorama, const Size2i &p_panorama_size, float p_lod, bool p_is_array);
+ void copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false);
+ void copy_depth_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, float p_z_near, float p_z_far);
+ 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 gaussian_glow(RID p_source_rd_texture, RID p_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, 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 cubemap_roughness(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);
- void make_mipmap(RID p_source_rd_texture, RID p_framebuffer_half, const Vector2 &p_pixel_size);
- void copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, float p_z_near, float p_z_far, float p_bias, bool p_dp_flip);
+ void make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size);
+ void copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, float p_z_near, float p_z_far, float p_bias, bool p_dp_flip);
void luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false);
void bokeh_dof(RID p_base_texture, RID p_depth_texture, const Size2i &p_base_texture_size, RID p_secondary_texture, RID p_bokeh_texture1, RID p_bokeh_texture2, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, RS::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal);
struct TonemapSettings {
-
bool use_glow = false;
enum GlowMode {
GLOW_MODE_ADD,
@@ -439,6 +591,9 @@ public:
bool use_color_correction = false;
RID color_correction_texture;
+
+ bool use_fxaa = false;
+ Vector2i texture_size;
};
void tonemapper(RID p_source_color, RID p_dst_framebuffer, const TonemapSettings &p_settings);
@@ -450,6 +605,10 @@ public:
void cubemap_filter(RID p_source_cubemap, Vector<RID> p_dest_cubemap, bool p_use_array);
void render_sky(RD::DrawListID p_list, float p_time, RID p_fb, RID p_samplers, RID p_lights, RenderPipelineVertexFormatCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, const CameraMatrix &p_camera, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position);
+ void screen_space_reflection(RID p_diffuse, RID p_normal, RS::EnvironmentSSRRoughnessQuality p_roughness_quality, RID p_roughness, RID p_blur_radius, RID p_blur_radius2, RID p_metallic, const Color &p_metallic_mask, RID p_depth, RID p_scale_depth, RID p_scale_normal, RID p_output, RID p_output_blur, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const CameraMatrix &p_camera);
+ void merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_base, RID p_reflection);
+ void sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_depth, const CameraMatrix &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RS::SubSurfaceScatteringQuality p_quality);
+
RasterizerEffectsRD();
~RasterizerEffectsRD();
};
diff --git a/servers/rendering/rasterizer_rd/rasterizer_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_rd.cpp
index 9c54f0caae..18cf4fa340 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_rd.cpp
+++ b/servers/rendering/rasterizer_rd/rasterizer_rd.cpp
@@ -30,12 +30,13 @@
#include "rasterizer_rd.h"
+#include "core/project_settings.h"
+
void RasterizerRD::prepare_for_blitting_render_targets() {
RD::get_singleton()->prepare_screen_for_drawing();
}
void RasterizerRD::blit_render_targets_to_screen(DisplayServer::WindowID p_screen, const BlitToScreen *p_render_targets, int p_amount) {
-
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin_for_screen(p_screen);
for (int i = 0; i < p_amount; i++) {
@@ -77,13 +78,17 @@ void RasterizerRD::blit_render_targets_to_screen(DisplayServer::WindowID p_scree
void RasterizerRD::begin_frame(double frame_step) {
frame++;
+ delta = frame_step;
time += frame_step;
+
+ double time_roll_over = GLOBAL_GET("rendering/limits/time/time_rollover_secs");
+ time = Math::fmod(time, time_roll_over);
+
canvas->set_time(time);
scene->set_time(time, frame_step);
}
void RasterizerRD::end_frame(bool p_swap_buffers) {
-
#ifndef _MSC_VER
#warning TODO: likely passa bool to swap buffers to avoid display?
#endif
@@ -91,7 +96,6 @@ void RasterizerRD::end_frame(bool p_swap_buffers) {
}
void RasterizerRD::initialize() {
-
{ //create framebuffer copy shader
RenderingDevice::ShaderStageData vert;
vert.shader_stage = RenderingDevice::SHADER_STAGE_VERTEX;
@@ -151,10 +155,9 @@ void RasterizerRD::initialize() {
}
ThreadWorkPool RasterizerRD::thread_work_pool;
-uint32_t RasterizerRD::frame = 1;
+uint64_t RasterizerRD::frame = 1;
void RasterizerRD::finalize() {
-
thread_work_pool.finish();
memdelete(scene);
@@ -167,7 +170,10 @@ void RasterizerRD::finalize() {
RD::get_singleton()->free(copy_viewports_sampler);
}
+RasterizerRD *RasterizerRD::singleton = nullptr;
+
RasterizerRD::RasterizerRD() {
+ singleton = this;
thread_work_pool.init();
time = 0;
diff --git a/servers/rendering/rasterizer_rd/rasterizer_rd.h b/servers/rendering/rasterizer_rd/rasterizer_rd.h
index 756b9499ca..cb53a531ac 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_rd.h
+++ b/servers/rendering/rasterizer_rd/rasterizer_rd.h
@@ -53,8 +53,9 @@ protected:
Map<RID, RID> render_target_descriptors;
double time;
+ float delta;
- static uint32_t frame;
+ static uint64_t frame;
public:
RasterizerStorage *get_storage() { return storage; }
@@ -71,7 +72,8 @@ public:
void end_frame(bool p_swap_buffers);
void finalize();
- static _ALWAYS_INLINE_ uint64_t get_frame_number() { return frame; }
+ _ALWAYS_INLINE_ uint64_t get_frame_number() const { return frame; }
+ _ALWAYS_INLINE_ float get_frame_delta_time() const { return delta; }
static Error is_viable() {
return OK;
@@ -89,6 +91,7 @@ public:
static ThreadWorkPool thread_work_pool;
+ static RasterizerRD *singleton;
RasterizerRD();
~RasterizerRD() {}
};
diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp
index bf3cd045f1..7d351f249a 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp
+++ b/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp
@@ -52,31 +52,50 @@ static _FORCE_INLINE_ void store_transform(const Transform &p_mtx, float *p_arra
p_array[15] = 1;
}
-static _FORCE_INLINE_ void store_transform_3x3(const Transform &p_mtx, float *p_array) {
- p_array[0] = p_mtx.basis.elements[0][0];
- p_array[1] = p_mtx.basis.elements[1][0];
- p_array[2] = p_mtx.basis.elements[2][0];
+static _FORCE_INLINE_ void store_basis_3x4(const Basis &p_mtx, float *p_array) {
+ p_array[0] = p_mtx.elements[0][0];
+ p_array[1] = p_mtx.elements[1][0];
+ p_array[2] = p_mtx.elements[2][0];
p_array[3] = 0;
- p_array[4] = p_mtx.basis.elements[0][1];
- p_array[5] = p_mtx.basis.elements[1][1];
- p_array[6] = p_mtx.basis.elements[2][1];
+ p_array[4] = p_mtx.elements[0][1];
+ p_array[5] = p_mtx.elements[1][1];
+ p_array[6] = p_mtx.elements[2][1];
p_array[7] = 0;
- p_array[8] = p_mtx.basis.elements[0][2];
- p_array[9] = p_mtx.basis.elements[1][2];
- p_array[10] = p_mtx.basis.elements[2][2];
+ p_array[8] = p_mtx.elements[0][2];
+ p_array[9] = p_mtx.elements[1][2];
+ p_array[10] = p_mtx.elements[2][2];
p_array[11] = 0;
}
-static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_array) {
+static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_mtx, float *p_array) {
+ p_array[0] = p_mtx.elements[0][0];
+ p_array[1] = p_mtx.elements[1][0];
+ p_array[2] = p_mtx.elements[2][0];
+ p_array[3] = 0;
+ p_array[4] = p_mtx.elements[0][1];
+ p_array[5] = p_mtx.elements[1][1];
+ p_array[6] = p_mtx.elements[2][1];
+ p_array[7] = 0;
+ p_array[8] = p_mtx.elements[0][2];
+ p_array[9] = p_mtx.elements[1][2];
+ p_array[10] = p_mtx.elements[2][2];
+ p_array[11] = 0;
+}
+static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_array) {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
-
p_array[i * 4 + j] = p_mtx.matrix[i][j];
}
}
}
+static _FORCE_INLINE_ void store_soft_shadow_kernel(const float *p_kernel, float *p_array) {
+ for (int i = 0; i < 128; i++) {
+ p_array[i] = p_kernel[i];
+ }
+}
+
/* SCENE SHADER */
void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) {
//compile
@@ -109,6 +128,7 @@ void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) {
unshaded = false;
uses_vertex = false;
uses_sss = false;
+ uses_transmittance = false;
uses_screen_texture = false;
uses_depth_texture = false;
uses_normal_texture = false;
@@ -142,6 +162,7 @@ void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) {
actions.render_mode_flags["depth_prepass_alpha"] = &uses_depth_pre_pass;
actions.usage_flag_pointers["SSS_STRENGTH"] = &uses_sss;
+ actions.usage_flag_pointers["SSS_TRANSMITTANCE_DEPTH"] = &uses_transmittance;
actions.usage_flag_pointers["SCREEN_TEXTURE"] = &uses_screen_texture;
actions.usage_flag_pointers["DEPTH_TEXTURE"] = &uses_depth_texture;
@@ -200,7 +221,6 @@ void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) {
switch (blend_mode) {
case BLEND_MODE_MIX: {
-
blend_attachment.enable_blend = true;
blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD;
blend_attachment.color_blend_op = RD::BLEND_OP_ADD;
@@ -211,7 +231,6 @@ void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) {
} break;
case BLEND_MODE_ADD: {
-
blend_attachment.enable_blend = true;
blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD;
blend_attachment.color_blend_op = RD::BLEND_OP_ADD;
@@ -223,7 +242,6 @@ void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) {
} break;
case BLEND_MODE_SUB: {
-
blend_attachment.enable_blend = true;
blend_attachment.alpha_blend_op = RD::BLEND_OP_SUBTRACT;
blend_attachment.color_blend_op = RD::BLEND_OP_SUBTRACT;
@@ -264,7 +282,6 @@ void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) {
}
for (int i = 0; i < CULL_VARIANT_MAX; i++) {
-
RD::PolygonCullMode cull_mode_rd_table[CULL_VARIANT_MAX][3] = {
{ RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_FRONT, RD::POLYGON_CULL_BACK },
{ RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_BACK, RD::POLYGON_CULL_FRONT },
@@ -274,7 +291,6 @@ void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) {
RD::PolygonCullMode cull_mode_rd = cull_mode_rd_table[i][cull];
for (int j = 0; j < RS::PRIMITIVE_MAX; j++) {
-
RD::RenderPrimitive primitive_rd_table[RS::PRIMITIVE_MAX] = {
RD::RENDER_PRIMITIVE_POINTS,
RD::RENDER_PRIMITIVE_LINES,
@@ -286,7 +302,6 @@ void RasterizerSceneHighEndRD::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++) {
-
RD::PipelineRasterizationState raster_state;
raster_state.cull_mode = cull_mode_rd;
raster_state.wireframe = wireframe;
@@ -313,7 +328,6 @@ void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) {
continue; // do not use this version (will error if using it is attempted)
}
} else {
-
if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_VCT_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) {
@@ -321,7 +335,7 @@ void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) {
} else if (k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL) {
blend_state = blend_state_depth_normal;
} else if (k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS) {
- blend_state = blend_state_depth_normal;
+ blend_state = blend_state_depth_normal_roughness;
} else if (k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL) {
blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way
@@ -349,10 +363,12 @@ void RasterizerSceneHighEndRD::ShaderData::set_default_texture_param(const Strin
}
void RasterizerSceneHighEndRD::ShaderData::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_LOCAL) {
+ continue;
+ }
if (E->get().texture_order >= 0) {
order[E->get().texture_order + 100000] = E->key();
@@ -362,13 +378,27 @@ void RasterizerSceneHighEndRD::ShaderData::get_param_list(List<PropertyInfo> *p_
}
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 RasterizerSceneHighEndRD::ShaderData::get_instance_param_list(List<RasterizerStorage::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;
+ }
+
+ RasterizerStorage::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().hint);
+ p_param_list->push_back(p);
+ }
+}
+
bool RasterizerSceneHighEndRD::ShaderData::is_param_texture(const StringName &p_param) const {
if (!uniforms.has(p_param)) {
return false;
@@ -384,6 +414,7 @@ bool RasterizerSceneHighEndRD::ShaderData::is_animated() const {
bool RasterizerSceneHighEndRD::ShaderData::casts_shadows() const {
return false;
}
+
Variant RasterizerSceneHighEndRD::ShaderData::get_default_parameter(const StringName &p_parameter) const {
if (uniforms.has(p_parameter)) {
ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter];
@@ -421,7 +452,6 @@ void RasterizerSceneHighEndRD::MaterialData::set_next_pass(RID p_pass) {
}
void RasterizerSceneHighEndRD::MaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
-
RasterizerSceneHighEndRD *scene_singleton = (RasterizerSceneHighEndRD *)RasterizerSceneHighEndRD::singleton;
if ((uint32_t)ubo_data.size() != shader_data->ubo_size) {
@@ -446,7 +476,6 @@ void RasterizerSceneHighEndRD::MaterialData::update_parameters(const Map<StringN
//check whether buffer changed
if (p_uniform_dirty && ubo_data.size()) {
-
update_uniform_buffer(shader_data->uniforms, shader_data->ubo_offsets.ptr(), p_parameters, ubo_data.ptrw(), ubo_data.size(), false);
RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw());
}
@@ -465,7 +494,6 @@ void RasterizerSceneHighEndRD::MaterialData::update_parameters(const Map<StringN
}
if (p_textures_dirty && tex_uniform_count) {
-
update_textures(p_parameters, shader_data->default_texture_params, shader_data->texture_uniforms, texture_cache.ptrw(), true);
}
@@ -482,7 +510,6 @@ void RasterizerSceneHighEndRD::MaterialData::update_parameters(const Map<StringN
Vector<RD::Uniform> uniforms;
{
-
if (shader_data->ubo_size) {
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
@@ -527,43 +554,102 @@ RasterizerSceneHighEndRD::RenderBufferDataHighEnd::~RenderBufferDataHighEnd() {
}
void RasterizerSceneHighEndRD::RenderBufferDataHighEnd::ensure_specular() {
-
if (!specular.is_valid()) {
RD::TextureFormat tf;
tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
tf.width = width;
tf.height = height;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ if (msaa != RS::VIEWPORT_MSAA_DISABLED) {
+ tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
+ } else {
+ tf.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+ }
specular = RD::get_singleton()->texture_create(tf, RD::TextureView());
- Vector<RID> fb;
- fb.push_back(color);
- fb.push_back(specular);
- fb.push_back(depth);
+ if (msaa == RS::VIEWPORT_MSAA_DISABLED) {
+ {
+ Vector<RID> fb;
+ fb.push_back(color);
+ fb.push_back(specular);
+ fb.push_back(depth);
+
+ color_specular_fb = RD::get_singleton()->framebuffer_create(fb);
+ }
+ {
+ Vector<RID> fb;
+ fb.push_back(specular);
+
+ specular_only_fb = RD::get_singleton()->framebuffer_create(fb);
+ }
+
+ } else {
+ tf.samples = texture_samples;
+ tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
+ specular_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView());
+
+ {
+ Vector<RID> fb;
+ fb.push_back(color_msaa);
+ fb.push_back(specular_msaa);
+ fb.push_back(depth_msaa);
+
+ color_specular_fb = RD::get_singleton()->framebuffer_create(fb);
+ }
+ {
+ Vector<RID> fb;
+ fb.push_back(specular_msaa);
- color_specular_fb = RD::get_singleton()->framebuffer_create(fb);
+ specular_only_fb = RD::get_singleton()->framebuffer_create(fb);
+ }
+ }
}
}
void RasterizerSceneHighEndRD::RenderBufferDataHighEnd::clear() {
+ if (color_msaa.is_valid()) {
+ RD::get_singleton()->free(color_msaa);
+ color_msaa = RID();
+ }
+
+ if (depth_msaa.is_valid()) {
+ RD::get_singleton()->free(depth_msaa);
+ depth_msaa = RID();
+ }
if (specular.is_valid()) {
+ if (specular_msaa.is_valid()) {
+ RD::get_singleton()->free(specular_msaa);
+ specular_msaa = RID();
+ }
RD::get_singleton()->free(specular);
specular = RID();
}
+ color = RID();
+ depth = RID();
color_specular_fb = RID();
+ specular_only_fb = RID();
color_fb = RID();
+ depth_fb = RID();
if (normal_buffer.is_valid()) {
RD::get_singleton()->free(normal_buffer);
+ if (normal_buffer_msaa.is_valid()) {
+ RD::get_singleton()->free(normal_buffer_msaa);
+ normal_buffer_msaa = RID();
+ }
normal_buffer = RID();
depth_normal_fb = RID();
}
if (roughness_buffer.is_valid()) {
RD::get_singleton()->free(roughness_buffer);
+ if (roughness_buffer_msaa.is_valid()) {
+ RD::get_singleton()->free(roughness_buffer_msaa);
+ roughness_buffer_msaa = RID();
+ }
roughness_buffer = RID();
depth_normal_roughness_fb = RID();
}
@@ -572,24 +658,67 @@ void RasterizerSceneHighEndRD::RenderBufferDataHighEnd::clear() {
void RasterizerSceneHighEndRD::RenderBufferDataHighEnd::configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa) {
clear();
+ msaa = p_msaa;
+
width = p_width;
height = p_height;
color = p_color_buffer;
depth = p_depth_buffer;
- {
- Vector<RID> fb;
- fb.push_back(p_color_buffer);
- fb.push_back(depth);
+ if (p_msaa == RS::VIEWPORT_MSAA_DISABLED) {
+ {
+ Vector<RID> fb;
+ fb.push_back(p_color_buffer);
+ fb.push_back(depth);
- color_fb = RD::get_singleton()->framebuffer_create(fb);
- }
- {
- Vector<RID> fb;
- fb.push_back(depth);
+ color_fb = RD::get_singleton()->framebuffer_create(fb);
+ }
+ {
+ Vector<RID> fb;
+ fb.push_back(depth);
+
+ depth_fb = RD::get_singleton()->framebuffer_create(fb);
+ }
+ } else {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ tf.width = p_width;
+ tf.height = p_height;
+ tf.type = RD::TEXTURE_TYPE_2D;
+ tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
+
+ RD::TextureSamples ts[RS::VIEWPORT_MSAA_MAX] = {
+ RD::TEXTURE_SAMPLES_1,
+ RD::TEXTURE_SAMPLES_2,
+ RD::TEXTURE_SAMPLES_4,
+ RD::TEXTURE_SAMPLES_8,
+ RD::TEXTURE_SAMPLES_16
+ };
+
+ texture_samples = ts[p_msaa];
+ tf.samples = texture_samples;
+
+ color_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView());
+
+ tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT;
+ tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
+
+ depth_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView());
+
+ {
+ Vector<RID> fb;
+ fb.push_back(color_msaa);
+ fb.push_back(depth_msaa);
- depth_fb = RD::get_singleton()->framebuffer_create(fb);
+ color_fb = RD::get_singleton()->framebuffer_create(fb);
+ }
+ {
+ Vector<RID> fb;
+ fb.push_back(depth_msaa);
+
+ depth_fb = RD::get_singleton()->framebuffer_create(fb);
+ }
}
}
@@ -602,19 +731,36 @@ void RasterizerSceneHighEndRD::_allocate_normal_texture(RenderBufferDataHighEnd
tf.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32;
tf.width = rb->width;
tf.height = rb->height;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT;
+
+ if (rb->msaa != RS::VIEWPORT_MSAA_DISABLED) {
+ tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
+ } else {
+ tf.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+ }
rb->normal_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
- Vector<RID> fb;
- fb.push_back(rb->depth);
- fb.push_back(rb->normal_buffer);
- rb->depth_normal_fb = RD::get_singleton()->framebuffer_create(fb);
+
+ if (rb->msaa == RS::VIEWPORT_MSAA_DISABLED) {
+ Vector<RID> fb;
+ fb.push_back(rb->depth);
+ fb.push_back(rb->normal_buffer);
+ rb->depth_normal_fb = RD::get_singleton()->framebuffer_create(fb);
+ } else {
+ tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
+ tf.samples = rb->texture_samples;
+ rb->normal_buffer_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView());
+
+ Vector<RID> fb;
+ fb.push_back(rb->depth_msaa);
+ fb.push_back(rb->normal_buffer_msaa);
+ rb->depth_normal_fb = RD::get_singleton()->framebuffer_create(fb);
+ }
_render_buffers_clear_uniform_set(rb);
}
void RasterizerSceneHighEndRD::_allocate_roughness_texture(RenderBufferDataHighEnd *rb) {
-
if (rb->roughness_buffer.is_valid()) {
return;
}
@@ -627,12 +773,31 @@ void RasterizerSceneHighEndRD::_allocate_roughness_texture(RenderBufferDataHighE
tf.height = rb->height;
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+ if (rb->msaa != RS::VIEWPORT_MSAA_DISABLED) {
+ tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
+ } else {
+ tf.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+ }
+
rb->roughness_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
- Vector<RID> fb;
- fb.push_back(rb->depth);
- fb.push_back(rb->normal_buffer);
- fb.push_back(rb->roughness_buffer);
- rb->depth_normal_roughness_fb = RD::get_singleton()->framebuffer_create(fb);
+
+ if (rb->msaa == RS::VIEWPORT_MSAA_DISABLED) {
+ Vector<RID> fb;
+ fb.push_back(rb->depth);
+ fb.push_back(rb->normal_buffer);
+ fb.push_back(rb->roughness_buffer);
+ rb->depth_normal_roughness_fb = RD::get_singleton()->framebuffer_create(fb);
+ } else {
+ tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
+ tf.samples = rb->texture_samples;
+ rb->roughness_buffer_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView());
+
+ Vector<RID> fb;
+ fb.push_back(rb->depth_msaa);
+ fb.push_back(rb->normal_buffer_msaa);
+ fb.push_back(rb->roughness_buffer_msaa);
+ rb->depth_normal_roughness_fb = RD::get_singleton()->framebuffer_create(fb);
+ }
_render_buffers_clear_uniform_set(rb);
}
@@ -649,15 +814,16 @@ bool RasterizerSceneHighEndRD::free(RID p_rid) {
}
void RasterizerSceneHighEndRD::_fill_instances(RenderList::Element **p_elements, int p_element_count, bool p_for_depth) {
+ uint32_t lightmap_captures_used = 0;
for (int i = 0; i < p_element_count; i++) {
-
const RenderList::Element *e = p_elements[i];
InstanceData &id = scene_state.instances[i];
store_transform(e->instance->transform, id.transform);
store_transform(Transform(e->instance->transform.basis.inverse().transposed()), id.normal_transform);
id.flags = 0;
id.mask = e->instance->layer_mask;
+ id.instance_uniforms_ofs = e->instance->instance_allocated_shader_parameters_offset >= 0 ? e->instance->instance_allocated_shader_parameters_offset : 0;
if (e->instance->base_type == RS::INSTANCE_MULTIMESH) {
id.flags |= INSTANCE_DATA_FLAG_MULTIMESH;
@@ -706,6 +872,7 @@ void RasterizerSceneHighEndRD::_fill_instances(RenderList::Element **p_elements,
if (written == 0) {
id.gi_offset = index;
+ id.flags |= INSTANCE_DATA_FLAG_USE_GIPROBE;
written = 1;
} else {
id.gi_offset = index << 16;
@@ -718,18 +885,51 @@ void RasterizerSceneHighEndRD::_fill_instances(RenderList::Element **p_elements,
} else if (written == 1) {
id.gi_offset |= 0xFFFF0000;
}
+ } else if (e->instance->lightmap) {
+ int32_t lightmap_index = storage->lightmap_get_array_index(e->instance->lightmap->base);
+ if (lightmap_index >= 0) {
+ id.gi_offset = lightmap_index;
+ id.gi_offset |= e->instance->lightmap_slice_index << 12;
+ id.gi_offset |= e->instance->lightmap_cull_index << 20;
+ id.lightmap_uv_scale[0] = e->instance->lightmap_uv_scale.position.x;
+ id.lightmap_uv_scale[1] = e->instance->lightmap_uv_scale.position.y;
+ id.lightmap_uv_scale[2] = e->instance->lightmap_uv_scale.size.width;
+ id.lightmap_uv_scale[3] = e->instance->lightmap_uv_scale.size.height;
+ id.flags |= INSTANCE_DATA_FLAG_USE_LIGHTMAP;
+ if (storage->lightmap_uses_spherical_harmonics(e->instance->lightmap->base)) {
+ id.flags |= INSTANCE_DATA_FLAG_USE_SH_LIGHTMAP;
+ }
+ } else {
+ id.gi_offset = 0xFFFFFFFF;
+ }
+ } else if (!e->instance->lightmap_sh.empty()) {
+ if (lightmap_captures_used < scene_state.max_lightmap_captures) {
+ const Color *src_capture = e->instance->lightmap_sh.ptr();
+ LightmapCaptureData &lcd = scene_state.lightmap_captures[lightmap_captures_used];
+ for (int j = 0; j < 9; j++) {
+ lcd.sh[j * 4 + 0] = src_capture[j].r;
+ lcd.sh[j * 4 + 1] = src_capture[j].g;
+ lcd.sh[j * 4 + 2] = src_capture[j].b;
+ lcd.sh[j * 4 + 3] = src_capture[j].a;
+ }
+ id.flags |= INSTANCE_DATA_FLAG_USE_LIGHTMAP_CAPTURE;
+ id.gi_offset = lightmap_captures_used;
+ lightmap_captures_used++;
+ }
} else {
id.gi_offset = 0xFFFFFFFF;
}
}
RD::get_singleton()->buffer_update(scene_state.instance_buffer, 0, sizeof(InstanceData) * p_element_count, scene_state.instances, true);
+ if (lightmap_captures_used) {
+ RD::get_singleton()->buffer_update(scene_state.lightmap_capture_buffer, 0, sizeof(LightmapCaptureData) * lightmap_captures_used, scene_state.lightmap_captures, true);
+ }
}
/// RENDERING ///
-void RasterizerSceneHighEndRD::_render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, RID p_radiance_uniform_set, RID p_render_buffers_uniform_set) {
-
+void RasterizerSceneHighEndRD::_render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, RID p_radiance_uniform_set, RID p_render_buffers_uniform_set, bool p_force_wireframe, const Vector2 &p_uv_offset) {
RD::DrawListID draw_list = p_draw_list;
RD::FramebufferFormatID framebuffer_format = p_framebuffer_Format;
@@ -757,9 +957,10 @@ void RasterizerSceneHighEndRD::_render_list(RenderingDevice::DrawListID p_draw_l
PushConstant push_constant;
zeromem(&push_constant, sizeof(PushConstant));
+ push_constant.bake_uv2_offset[0] = p_uv_offset.x;
+ push_constant.bake_uv2_offset[1] = p_uv_offset.y;
for (int i = 0; i < p_element_count; i++) {
-
const RenderList::Element *e = p_elements[i];
MaterialData *material = e->material;
@@ -769,7 +970,7 @@ void RasterizerSceneHighEndRD::_render_list(RenderingDevice::DrawListID p_draw_l
//find cull variant
ShaderData::CullVariant cull_variant;
- if ((p_pass_mode == PASS_MODE_SHADOW || p_pass_mode == PASS_MODE_SHADOW_DP) && e->instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED) {
+ if (p_pass_mode == PASS_MODE_DEPTH_MATERIAL || ((p_pass_mode == PASS_MODE_SHADOW || p_pass_mode == PASS_MODE_SHADOW_DP) && e->instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED)) {
cull_variant = ShaderData::CULL_VARIANT_DOUBLE_SIDED;
} else {
bool mirror = e->instance->mirror;
@@ -888,7 +1089,7 @@ void RasterizerSceneHighEndRD::_render_list(RenderingDevice::DrawListID p_draw_l
prev_index_array_rd = index_array_rd;
}
- RID pipeline_rd = pipeline->get_render_pipeline(vertex_format, framebuffer_format);
+ RID pipeline_rd = pipeline->get_render_pipeline(vertex_format, framebuffer_format, p_force_wireframe);
if (pipeline_rd != prev_pipeline_rd) {
// checking with prev shader does not make so much sense, as
@@ -923,10 +1124,8 @@ void RasterizerSceneHighEndRD::_render_list(RenderingDevice::DrawListID p_draw_l
RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid(), instances);
} break;
case RS::INSTANCE_IMMEDIATE: {
-
} break;
case RS::INSTANCE_PARTICLES: {
-
} break;
default: {
ERR_CONTINUE(true); //should be a bug
@@ -935,8 +1134,7 @@ void RasterizerSceneHighEndRD::_render_list(RenderingDevice::DrawListID p_draw_l
}
}
-void RasterizerSceneHighEndRD::_setup_environment(RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers) {
-
+void RasterizerSceneHighEndRD::_setup_environment(RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers, bool p_pancake_shadows) {
//CameraMatrix projection = p_cam_projection;
//projection.flip_y(); // Vulkan and modern APIs use Y-Down
CameraMatrix correction;
@@ -952,6 +1150,18 @@ void RasterizerSceneHighEndRD::_setup_environment(RID p_environment, const Camer
scene_state.ubo.z_far = p_zfar;
scene_state.ubo.z_near = p_znear;
+ scene_state.ubo.pancake_shadows = p_pancake_shadows;
+
+ store_soft_shadow_kernel(directional_penumbra_shadow_kernel_get(), scene_state.ubo.directional_penumbra_shadow_kernel);
+ store_soft_shadow_kernel(directional_soft_shadow_kernel_get(), scene_state.ubo.directional_soft_shadow_kernel);
+ store_soft_shadow_kernel(penumbra_shadow_kernel_get(), scene_state.ubo.penumbra_shadow_kernel);
+ store_soft_shadow_kernel(soft_shadow_kernel_get(), scene_state.ubo.soft_shadow_kernel);
+
+ scene_state.ubo.directional_penumbra_shadow_samples = directional_penumbra_shadow_samples_get();
+ scene_state.ubo.directional_soft_shadow_samples = directional_soft_shadow_samples_get();
+ scene_state.ubo.penumbra_shadow_samples = penumbra_shadow_samples_get();
+ scene_state.ubo.soft_shadow_samples = soft_shadow_samples_get();
+
scene_state.ubo.screen_pixel_size[0] = p_screen_pixel_size.x;
scene_state.ubo.screen_pixel_size[1] = p_screen_pixel_size.y;
@@ -969,7 +1179,6 @@ void RasterizerSceneHighEndRD::_setup_environment(RID p_environment, const Camer
scene_state.ubo.time = time;
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_UNSHADED) {
-
scene_state.ubo.use_ambient_light = true;
scene_state.ubo.ambient_light_color_energy[0] = 1;
scene_state.ubo.ambient_light_color_energy[1] = 1;
@@ -980,9 +1189,8 @@ void RasterizerSceneHighEndRD::_setup_environment(RID p_environment, const Camer
scene_state.ubo.ssao_enabled = false;
} else if (is_environment(p_environment)) {
-
RS::EnvironmentBG env_bg = environment_get_background(p_environment);
- RS::EnvironmentAmbientSource ambient_src = environment_get_ambient_light_ambient_source(p_environment);
+ RS::EnvironmentAmbientSource ambient_src = environment_get_ambient_source(p_environment);
float bg_energy = environment_get_bg_energy(p_environment);
scene_state.ubo.ambient_light_color_energy[3] = bg_energy;
@@ -991,7 +1199,6 @@ void RasterizerSceneHighEndRD::_setup_environment(RID p_environment, const Camer
//ambient
if (ambient_src == RS::ENV_AMBIENT_SOURCE_BG && (env_bg == RS::ENV_BG_CLEAR_COLOR || env_bg == RS::ENV_BG_COLOR)) {
-
Color color = env_bg == RS::ENV_BG_CLEAR_COLOR ? p_default_bg_color : environment_get_bg_color(p_environment);
color = color.to_linear();
@@ -1001,8 +1208,7 @@ void RasterizerSceneHighEndRD::_setup_environment(RID p_environment, const Camer
scene_state.ubo.use_ambient_light = true;
scene_state.ubo.use_ambient_cubemap = false;
} else {
-
- float energy = environment_get_ambient_light_ambient_energy(p_environment);
+ float energy = environment_get_ambient_light_energy(p_environment);
Color color = environment_get_ambient_light_color(p_environment);
color = color.to_linear();
scene_state.ubo.ambient_light_color_energy[0] = color.r * energy;
@@ -1036,7 +1242,6 @@ void RasterizerSceneHighEndRD::_setup_environment(RID p_environment, const Camer
scene_state.ubo.ao_color[3] = ao_color.a;
} else {
-
if (p_reflection_probe.is_valid() && storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_reflection_probe))) {
scene_state.ubo.use_ambient_light = false;
} else {
@@ -1051,6 +1256,7 @@ void RasterizerSceneHighEndRD::_setup_environment(RID p_environment, const Camer
scene_state.ubo.use_ambient_cubemap = false;
scene_state.ubo.use_reflection_cubemap = false;
+ scene_state.ubo.ssao_enabled = false;
}
scene_state.ubo.roughness_limiter_enabled = p_opaque_render_buffers && screen_space_roughness_limiter_is_active();
@@ -1059,7 +1265,6 @@ void RasterizerSceneHighEndRD::_setup_environment(RID p_environment, const Camer
}
void RasterizerSceneHighEndRD::_add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode, uint32_t p_geometry_index) {
-
RID m_src;
m_src = p_instance->material_override.is_valid() ? p_instance->material_override : p_material;
@@ -1067,19 +1272,17 @@ void RasterizerSceneHighEndRD::_add_geometry(InstanceBase *p_instance, uint32_t
if (unlikely(get_debug_draw_mode() != RS::VIEWPORT_DEBUG_DRAW_DISABLED)) {
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_OVERDRAW) {
m_src = overdraw_material;
- } else if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME) {
- m_src = wireframe_material;
} else if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_LIGHTING) {
m_src = default_material;
}
}
- MaterialData *material = NULL;
+ MaterialData *material = nullptr;
if (m_src.is_valid()) {
material = (MaterialData *)storage->material_get_data(m_src, RasterizerStorageRD::SHADER_TYPE_3D);
if (!material || !material->shader_data->valid) {
- material = NULL;
+ material = nullptr;
}
}
@@ -1093,16 +1296,15 @@ void RasterizerSceneHighEndRD::_add_geometry(InstanceBase *p_instance, uint32_t
_add_geometry_with_material(p_instance, p_surface, material, m_src, p_pass_mode, p_geometry_index);
while (material->next_pass.is_valid()) {
-
material = (MaterialData *)storage->material_get_data(material->next_pass, RasterizerStorageRD::SHADER_TYPE_3D);
- if (!material || !material->shader_data->valid)
+ if (!material || !material->shader_data->valid) {
break;
+ }
_add_geometry_with_material(p_instance, p_surface, material, material->next_pass, p_pass_mode, p_geometry_index);
}
}
void RasterizerSceneHighEndRD::_add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, RID p_material_rid, PassMode p_pass_mode, uint32_t p_geometry_index) {
-
bool has_read_screen_alpha = p_material->shader_data->uses_screen_texture || p_material->shader_data->uses_depth_texture || p_material->shader_data->uses_normal_texture;
bool has_base_alpha = (p_material->shader_data->uses_alpha || has_read_screen_alpha);
bool has_blend_alpha = p_material->shader_data->uses_blend_alpha;
@@ -1125,7 +1327,6 @@ void RasterizerSceneHighEndRD::_add_geometry_with_material(InstanceBase *p_insta
}
if (p_pass_mode != PASS_MODE_COLOR && p_pass_mode != PASS_MODE_COLOR_SPECULAR) {
-
if (has_blend_alpha || has_read_screen_alpha || (has_base_alpha && !p_material->shader_data->uses_depth_pre_pass) || p_material->shader_data->depth_draw == ShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == ShaderData::DEPTH_TEST_DISABLED || p_instance->cast_shadows == RS::SHADOW_CASTING_SETTING_OFF) {
//conditions in which no depth pass should be processed
return;
@@ -1147,8 +1348,9 @@ void RasterizerSceneHighEndRD::_add_geometry_with_material(InstanceBase *p_insta
RenderList::Element *e = (has_alpha || p_material->shader_data->depth_test == ShaderData::DEPTH_TEST_DISABLED) ? render_list.add_alpha_element() : render_list.add_element();
- if (!e)
+ if (!e) {
return;
+ }
e->instance = p_instance;
e->material = p_material;
@@ -1170,7 +1372,7 @@ void RasterizerSceneHighEndRD::_add_geometry_with_material(InstanceBase *p_insta
e->geometry_index = p_geometry_index;
e->material_index = e->material->index;
e->uses_instancing = e->instance->base_type == RS::INSTANCE_MULTIMESH;
- e->uses_lightmap = e->instance->lightmap.is_valid();
+ e->uses_lightmap = e->instance->lightmap != nullptr || !e->instance->lightmap_sh.empty();
e->uses_vct = e->instance->gi_probe_instances.size();
e->shader_index = e->shader_index;
e->depth_layer = e->instance->depth_layer;
@@ -1182,7 +1384,6 @@ void RasterizerSceneHighEndRD::_add_geometry_with_material(InstanceBase *p_insta
}
void RasterizerSceneHighEndRD::_fill_render_list(InstanceBase **p_cull_result, int p_cull_count, PassMode p_pass_mode, bool p_no_gi) {
-
scene_state.current_shader_index = 0;
scene_state.current_material_index = 0;
scene_state.used_sss = false;
@@ -1195,15 +1396,12 @@ void RasterizerSceneHighEndRD::_fill_render_list(InstanceBase **p_cull_result, i
//fill list
for (int i = 0; i < p_cull_count; i++) {
-
InstanceBase *inst = p_cull_result[i];
//add geometry for drawing
switch (inst->base_type) {
-
case RS::INSTANCE_MESH: {
-
- const RID *materials = NULL;
+ const RID *materials = nullptr;
uint32_t surface_count;
materials = storage->mesh_get_surface_count_and_materials(inst->base, surface_count);
@@ -1214,7 +1412,6 @@ void RasterizerSceneHighEndRD::_fill_render_list(InstanceBase **p_cull_result, i
const RID *inst_materials = inst->materials.ptr();
for (uint32_t j = 0; j < surface_count; j++) {
-
RID material = inst_materials[j].is_valid() ? inst_materials[j] : materials[j];
uint32_t surface_index = storage->mesh_surface_get_render_pass_index(inst->base, j, render_pass, &geometry_index);
@@ -1226,7 +1423,6 @@ void RasterizerSceneHighEndRD::_fill_render_list(InstanceBase **p_cull_result, i
} break;
case RS::INSTANCE_MULTIMESH: {
-
if (storage->multimesh_get_instances_to_draw(inst->base) == 0) {
//not visible, 0 instances
continue;
@@ -1237,7 +1433,7 @@ void RasterizerSceneHighEndRD::_fill_render_list(InstanceBase **p_cull_result, i
continue;
}
- const RID *materials = NULL;
+ const RID *materials = nullptr;
uint32_t surface_count;
materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count);
@@ -1246,7 +1442,6 @@ void RasterizerSceneHighEndRD::_fill_render_list(InstanceBase **p_cull_result, i
}
for (uint32_t j = 0; j < surface_count; j++) {
-
uint32_t surface_index = storage->mesh_surface_get_multimesh_render_pass_index(mesh, j, render_pass, &geometry_index);
_add_geometry(inst, j, materials[j], p_pass_mode, surface_index);
}
@@ -1258,7 +1453,7 @@ void RasterizerSceneHighEndRD::_fill_render_list(InstanceBase **p_cull_result, i
RasterizerStorageGLES3::Immediate *immediate = storage->immediate_owner.getornull(inst->base);
ERR_CONTINUE(!immediate);
- _add_geometry(immediate, inst, NULL, -1, p_depth_pass, p_shadow_pass);
+ _add_geometry(immediate, inst, nullptr, -1, p_depth_pass, p_shadow_pass);
} break;
case RS::INSTANCE_PARTICLES: {
@@ -1293,9 +1488,7 @@ void RasterizerSceneHighEndRD::_fill_render_list(InstanceBase **p_cull_result, i
}
void RasterizerSceneHighEndRD::_setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, RID p_environment) {
-
for (int i = 0; i < p_reflection_probe_cull_count; i++) {
-
RID rpi = p_reflection_probe_cull_result[i];
if (i >= (int)scene_state.max_reflections) {
@@ -1344,7 +1537,7 @@ void RasterizerSceneHighEndRD::_setup_reflections(RID *p_reflection_probe_cull_r
Color ambient_linear = storage->reflection_probe_get_interior_ambient(base_probe).to_linear();
if (is_environment(p_environment)) {
Color env_ambient_color = environment_get_ambient_light_color(p_environment).to_linear();
- float env_ambient_energy = environment_get_ambient_light_ambient_energy(p_environment);
+ float env_ambient_energy = environment_get_ambient_light_energy(p_environment);
ambient_linear = env_ambient_color;
ambient_linear.r *= env_ambient_energy;
ambient_linear.g *= env_ambient_energy;
@@ -1371,12 +1564,29 @@ void RasterizerSceneHighEndRD::_setup_reflections(RID *p_reflection_probe_cull_r
}
}
-void RasterizerSceneHighEndRD::_setup_gi_probes(RID *p_gi_probe_probe_cull_result, int p_gi_probe_probe_cull_count, const Transform &p_camera_transform) {
+void RasterizerSceneHighEndRD::_setup_lightmaps(InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, const Transform &p_cam_transform) {
+ uint32_t lightmaps_used = 0;
+ for (int i = 0; i < p_lightmap_cull_count; i++) {
+ if (i >= (int)scene_state.max_lightmaps) {
+ break;
+ }
+ InstanceBase *lm = p_lightmap_cull_result[i];
+ Basis to_lm = lm->transform.basis.inverse() * p_cam_transform.basis;
+ to_lm = to_lm.inverse().transposed(); //will transform normals
+ store_transform_3x3(to_lm, scene_state.lightmaps[i].normal_xform);
+ lm->lightmap_cull_index = i;
+ lightmaps_used++;
+ }
+ if (lightmaps_used > 0) {
+ RD::get_singleton()->buffer_update(scene_state.lightmap_buffer, 0, sizeof(LightmapData) * lightmaps_used, scene_state.lightmaps, true);
+ }
+}
+
+void RasterizerSceneHighEndRD::_setup_gi_probes(RID *p_gi_probe_probe_cull_result, int p_gi_probe_probe_cull_count, const Transform &p_camera_transform) {
int index = 0;
for (int i = 0; i < p_gi_probe_probe_cull_count; i++) {
-
RID rpi = p_gi_probe_probe_cull_result[i];
if (index >= (int)scene_state.max_gi_probes) {
@@ -1427,13 +1637,11 @@ void RasterizerSceneHighEndRD::_setup_gi_probes(RID *p_gi_probe_probe_cull_resul
}
void RasterizerSceneHighEndRD::_setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, RID p_shadow_atlas, bool p_using_shadows) {
-
uint32_t light_count = 0;
scene_state.ubo.directional_light_count = 0;
sky_scene_state.directional_light_count = 0;
for (int i = 0; i < p_light_cull_count; i++) {
-
RID li = p_light_cull_result[i];
RID base = light_instance_get_base_light(li);
@@ -1441,9 +1649,7 @@ void RasterizerSceneHighEndRD::_setup_lights(RID *p_light_cull_result, int p_lig
RS::LightType type = storage->light_get_type(base);
switch (type) {
-
case RS::LIGHT_DIRECTIONAL: {
-
if (scene_state.ubo.directional_light_count >= scene_state.max_directional_lights) {
continue;
}
@@ -1470,16 +1676,62 @@ void RasterizerSceneHighEndRD::_setup_lights(RID *p_light_cull_result, int p_lig
light_data.specular = storage->light_get_param(base, RS::LIGHT_PARAM_SPECULAR);
light_data.mask = storage->light_get_cull_mask(base);
+ float size = storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
+
+ light_data.size = 1.0 - Math::cos(Math::deg2rad(size)); //angle to cosine offset
+
Color shadow_col = storage->light_get_shadow_color(base).to_linear();
- light_data.shadow_color[0] = shadow_col.r;
- light_data.shadow_color[1] = shadow_col.g;
- light_data.shadow_color[2] = shadow_col.b;
+ if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_PSSM_SPLITS) {
+ light_data.shadow_color1[0] = 1.0;
+ light_data.shadow_color1[1] = 0.0;
+ light_data.shadow_color1[2] = 0.0;
+ light_data.shadow_color1[3] = 1.0;
+ light_data.shadow_color2[0] = 0.0;
+ light_data.shadow_color2[1] = 1.0;
+ light_data.shadow_color2[2] = 0.0;
+ light_data.shadow_color2[3] = 1.0;
+ light_data.shadow_color3[0] = 0.0;
+ light_data.shadow_color3[1] = 0.0;
+ light_data.shadow_color3[2] = 1.0;
+ light_data.shadow_color3[3] = 1.0;
+ light_data.shadow_color4[0] = 1.0;
+ light_data.shadow_color4[1] = 1.0;
+ light_data.shadow_color4[2] = 0.0;
+ light_data.shadow_color4[3] = 1.0;
+
+ } else {
+ light_data.shadow_color1[0] = shadow_col.r;
+ light_data.shadow_color1[1] = shadow_col.g;
+ light_data.shadow_color1[2] = shadow_col.b;
+ light_data.shadow_color1[3] = 1.0;
+ light_data.shadow_color2[0] = shadow_col.r;
+ light_data.shadow_color2[1] = shadow_col.g;
+ light_data.shadow_color2[2] = shadow_col.b;
+ light_data.shadow_color2[3] = 1.0;
+ light_data.shadow_color3[0] = shadow_col.r;
+ light_data.shadow_color3[1] = shadow_col.g;
+ light_data.shadow_color3[2] = shadow_col.b;
+ light_data.shadow_color3[3] = 1.0;
+ light_data.shadow_color4[0] = shadow_col.r;
+ light_data.shadow_color4[1] = shadow_col.g;
+ light_data.shadow_color4[2] = shadow_col.b;
+ light_data.shadow_color4[3] = 1.0;
+ }
light_data.shadow_enabled = p_using_shadows && storage->light_has_shadow(base);
- if (light_data.shadow_enabled) {
+ float angular_diameter = storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
+ if (angular_diameter > 0.0) {
+ // I know tan(0) is 0, but let's not risk it with numerical precision.
+ // technically this will keep expanding until reaching the sun, but all we care
+ // is expand until we reach the radius of the near plane (there can't be more occluders than that)
+ angular_diameter = Math::tan(Math::deg2rad(angular_diameter));
+ } else {
+ angular_diameter = 0.0;
+ }
+ if (light_data.shadow_enabled) {
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);
@@ -1498,17 +1750,50 @@ void RasterizerSceneHighEndRD::_setup_lights(RID *p_light_cull_result, int p_lig
CameraMatrix shadow_mtx = rectm * bias * matrix * modelview;
light_data.shadow_split_offsets[j] = split;
+ float bias_scale = light_instance_get_shadow_bias_scale(li, j);
+ light_data.shadow_bias[j] = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) * bias_scale;
+ light_data.shadow_normal_bias[j] = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * light_instance_get_directional_shadow_texel_size(li, j);
+ light_data.shadow_transmittance_bias[j] = storage->light_get_transmittance_bias(base) * bias_scale;
+ light_data.shadow_transmittance_z_scale[j] = light_instance_get_shadow_range(li, j);
+ light_data.shadow_range_begin[j] = light_instance_get_shadow_range_begin(li, j);
store_camera(shadow_mtx, light_data.shadow_matrices[j]);
+
+ Vector2 uv_scale = light_instance_get_shadow_uv_scale(li, j);
+ uv_scale *= atlas_rect.size; //adapt to atlas size
+ switch (j) {
+ case 0: {
+ light_data.uv_scale1[0] = uv_scale.x;
+ light_data.uv_scale1[1] = uv_scale.y;
+ } break;
+ case 1: {
+ light_data.uv_scale2[0] = uv_scale.x;
+ light_data.uv_scale2[1] = uv_scale.y;
+ } break;
+ case 2: {
+ light_data.uv_scale3[0] = uv_scale.x;
+ light_data.uv_scale3[1] = uv_scale.y;
+ } break;
+ case 3: {
+ light_data.uv_scale4[0] = uv_scale.x;
+ light_data.uv_scale4[1] = uv_scale.y;
+ } break;
+ }
}
float fade_start = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_FADE_START);
light_data.fade_from = -light_data.shadow_split_offsets[3] * MIN(fade_start, 0.999); //using 1.0 would break smoothstep
light_data.fade_to = -light_data.shadow_split_offsets[3];
+
+ light_data.soft_shadow_scale = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BLUR);
+ light_data.softshadow_angle = angular_diameter;
+
+ if (angular_diameter <= 0.0) {
+ light_data.soft_shadow_scale *= directional_shadow_quality_radius_get(); // Only use quality radius for PCF
+ }
}
// Copy to SkyDirectionalLightData
if (sky_scene_state.directional_light_count < sky_scene_state.max_directional_lights) {
-
SkyDirectionalLightData &sky_light_data = sky_scene_state.directional_lights[sky_scene_state.directional_light_count];
Vector3 world_direction = light_transform.basis.xform(Vector3(0, 0, 1)).normalized();
@@ -1524,6 +1809,7 @@ void RasterizerSceneHighEndRD::_setup_lights(RID *p_light_cull_result, int p_lig
sky_light_data.color[2] = light_data.color[2];
sky_light_data.enabled = true;
+ sky_light_data.size = angular_diameter;
sky_scene_state.directional_light_count++;
}
@@ -1531,7 +1817,6 @@ void RasterizerSceneHighEndRD::_setup_lights(RID *p_light_cull_result, int p_lig
} break;
case RS::LIGHT_SPOT:
case RS::LIGHT_OMNI: {
-
if (light_count >= scene_state.max_lights) {
continue;
}
@@ -1566,51 +1851,110 @@ void RasterizerSceneHighEndRD::_setup_lights(RID *p_light_cull_result, int p_lig
light_data.direction[1] = direction.y;
light_data.direction[2] = direction.z;
+ float size = storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
+
+ light_data.size = size;
+
light_data.cone_attenuation_angle[0] = Math::make_half_float(storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ATTENUATION));
float spot_angle = storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ANGLE);
light_data.cone_attenuation_angle[1] = Math::make_half_float(Math::cos(Math::deg2rad(spot_angle)));
light_data.mask = storage->light_get_cull_mask(base);
- Color shadow_color = storage->light_get_shadow_color(base);
-
- bool has_shadow = p_using_shadows && storage->light_has_shadow(base);
- light_data.shadow_color_enabled[0] = MIN(uint32_t(shadow_color.r * 255), 255);
- light_data.shadow_color_enabled[1] = MIN(uint32_t(shadow_color.g * 255), 255);
- light_data.shadow_color_enabled[2] = MIN(uint32_t(shadow_color.b * 255), 255);
- light_data.shadow_color_enabled[3] = has_shadow ? 255 : 0;
-
light_data.atlas_rect[0] = 0;
light_data.atlas_rect[1] = 0;
light_data.atlas_rect[2] = 0;
light_data.atlas_rect[3] = 0;
+ RID projector = storage->light_get_projector(base);
+
+ if (projector.is_valid()) {
+ Rect2 rect = storage->decal_atlas_get_texture_rect(projector);
+
+ if (type == RS::LIGHT_SPOT) {
+ light_data.projector_rect[0] = rect.position.x;
+ light_data.projector_rect[1] = rect.position.y + rect.size.height; //flip because shadow is flipped
+ light_data.projector_rect[2] = rect.size.width;
+ light_data.projector_rect[3] = -rect.size.height;
+ } else {
+ light_data.projector_rect[0] = rect.position.x;
+ light_data.projector_rect[1] = rect.position.y;
+ light_data.projector_rect[2] = rect.size.width;
+ light_data.projector_rect[3] = rect.size.height * 0.5; //used by dp, so needs to be half
+ }
+ } else {
+ light_data.projector_rect[0] = 0;
+ light_data.projector_rect[1] = 0;
+ light_data.projector_rect[2] = 0;
+ light_data.projector_rect[3] = 0;
+ }
+
if (p_using_shadows && p_shadow_atlas.is_valid() && shadow_atlas_owns_light_instance(p_shadow_atlas, li)) {
// fill in the shadow information
+ Color shadow_color = storage->light_get_shadow_color(base);
+
+ light_data.shadow_color_enabled[0] = MIN(uint32_t(shadow_color.r * 255), 255);
+ light_data.shadow_color_enabled[1] = MIN(uint32_t(shadow_color.g * 255), 255);
+ light_data.shadow_color_enabled[2] = MIN(uint32_t(shadow_color.b * 255), 255);
+ light_data.shadow_color_enabled[3] = 255;
+
+ if (type == RS::LIGHT_SPOT) {
+ light_data.shadow_bias = (storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) * radius / 10.0);
+ float shadow_texel_size = Math::tan(Math::deg2rad(spot_angle)) * radius * 2.0;
+ shadow_texel_size *= light_instance_get_shadow_texel_size(li, p_shadow_atlas);
+
+ light_data.shadow_normal_bias = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * shadow_texel_size;
+
+ } else { //omni
+ light_data.shadow_bias = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) * radius / 10.0;
+ float shadow_texel_size = light_instance_get_shadow_texel_size(li, p_shadow_atlas);
+ light_data.shadow_normal_bias = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * shadow_texel_size * 2.0; // applied in -1 .. 1 space
+ }
+
+ light_data.transmittance_bias = storage->light_get_transmittance_bias(base);
+
Rect2 rect = light_instance_get_shadow_atlas_rect(li, p_shadow_atlas);
- if (type == RS::LIGHT_OMNI) {
+ light_data.atlas_rect[0] = rect.position.x;
+ light_data.atlas_rect[1] = rect.position.y;
+ light_data.atlas_rect[2] = rect.size.width;
+ light_data.atlas_rect[3] = rect.size.height;
- light_data.atlas_rect[0] = rect.position.x;
- light_data.atlas_rect[1] = rect.position.y;
- light_data.atlas_rect[2] = rect.size.width;
- light_data.atlas_rect[3] = rect.size.height * 0.5;
+ light_data.soft_shadow_scale = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BLUR);
+ if (type == RS::LIGHT_OMNI) {
+ light_data.atlas_rect[3] *= 0.5; //one paraboloid on top of another
Transform proj = (p_camera_inverse_transform * light_transform).inverse();
store_transform(proj, light_data.shadow_matrix);
- } else if (type == RS::LIGHT_SPOT) {
+ if (size > 0.0) {
+ light_data.soft_shadow_size = size;
+ } else {
+ light_data.soft_shadow_size = 0.0;
+ light_data.soft_shadow_scale *= shadows_quality_radius_get(); // Only use quality radius for PCF
+ }
+
+ } else if (type == RS::LIGHT_SPOT) {
Transform modelview = (p_camera_inverse_transform * light_transform).inverse();
CameraMatrix bias;
bias.set_light_bias();
- CameraMatrix rectm;
- rectm.set_light_atlas_rect(rect);
- CameraMatrix shadow_mtx = rectm * bias * light_instance_get_shadow_camera(li, 0) * modelview;
+ CameraMatrix shadow_mtx = bias * light_instance_get_shadow_camera(li, 0) * modelview;
store_camera(shadow_mtx, light_data.shadow_matrix);
+
+ if (size > 0.0) {
+ CameraMatrix cm = light_instance_get_shadow_camera(li, 0);
+ float half_np = cm.get_z_near() * Math::tan(Math::deg2rad(spot_angle));
+ light_data.soft_shadow_size = (size * 0.5 / radius) / (half_np / cm.get_z_near()) * rect.size.width;
+ } else {
+ light_data.soft_shadow_size = 0.0;
+ light_data.soft_shadow_scale *= shadows_quality_radius_get(); // Only use quality radius for PCF
+ }
}
+ } else {
+ light_data.shadow_color_enabled[3] = 0;
}
light_instance_set_index(li, light_count);
@@ -1635,9 +1979,138 @@ void RasterizerSceneHighEndRD::_setup_lights(RID *p_light_cull_result, int p_lig
}
}
-void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color) {
+void RasterizerSceneHighEndRD::_setup_decals(const RID *p_decal_instances, int p_decal_count, const Transform &p_camera_inverse_xform) {
+ Transform uv_xform;
+ uv_xform.basis.scale(Vector3(2.0, 1.0, 2.0));
+ uv_xform.origin = Vector3(-1.0, 0.0, -1.0);
+
+ p_decal_count = MIN((uint32_t)p_decal_count, scene_state.max_decals);
+ int idx = 0;
+ for (int i = 0; i < p_decal_count; i++) {
+ RID di = p_decal_instances[i];
+ RID decal = decal_instance_get_base(di);
+
+ Transform xform = decal_instance_get_transform(di);
- RenderBufferDataHighEnd *render_buffer = NULL;
+ float fade = 1.0;
+
+ if (storage->decal_is_distance_fade_enabled(decal)) {
+ real_t distance = -p_camera_inverse_xform.xform(xform.origin).z;
+ float fade_begin = storage->decal_get_distance_fade_begin(decal);
+ float fade_length = storage->decal_get_distance_fade_length(decal);
+
+ if (distance > fade_begin) {
+ if (distance > fade_begin + fade_length) {
+ continue; // do not use this decal, its invisible
+ }
+
+ fade = 1.0 - (distance - fade_begin) / fade_length;
+ }
+ }
+
+ DecalData &dd = scene_state.decals[idx];
+
+ Vector3 decal_extents = storage->decal_get_extents(decal);
+
+ Transform scale_xform;
+ scale_xform.basis.scale(Vector3(decal_extents.x, decal_extents.y, decal_extents.z));
+ Transform to_decal_xform = (p_camera_inverse_xform * decal_instance_get_transform(di) * scale_xform * uv_xform).affine_inverse();
+ store_transform(to_decal_xform, dd.xform);
+
+ Vector3 normal = xform.basis.get_axis(Vector3::AXIS_Y).normalized();
+ normal = p_camera_inverse_xform.basis.xform(normal); //camera is normalized, so fine
+
+ dd.normal[0] = normal.x;
+ dd.normal[1] = normal.y;
+ dd.normal[2] = normal.z;
+ dd.normal_fade = storage->decal_get_normal_fade(decal);
+
+ RID albedo_tex = storage->decal_get_texture(decal, RS::DECAL_TEXTURE_ALBEDO);
+ RID emission_tex = storage->decal_get_texture(decal, RS::DECAL_TEXTURE_EMISSION);
+ if (albedo_tex.is_valid()) {
+ Rect2 rect = storage->decal_atlas_get_texture_rect(albedo_tex);
+ dd.albedo_rect[0] = rect.position.x;
+ dd.albedo_rect[1] = rect.position.y;
+ dd.albedo_rect[2] = rect.size.x;
+ dd.albedo_rect[3] = rect.size.y;
+ } else {
+ if (!emission_tex.is_valid()) {
+ continue; //no albedo, no emission, no decal.
+ }
+ dd.albedo_rect[0] = 0;
+ dd.albedo_rect[1] = 0;
+ dd.albedo_rect[2] = 0;
+ dd.albedo_rect[3] = 0;
+ }
+
+ RID normal_tex = storage->decal_get_texture(decal, RS::DECAL_TEXTURE_NORMAL);
+
+ if (normal_tex.is_valid()) {
+ Rect2 rect = storage->decal_atlas_get_texture_rect(normal_tex);
+ dd.normal_rect[0] = rect.position.x;
+ dd.normal_rect[1] = rect.position.y;
+ dd.normal_rect[2] = rect.size.x;
+ dd.normal_rect[3] = rect.size.y;
+
+ Basis normal_xform = p_camera_inverse_xform.basis * xform.basis.orthonormalized();
+ store_basis_3x4(normal_xform, dd.normal_xform);
+ } else {
+ dd.normal_rect[0] = 0;
+ dd.normal_rect[1] = 0;
+ dd.normal_rect[2] = 0;
+ dd.normal_rect[3] = 0;
+ }
+
+ RID orm_tex = storage->decal_get_texture(decal, RS::DECAL_TEXTURE_ORM);
+ if (orm_tex.is_valid()) {
+ Rect2 rect = storage->decal_atlas_get_texture_rect(orm_tex);
+ dd.orm_rect[0] = rect.position.x;
+ dd.orm_rect[1] = rect.position.y;
+ dd.orm_rect[2] = rect.size.x;
+ dd.orm_rect[3] = rect.size.y;
+ } else {
+ dd.orm_rect[0] = 0;
+ dd.orm_rect[1] = 0;
+ dd.orm_rect[2] = 0;
+ dd.orm_rect[3] = 0;
+ }
+
+ if (emission_tex.is_valid()) {
+ Rect2 rect = storage->decal_atlas_get_texture_rect(emission_tex);
+ dd.emission_rect[0] = rect.position.x;
+ dd.emission_rect[1] = rect.position.y;
+ dd.emission_rect[2] = rect.size.x;
+ dd.emission_rect[3] = rect.size.y;
+ } else {
+ dd.emission_rect[0] = 0;
+ dd.emission_rect[1] = 0;
+ dd.emission_rect[2] = 0;
+ dd.emission_rect[3] = 0;
+ }
+
+ Color modulate = storage->decal_get_modulate(decal);
+ dd.modulate[0] = modulate.r;
+ dd.modulate[1] = modulate.g;
+ dd.modulate[2] = modulate.b;
+ dd.modulate[3] = modulate.a * fade;
+ dd.emission_energy = storage->decal_get_emission_energy(decal) * fade;
+ dd.albedo_mix = storage->decal_get_albedo_mix(decal);
+ dd.mask = storage->decal_get_cull_mask(decal);
+ dd.upper_fade = storage->decal_get_upper_fade(decal);
+ dd.lower_fade = storage->decal_get_lower_fade(decal);
+
+ cluster_builder.add_decal(xform, decal_extents);
+
+ idx++;
+ }
+
+ if (idx > 0) {
+ RD::get_singleton()->buffer_update(scene_state.decal_buffer, 0, sizeof(DecalData) * idx, scene_state.decals, true);
+ }
+}
+
+void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color) {
+ RenderBufferDataHighEnd *render_buffer = nullptr;
if (p_render_buffer.is_valid()) {
render_buffer = (RenderBufferDataHighEnd *)render_buffers_get_data(p_render_buffer);
}
@@ -1646,27 +2119,6 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor
render_pass++;
//fill up ubo
-#if 0
- storage->info.render.object_count += p_cull_count;
-
- Environment *env = environment_owner.getornull(p_environment);
- ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
- ReflectionAtlas *reflection_atlas = reflection_atlas_owner.getornull(p_reflection_atlas);
-
- if (shadow_atlas && shadow_atlas->size) {
- glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 5);
- glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LESS);
- scene_state.ubo.shadow_atlas_pixel_size[0] = 1.0 / shadow_atlas->size;
- scene_state.ubo.shadow_atlas_pixel_size[1] = 1.0 / shadow_atlas->size;
- }
-
- if (reflection_atlas && reflection_atlas->size) {
- glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 3);
- glBindTexture(GL_TEXTURE_2D, reflection_atlas->color);
- }
-#endif
RENDER_TIMESTAMP("Setup 3D Scene");
@@ -1689,9 +2141,6 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor
//scene_state.ubo.subsurface_scatter_width = subsurface_scatter_size;
- scene_state.ubo.shadow_z_offset = 0;
- scene_state.ubo.shadow_z_slope_scale = 0;
-
Vector2 vp_he = p_cam_projection.get_viewport_half_extents();
scene_state.ubo.viewport_size[0] = vp_he.x;
scene_state.ubo.viewport_size[1] = vp_he.y;
@@ -1699,11 +2148,14 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor
Size2 screen_pixel_size;
Size2i screen_size;
RID opaque_framebuffer;
+ RID opaque_specular_framebuffer;
RID depth_framebuffer;
RID alpha_framebuffer;
PassMode depth_pass_mode = PASS_MODE_DEPTH;
Vector<Color> depth_pass_clear;
+ bool using_separate_specular = false;
+ bool using_ssr = false;
if (render_buffer) {
screen_pixel_size.width = 1.0 / render_buffer->width;
@@ -1715,6 +2167,10 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor
if (p_environment.is_valid() && environment_is_ssr_enabled(p_environment)) {
depth_pass_mode = PASS_MODE_DEPTH_NORMAL_ROUGHNESS;
+ render_buffer->ensure_specular();
+ using_separate_specular = true;
+ using_ssr = true;
+ opaque_specular_framebuffer = render_buffer->color_specular_fb;
} else if (screen_space_roughness_limiter_is_active()) {
depth_pass_mode = PASS_MODE_DEPTH_NORMAL;
//we need to allocate both these, if not allocated
@@ -1768,8 +2224,10 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor
cluster_builder.begin(p_cam_transform.affine_inverse(), p_cam_projection); //prepare cluster
_setup_lights(p_light_cull_result, p_light_cull_count, p_cam_transform.affine_inverse(), p_shadow_atlas, using_shadows);
+ _setup_decals(p_decal_cull_result, p_decal_cull_count, p_cam_transform.affine_inverse());
_setup_reflections(p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_cam_transform.affine_inverse(), p_environment);
_setup_gi_probes(p_gi_probe_cull_result, p_gi_probe_cull_count, p_cam_transform);
+ _setup_lightmaps(p_lightmap_cull_result, p_lightmap_cull_count, p_cam_transform);
_setup_environment(p_environment, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_pixel_size, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color, p_cam_projection.get_z_near(), p_cam_projection.get_z_far(), false);
cluster_builder.bake_cluster(); //bake to cluster
@@ -1779,6 +2237,14 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor
render_list.clear();
_fill_render_list(p_cull_result, p_cull_count, PASS_MODE_COLOR, render_buffer == nullptr);
+ bool using_sss = render_buffer && scene_state.used_sss && sub_surface_scattering_get_quality() != RS::SUB_SURFACE_SCATTERING_QUALITY_DISABLED;
+
+ if (using_sss) {
+ using_separate_specular = true;
+ render_buffer->ensure_specular();
+ using_separate_specular = true;
+ opaque_specular_framebuffer = render_buffer->color_specular_fb;
+ }
RID radiance_uniform_set;
bool draw_sky = false;
@@ -1804,23 +2270,7 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor
clear_color.b *= bg_energy;
} break;
case RS::ENV_BG_SKY: {
- RID sky = environment_get_sky(p_environment);
- if (sky.is_valid()) {
-
- RENDER_TIMESTAMP("Setup Sky");
- CameraMatrix projection = p_cam_projection;
- if (p_reflection_probe.is_valid()) {
- CameraMatrix correction;
- correction.set_depth_correction(true);
- projection = correction * p_cam_projection;
- }
-
- _setup_sky(p_environment, p_cam_transform.origin, screen_size);
- _update_sky(p_environment, projection, p_cam_transform);
- radiance_uniform_set = sky_get_radiance_uniform_set_rd(sky, default_shader_rd, RADIANCE_UNIFORM_SET);
-
- draw_sky = true;
- }
+ draw_sky = true;
} break;
case RS::ENV_BG_CANVAS: {
keep_color = true;
@@ -1829,13 +2279,31 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor
keep_color = true;
} break;
case RS::ENV_BG_CAMERA_FEED: {
-
} break;
default: {
}
}
- } else {
+ // setup sky if used for ambient, reflections, or background
+ if (draw_sky || environment_get_reflection_source(p_environment) == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(p_environment) == RS::ENV_AMBIENT_SOURCE_SKY) {
+ RID sky = environment_get_sky(p_environment);
+ if (sky.is_valid()) {
+ RENDER_TIMESTAMP("Setup Sky");
+ CameraMatrix projection = p_cam_projection;
+ if (p_reflection_probe.is_valid()) {
+ CameraMatrix correction;
+ correction.set_depth_correction(true);
+ projection = correction * p_cam_projection;
+ }
+ _setup_sky(p_environment, p_cam_transform.origin, screen_size);
+ _update_sky(p_environment, projection, p_cam_transform);
+ radiance_uniform_set = sky_get_radiance_uniform_set_rd(sky, default_shader_rd, RADIANCE_UNIFORM_SET);
+ } else {
+ // do not try to draw sky if invalid
+ draw_sky = false;
+ }
+ }
+ } else {
clear_color = p_default_bg_color;
}
@@ -1845,22 +2313,36 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor
_fill_instances(render_list.elements, render_list.element_count, false);
- bool can_continue = true; //unless the middle buffers are needed
bool debug_giprobes = get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_ALBEDO || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION;
- bool using_separate_specular = false;
bool depth_pre_pass = depth_framebuffer.is_valid();
RID render_buffers_uniform_set;
+ bool using_ssao = depth_pre_pass && p_render_buffer.is_valid() && p_environment.is_valid() && environment_is_ssao_enabled(p_environment);
+
if (depth_pre_pass) { //depth pre pass
RENDER_TIMESTAMP("Render Depth Pre-Pass");
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(depth_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_CONTINUE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_CONTINUE, depth_pass_clear);
- _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(depth_framebuffer), render_list.elements, render_list.element_count, false, depth_pass_mode, render_buffer == nullptr, radiance_uniform_set, RID());
+ bool finish_depth = using_ssao;
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(depth_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, finish_depth ? RD::FINAL_ACTION_READ : RD::FINAL_ACTION_CONTINUE, depth_pass_clear);
+ _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(depth_framebuffer), render_list.elements, render_list.element_count, false, depth_pass_mode, render_buffer == nullptr, radiance_uniform_set, RID(), get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME);
RD::get_singleton()->draw_list_end();
+
+ if (render_buffer && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) {
+ if (finish_depth) {
+ RD::get_singleton()->texture_resolve_multisample(render_buffer->depth_msaa, render_buffer->depth, true);
+ }
+
+ if (depth_pass_mode == PASS_MODE_DEPTH_NORMAL || depth_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS) {
+ RD::get_singleton()->texture_resolve_multisample(render_buffer->normal_buffer_msaa, render_buffer->normal_buffer, true);
+ if (depth_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS) {
+ RD::get_singleton()->texture_resolve_multisample(render_buffer->roughness_buffer_msaa, render_buffer->roughness_buffer, true);
+ }
+ }
+ }
}
- if (p_render_buffer.is_valid() && p_environment.is_valid() && environment_is_ssao_enabled(p_environment)) {
+ if (using_ssao) {
_process_ssao(p_render_buffer, p_environment, render_buffer->normal_buffer, p_cam_projection);
}
@@ -1878,23 +2360,45 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor
RENDER_TIMESTAMP("Render Opaque Pass");
+ bool can_continue_color = !scene_state.used_screen_texture && !using_ssr && !using_sss;
+ bool can_continue_depth = !scene_state.used_depth_texture && !using_ssr && !using_sss;
+
{
- bool will_continue = (can_continue || draw_sky || debug_giprobes);
+ bool will_continue_color = (can_continue_color || draw_sky || debug_giprobes);
+ bool will_continue_depth = (can_continue_depth || draw_sky || debug_giprobes);
+
//regular forward for now
Vector<Color> c;
- c.push_back(clear_color.to_linear());
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(opaque_framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, will_continue ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, depth_pre_pass ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_CLEAR, will_continue ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0);
- _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(opaque_framebuffer), render_list.elements, render_list.element_count, false, PASS_MODE_COLOR, render_buffer == nullptr, radiance_uniform_set, render_buffers_uniform_set);
+ if (using_separate_specular) {
+ Color cc = clear_color.to_linear();
+ cc.a = 0; //subsurf scatter must be 0
+ c.push_back(cc);
+ c.push_back(Color(0, 0, 0, 0));
+ } else {
+ c.push_back(clear_color.to_linear());
+ }
+
+ RID framebuffer = using_separate_specular ? opaque_specular_framebuffer : opaque_framebuffer;
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, depth_pre_pass ? (using_ssao ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CONTINUE) : RD::INITIAL_ACTION_CLEAR, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0);
+ _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(framebuffer), render_list.elements, render_list.element_count, false, using_separate_specular ? PASS_MODE_COLOR_SPECULAR : PASS_MODE_COLOR, render_buffer == nullptr, radiance_uniform_set, render_buffers_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME);
RD::get_singleton()->draw_list_end();
+
+ if (will_continue_color && using_separate_specular) {
+ // close the specular framebuffer, as it's no longer used
+ draw_list = RD::get_singleton()->draw_list_begin(render_buffer->specular_only_fb, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_CONTINUE);
+ RD::get_singleton()->draw_list_end();
+ }
}
if (debug_giprobes) {
//debug giprobes
- bool will_continue = (can_continue || draw_sky);
+ bool will_continue_color = (can_continue_color || draw_sky);
+ bool will_continue_depth = (can_continue_depth || draw_sky);
+
CameraMatrix dc;
dc.set_depth_correction(true);
CameraMatrix cm = (dc * p_cam_projection) * CameraMatrix(p_cam_transform.affine_inverse());
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(opaque_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ);
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(opaque_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ);
for (int i = 0; i < p_gi_probe_cull_count; i++) {
_debug_giprobe(p_gi_probe_cull_result[i], draw_list, opaque_framebuffer, cm, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION, 1.0);
}
@@ -1911,12 +2415,33 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor
projection = correction * p_cam_projection;
}
- _draw_sky(can_continue, opaque_framebuffer, p_environment, projection, p_cam_transform);
+ _draw_sky(can_continue_color, can_continue_depth, opaque_framebuffer, p_environment, projection, p_cam_transform);
+ }
- if (using_separate_specular && !can_continue) {
- //can't continue, so close the buffers
- //RD::get_singleton()->draw_list_begin(render_buffer->color_specular_fb, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_READ_COLOR_AND_DEPTH, c);
- //RD::get_singleton()->draw_list_end();
+ if (render_buffer && !can_continue_color && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) {
+ RD::get_singleton()->texture_resolve_multisample(render_buffer->color_msaa, render_buffer->color, true);
+ if (using_separate_specular) {
+ RD::get_singleton()->texture_resolve_multisample(render_buffer->specular_msaa, render_buffer->specular, true);
+ }
+ }
+
+ if (render_buffer && !can_continue_depth && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) {
+ RD::get_singleton()->texture_resolve_multisample(render_buffer->depth_msaa, render_buffer->depth, true);
+ }
+
+ if (using_separate_specular) {
+ if (using_sss) {
+ RENDER_TIMESTAMP("Sub Surface Scattering");
+ _process_sss(p_render_buffer, p_cam_projection);
+ }
+
+ if (using_ssr) {
+ RENDER_TIMESTAMP("Screen Space Reflection");
+ _process_ssr(p_render_buffer, render_buffer->color_fb, render_buffer->normal_buffer, render_buffer->roughness_buffer, render_buffer->specular, render_buffer->specular, Color(0, 0, 0, 1), p_environment, p_cam_projection, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED);
+ } else {
+ //just mix specular back
+ RENDER_TIMESTAMP("Merge Specular");
+ storage->get_effects()->merge_specular(render_buffer->color_fb, render_buffer->specular, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED ? RID() : render_buffer->color, RID());
}
}
@@ -1929,95 +2454,26 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor
_fill_instances(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, false);
{
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(alpha_framebuffer, can_continue ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, can_continue ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ);
- _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(alpha_framebuffer), &render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, false, PASS_MODE_COLOR, render_buffer == nullptr, radiance_uniform_set, render_buffers_uniform_set);
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(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);
+ _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(alpha_framebuffer), &render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, false, PASS_MODE_COLOR, render_buffer == nullptr, radiance_uniform_set, render_buffers_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME);
RD::get_singleton()->draw_list_end();
}
- //_render_list
-#if 0
- if (state.directional_light_count == 0) {
- directional_light = NULL;
- _render_list(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, p_cam_transform, p_cam_projection, env_radiance_tex, false, true, false, false, shadow_atlas != NULL);
- } else {
- for (int i = 0; i < state.directional_light_count; i++) {
- directional_light = directional_lights[i];
- _setup_directional_light(i, p_cam_transform.affine_inverse(), shadow_atlas != NULL && shadow_atlas->size > 0);
- _render_list(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, p_cam_transform, p_cam_projection, env_radiance_tex, false, true, false, i > 0, shadow_atlas != NULL);
- }
- }
-#endif
-
-#if 0
- _post_process(env, p_cam_projection);
- // Needed only for debugging
- /* if (shadow_atlas && storage->frame.current_rt) {
-
- //_copy_texture_to_front_buffer(shadow_atlas->depth);
- storage->canvas->canvas_begin();
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
- storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1));
- }
-
- if (storage->frame.current_rt) {
-
- //_copy_texture_to_front_buffer(shadow_atlas->depth);
- storage->canvas->canvas_begin();
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, exposure_shrink[4].color);
- //glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->exposure.color);
- storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 16, storage->frame.current_rt->height / 16), Rect2(0, 0, 1, 1));
- }
-
- if (reflection_atlas && storage->frame.current_rt) {
-
- //_copy_texture_to_front_buffer(shadow_atlas->depth);
- storage->canvas->canvas_begin();
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, reflection_atlas->color);
- storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1));
+ if (render_buffer && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) {
+ RD::get_singleton()->texture_resolve_multisample(render_buffer->color_msaa, render_buffer->color, true);
}
-
- if (directional_shadow.fbo) {
-
- //_copy_texture_to_front_buffer(shadow_atlas->depth);
- storage->canvas->canvas_begin();
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, directional_shadow.depth);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
- storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1));
- }
-
- if ( env_radiance_tex) {
-
- //_copy_texture_to_front_buffer(shadow_atlas->depth);
- storage->canvas->canvas_begin();
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, env_radiance_tex);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1));
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- }*/
- //disable all stuff
-#endif
}
-void RasterizerSceneHighEndRD::_render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip) {
+void RasterizerSceneHighEndRD::_render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake) {
RENDER_TIMESTAMP("Setup Rendering Shadow");
_update_render_base_uniform_set();
render_pass++;
- scene_state.ubo.shadow_z_offset = p_bias;
- scene_state.ubo.shadow_z_slope_scale = p_normal_bias;
scene_state.ubo.dual_paraboloid_side = p_use_dp_flip ? -1 : 1;
- _setup_environment(RID(), p_projection, p_transform, RID(), true, Vector2(1, 1), RID(), true, Color(), 0, p_zfar);
+ _setup_environment(RID(), p_projection, p_transform, RID(), true, Vector2(1, 1), RID(), true, Color(), 0, p_zfar, false, p_use_pancake);
render_list.clear();
@@ -2042,15 +2498,14 @@ void RasterizerSceneHighEndRD::_render_shadow(RID p_framebuffer, InstanceBase **
}
void RasterizerSceneHighEndRD::_render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) {
- RENDER_TIMESTAMP("Setup Rendering Shadow");
+ RENDER_TIMESTAMP("Setup Rendering Material");
_update_render_base_uniform_set();
render_pass++;
- scene_state.ubo.shadow_z_offset = 0;
- scene_state.ubo.shadow_z_slope_scale = 0;
scene_state.ubo.dual_paraboloid_side = 0;
+ scene_state.ubo.material_uv2_mode = true;
_setup_environment(RID(), p_cam_projection, p_cam_transform, RID(), true, Vector2(1, 1), RID(), false, Color(), 0, 0);
@@ -2081,8 +2536,68 @@ void RasterizerSceneHighEndRD::_render_material(const Transform &p_cam_transform
}
}
-void RasterizerSceneHighEndRD::_base_uniforms_changed() {
+void RasterizerSceneHighEndRD::_render_uv2(InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) {
+ RENDER_TIMESTAMP("Setup Rendering UV2");
+
+ _update_render_base_uniform_set();
+
+ render_pass++;
+ scene_state.ubo.dual_paraboloid_side = 0;
+ scene_state.ubo.material_uv2_mode = true;
+
+ _setup_environment(RID(), CameraMatrix(), Transform(), RID(), true, Vector2(1, 1), RID(), false, Color(), 0, 0);
+
+ render_list.clear();
+
+ PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL;
+ _fill_render_list(p_cull_result, p_cull_count, pass_mode, true);
+
+ _setup_view_dependant_uniform_set(RID(), RID());
+
+ RENDER_TIMESTAMP("Render Material");
+
+ render_list.sort_by_key(false);
+
+ _fill_instances(render_list.elements, render_list.element_count, true);
+
+ {
+ //regular forward for now
+ Vector<Color> clear;
+ clear.push_back(Color(0, 0, 0, 0));
+ clear.push_back(Color(0, 0, 0, 0));
+ clear.push_back(Color(0, 0, 0, 0));
+ clear.push_back(Color(0, 0, 0, 0));
+ clear.push_back(Color(0, 0, 0, 0));
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, clear, 1.0, 0, p_region);
+
+ const int uv_offset_count = 9;
+ static const Vector2 uv_offsets[uv_offset_count] = {
+ Vector2(-1, 1),
+ Vector2(1, 1),
+ Vector2(1, -1),
+ Vector2(-1, -1),
+ Vector2(-1, 0),
+ Vector2(1, 0),
+ Vector2(0, -1),
+ Vector2(0, 1),
+ Vector2(0, 0),
+
+ };
+
+ for (int i = 0; i < uv_offset_count; i++) {
+ Vector2 ofs = uv_offsets[i];
+ ofs.x /= p_region.size.width;
+ ofs.y /= p_region.size.height;
+ _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), render_list.elements, render_list.element_count, true, pass_mode, true, RID(), RID(), true, ofs); //first wireframe, for pseudo conservative
+ }
+ _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), render_list.elements, render_list.element_count, true, pass_mode, true, RID(), RID(), false); //second regular triangles
+
+ RD::get_singleton()->draw_list_end();
+ }
+}
+
+void RasterizerSceneHighEndRD::_base_uniforms_changed() {
if (!render_base_uniform_set.is_null() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) {
RD::get_singleton()->free(render_base_uniform_set);
}
@@ -2090,13 +2605,13 @@ void RasterizerSceneHighEndRD::_base_uniforms_changed() {
}
void RasterizerSceneHighEndRD::_update_render_base_uniform_set() {
-
- if (render_base_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(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_valid() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) {
RD::get_singleton()->free(render_base_uniform_set);
}
+ lightmap_texture_array_version = storage->lightmap_array_get_version();
+
Vector<RD::Uniform> uniforms;
{
@@ -2146,7 +2661,7 @@ void RasterizerSceneHighEndRD::_update_render_base_uniform_set() {
{
RD::Uniform u;
u.binding = 5;
- u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.ids.push_back(scene_state.light_buffer);
uniforms.push_back(u);
}
@@ -2184,7 +2699,6 @@ void RasterizerSceneHighEndRD::_update_render_base_uniform_set() {
}
for (int i = 0; i < slot_count; i++) {
-
RID probe = gi_probe_get_slots()[i];
if (gi_probe_is_anisotropic()) {
@@ -2209,17 +2723,61 @@ void RasterizerSceneHighEndRD::_update_render_base_uniform_set() {
uniforms.push_back(u);
}
-
{
RD::Uniform u;
u.binding = 10;
+ u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.ids.push_back(scene_state.lightmap_buffer);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 11;
+ u.type = RD::UNIFORM_TYPE_TEXTURE;
+ u.ids = storage->lightmap_array_get_textures();
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 12;
+ u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.ids.push_back(scene_state.lightmap_capture_buffer);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 13;
+ u.type = RD::UNIFORM_TYPE_TEXTURE;
+ RID decal_atlas = storage->decal_atlas_get_texture();
+ u.ids.push_back(decal_atlas);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 14;
+ u.type = RD::UNIFORM_TYPE_TEXTURE;
+ RID decal_atlas = storage->decal_atlas_get_texture_srgb();
+ u.ids.push_back(decal_atlas);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 15;
+ u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.ids.push_back(scene_state.decal_buffer);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.binding = 16;
u.type = RD::UNIFORM_TYPE_TEXTURE;
u.ids.push_back(cluster_builder.get_cluster_texture());
uniforms.push_back(u);
}
{
RD::Uniform u;
- u.binding = 11;
+ u.binding = 17;
u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.ids.push_back(cluster_builder.get_cluster_indices_buffer());
uniforms.push_back(u);
@@ -2227,7 +2785,7 @@ void RasterizerSceneHighEndRD::_update_render_base_uniform_set() {
{
RD::Uniform u;
- u.binding = 12;
+ u.binding = 18;
u.type = RD::UNIFORM_TYPE_TEXTURE;
if (directional_shadow_get_texture().is_valid()) {
u.ids.push_back(directional_shadow_get_texture());
@@ -2237,12 +2795,19 @@ void RasterizerSceneHighEndRD::_update_render_base_uniform_set() {
uniforms.push_back(u);
}
+ {
+ RD::Uniform u;
+ u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 19;
+ u.ids.push_back(storage->global_variables_get_storage_buffer());
+ uniforms.push_back(u);
+ }
+
render_base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, SCENE_UNIFORM_SET);
}
}
void RasterizerSceneHighEndRD::_setup_view_dependant_uniform_set(RID p_shadow_atlas, RID p_reflection_atlas) {
-
if (view_dependant_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(view_dependant_uniform_set)) {
RD::get_singleton()->free(view_dependant_uniform_set);
}
@@ -2252,7 +2817,6 @@ void RasterizerSceneHighEndRD::_setup_view_dependant_uniform_set(RID p_shadow_at
Vector<RD::Uniform> uniforms;
{
-
RID ref_texture = p_reflection_atlas.is_valid() ? reflection_atlas_get_texture(p_reflection_atlas) : RID();
RD::Uniform u;
u.binding = 0;
@@ -2284,7 +2848,6 @@ void RasterizerSceneHighEndRD::_setup_view_dependant_uniform_set(RID p_shadow_at
}
void RasterizerSceneHighEndRD::_render_buffers_clear_uniform_set(RenderBufferDataHighEnd *rb) {
-
if (!rb->uniform_set.is_null() && RD::get_singleton()->uniform_set_is_valid(rb->uniform_set)) {
RD::get_singleton()->free(rb->uniform_set);
}
@@ -2292,7 +2855,6 @@ void RasterizerSceneHighEndRD::_render_buffers_clear_uniform_set(RenderBufferDat
}
void RasterizerSceneHighEndRD::_render_buffers_uniform_set_changed(RID p_render_buffers) {
-
RenderBufferDataHighEnd *rb = (RenderBufferDataHighEnd *)render_buffers_get_data(p_render_buffers);
_render_buffers_clear_uniform_set(rb);
@@ -2311,11 +2873,9 @@ RID RasterizerSceneHighEndRD::_render_buffers_get_normal_texture(RID p_render_bu
}
void RasterizerSceneHighEndRD::_update_render_buffers_uniform_set(RID p_render_buffers) {
-
RenderBufferDataHighEnd *rb = (RenderBufferDataHighEnd *)render_buffers_get_data(p_render_buffers);
if (rb->uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->uniform_set)) {
-
Vector<RD::Uniform> uniforms;
{
RD::Uniform u;
@@ -2366,7 +2926,7 @@ void RasterizerSceneHighEndRD::_update_render_buffers_uniform_set(RID p_render_b
}
}
-RasterizerSceneHighEndRD *RasterizerSceneHighEndRD::singleton = NULL;
+RasterizerSceneHighEndRD *RasterizerSceneHighEndRD::singleton = nullptr;
void RasterizerSceneHighEndRD::set_time(double p_time, double p_step) {
time = p_time;
@@ -2405,11 +2965,11 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag
}
{ //lights
- scene_state.max_lights = MIN(65536, uniform_max_size) / sizeof(LightData);
+ scene_state.max_lights = MIN(1024 * 1024, uniform_max_size) / sizeof(LightData); //1mb of lights
uint32_t light_buffer_size = scene_state.max_lights * sizeof(LightData);
scene_state.lights = memnew_arr(LightData, scene_state.max_lights);
- scene_state.light_buffer = RD::get_singleton()->uniform_buffer_create(light_buffer_size);
- defines += "\n#define MAX_LIGHT_DATA_STRUCTS " + itos(scene_state.max_lights) + "\n";
+ scene_state.light_buffer = RD::get_singleton()->storage_buffer_create(light_buffer_size);
+ //defines += "\n#define MAX_LIGHT_DATA_STRUCTS " + itos(scene_state.max_lights) + "\n";
scene_state.max_directional_lights = 8;
uint32_t directional_light_buffer_size = scene_state.max_directional_lights * sizeof(DirectionalLightData);
@@ -2447,6 +3007,31 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag
scene_state.gi_probe_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(GIProbeData) * scene_state.max_gi_probes);
defines += "\n#define MAX_GI_PROBES " + itos(scene_state.max_gi_probes) + "\n";
}
+ {
+ //lightmaps
+ scene_state.max_lightmaps = storage->lightmap_array_get_size();
+ defines += "\n#define MAX_LIGHTMAP_TEXTURES " + itos(scene_state.max_lightmaps) + "\n";
+ defines += "\n#define MAX_LIGHTMAPS " + itos(scene_state.max_lightmaps) + "\n";
+
+ scene_state.lightmaps = memnew_arr(LightmapData, scene_state.max_lightmaps);
+ scene_state.lightmap_buffer = RD::get_singleton()->storage_buffer_create(sizeof(LightmapData) * scene_state.max_lightmaps);
+ }
+ {
+ //captures
+ scene_state.max_lightmap_captures = 2048;
+ scene_state.lightmap_captures = memnew_arr(LightmapCaptureData, scene_state.max_lightmap_captures);
+ scene_state.lightmap_capture_buffer = RD::get_singleton()->storage_buffer_create(sizeof(LightmapCaptureData) * scene_state.max_lightmap_captures);
+ }
+ { //decals
+ scene_state.max_decals = MIN(1024 * 1024, uniform_max_size) / sizeof(DecalData); //1mb of decals
+ uint32_t decal_buffer_size = scene_state.max_decals * sizeof(DecalData);
+ scene_state.decals = memnew_arr(DecalData, scene_state.max_decals);
+ scene_state.decal_buffer = RD::get_singleton()->storage_buffer_create(decal_buffer_size);
+ }
+
+ {
+ defines += "\n#define MATERIAL_UNIFORM_SET " + itos(MATERIAL_UNIFORM_SET) + "\n";
+ }
Vector<String> shader_versions;
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n");
@@ -2511,7 +3096,11 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag
actions.renames["ANISOTROPY"] = "anisotropy";
actions.renames["ANISOTROPY_FLOW"] = "anisotropy_flow";
actions.renames["SSS_STRENGTH"] = "sss_strength";
- actions.renames["TRANSMISSION"] = "transmission";
+ actions.renames["SSS_TRANSMITTANCE_COLOR"] = "transmittance_color";
+ actions.renames["SSS_TRANSMITTANCE_DEPTH"] = "transmittance_depth";
+ actions.renames["SSS_TRANSMITTANCE_CURVE"] = "transmittance_curve";
+ actions.renames["SSS_TRANSMITTANCE_BOOST"] = "transmittance_boost";
+ actions.renames["BACKLIGHT"] = "backlight";
actions.renames["AO"] = "ao";
actions.renames["AO_LIGHT_AFFECT"] = "ao_light_affect";
actions.renames["EMISSION"] = "emission";
@@ -2551,7 +3140,8 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag
actions.usage_defines["POSITION"] = "#define OVERRIDE_POSITION\n";
actions.usage_defines["SSS_STRENGTH"] = "#define ENABLE_SSS\n";
- actions.usage_defines["TRANSMISSION"] = "#define LIGHT_TRANSMISSION_USED\n";
+ actions.usage_defines["SSS_TRANSMITTANCE_DEPTH"] = "#define ENABLE_TRANSMITTANCE\n";
+ actions.usage_defines["BACKLIGHT"] = "#define LIGHT_BACKLIGHT_USED\n";
actions.usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n";
actions.usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n";
@@ -2574,6 +3164,8 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag
actions.render_mode_defines["diffuse_lambert_wrap"] = "#define DIFFUSE_LAMBERT_WRAP\n";
actions.render_mode_defines["diffuse_toon"] = "#define DIFFUSE_TOON\n";
+ actions.render_mode_defines["sss_mode_skin"] = "#define SSS_MODE_SKIN\n";
+
bool force_blinn = GLOBAL_GET("rendering/quality/shading/force_blinn_over_ggx");
if (!force_blinn) {
@@ -2599,6 +3191,8 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag
actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
+ actions.global_buffer_array_variable = "global_variables.data";
+ actions.instance_uniform_index_variable = "instances.data[instance_index].instance_uniforms_ofs";
shader.compiler.initialize(actions);
}
@@ -2609,7 +3203,6 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag
render_pass = 0;
{
-
scene_state.max_instances = render_list.max_elements;
scene_state.instances = memnew_arr(InstanceData, scene_state.max_instances);
scene_state.instance_buffer = RD::get_singleton()->storage_buffer_create(sizeof(InstanceData) * scene_state.max_instances);
@@ -2629,7 +3222,6 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag
}
{
-
overdraw_material_shader = storage->shader_create();
storage->shader_set_code(overdraw_material_shader, "shader_type spatial;\nrender_mode blend_add,unshaded;\n void fragment() { ALBEDO=vec3(0.4,0.8,0.8); ALPHA=0.2; }");
overdraw_material = storage->material_create();
@@ -2653,7 +3245,6 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag
default_vec4_xform_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, TRANSFORMS_UNIFORM_SET);
}
{
-
RD::SamplerState sampler;
sampler.mag_filter = RD::SAMPLER_FILTER_LINEAR;
sampler.min_filter = RD::SAMPLER_FILTER_LINEAR;
@@ -2719,11 +3310,17 @@ RasterizerSceneHighEndRD::~RasterizerSceneHighEndRD() {
RD::get_singleton()->free(scene_state.gi_probe_buffer);
RD::get_singleton()->free(scene_state.directional_light_buffer);
RD::get_singleton()->free(scene_state.light_buffer);
+ RD::get_singleton()->free(scene_state.lightmap_buffer);
+ RD::get_singleton()->free(scene_state.lightmap_capture_buffer);
RD::get_singleton()->free(scene_state.reflection_buffer);
+ RD::get_singleton()->free(scene_state.decal_buffer);
memdelete_arr(scene_state.instances);
memdelete_arr(scene_state.gi_probes);
memdelete_arr(scene_state.directional_lights);
memdelete_arr(scene_state.lights);
+ memdelete_arr(scene_state.lightmaps);
+ memdelete_arr(scene_state.lightmap_captures);
memdelete_arr(scene_state.reflections);
+ memdelete_arr(scene_state.decals);
}
}
diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h b/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h
index 4c3422cedb..8438a4f730 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h
+++ b/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h
@@ -38,7 +38,6 @@
#include "servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl.gen.h"
class RasterizerSceneHighEndRD : public RasterizerSceneRD {
-
enum {
SCENE_UNIFORM_SET = 0,
RADIANCE_UNIFORM_SET = 1,
@@ -75,7 +74,6 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
/* Material */
struct ShaderData : public RasterizerStorageRD::ShaderData {
-
enum BlendMode { //used internally
BLEND_MODE_MIX,
BLEND_MODE_ADD,
@@ -138,6 +136,7 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
bool unshaded;
bool uses_vertex;
bool uses_sss;
+ bool uses_transmittance;
bool uses_screen_texture;
bool uses_depth_texture;
bool uses_normal_texture;
@@ -151,6 +150,8 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
virtual void set_code(const String &p_Code);
virtual void set_default_texture_param(const StringName &p_name, RID p_texture);
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
+ void get_instance_param_list(List<RasterizerStorage::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;
@@ -190,23 +191,36 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
struct PushConstant {
uint32_t index;
- uint32_t pad[3];
+ uint32_t pad;
+ float bake_uv2_offset[2];
};
/* Framebuffer */
struct RenderBufferDataHighEnd : public RenderBufferData {
//for rendering, may be MSAAd
+
RID color;
RID depth;
RID specular;
RID normal_buffer;
RID roughness_buffer;
+
+ RS::ViewportMSAA msaa;
+ RD::TextureSamples texture_samples;
+
+ RID color_msaa;
+ RID depth_msaa;
+ RID specular_msaa;
+ RID normal_buffer_msaa;
+ RID roughness_buffer_msaa;
+
RID depth_fb;
RID depth_normal_fb;
RID depth_normal_roughness_fb;
RID color_fb;
RID color_specular_fb;
+ RID specular_only_fb;
int width, height;
void ensure_specular();
@@ -226,6 +240,8 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
RID render_base_uniform_set;
RID view_dependant_uniform_set;
+ uint64_t lightmap_texture_array_version = 0xFFFFFFFF;
+
virtual void _base_uniforms_changed();
void _render_buffers_clear_uniform_set(RenderBufferDataHighEnd *rb);
virtual void _render_buffers_uniform_set_changed(RID p_render_buffers);
@@ -252,29 +268,51 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
float position[3];
float inv_radius;
float direction[3];
+ float size;
uint16_t attenuation_energy[2]; //16 bits attenuation, then energy
uint8_t color_specular[4]; //rgb color, a specular (8 bit unorm)
uint16_t cone_attenuation_angle[2]; // attenuation and angle, (16bit float)
- uint32_t mask;
uint8_t shadow_color_enabled[4]; //shadow rgb color, a>0.5 enabled (8bit unorm)
float atlas_rect[4]; // in omni, used for atlas uv, in spot, used for projector uv
float shadow_matrix[16];
+ float shadow_bias;
+ float shadow_normal_bias;
+ float transmittance_bias;
+ float soft_shadow_size;
+ float soft_shadow_scale;
+ uint32_t mask;
+ uint32_t pad[2];
+ float projector_rect[4];
};
struct DirectionalLightData {
-
float direction[3];
float energy;
float color[3];
+ float size;
float specular;
- float shadow_color[3];
uint32_t mask;
+ float softshadow_angle;
+ float soft_shadow_scale;
uint32_t blend_splits;
uint32_t shadow_enabled;
float fade_from;
float fade_to;
+ float shadow_bias[4];
+ float shadow_normal_bias[4];
+ float shadow_transmittance_bias[4];
+ float shadow_transmittance_z_scale[4];
+ float shadow_range_begin[4];
float shadow_split_offsets[4];
float shadow_matrices[4][16];
+ float shadow_color1[4];
+ float shadow_color2[4];
+ float shadow_color3[4];
+ float shadow_color4[4];
+ float uv_scale1[2];
+ float uv_scale2[2];
+ float uv_scale3[2];
+ float uv_scale4[2];
};
struct GIProbeData {
@@ -293,7 +331,37 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
uint32_t pad[1];
};
+ struct LightmapData {
+ float normal_xform[12];
+ };
+
+ struct DecalData {
+ float xform[16];
+ float inv_extents[3];
+ float albedo_mix;
+ float albedo_rect[4];
+ float normal_rect[4];
+ float orm_rect[4];
+ float emission_rect[4];
+ float modulate[4];
+ float emission_energy;
+ uint32_t mask;
+ float upper_fade;
+ float lower_fade;
+ float normal_xform[12];
+ float normal[3];
+ float normal_fade;
+ };
+
+ struct LightmapCaptureData {
+ float sh[9 * 4];
+ };
+
enum {
+ INSTANCE_DATA_FLAG_USE_LIGHTMAP_CAPTURE = 1 << 8,
+ INSTANCE_DATA_FLAG_USE_LIGHTMAP = 1 << 9,
+ INSTANCE_DATA_FLAG_USE_SH_LIGHTMAP = 1 << 10,
+ INSTANCE_DATA_FLAG_USE_GIPROBE = 1 << 11,
INSTANCE_DATA_FLAG_MULTIMESH = 1 << 12,
INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D = 1 << 13,
INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR = 1 << 14,
@@ -307,9 +375,10 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
float transform[16];
float normal_transform[16];
uint32_t flags;
- uint32_t instance_ofs; //instance_offset in instancing/skeleton buffer
+ uint32_t instance_uniforms_ofs; //instance_offset in instancing/skeleton buffer
uint32_t gi_offset; //GI information when using lightmapping (VCT or lightmap)
uint32_t mask;
+ float lightmap_uv_scale[4];
};
struct SceneState {
@@ -323,12 +392,22 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
float viewport_size[2];
float screen_pixel_size[2];
- float shadow_z_offset;
- float shadow_z_slope_scale;
-
float time;
float reflection_multiplier;
+ uint32_t pancake_shadows;
+ uint32_t pad;
+
+ float directional_penumbra_shadow_kernel[128]; //32 vec4s
+ float directional_soft_shadow_kernel[128];
+ float penumbra_shadow_kernel[128];
+ float soft_shadow_kernel[128];
+
+ uint32_t directional_penumbra_shadow_samples;
+ uint32_t directional_soft_shadow_samples;
+ uint32_t penumbra_shadow_samples;
+ uint32_t soft_shadow_samples;
+
float ambient_light_color_energy[4];
float ambient_color_sky_mix;
@@ -352,6 +431,9 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
uint32_t roughness_limiter_enabled;
float ao_color[4];
+
+ uint32_t material_uv2_mode;
+ uint32_t pad_material[3];
};
UBO ubo;
@@ -368,6 +450,14 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
RID gi_probe_buffer;
uint32_t max_gi_probe_probes_per_instance;
+ LightmapData *lightmaps;
+ uint32_t max_lightmaps;
+ RID lightmap_buffer;
+
+ DecalData *decals;
+ uint32_t max_decals;
+ RID decal_buffer;
+
LightData *lights;
uint32_t max_lights;
RID light_buffer;
@@ -376,6 +466,10 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
uint32_t max_directional_lights;
RID directional_light_buffer;
+ LightmapCaptureData *lightmap_captures;
+ uint32_t max_lightmap_captures;
+ RID lightmap_capture_buffer;
+
RID instance_buffer;
InstanceData *instances;
uint32_t max_instances;
@@ -386,12 +480,12 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
bool used_sss = false;
uint32_t current_shader_index = 0;
uint32_t current_material_index = 0;
+
} scene_state;
/* Render List */
struct RenderList {
-
int max_elements;
struct Element {
@@ -422,7 +516,6 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
int alpha_element_count;
void clear() {
-
element_count = 0;
alpha_element_count = 0;
}
@@ -430,14 +523,12 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
//should eventually be replaced by radix
struct SortByKey {
-
_FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const {
return A->sort_key < B->sort_key;
}
};
void sort_by_key(bool p_alpha) {
-
SortArray<Element *, SortByKey> sorter;
if (p_alpha) {
sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count);
@@ -447,7 +538,6 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
}
struct SortByDepth {
-
_FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const {
return A->instance->depth < B->instance->depth;
}
@@ -464,7 +554,6 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
}
struct SortByReverseDepthAndPriority {
-
_FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const {
uint32_t layer_A = uint32_t(A->priority);
uint32_t layer_B = uint32_t(B->priority);
@@ -487,17 +576,17 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
}
_FORCE_INLINE_ Element *add_element() {
-
- if (element_count + alpha_element_count >= max_elements)
- return NULL;
+ if (element_count + alpha_element_count >= max_elements) {
+ return nullptr;
+ }
elements[element_count] = &base_elements[element_count];
return elements[element_count++];
}
_FORCE_INLINE_ Element *add_alpha_element() {
-
- if (element_count + alpha_element_count >= max_elements)
- return NULL;
+ if (element_count + alpha_element_count >= max_elements) {
+ return nullptr;
+ }
int idx = max_elements - alpha_element_count - 1;
elements[idx] = &base_elements[idx];
alpha_element_count++;
@@ -505,17 +594,16 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
}
void init() {
-
element_count = 0;
alpha_element_count = 0;
elements = memnew_arr(Element *, max_elements);
base_elements = memnew_arr(Element, max_elements);
- for (int i = 0; i < max_elements; i++)
+ for (int i = 0; i < max_elements; i++) {
elements[i] = &base_elements[i]; // assign elements
+ }
}
RenderList() {
-
max_elements = 0;
}
@@ -557,22 +645,25 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
PASS_MODE_DEPTH_MATERIAL,
};
- void _setup_environment(RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers = false);
+ void _setup_environment(RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false);
void _setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, RID p_shadow_atlas, bool p_using_shadows);
+ void _setup_decals(const RID *p_decal_instances, int p_decal_count, const Transform &p_camera_inverse_xform);
void _setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, RID p_environment);
void _setup_gi_probes(RID *p_gi_probe_probe_cull_result, int p_gi_probe_probe_cull_count, const Transform &p_camera_transform);
+ void _setup_lightmaps(InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, const Transform &p_cam_transform);
void _fill_instances(RenderList::Element **p_elements, int p_element_count, bool p_for_depth);
- void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, RID p_radiance_uniform_set, RID p_render_buffers_uniform_set);
+ void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, RID p_radiance_uniform_set, RID p_render_buffers_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2());
_FORCE_INLINE_ void _add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode, uint32_t p_geometry_index);
_FORCE_INLINE_ void _add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, RID p_material_rid, PassMode p_pass_mode, uint32_t p_geometry_index);
void _fill_render_list(InstanceBase **p_cull_result, int p_cull_count, PassMode p_pass_mode, bool p_no_gi);
protected:
- virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color);
- virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip);
+ virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color);
+ virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake);
virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region);
+ virtual void _render_uv2(InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region);
public:
virtual void set_time(double p_time, double p_step);
diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp
index 517eea12f4..689552be2f 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp
+++ b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp
@@ -36,8 +36,19 @@
uint64_t RasterizerSceneRD::auto_exposure_counter = 2;
-void RasterizerSceneRD::_clear_reflection_data(ReflectionData &rd) {
+void get_vogel_disk(float *r_kernel, int p_sample_count) {
+ const float golden_angle = 2.4;
+
+ for (int i = 0; i < p_sample_count; i++) {
+ float r = Math::sqrt(float(i) + 0.5) / Math::sqrt(float(p_sample_count));
+ float theta = float(i) * golden_angle;
+
+ r_kernel[i * 4] = Math::cos(theta) * r;
+ r_kernel[i * 4 + 1] = Math::sin(theta) * r;
+ }
+}
+void RasterizerSceneRD::_clear_reflection_data(ReflectionData &rd) {
rd.layers.clear();
rd.radiance_base_cubemap = RID();
if (rd.downsampled_radiance_cubemap.is_valid()) {
@@ -140,7 +151,6 @@ void RasterizerSceneRD::_update_reflection_data(ReflectionData &rd, int p_size,
}
void RasterizerSceneRD::_create_reflection_fast_filter(ReflectionData &rd, bool p_use_arrays) {
-
storage->get_effects()->cubemap_downsample(rd.radiance_base_cubemap, rd.downsampled_layer.mipmaps[0].view, rd.downsampled_layer.mipmaps[0].size);
for (int i = 1; i < rd.downsampled_layer.mipmaps.size(); i++) {
@@ -162,29 +172,23 @@ void RasterizerSceneRD::_create_reflection_fast_filter(ReflectionData &rd, bool
}
void RasterizerSceneRD::_create_reflection_importance_sample(ReflectionData &rd, bool p_use_arrays, int p_cube_side, int p_base_layer) {
-
if (p_use_arrays) {
-
//render directly to the layers
storage->get_effects()->cubemap_roughness(rd.radiance_base_cubemap, rd.layers[p_base_layer].views[0], p_cube_side, sky_ggx_samples_quality, float(p_base_layer) / (rd.layers.size() - 1.0), rd.layers[p_base_layer].mipmaps[0].size.x);
} else {
-
storage->get_effects()->cubemap_roughness(rd.layers[0].views[p_base_layer - 1], rd.layers[0].views[p_base_layer], p_cube_side, sky_ggx_samples_quality, float(p_base_layer) / (rd.layers[0].mipmaps.size() - 1.0), rd.layers[0].mipmaps[p_base_layer].size.x);
}
}
void RasterizerSceneRD::_update_reflection_mipmaps(ReflectionData &rd) {
-
if (sky_use_cubemap_array) {
-
for (int i = 0; i < rd.layers.size(); i++) {
for (int j = 0; j < rd.layers[i].mipmaps.size() - 1; j++) {
for (int k = 0; k < 6; k++) {
RID view = rd.layers[i].mipmaps[j].views[k];
- RID fb = rd.layers[i].mipmaps[j + 1].framebuffers[k];
- Vector2 size = rd.layers[i].mipmaps[j].size;
- size = Vector2(1.0 / size.x, 1.0 / size.y);
- storage->get_effects()->make_mipmap(view, fb, size);
+ RID texture = rd.layers[i].mipmaps[j + 1].views[k];
+ Size2i size = rd.layers[i].mipmaps[j + 1].size;
+ storage->get_effects()->make_mipmap(view, texture, size);
}
}
}
@@ -252,13 +256,49 @@ void RasterizerSceneRD::sky_set_material(RID p_sky, RID p_material) {
Sky *sky = sky_owner.getornull(p_sky);
ERR_FAIL_COND(!sky);
sky->material = p_material;
+ _sky_invalidate(sky);
+}
+
+Ref<Image> RasterizerSceneRD::sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) {
+ Sky *sky = sky_owner.getornull(p_sky);
+ ERR_FAIL_COND_V(!sky, Ref<Image>());
+
+ _update_dirty_skys();
+
+ if (sky->radiance.is_valid()) {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
+ tf.width = p_size.width;
+ tf.height = p_size.height;
+ tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
+
+ RID rad_tex = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ storage->get_effects()->copy_cubemap_to_panorama(sky->radiance, rad_tex, p_size, p_bake_irradiance ? roughness_layers : 0, sky->reflection.layers.size() > 1);
+ Vector<uint8_t> data = RD::get_singleton()->texture_get_data(rad_tex, 0);
+ RD::get_singleton()->free(rad_tex);
+
+ Ref<Image> img;
+ img.instance();
+ img->create(p_size.width, p_size.height, false, Image::FORMAT_RGBAF, data);
+ for (int i = 0; i < p_size.width; i++) {
+ for (int j = 0; j < p_size.height; j++) {
+ Color c = img->get_pixel(i, j);
+ c.r *= p_energy;
+ c.g *= p_energy;
+ c.b *= p_energy;
+ img->set_pixel(i, j, c);
+ }
+ }
+ return img;
+ }
+
+ return Ref<Image>();
}
-void RasterizerSceneRD::_update_dirty_skys() {
+void RasterizerSceneRD::_update_dirty_skys() {
Sky *sky = dirty_sky_list;
while (sky) {
-
bool texture_set_dirty = false;
//update sky configuration if texture is missing
@@ -370,7 +410,6 @@ RID RasterizerSceneRD::sky_get_radiance_uniform_set_rd(RID p_sky, RID p_shader,
ERR_FAIL_COND_V(!sky, RID());
if (sky->uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(sky->uniform_set)) {
-
sky->uniform_set = RID();
if (sky->radiance.is_valid()) {
Vector<RD::Uniform> uniforms;
@@ -390,7 +429,6 @@ RID RasterizerSceneRD::sky_get_radiance_uniform_set_rd(RID p_sky, RID p_shader,
}
RID RasterizerSceneRD::_get_sky_textures(Sky *p_sky, SkyTextureSetVersion p_version) {
-
if (p_sky->texture_uniform_sets[p_version].is_valid() && RD::get_singleton()->uniform_set_is_valid(p_sky->texture_uniform_sets[p_version])) {
return p_sky->texture_uniform_sets[p_version];
}
@@ -456,8 +494,7 @@ RID RasterizerSceneRD::sky_get_material(RID p_sky) const {
return sky->material;
}
-void RasterizerSceneRD::_draw_sky(bool p_can_continue, RID p_fb, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform) {
-
+void RasterizerSceneRD::_draw_sky(bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform) {
ERR_FAIL_COND(!is_environment(p_environment));
Sky *sky = sky_owner.getornull(environment_get_sky(p_environment));
@@ -465,12 +502,12 @@ void RasterizerSceneRD::_draw_sky(bool p_can_continue, RID p_fb, RID p_environme
RID sky_material = sky_get_material(environment_get_sky(p_environment));
- SkyMaterialData *material = NULL;
+ SkyMaterialData *material = nullptr;
if (sky_material.is_valid()) {
material = (SkyMaterialData *)storage->material_get_data(sky_material, RasterizerStorageRD::SHADER_TYPE_SKY);
if (!material || !material->shader_data->valid) {
- material = NULL;
+ material = nullptr;
}
}
@@ -494,7 +531,6 @@ void RasterizerSceneRD::_draw_sky(bool p_can_continue, RID p_fb, RID p_environme
CameraMatrix camera;
if (custom_fov) {
-
float near_plane = p_projection.get_z_near();
float far_plane = p_projection.get_z_far();
float aspect = p_projection.get_aspect();
@@ -537,13 +573,12 @@ void RasterizerSceneRD::_draw_sky(bool p_can_continue, RID p_fb, RID p_environme
RID texture_uniform_set = _get_sky_textures(sky, SKY_TEXTURE_SET_BACKGROUND);
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_fb, RD::INITIAL_ACTION_CONTINUE, p_can_continue ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, p_can_continue ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ);
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_fb, RD::INITIAL_ACTION_CONTINUE, p_can_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, p_can_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ);
storage->get_effects()->render_sky(draw_list, time, p_fb, sky_scene_state.sampler_uniform_set, sky_scene_state.light_uniform_set, pipeline, material->uniform_set, texture_uniform_set, camera, sky_transform, multiplier, p_transform.origin);
RD::get_singleton()->draw_list_end();
}
void RasterizerSceneRD::_setup_sky(RID p_environment, const Vector3 &p_position, const Size2i p_screen_size) {
-
ERR_FAIL_COND(!is_environment(p_environment));
Sky *sky = sky_owner.getornull(environment_get_sky(p_environment));
@@ -551,12 +586,12 @@ void RasterizerSceneRD::_setup_sky(RID p_environment, const Vector3 &p_position,
RID sky_material = sky_get_material(environment_get_sky(p_environment));
- SkyMaterialData *material = NULL;
+ SkyMaterialData *material = nullptr;
if (sky_material.is_valid()) {
material = (SkyMaterialData *)storage->material_get_data(sky_material, RasterizerStorageRD::SHADER_TYPE_SKY);
if (!material || !material->shader_data->valid) {
- material = NULL;
+ material = nullptr;
}
}
@@ -601,26 +636,22 @@ void RasterizerSceneRD::_setup_sky(RID p_environment, const Vector3 &p_position,
}
if (shader_data->uses_time && time - sky->prev_time > 0.00001) {
-
sky->prev_time = time;
sky->reflection.dirty = true;
RenderingServerRaster::redraw_request();
}
if (material != sky->prev_material) {
-
sky->prev_material = material;
sky->reflection.dirty = true;
}
if (material->uniform_set_updated) {
-
material->uniform_set_updated = false;
sky->reflection.dirty = true;
}
if (!p_position.is_equal_approx(sky->prev_position) && shader_data->uses_position) {
-
sky->prev_position = p_position;
sky->reflection.dirty = true;
}
@@ -644,7 +675,8 @@ void RasterizerSceneRD::_setup_sky(RID p_environment, const Vector3 &p_position,
sky_scene_state.directional_lights[i].color[0] != sky_scene_state.last_frame_directional_lights[i].color[0] ||
sky_scene_state.directional_lights[i].color[1] != sky_scene_state.last_frame_directional_lights[i].color[1] ||
sky_scene_state.directional_lights[i].color[2] != sky_scene_state.last_frame_directional_lights[i].color[2] ||
- sky_scene_state.directional_lights[i].enabled != sky_scene_state.last_frame_directional_lights[i].enabled) {
+ sky_scene_state.directional_lights[i].enabled != sky_scene_state.last_frame_directional_lights[i].enabled ||
+ sky_scene_state.directional_lights[i].size != sky_scene_state.last_frame_directional_lights[i].size) {
light_data_dirty = true;
break;
}
@@ -652,7 +684,6 @@ void RasterizerSceneRD::_setup_sky(RID p_environment, const Vector3 &p_position,
}
if (light_data_dirty || sky_scene_state.light_uniform_set.is_null()) {
-
RD::get_singleton()->buffer_update(sky_scene_state.directional_light_buffer, 0, sizeof(SkyDirectionalLightData) * sky_scene_state.max_directional_lights, sky_scene_state.directional_lights, true);
if (sky_scene_state.light_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sky_scene_state.light_uniform_set)) {
@@ -680,7 +711,6 @@ void RasterizerSceneRD::_setup_sky(RID p_environment, const Vector3 &p_position,
}
void RasterizerSceneRD::_update_sky(RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform) {
-
ERR_FAIL_COND(!is_environment(p_environment));
Sky *sky = sky_owner.getornull(environment_get_sky(p_environment));
@@ -688,12 +718,12 @@ void RasterizerSceneRD::_update_sky(RID p_environment, const CameraMatrix &p_pro
RID sky_material = sky_get_material(environment_get_sky(p_environment));
- SkyMaterialData *material = NULL;
+ SkyMaterialData *material = nullptr;
if (sky_material.is_valid()) {
material = (SkyMaterialData *)storage->material_get_data(sky_material, RasterizerStorageRD::SHADER_TYPE_SKY);
if (!material || !material->shader_data->valid) {
- material = NULL;
+ material = nullptr;
}
}
@@ -712,7 +742,6 @@ void RasterizerSceneRD::_update_sky(RID p_environment, const CameraMatrix &p_pro
// Update radiance cubemap
if (sky->reflection.dirty) {
-
static const Vector3 view_normals[6] = {
Vector3(+1, 0, 0),
Vector3(-1, 0, 0),
@@ -840,18 +869,22 @@ void RasterizerSceneRD::SkyShaderData::set_code(const String &p_code) {
actions.usage_flag_pointers["LIGHT0_ENERGY"] = &uses_light;
actions.usage_flag_pointers["LIGHT0_DIRECTION"] = &uses_light;
actions.usage_flag_pointers["LIGHT0_COLOR"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT0_SIZE"] = &uses_light;
actions.usage_flag_pointers["LIGHT1_ENABLED"] = &uses_light;
actions.usage_flag_pointers["LIGHT1_ENERGY"] = &uses_light;
actions.usage_flag_pointers["LIGHT1_DIRECTION"] = &uses_light;
actions.usage_flag_pointers["LIGHT1_COLOR"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT1_SIZE"] = &uses_light;
actions.usage_flag_pointers["LIGHT2_ENABLED"] = &uses_light;
actions.usage_flag_pointers["LIGHT2_ENERGY"] = &uses_light;
actions.usage_flag_pointers["LIGHT2_DIRECTION"] = &uses_light;
actions.usage_flag_pointers["LIGHT2_COLOR"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT2_SIZE"] = &uses_light;
actions.usage_flag_pointers["LIGHT3_ENABLED"] = &uses_light;
actions.usage_flag_pointers["LIGHT3_ENERGY"] = &uses_light;
actions.usage_flag_pointers["LIGHT3_DIRECTION"] = &uses_light;
actions.usage_flag_pointers["LIGHT3_COLOR"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT3_SIZE"] = &uses_light;
actions.uniforms = &uniforms;
@@ -889,7 +922,6 @@ void RasterizerSceneRD::SkyShaderData::set_code(const String &p_code) {
//update pipelines
for (int i = 0; i < SKY_VERSION_MAX; i++) {
-
RD::PipelineDepthStencilState depth_stencil_state;
depth_stencil_state.enable_depth_test = true;
depth_stencil_state.depth_compare_operator = RD::COMPARE_OP_LESS_OR_EQUAL;
@@ -910,10 +942,12 @@ void RasterizerSceneRD::SkyShaderData::set_default_texture_param(const StringNam
}
void RasterizerSceneRD::SkyShaderData::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();
@@ -923,13 +957,27 @@ void RasterizerSceneRD::SkyShaderData::get_param_list(List<PropertyInfo> *p_para
}
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 RasterizerSceneRD::SkyShaderData::get_instance_param_list(List<RasterizerStorage::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;
+ }
+
+ RasterizerStorage::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().hint);
+ p_param_list->push_back(p);
+ }
+}
+
bool RasterizerSceneRD::SkyShaderData::is_param_texture(const StringName &p_param) const {
if (!uniforms.has(p_param)) {
return false;
@@ -974,7 +1022,6 @@ RasterizerStorageRD::ShaderData *RasterizerSceneRD::_create_sky_shader_func() {
}
void RasterizerSceneRD::SkyMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
-
RasterizerSceneRD *scene_singleton = (RasterizerSceneRD *)RasterizerSceneRD::singleton;
uniform_set_updated = true;
@@ -1001,7 +1048,6 @@ void RasterizerSceneRD::SkyMaterialData::update_parameters(const Map<StringName,
//check whether buffer changed
if (p_uniform_dirty && ubo_data.size()) {
-
update_uniform_buffer(shader_data->uniforms, shader_data->ubo_offsets.ptr(), p_parameters, ubo_data.ptrw(), ubo_data.size(), false);
RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw());
}
@@ -1020,7 +1066,6 @@ void RasterizerSceneRD::SkyMaterialData::update_parameters(const Map<StringName,
}
if (p_textures_dirty && tex_uniform_count) {
-
update_textures(p_parameters, shader_data->default_texture_params, shader_data->texture_uniforms, texture_cache.ptrw(), true);
}
@@ -1037,7 +1082,6 @@ void RasterizerSceneRD::SkyMaterialData::update_parameters(const Map<StringName,
Vector<RD::Uniform> uniforms;
{
-
if (shader_data->ubo_size) {
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
@@ -1078,7 +1122,6 @@ RasterizerStorageRD::MaterialData *RasterizerSceneRD::_create_sky_material_func(
}
RID RasterizerSceneRD::environment_create() {
-
return environment_owner.make_rid(Environent());
}
@@ -1087,36 +1130,43 @@ void RasterizerSceneRD::environment_set_background(RID p_env, RS::EnvironmentBG
ERR_FAIL_COND(!env);
env->background = p_bg;
}
+
void RasterizerSceneRD::environment_set_sky(RID p_env, RID p_sky) {
Environent *env = environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);
env->sky = p_sky;
}
+
void RasterizerSceneRD::environment_set_sky_custom_fov(RID p_env, float p_scale) {
Environent *env = environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);
env->sky_custom_fov = p_scale;
}
+
void RasterizerSceneRD::environment_set_sky_orientation(RID p_env, const Basis &p_orientation) {
Environent *env = environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);
env->sky_orientation = p_orientation;
}
+
void RasterizerSceneRD::environment_set_bg_color(RID p_env, const Color &p_color) {
Environent *env = environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);
env->bg_color = p_color;
}
+
void RasterizerSceneRD::environment_set_bg_energy(RID p_env, float p_energy) {
Environent *env = environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);
env->bg_energy = p_energy;
}
+
void RasterizerSceneRD::environment_set_canvas_max_layer(RID p_env, int p_max_layer) {
Environent *env = environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);
env->canvas_max_layer = p_max_layer;
}
+
void RasterizerSceneRD::environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient, float p_energy, float p_sky_contribution, RS::EnvironmentReflectionSource p_reflection_source, const Color &p_ao_color) {
Environent *env = environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);
@@ -1133,56 +1183,67 @@ RS::EnvironmentBG RasterizerSceneRD::environment_get_background(RID p_env) const
ERR_FAIL_COND_V(!env, RS::ENV_BG_MAX);
return env->background;
}
+
RID RasterizerSceneRD::environment_get_sky(RID p_env) const {
Environent *env = environment_owner.getornull(p_env);
ERR_FAIL_COND_V(!env, RID());
return env->sky;
}
+
float RasterizerSceneRD::environment_get_sky_custom_fov(RID p_env) const {
Environent *env = environment_owner.getornull(p_env);
ERR_FAIL_COND_V(!env, 0);
return env->sky_custom_fov;
}
+
Basis RasterizerSceneRD::environment_get_sky_orientation(RID p_env) const {
Environent *env = environment_owner.getornull(p_env);
ERR_FAIL_COND_V(!env, Basis());
return env->sky_orientation;
}
+
Color RasterizerSceneRD::environment_get_bg_color(RID p_env) const {
Environent *env = environment_owner.getornull(p_env);
ERR_FAIL_COND_V(!env, Color());
return env->bg_color;
}
+
float RasterizerSceneRD::environment_get_bg_energy(RID p_env) const {
Environent *env = environment_owner.getornull(p_env);
ERR_FAIL_COND_V(!env, 0);
return env->bg_energy;
}
+
int RasterizerSceneRD::environment_get_canvas_max_layer(RID p_env) const {
Environent *env = environment_owner.getornull(p_env);
ERR_FAIL_COND_V(!env, 0);
return env->canvas_max_layer;
}
+
Color RasterizerSceneRD::environment_get_ambient_light_color(RID p_env) const {
Environent *env = environment_owner.getornull(p_env);
ERR_FAIL_COND_V(!env, Color());
return env->ambient_light;
}
-RS::EnvironmentAmbientSource RasterizerSceneRD::environment_get_ambient_light_ambient_source(RID p_env) const {
+
+RS::EnvironmentAmbientSource RasterizerSceneRD::environment_get_ambient_source(RID p_env) const {
Environent *env = environment_owner.getornull(p_env);
ERR_FAIL_COND_V(!env, RS::ENV_AMBIENT_SOURCE_BG);
return env->ambient_source;
}
-float RasterizerSceneRD::environment_get_ambient_light_ambient_energy(RID p_env) const {
+
+float RasterizerSceneRD::environment_get_ambient_light_energy(RID p_env) const {
Environent *env = environment_owner.getornull(p_env);
ERR_FAIL_COND_V(!env, 0);
return env->ambient_light_energy;
}
+
float RasterizerSceneRD::environment_get_ambient_sky_contribution(RID p_env) const {
Environent *env = environment_owner.getornull(p_env);
ERR_FAIL_COND_V(!env, 0);
return env->ambient_sky_contribution;
}
+
RS::EnvironmentReflectionSource RasterizerSceneRD::environment_get_reflection_source(RID p_env) const {
Environent *env = environment_owner.getornull(p_env);
ERR_FAIL_COND_V(!env, RS::ENV_REFLECTION_SOURCE_DISABLED);
@@ -1212,7 +1273,6 @@ void RasterizerSceneRD::environment_set_tonemap(RID p_env, RS::EnvironmentToneMa
}
void RasterizerSceneRD::environment_set_glow(RID p_env, bool p_enable, int p_level_flags, 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) {
-
Environent *env = environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);
env->glow_enabled = p_enable;
@@ -1231,8 +1291,26 @@ void RasterizerSceneRD::environment_glow_set_use_bicubic_upscale(bool p_enable)
glow_bicubic_upscale = p_enable;
}
-void RasterizerSceneRD::environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_bias, float p_light_affect, float p_ao_channel_affect, RS::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) {
+void RasterizerSceneRD::environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) {
+ Environent *env = environment_owner.getornull(p_env);
+ ERR_FAIL_COND(!env);
+
+ env->ssr_enabled = p_enable;
+ env->ssr_max_steps = p_max_steps;
+ env->ssr_fade_in = p_fade_int;
+ env->ssr_fade_out = p_fade_out;
+ env->ssr_depth_tolerance = p_depth_tolerance;
+}
+void RasterizerSceneRD::environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) {
+ ssr_roughness_quality = p_quality;
+}
+
+RS::EnvironmentSSRRoughnessQuality RasterizerSceneRD::environment_get_ssr_roughness_quality() const {
+ return ssr_roughness_quality;
+}
+
+void RasterizerSceneRD::environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_bias, float p_light_affect, float p_ao_channel_affect, RS::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) {
Environent *env = environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);
@@ -1251,7 +1329,6 @@ void RasterizerSceneRD::environment_set_ssao_quality(RS::EnvironmentSSAOQuality
}
bool RasterizerSceneRD::environment_is_ssao_enabled(RID p_env) const {
-
Environent *env = environment_owner.getornull(p_env);
ERR_FAIL_COND_V(!env, false);
return env->ssao_enabled;
@@ -1262,6 +1339,7 @@ float RasterizerSceneRD::environment_get_ssao_ao_affect(RID p_env) const {
ERR_FAIL_COND_V(!env, false);
return env->ssao_ao_channel_affect;
}
+
float RasterizerSceneRD::environment_get_ssao_light_affect(RID p_env) const {
Environent *env = environment_owner.getornull(p_env);
ERR_FAIL_COND_V(!env, false);
@@ -1269,20 +1347,55 @@ float RasterizerSceneRD::environment_get_ssao_light_affect(RID p_env) const {
}
bool RasterizerSceneRD::environment_is_ssr_enabled(RID p_env) const {
-
Environent *env = environment_owner.getornull(p_env);
ERR_FAIL_COND_V(!env, false);
- return false;
+ return env->ssr_enabled;
}
bool RasterizerSceneRD::is_environment(RID p_env) const {
return environment_owner.owns(p_env);
}
+Ref<Image> RasterizerSceneRD::environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) {
+ Environent *env = environment_owner.getornull(p_env);
+ ERR_FAIL_COND_V(!env, Ref<Image>());
+
+ if (env->background == RS::ENV_BG_CAMERA_FEED || env->background == RS::ENV_BG_CANVAS || env->background == RS::ENV_BG_KEEP) {
+ return Ref<Image>(); //nothing to bake
+ }
+
+ if (env->background == RS::ENV_BG_CLEAR_COLOR || env->background == RS::ENV_BG_COLOR) {
+ Color color;
+ if (env->background == RS::ENV_BG_CLEAR_COLOR) {
+ color = storage->get_default_clear_color();
+ } else {
+ color = env->bg_color;
+ }
+ color.r *= env->bg_energy;
+ color.g *= env->bg_energy;
+ color.b *= env->bg_energy;
+
+ Ref<Image> ret;
+ ret.instance();
+ ret->create(p_size.width, p_size.height, false, Image::FORMAT_RGBAF);
+ for (int i = 0; i < p_size.width; i++) {
+ for (int j = 0; j < p_size.height; j++) {
+ ret->set_pixel(i, j, color);
+ }
+ }
+ return ret;
+ }
+
+ if (env->background == RS::ENV_BG_SKY && env->sky.is_valid()) {
+ return sky_bake_panorama(env->sky, env->bg_energy, p_bake_irradiance, p_size);
+ }
+
+ return Ref<Image>();
+}
+
////////////////////////////////////////////////////////////
RID RasterizerSceneRD::reflection_atlas_create() {
-
ReflectionAtlas ra;
ra.count = GLOBAL_GET("rendering/quality/reflection_atlas/reflection_count");
ra.size = GLOBAL_GET("rendering/quality/reflection_atlas/reflection_size");
@@ -1291,7 +1404,6 @@ RID RasterizerSceneRD::reflection_atlas_create() {
}
void RasterizerSceneRD::reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) {
-
ReflectionAtlas *ra = reflection_atlas_owner.getornull(p_ref_atlas);
ERR_FAIL_COND(!ra);
@@ -1338,7 +1450,6 @@ void RasterizerSceneRD::reflection_probe_instance_set_transform(RID p_instance,
}
void RasterizerSceneRD::reflection_probe_release_atlas_index(RID p_instance) {
-
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
ERR_FAIL_COND(!rpi);
@@ -1354,7 +1465,6 @@ void RasterizerSceneRD::reflection_probe_release_atlas_index(RID p_instance) {
}
bool RasterizerSceneRD::reflection_probe_instance_needs_redraw(RID p_instance) {
-
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
ERR_FAIL_COND_V(!rpi, false);
@@ -1374,7 +1484,6 @@ bool RasterizerSceneRD::reflection_probe_instance_needs_redraw(RID p_instance) {
}
bool RasterizerSceneRD::reflection_probe_instance_has_reflection(RID p_instance) {
-
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
ERR_FAIL_COND_V(!rpi, false);
@@ -1382,7 +1491,6 @@ bool RasterizerSceneRD::reflection_probe_instance_has_reflection(RID p_instance)
}
bool RasterizerSceneRD::reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) {
-
ReflectionAtlas *atlas = reflection_atlas_owner.getornull(p_reflection_atlas);
ERR_FAIL_COND_V(!atlas, false);
@@ -1427,7 +1535,6 @@ bool RasterizerSceneRD::reflection_probe_instance_begin_render(RID p_instance, R
atlas->reflection = RD::get_singleton()->texture_create(tf, RD::TextureView());
}
{
-
RD::TextureFormat tf;
tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D32_SFLOAT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D32_SFLOAT : RD::DATA_FORMAT_X8_D24_UNORM_PACK32;
tf.width = atlas->size;
@@ -1483,7 +1590,6 @@ bool RasterizerSceneRD::reflection_probe_instance_begin_render(RID p_instance, R
}
bool RasterizerSceneRD::reflection_probe_instance_postprocess_step(RID p_instance) {
-
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
ERR_FAIL_COND_V(!rpi, false);
ERR_FAIL_COND_V(!rpi->rendering, false);
@@ -1561,25 +1667,23 @@ RID RasterizerSceneRD::reflection_probe_instance_get_depth_framebuffer(RID p_ins
///////////////////////////////////////////////////////////
RID RasterizerSceneRD::shadow_atlas_create() {
-
return shadow_atlas_owner.make_rid(ShadowAtlas());
}
void RasterizerSceneRD::shadow_atlas_set_size(RID p_atlas, int p_size) {
-
ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_atlas);
ERR_FAIL_COND(!shadow_atlas);
ERR_FAIL_COND(p_size < 0);
p_size = next_power_of_2(p_size);
- if (p_size == shadow_atlas->size)
+ if (p_size == shadow_atlas->size) {
return;
+ }
// erasing atlas
if (shadow_atlas->depth.is_valid()) {
RD::get_singleton()->free(shadow_atlas->depth);
shadow_atlas->depth = RID();
- shadow_atlas->fb = RID();
}
for (int i = 0; i < 4; i++) {
//clear subdivisions
@@ -1600,23 +1704,17 @@ void RasterizerSceneRD::shadow_atlas_set_size(RID p_atlas, int p_size) {
shadow_atlas->size = p_size;
if (shadow_atlas->size) {
-
RD::TextureFormat tf;
tf.format = RD::DATA_FORMAT_R32_SFLOAT;
tf.width = shadow_atlas->size;
tf.height = shadow_atlas->size;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
shadow_atlas->depth = RD::get_singleton()->texture_create(tf, RD::TextureView());
-
- Vector<RID> fb;
- fb.push_back(shadow_atlas->depth);
- shadow_atlas->fb = RD::get_singleton()->framebuffer_create(fb);
}
}
void RasterizerSceneRD::shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) {
-
ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_atlas);
ERR_FAIL_COND(!shadow_atlas);
ERR_FAIL_INDEX(p_quadrant, 4);
@@ -1631,12 +1729,12 @@ void RasterizerSceneRD::shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p
//obtain the number that will be x*x
- if (shadow_atlas->quadrants[p_quadrant].subdivision == subdiv)
+ if (shadow_atlas->quadrants[p_quadrant].subdivision == subdiv) {
return;
+ }
//erase all data from quadrant
for (int i = 0; i < shadow_atlas->quadrants[p_quadrant].shadows.size(); i++) {
-
if (shadow_atlas->quadrants[p_quadrant].shadows[i].owner.is_valid()) {
shadow_atlas->shadow_owners.erase(shadow_atlas->quadrants[p_quadrant].shadows[i].owner);
LightInstance *li = light_instance_owner.getornull(shadow_atlas->quadrants[p_quadrant].shadows[i].owner);
@@ -1679,9 +1777,7 @@ void RasterizerSceneRD::shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p
}
bool RasterizerSceneRD::_shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow) {
-
for (int i = p_quadrant_count - 1; i >= 0; i--) {
-
int qidx = p_in_quadrants[i];
if (shadow_atlas->quadrants[qidx].subdivision == (uint32_t)p_current_subdiv) {
@@ -1706,10 +1802,10 @@ bool RasterizerSceneRD::_shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int
ERR_CONTINUE(!sli);
if (sli->last_scene_pass != scene_pass) {
-
//was just allocated, don't kill it so soon, wait a bit..
- if (p_tick - sarr[j].alloc_tick < shadow_atlas_realloc_tolerance_msec)
+ if (p_tick - sarr[j].alloc_tick < shadow_atlas_realloc_tolerance_msec) {
continue;
+ }
if (found_used_idx == -1 || sli->last_scene_pass < min_pass) {
found_used_idx = j;
@@ -1718,8 +1814,9 @@ bool RasterizerSceneRD::_shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int
}
}
- if (found_free_idx == -1 && found_used_idx == -1)
+ if (found_free_idx == -1 && found_used_idx == -1) {
continue; //nothing found
+ }
if (found_free_idx == -1 && found_used_idx != -1) {
found_free_idx = found_used_idx;
@@ -1735,7 +1832,6 @@ bool RasterizerSceneRD::_shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int
}
bool RasterizerSceneRD::shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) {
-
ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_atlas);
ERR_FAIL_COND_V(!shadow_atlas, false);
@@ -1758,13 +1854,15 @@ bool RasterizerSceneRD::shadow_atlas_update_light(RID p_atlas, RID p_light_intan
for (int i = 0; i < 4; i++) {
int q = shadow_atlas->size_order[i];
int sd = shadow_atlas->quadrants[q].subdivision;
- if (sd == 0)
+ if (sd == 0) {
continue; //unused
+ }
int max_fit = quad_size / sd;
- if (best_size != -1 && max_fit > best_size)
+ if (best_size != -1 && max_fit > best_size) {
break; //too large
+ }
valid_quadrants[valid_quadrant_count++] = q;
best_subdiv = sd;
@@ -1869,7 +1967,6 @@ bool RasterizerSceneRD::shadow_atlas_update_light(RID p_atlas, RID p_light_intan
}
void RasterizerSceneRD::directional_shadow_atlas_set_size(int p_size) {
-
p_size = nearest_power_of_2_templated(p_size);
if (directional_shadow.size == p_size) {
@@ -1881,34 +1978,27 @@ void RasterizerSceneRD::directional_shadow_atlas_set_size(int p_size) {
if (directional_shadow.depth.is_valid()) {
RD::get_singleton()->free(directional_shadow.depth);
directional_shadow.depth = RID();
- directional_shadow.fb = RID();
}
if (p_size > 0) {
-
RD::TextureFormat tf;
tf.format = RD::DATA_FORMAT_R32_SFLOAT;
tf.width = p_size;
tf.height = p_size;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
directional_shadow.depth = RD::get_singleton()->texture_create(tf, RD::TextureView());
- Vector<RID> fb;
- fb.push_back(directional_shadow.depth);
- directional_shadow.fb = RD::get_singleton()->framebuffer_create(fb);
}
_base_uniforms_changed();
}
void RasterizerSceneRD::set_directional_shadow_count(int p_count) {
-
directional_shadow.light_count = p_count;
directional_shadow.current_light = 0;
}
static Rect2i _get_directional_shadow_rect(int p_size, int p_shadow_count, int p_shadow_index) {
-
int split_h = 1;
int split_v = 1;
@@ -1931,7 +2021,6 @@ static Rect2i _get_directional_shadow_rect(int p_size, int p_shadow_count, int p
}
int RasterizerSceneRD::get_directional_light_shadow_size(RID p_light_intance) {
-
ERR_FAIL_COND_V(directional_shadow.light_count == 0, 0);
Rect2i r = _get_directional_shadow_rect(directional_shadow.size, directional_shadow.light_count, 0);
@@ -1942,8 +2031,12 @@ int RasterizerSceneRD::get_directional_light_shadow_size(RID p_light_intance) {
switch (storage->light_directional_get_shadow_mode(light_instance->light)) {
case RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL:
break; //none
- case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: r.size.height /= 2; break;
- case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: r.size /= 2; break;
+ case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS:
+ r.size.height /= 2;
+ break;
+ case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS:
+ r.size /= 2;
+ break;
}
return MAX(r.size.width, r.size.height);
@@ -1952,18 +2045,15 @@ int RasterizerSceneRD::get_directional_light_shadow_size(RID p_light_intance) {
//////////////////////////////////////////////////
RID RasterizerSceneRD::camera_effects_create() {
-
return camera_effects_owner.make_rid(CameraEffects());
}
void RasterizerSceneRD::camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) {
-
dof_blur_quality = p_quality;
dof_blur_use_jitter = p_use_jitter;
}
void RasterizerSceneRD::camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape) {
-
dof_blur_bokeh_shape = p_shape;
}
@@ -1983,7 +2073,6 @@ void RasterizerSceneRD::camera_effects_set_dof_blur(RID p_camera_effects, bool p
}
void RasterizerSceneRD::camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) {
-
CameraEffects *camfx = camera_effects_owner.getornull(p_camera_effects);
ERR_FAIL_COND(!camfx);
@@ -1992,7 +2081,6 @@ void RasterizerSceneRD::camera_effects_set_custom_exposure(RID p_camera_effects,
}
RID RasterizerSceneRD::light_instance_create(RID p_light) {
-
RID li = light_instance_owner.make_rid(LightInstance());
LightInstance *light_instance = light_instance_owner.getornull(li);
@@ -2005,15 +2093,13 @@ RID RasterizerSceneRD::light_instance_create(RID p_light) {
}
void RasterizerSceneRD::light_instance_set_transform(RID p_light_instance, const Transform &p_transform) {
-
LightInstance *light_instance = light_instance_owner.getornull(p_light_instance);
ERR_FAIL_COND(!light_instance);
light_instance->transform = p_transform;
}
-void RasterizerSceneRD::light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale) {
-
+void RasterizerSceneRD::light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale, float p_range_begin, const Vector2 &p_uv_scale) {
LightInstance *light_instance = light_instance_owner.getornull(p_light_instance);
ERR_FAIL_COND(!light_instance);
@@ -2028,10 +2114,12 @@ void RasterizerSceneRD::light_instance_set_shadow_transform(RID p_light_instance
light_instance->shadow_transform[p_pass].farplane = p_far;
light_instance->shadow_transform[p_pass].split = p_split;
light_instance->shadow_transform[p_pass].bias_scale = p_bias_scale;
+ light_instance->shadow_transform[p_pass].range_begin = p_range_begin;
+ light_instance->shadow_transform[p_pass].shadow_texel_size = p_shadow_texel_size;
+ light_instance->shadow_transform[p_pass].uv_scale = p_uv_scale;
}
void RasterizerSceneRD::light_instance_mark_visible(RID p_light_instance) {
-
LightInstance *light_instance = light_instance_owner.getornull(p_light_instance);
ERR_FAIL_COND(!light_instance);
@@ -2039,9 +2127,7 @@ void RasterizerSceneRD::light_instance_mark_visible(RID p_light_instance) {
}
RasterizerSceneRD::ShadowCubemap *RasterizerSceneRD::_get_shadow_cubemap(int p_size) {
-
if (!shadow_cubemaps.has(p_size)) {
-
ShadowCubemap sc;
{
RD::TextureFormat tf;
@@ -2068,9 +2154,7 @@ RasterizerSceneRD::ShadowCubemap *RasterizerSceneRD::_get_shadow_cubemap(int p_s
}
RasterizerSceneRD::ShadowMap *RasterizerSceneRD::_get_shadow_map(const Size2i &p_size) {
-
if (!shadow_maps.has(p_size)) {
-
ShadowMap sm;
{
RD::TextureFormat tf;
@@ -2091,6 +2175,21 @@ RasterizerSceneRD::ShadowMap *RasterizerSceneRD::_get_shadow_map(const Size2i &p
return &shadow_maps[p_size];
}
+
+//////////////////////////
+
+RID RasterizerSceneRD::decal_instance_create(RID p_decal) {
+ DecalInstance di;
+ di.decal = p_decal;
+ return decal_instance_owner.make_rid(di);
+}
+
+void RasterizerSceneRD::decal_instance_set_transform(RID p_decal, const Transform &p_transform) {
+ DecalInstance *di = decal_instance_owner.getornull(p_decal);
+ ERR_FAIL_COND(!di);
+ di->transform = p_transform;
+}
+
/////////////////////////////////
RID RasterizerSceneRD::gi_probe_instance_create(RID p_base) {
@@ -2115,7 +2214,6 @@ RID RasterizerSceneRD::gi_probe_instance_create(RID p_base) {
}
void RasterizerSceneRD::gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) {
-
GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe);
ERR_FAIL_COND(!gi_probe);
@@ -2131,7 +2229,6 @@ bool RasterizerSceneRD::gi_probe_needs_update(RID p_probe) const {
}
void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, int p_dynamic_object_count, InstanceBase **p_dynamic_objects) {
-
GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe);
ERR_FAIL_COND(!gi_probe);
@@ -2383,7 +2480,6 @@ void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instanc
dmap.depth = RD::get_singleton()->texture_create(dtf, RD::TextureView());
if (gi_probe->dynamic_maps.size() == 0) {
-
dtf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
dtf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
dmap.albedo = RD::get_singleton()->texture_create(dtf, RD::TextureView());
@@ -2491,7 +2587,6 @@ void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instanc
}
if (write) {
-
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_IMAGE;
@@ -2524,7 +2619,6 @@ void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instanc
}
if (plot) {
-
{
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_IMAGE;
@@ -2578,7 +2672,6 @@ void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instanc
uint32_t light_count = 0;
if (p_update_light_instances || p_dynamic_object_count > 0) {
-
light_count = MIN(gi_probe_max_lights, (uint32_t)p_light_instances.size());
{
@@ -2658,9 +2751,7 @@ void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instanc
int wg_limit_x = RD::get_singleton()->limit_get(RD::LIMIT_MAX_COMPUTE_WORKGROUP_COUNT_X);
for (int pass = 0; pass < passes; pass++) {
-
if (p_update_light_instances) {
-
for (int i = 0; i < gi_probe->mipmaps.size(); i++) {
if (i == 0) {
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, giprobe_lighting_shader_version_pipelines[pass == 0 ? GI_PROBE_SHADER_VERSION_COMPUTE_LIGHT : GI_PROBE_SHADER_VERSION_COMPUTE_SECOND_BOUNCE]);
@@ -2696,7 +2787,6 @@ void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instanc
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_WRITE_TEXTURE]);
for (int i = 0; i < gi_probe->mipmaps.size(); i++) {
-
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, gi_probe->mipmaps[i].write_uniform_set, 0);
push_constant.cell_offset = gi_probe->mipmaps[i].cell_offset;
@@ -2720,7 +2810,6 @@ void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instanc
gi_probe->has_dynamic_object_data = false; //clear until dynamic object data is used again
if (p_dynamic_object_count && gi_probe->dynamic_maps.size()) {
-
Vector3i octree_size = storage->gi_probe_get_octree_size(gi_probe->probe);
int multiplier = gi_probe->dynamic_maps[0].size / MAX(MAX(octree_size.x, octree_size.y), octree_size.z);
@@ -2735,7 +2824,6 @@ void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instanc
//this could probably be better parallelized in compute..
for (int i = 0; i < p_dynamic_object_count; i++) {
-
InstanceBase *instance = p_dynamic_objects[i];
//not used, so clear
instance->depth_layer = 0;
@@ -2764,7 +2852,6 @@ void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instanc
//print_line("aabb: " + aabb);
for (int j = 0; j < 6; j++) {
-
//if (j != 0 && j != 3) {
// continue;
//}
@@ -2853,7 +2940,6 @@ void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instanc
//print_line("rect: " + itos(i) + ": " + rect);
for (int k = 1; k < gi_probe->dynamic_maps.size(); k++) {
-
// enlarge the rect if needed so all pixels fit when downscaled,
// this ensures downsampling is smooth and optimal because no pixels are left behind
@@ -2951,7 +3037,6 @@ void RasterizerSceneRD::_debug_giprobe(RID p_gi_probe, RD::DrawListID p_draw_lis
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
-
push_constant.projection[i * 4 + j] = transform.matrix[i][j];
}
}
@@ -3014,7 +3099,6 @@ void RasterizerSceneRD::_debug_giprobe(RID p_gi_probe, RD::DrawListID p_draw_lis
}
const Vector<RID> &RasterizerSceneRD::gi_probe_get_slots() const {
-
return gi_probe_slots;
}
@@ -3039,7 +3123,7 @@ void RasterizerSceneRD::_allocate_blur_textures(RenderBuffers *rb) {
tf.width = rb->width;
tf.height = rb->height;
tf.type = RD::TEXTURE_TYPE_2D;
- tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
+ tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
tf.mipmaps = mipmaps_required;
rb->blur[0].texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
@@ -3053,14 +3137,8 @@ void RasterizerSceneRD::_allocate_blur_textures(RenderBuffers *rb) {
int base_height = rb->height;
for (uint32_t i = 0; i < mipmaps_required; i++) {
-
RenderBuffers::Blur::Mipmap mm;
mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->blur[0].texture, 0, i);
- {
- Vector<RID> fbs;
- fbs.push_back(mm.texture);
- mm.framebuffer = RD::get_singleton()->framebuffer_create(fbs);
- }
mm.width = base_width;
mm.height = base_height;
@@ -3068,13 +3146,7 @@ void RasterizerSceneRD::_allocate_blur_textures(RenderBuffers *rb) {
rb->blur[0].mipmaps.push_back(mm);
if (i > 0) {
-
mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->blur[1].texture, 0, i - 1);
- {
- Vector<RID> fbs;
- fbs.push_back(mm.texture);
- mm.framebuffer = RD::get_singleton()->framebuffer_create(fbs);
- }
rb->blur[1].mipmaps.push_back(mm);
}
@@ -3118,7 +3190,6 @@ void RasterizerSceneRD::_allocate_luminance_textures(RenderBuffers *rb) {
}
void RasterizerSceneRD::_free_render_buffer_data(RenderBuffers *rb) {
-
if (rb->texture.is_valid()) {
RD::get_singleton()->free(rb->texture);
rb->texture = RID();
@@ -3167,10 +3238,95 @@ void RasterizerSceneRD::_free_render_buffer_data(RenderBuffers *rb) {
rb->ssao.ao_full = RID();
rb->ssao.depth_slices.clear();
}
+
+ if (rb->ssr.blur_radius[0].is_valid()) {
+ RD::get_singleton()->free(rb->ssr.blur_radius[0]);
+ RD::get_singleton()->free(rb->ssr.blur_radius[1]);
+ rb->ssr.blur_radius[0] = RID();
+ rb->ssr.blur_radius[1] = RID();
+ }
+
+ if (rb->ssr.depth_scaled.is_valid()) {
+ RD::get_singleton()->free(rb->ssr.depth_scaled);
+ rb->ssr.depth_scaled = RID();
+ RD::get_singleton()->free(rb->ssr.normal_scaled);
+ rb->ssr.normal_scaled = RID();
+ }
}
-void RasterizerSceneRD::_process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection) {
+void RasterizerSceneRD::_process_sss(RID p_render_buffers, const CameraMatrix &p_camera) {
+ RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ ERR_FAIL_COND(!rb);
+
+ bool can_use_effects = rb->width >= 8 && rb->height >= 8;
+
+ if (!can_use_effects) {
+ //just copy
+ return;
+ }
+
+ if (rb->blur[0].texture.is_null()) {
+ _allocate_blur_textures(rb);
+ _render_buffers_uniform_set_changed(p_render_buffers);
+ }
+
+ 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);
+}
+
+void RasterizerSceneRD::_process_ssr(RID p_render_buffers, RID p_dest_framebuffer, RID p_normal_buffer, RID p_roughness_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.getornull(p_render_buffers);
+ ERR_FAIL_COND(!rb);
+
+ bool can_use_effects = rb->width >= 8 && rb->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());
+ return;
+ }
+
+ Environent *env = environment_owner.getornull(p_environment);
+ ERR_FAIL_COND(!env);
+
+ ERR_FAIL_COND(!env->ssr_enabled);
+
+ 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.type = RD::TEXTURE_TYPE_2D;
+ tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT;
+
+ rb->ssr.depth_scaled = RD::get_singleton()->texture_create(tf, RD::TextureView());
+
+ tf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+
+ rb->ssr.normal_scaled = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ }
+
+ if (ssr_roughness_quality != RS::ENV_SSR_ROUGNESS_QUALITY_DISABLED && !rb->ssr.blur_radius[0].is_valid()) {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R8_UNORM;
+ tf.width = rb->width / 2;
+ tf.height = rb->height / 2;
+ tf.type = RD::TEXTURE_TYPE_2D;
+ tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
+
+ rb->ssr.blur_radius[0] = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ rb->ssr.blur_radius[1] = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ }
+ if (rb->blur[0].texture.is_null()) {
+ _allocate_blur_textures(rb);
+ _render_buffers_uniform_set_changed(p_render_buffers);
+ }
+
+ storage->get_effects()->screen_space_reflection(rb->texture, p_normal_buffer, ssr_roughness_quality, p_roughness_buffer, 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);
+}
+
+void RasterizerSceneRD::_process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection) {
RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
ERR_FAIL_COND(!rb);
@@ -3238,7 +3394,6 @@ void RasterizerSceneRD::_process_ssao(RID p_render_buffers, RID p_environment, R
}
void RasterizerSceneRD::_render_buffers_post_process_and_tonemap(RID p_render_buffers, RID p_environment, RID p_camera_effects, const CameraMatrix &p_projection) {
-
RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
ERR_FAIL_COND(!rb);
@@ -3249,7 +3404,6 @@ void RasterizerSceneRD::_render_buffers_post_process_and_tonemap(RID p_render_bu
bool can_use_effects = rb->width >= 8 && rb->height >= 8;
if (can_use_effects && camfx && (camfx->dof_blur_near_enabled || camfx->dof_blur_far_enabled) && camfx->dof_blur_amount > 0.0) {
-
if (rb->blur[0].texture.is_null()) {
_allocate_blur_textures(rb);
_render_buffers_uniform_set_changed(p_render_buffers);
@@ -3260,7 +3414,6 @@ void RasterizerSceneRD::_render_buffers_post_process_and_tonemap(RID p_render_bu
}
if (can_use_effects && env && env->auto_exposure) {
-
if (rb->luminance.current.is_null()) {
_allocate_luminance_textures(rb);
_render_buffers_uniform_set_changed(p_render_buffers);
@@ -3281,7 +3434,6 @@ void RasterizerSceneRD::_render_buffers_post_process_and_tonemap(RID p_render_bu
int glow_mask = 0;
if (can_use_effects && env && env->glow_enabled) {
-
/* see that blur textures are allocated */
if (rb->blur[0].texture.is_null()) {
@@ -3291,7 +3443,6 @@ void RasterizerSceneRD::_render_buffers_post_process_and_tonemap(RID p_render_bu
for (int i = 0; i < RS::MAX_GLOW_LEVELS; i++) {
if (env->glow_levels & (1 << i)) {
-
if (i >= rb->blur[1].mipmaps.size()) {
max_glow_level = rb->blur[1].mipmaps.size() - 1;
glow_mask |= 1 << max_glow_level;
@@ -3304,7 +3455,6 @@ void RasterizerSceneRD::_render_buffers_post_process_and_tonemap(RID p_render_bu
}
for (int i = 0; i < (max_glow_level + 1); i++) {
-
int vp_w = rb->blur[1].mipmaps[i].width;
int vp_h = rb->blur[1].mipmaps[i].height;
@@ -3313,9 +3463,9 @@ void RasterizerSceneRD::_render_buffers_post_process_and_tonemap(RID p_render_bu
if (env->auto_exposure && rb->luminance.current.is_valid()) {
luminance_texture = rb->luminance.current;
}
- storage->get_effects()->gaussian_glow(rb->texture, rb->blur[0].mipmaps[i + 1].framebuffer, rb->blur[0].mipmaps[i + 1].texture, rb->blur[1].mipmaps[i].framebuffer, Vector2(1.0 / vp_w, 1.0 / vp_h), env->glow_strength, 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->texture, rb->blur[0].mipmaps[i + 1].texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, 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(rb->blur[1].mipmaps[i - 1].texture, rb->blur[0].mipmaps[i + 1].framebuffer, rb->blur[0].mipmaps[i + 1].texture, rb->blur[1].mipmaps[i].framebuffer, Vector2(1.0 / vp_w, 1.0 / vp_h), env->glow_strength);
+ storage->get_effects()->gaussian_glow(rb->blur[1].mipmaps[i - 1].texture, rb->blur[0].mipmaps[i + 1].texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength);
}
}
}
@@ -3331,7 +3481,6 @@ void RasterizerSceneRD::_render_buffers_post_process_and_tonemap(RID p_render_bu
tonemap.exposure_texture = rb->luminance.current;
tonemap.auto_exposure_grey = env->auto_exp_scale;
} else {
-
tonemap.exposure_texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE);
}
@@ -3348,6 +3497,12 @@ void RasterizerSceneRD::_render_buffers_post_process_and_tonemap(RID p_render_bu
tonemap.glow_texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK);
}
+ if (rb->screen_space_aa == RS::VIEWPORT_SCREEN_SPACE_AA_FXAA) {
+ tonemap.use_fxaa = true;
+ }
+
+ tonemap.texture_size = Vector2i(rb->width, rb->height);
+
if (env) {
tonemap.tonemap_mode = env->tone_mapper;
tonemap.white = env->white;
@@ -3371,7 +3526,7 @@ void RasterizerSceneRD::_render_buffers_debug_draw(RID p_render_buffers, RID p_s
RID shadow_atlas_texture = shadow_atlas_get_texture(p_shadow_atlas);
Size2 rtsize = storage->render_target_get_size(rb->render_target);
- effects->copy_to_rect(shadow_atlas_texture, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize / 2), false, true);
+ effects->copy_to_fb_rect(shadow_atlas_texture, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, true);
}
}
@@ -3380,7 +3535,17 @@ void RasterizerSceneRD::_render_buffers_debug_draw(RID p_render_buffers, RID p_s
RID shadow_atlas_texture = directional_shadow_get_texture();
Size2 rtsize = storage->render_target_get_size(rb->render_target);
- effects->copy_to_rect(shadow_atlas_texture, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize / 2), false, true);
+ effects->copy_to_fb_rect(shadow_atlas_texture, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, true);
+ }
+ }
+
+ if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_DECAL_ATLAS) {
+ RID decal_atlas = storage->decal_atlas_get_texture();
+
+ if (decal_atlas.is_valid()) {
+ Size2 rtsize = storage->render_target_get_size(rb->render_target);
+
+ effects->copy_to_fb_rect(decal_atlas, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, false, true);
}
}
@@ -3388,29 +3553,28 @@ void RasterizerSceneRD::_render_buffers_debug_draw(RID p_render_buffers, RID p_s
if (rb->luminance.current.is_valid()) {
Size2 rtsize = storage->render_target_get_size(rb->render_target);
- effects->copy_to_rect(rb->luminance.current, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize / 8), false, true);
+ effects->copy_to_fb_rect(rb->luminance.current, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize / 8), false, true);
}
}
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SSAO && rb->ssao.ao[0].is_valid()) {
Size2 rtsize = storage->render_target_get_size(rb->render_target);
RID ao_buf = rb->ssao.ao_full.is_valid() ? rb->ssao.ao_full : rb->ssao.ao[0];
- effects->copy_to_rect(ao_buf, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, true);
+ effects->copy_to_fb_rect(ao_buf, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, true);
}
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_ROUGHNESS_LIMITER && _render_buffers_get_roughness_texture(p_render_buffers).is_valid()) {
Size2 rtsize = storage->render_target_get_size(rb->render_target);
- effects->copy_to_rect(_render_buffers_get_roughness_texture(p_render_buffers), storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, true);
+ effects->copy_to_fb_rect(_render_buffers_get_roughness_texture(p_render_buffers), storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, true);
}
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER && _render_buffers_get_normal_texture(p_render_buffers).is_valid()) {
Size2 rtsize = storage->render_target_get_size(rb->render_target);
- effects->copy_to_rect(_render_buffers_get_normal_texture(p_render_buffers), storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize));
+ effects->copy_to_fb_rect(_render_buffers_get_normal_texture(p_render_buffers), storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false);
}
}
RID RasterizerSceneRD::render_buffers_get_back_buffer_texture(RID p_render_buffers) {
-
RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
ERR_FAIL_COND_V(!rb, RID());
if (!rb->blur[0].texture.is_valid()) {
@@ -3426,13 +3590,13 @@ RID RasterizerSceneRD::render_buffers_get_ao_texture(RID p_render_buffers) {
return rb->ssao.ao_full.is_valid() ? rb->ssao.ao_full : rb->ssao.ao[0];
}
-void RasterizerSceneRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa) {
-
+void RasterizerSceneRD::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) {
RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
rb->width = p_width;
rb->height = p_height;
rb->render_target = p_render_target;
rb->msaa = p_msaa;
+ rb->screen_space_aa = p_screen_space_aa;
_free_render_buffer_data(rb);
{
@@ -3440,7 +3604,12 @@ void RasterizerSceneRD::render_buffers_configure(RID p_render_buffers, RID p_ren
tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
tf.width = rb->width;
tf.height = rb->height;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ if (rb->msaa != RS::VIEWPORT_MSAA_DISABLED) {
+ tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
+ } else {
+ tf.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+ }
rb->texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
}
@@ -3451,6 +3620,9 @@ void RasterizerSceneRD::render_buffers_configure(RID p_render_buffers, RID p_ren
tf.width = p_width;
tf.height = p_height;
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
+ if (rb->msaa != RS::VIEWPORT_MSAA_DISABLED) {
+ tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
+ }
rb->depth_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
}
@@ -3459,6 +3631,99 @@ void RasterizerSceneRD::render_buffers_configure(RID p_render_buffers, RID p_ren
_render_buffers_uniform_set_changed(p_render_buffers);
}
+void RasterizerSceneRD::sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) {
+ sss_quality = p_quality;
+}
+
+RS::SubSurfaceScatteringQuality RasterizerSceneRD::sub_surface_scattering_get_quality() const {
+ return sss_quality;
+}
+
+void RasterizerSceneRD::sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) {
+ sss_scale = p_scale;
+ sss_depth_scale = p_depth_scale;
+}
+
+void RasterizerSceneRD::shadows_quality_set(RS::ShadowQuality p_quality) {
+ ERR_FAIL_INDEX_MSG(p_quality, RS::SHADOW_QUALITY_MAX, "Shadow quality too high, please see RenderingServer's ShadowQuality enum");
+
+ if (shadows_quality != p_quality) {
+ shadows_quality = p_quality;
+
+ switch (shadows_quality) {
+ case RS::SHADOW_QUALITY_HARD: {
+ penumbra_shadow_samples = 4;
+ soft_shadow_samples = 1;
+ shadows_quality_radius = 1.0;
+ } break;
+ case RS::SHADOW_QUALITY_SOFT_LOW: {
+ penumbra_shadow_samples = 8;
+ soft_shadow_samples = 4;
+ shadows_quality_radius = 2.0;
+ } break;
+ case RS::SHADOW_QUALITY_SOFT_MEDIUM: {
+ penumbra_shadow_samples = 12;
+ soft_shadow_samples = 8;
+ shadows_quality_radius = 2.0;
+ } break;
+ case RS::SHADOW_QUALITY_SOFT_HIGH: {
+ penumbra_shadow_samples = 24;
+ soft_shadow_samples = 16;
+ shadows_quality_radius = 3.0;
+ } break;
+ case RS::SHADOW_QUALITY_SOFT_ULTRA: {
+ penumbra_shadow_samples = 32;
+ soft_shadow_samples = 32;
+ shadows_quality_radius = 4.0;
+ } break;
+ case RS::SHADOW_QUALITY_MAX:
+ break;
+ }
+ get_vogel_disk(penumbra_shadow_kernel, penumbra_shadow_samples);
+ get_vogel_disk(soft_shadow_kernel, soft_shadow_samples);
+ }
+}
+
+void RasterizerSceneRD::directional_shadow_quality_set(RS::ShadowQuality p_quality) {
+ ERR_FAIL_INDEX_MSG(p_quality, RS::SHADOW_QUALITY_MAX, "Shadow quality too high, please see RenderingServer's ShadowQuality enum");
+
+ if (directional_shadow_quality != p_quality) {
+ directional_shadow_quality = p_quality;
+
+ switch (directional_shadow_quality) {
+ case RS::SHADOW_QUALITY_HARD: {
+ directional_penumbra_shadow_samples = 4;
+ directional_soft_shadow_samples = 1;
+ directional_shadow_quality_radius = 1.0;
+ } break;
+ case RS::SHADOW_QUALITY_SOFT_LOW: {
+ directional_penumbra_shadow_samples = 8;
+ directional_soft_shadow_samples = 4;
+ directional_shadow_quality_radius = 2.0;
+ } break;
+ case RS::SHADOW_QUALITY_SOFT_MEDIUM: {
+ directional_penumbra_shadow_samples = 12;
+ directional_soft_shadow_samples = 8;
+ directional_shadow_quality_radius = 2.0;
+ } break;
+ case RS::SHADOW_QUALITY_SOFT_HIGH: {
+ directional_penumbra_shadow_samples = 24;
+ directional_soft_shadow_samples = 16;
+ directional_shadow_quality_radius = 3.0;
+ } break;
+ case RS::SHADOW_QUALITY_SOFT_ULTRA: {
+ directional_penumbra_shadow_samples = 32;
+ directional_soft_shadow_samples = 32;
+ directional_shadow_quality_radius = 4.0;
+ } break;
+ case RS::SHADOW_QUALITY_MAX:
+ break;
+ }
+ get_vogel_disk(directional_penumbra_shadow_kernel, directional_penumbra_shadow_samples);
+ get_vogel_disk(directional_soft_shadow_kernel, directional_soft_shadow_samples);
+ }
+}
+
int RasterizerSceneRD::get_roughness_layers() const {
return roughness_layers;
}
@@ -3469,12 +3734,11 @@ bool RasterizerSceneRD::is_using_radiance_cubemap_array() const {
RasterizerSceneRD::RenderBufferData *RasterizerSceneRD::render_buffers_get_data(RID p_render_buffers) {
RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
- ERR_FAIL_COND_V(!rb, NULL);
+ ERR_FAIL_COND_V(!rb, nullptr);
return rb->data;
}
-void RasterizerSceneRD::render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {
-
+void RasterizerSceneRD::render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {
Color clear_color;
if (p_render_buffers.is_valid()) {
RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
@@ -3484,7 +3748,7 @@ void RasterizerSceneRD::render_scene(RID p_render_buffers, const Transform &p_ca
clear_color = storage->get_default_clear_color();
}
- _render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_ortogonal, p_cull_result, p_cull_count, p_light_cull_result, p_light_cull_count, p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_gi_probe_cull_result, p_gi_probe_cull_count, p_environment, p_camera_effects, p_shadow_atlas, p_reflection_atlas, p_reflection_probe, p_reflection_probe_pass, clear_color);
+ _render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_ortogonal, p_cull_result, p_cull_count, p_light_cull_result, p_light_cull_count, p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_gi_probe_cull_result, p_gi_probe_cull_count, p_decal_cull_result, p_decal_cull_count, p_lightmap_cull_result, p_lightmap_cull_count, p_environment, p_camera_effects, p_shadow_atlas, p_reflection_atlas, p_reflection_probe, p_reflection_probe_pass, clear_color);
if (p_render_buffers.is_valid()) {
RENDER_TIMESTAMP("Tonemap");
@@ -3495,21 +3759,23 @@ void RasterizerSceneRD::render_scene(RID p_render_buffers, const Transform &p_ca
}
void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) {
-
LightInstance *light_instance = light_instance_owner.getornull(p_light);
ERR_FAIL_COND(!light_instance);
Rect2i atlas_rect;
- RID atlas_fb;
+ RID atlas_texture;
bool using_dual_paraboloid = false;
bool using_dual_paraboloid_flip = false;
+ float znear = 0;
float zfar = 0;
RID render_fb;
RID render_texture;
float bias = 0;
float normal_bias = 0;
+ bool use_pancake = false;
+ bool use_linear_depth = false;
bool render_cubemap = false;
bool finalize_cubemap = false;
@@ -3524,6 +3790,7 @@ void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pas
light_instance->last_scene_shadow_pass = scene_pass;
}
+ use_pancake = storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE) > 0;
light_projection = light_instance->shadow_transform[p_pass].camera;
light_transform = light_instance->shadow_transform[p_pass].transform;
@@ -3533,7 +3800,6 @@ void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pas
atlas_rect.size.height = light_instance->directional_rect.size.y;
if (storage->light_directional_get_shadow_mode(light_instance->light) == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) {
-
atlas_rect.size.width /= 2;
atlas_rect.size.height /= 2;
@@ -3547,11 +3813,9 @@ void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pas
}
} else if (storage->light_directional_get_shadow_mode(light_instance->light) == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) {
-
atlas_rect.size.height /= 2;
if (p_pass == 0) {
-
} else {
atlas_rect.position.y += atlas_rect.size.height;
}
@@ -3562,7 +3826,7 @@ void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pas
light_instance->shadow_transform[p_pass].atlas_rect.position /= directional_shadow.size;
light_instance->shadow_transform[p_pass].atlas_rect.size /= directional_shadow.size;
- float bias_mult = Math::lerp(1.0f, light_instance->shadow_transform[p_pass].bias_scale, storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE));
+ float bias_mult = light_instance->shadow_transform[p_pass].bias_scale;
zfar = storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_RANGE);
bias = storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_SHADOW_BIAS) * bias_mult;
normal_bias = storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * bias_mult;
@@ -3570,7 +3834,7 @@ void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pas
ShadowMap *shadow_map = _get_shadow_map(atlas_rect.size);
render_fb = shadow_map->fb;
render_texture = shadow_map->depth;
- atlas_fb = directional_shadow.fb;
+ atlas_texture = directional_shadow.depth;
} else {
//set from shadow atlas
@@ -3597,16 +3861,14 @@ void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pas
atlas_rect.size.width = shadow_size;
atlas_rect.size.height = shadow_size;
- atlas_fb = shadow_atlas->fb;
+ atlas_texture = shadow_atlas->depth;
zfar = storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_RANGE);
bias = storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_SHADOW_BIAS);
normal_bias = storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS);
if (storage->light_get_type(light_instance->light) == RS::LIGHT_OMNI) {
-
if (storage->light_omni_get_shadow_mode(light_instance->light) == RS::LIGHT_OMNI_SHADOW_CUBE) {
-
ShadowCubemap *cubemap = _get_shadow_cubemap(shadow_size / 2);
render_fb = cubemap->side_fb[p_pass];
@@ -3618,7 +3880,6 @@ void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pas
finalize_cubemap = p_pass == 5;
} else {
-
light_projection = light_instance->shadow_transform[0].camera;
light_transform = light_instance->shadow_transform[0].transform;
@@ -3634,33 +3895,39 @@ void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pas
}
} else if (storage->light_get_type(light_instance->light) == RS::LIGHT_SPOT) {
-
light_projection = light_instance->shadow_transform[0].camera;
light_transform = light_instance->shadow_transform[0].transform;
ShadowMap *shadow_map = _get_shadow_map(atlas_rect.size);
render_fb = shadow_map->fb;
render_texture = shadow_map->depth;
+
+ znear = light_instance->shadow_transform[0].camera.get_z_near();
+ use_linear_depth = true;
}
}
if (render_cubemap) {
//rendering to cubemap
- _render_shadow(render_fb, p_cull_result, p_cull_count, light_projection, light_transform, zfar, 0, 0, false, false);
+ _render_shadow(render_fb, p_cull_result, p_cull_count, light_projection, light_transform, zfar, 0, 0, false, false, use_pancake);
if (finalize_cubemap) {
//reblit
atlas_rect.size.height /= 2;
- storage->get_effects()->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect, light_projection.get_z_near(), light_projection.get_z_far(), bias, false);
+ storage->get_effects()->copy_cubemap_to_dp(render_texture, atlas_texture, atlas_rect, light_projection.get_z_near(), light_projection.get_z_far(), 0.0, false);
atlas_rect.position.y += atlas_rect.size.height;
- storage->get_effects()->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect, light_projection.get_z_near(), light_projection.get_z_far(), bias, true);
+ storage->get_effects()->copy_cubemap_to_dp(render_texture, atlas_texture, atlas_rect, light_projection.get_z_near(), light_projection.get_z_far(), 0.0, true);
}
} else {
//render shadow
- _render_shadow(render_fb, p_cull_result, p_cull_count, light_projection, light_transform, zfar, bias, normal_bias, using_dual_paraboloid, using_dual_paraboloid_flip);
+ _render_shadow(render_fb, p_cull_result, p_cull_count, light_projection, light_transform, zfar, bias, normal_bias, using_dual_paraboloid, using_dual_paraboloid_flip, use_pancake);
//copy to atlas
- storage->get_effects()->copy_to_rect(render_texture, atlas_fb, atlas_rect, true);
+ if (use_linear_depth) {
+ storage->get_effects()->copy_depth_to_rect_and_linearize(render_texture, atlas_texture, atlas_rect, true, znear, zfar);
+ } else {
+ storage->get_effects()->copy_depth_to_rect(render_texture, atlas_texture, atlas_rect, true);
+ }
//does not work from depth to color
//RD::get_singleton()->texture_copy(render_texture, atlas_texture, Vector3(0, 0, 0), Vector3(atlas_rect.position.x, atlas_rect.position.y, 0), Vector3(atlas_rect.size.x, atlas_rect.size.y, 1), 0, 0, 0, 0, true);
@@ -3668,12 +3935,10 @@ void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pas
}
void RasterizerSceneRD::render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) {
-
_render_material(p_cam_transform, p_cam_projection, p_cam_ortogonal, p_cull_result, p_cull_count, p_framebuffer, p_region);
}
bool RasterizerSceneRD::free(RID p_rid) {
-
if (render_buffers_owner.owns(p_rid)) {
RenderBuffers *rb = render_buffers_owner.getornull(p_rid);
_free_render_buffer_data(rb);
@@ -3693,6 +3958,8 @@ bool RasterizerSceneRD::free(RID p_rid) {
//ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_rid);
reflection_probe_release_atlas_index(p_rid);
reflection_probe_instance_owner.free(p_rid);
+ } else if (decal_instance_owner.owns(p_rid)) {
+ decal_instance_owner.free(p_rid);
} else if (gi_probe_instance_owner.owns(p_rid)) {
GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_rid);
if (gi_probe->texture.is_valid()) {
@@ -3743,7 +4010,6 @@ bool RasterizerSceneRD::free(RID p_rid) {
sky_owner.free(p_rid);
} else if (light_instance_owner.owns(p_rid)) {
-
LightInstance *light_instance = light_instance_owner.getornull(p_rid);
//remove from shadow atlases..
@@ -3761,7 +4027,6 @@ bool RasterizerSceneRD::free(RID p_rid) {
light_instance_owner.free(p_rid);
} else if (shadow_atlas_owner.owns(p_rid)) {
-
shadow_atlas_set_size(p_rid, 0);
shadow_atlas_owner.free(p_rid);
@@ -3798,7 +4063,98 @@ float RasterizerSceneRD::screen_space_roughness_limiter_get_curve() const {
return screen_space_roughness_limiter_curve;
}
-RasterizerSceneRD *RasterizerSceneRD::singleton = NULL;
+TypedArray<Image> RasterizerSceneRD::bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ tf.width = p_image_size.width; // Always 64x64
+ tf.height = p_image_size.height;
+ tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
+
+ RID albedo_alpha_tex = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RID normal_tex = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RID orm_tex = RD::get_singleton()->texture_create(tf, RD::TextureView());
+
+ tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ RID emission_tex = RD::get_singleton()->texture_create(tf, RD::TextureView());
+
+ tf.format = RD::DATA_FORMAT_R32_SFLOAT;
+ RID depth_write_tex = RD::get_singleton()->texture_create(tf, RD::TextureView());
+
+ tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
+ tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D32_SFLOAT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D32_SFLOAT : RD::DATA_FORMAT_X8_D24_UNORM_PACK32;
+ RID depth_tex = RD::get_singleton()->texture_create(tf, RD::TextureView());
+
+ Vector<RID> fb_tex;
+ fb_tex.push_back(albedo_alpha_tex);
+ fb_tex.push_back(normal_tex);
+ fb_tex.push_back(orm_tex);
+ fb_tex.push_back(emission_tex);
+ fb_tex.push_back(depth_write_tex);
+ fb_tex.push_back(depth_tex);
+
+ RID fb = RD::get_singleton()->framebuffer_create(fb_tex);
+
+ //RID sampled_light;
+
+ InstanceBase ins;
+
+ ins.base_type = RSG::storage->get_base_type(p_base);
+ ins.base = p_base;
+ ins.materials.resize(RSG::storage->mesh_get_surface_count(p_base));
+ for (int i = 0; i < ins.materials.size(); i++) {
+ if (i < p_material_overrides.size()) {
+ ins.materials.write[i] = p_material_overrides[i];
+ }
+ }
+
+ InstanceBase *cull = &ins;
+ _render_uv2(&cull, 1, fb, Rect2i(0, 0, p_image_size.width, p_image_size.height));
+
+ TypedArray<Image> ret;
+
+ {
+ PackedByteArray data = RD::get_singleton()->texture_get_data(albedo_alpha_tex, 0);
+ Ref<Image> img;
+ img.instance();
+ img->create(p_image_size.width, p_image_size.height, false, Image::FORMAT_RGBA8, data);
+ RD::get_singleton()->free(albedo_alpha_tex);
+ ret.push_back(img);
+ }
+
+ {
+ PackedByteArray data = RD::get_singleton()->texture_get_data(normal_tex, 0);
+ Ref<Image> img;
+ img.instance();
+ img->create(p_image_size.width, p_image_size.height, false, Image::FORMAT_RGBA8, data);
+ RD::get_singleton()->free(normal_tex);
+ ret.push_back(img);
+ }
+
+ {
+ PackedByteArray data = RD::get_singleton()->texture_get_data(orm_tex, 0);
+ Ref<Image> img;
+ img.instance();
+ img->create(p_image_size.width, p_image_size.height, false, Image::FORMAT_RGBA8, data);
+ RD::get_singleton()->free(orm_tex);
+ ret.push_back(img);
+ }
+
+ {
+ PackedByteArray data = RD::get_singleton()->texture_get_data(emission_tex, 0);
+ Ref<Image> img;
+ img.instance();
+ img->create(p_image_size.width, p_image_size.height, false, Image::FORMAT_RGBAH, data);
+ RD::get_singleton()->free(emission_tex);
+ ret.push_back(img);
+ }
+
+ RD::get_singleton()->free(depth_write_tex);
+ RD::get_singleton()->free(depth_tex);
+
+ return ret;
+}
+
+RasterizerSceneRD *RasterizerSceneRD::singleton = nullptr;
RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) {
storage = p_storage;
@@ -3812,7 +4168,6 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) {
uint32_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE);
{
-
//kinda complicated to compute the amount of slots, we try to use as many as we can
gi_probe_max_lights = 32;
@@ -3867,7 +4222,6 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) {
}
{
-
String defines;
if (gi_probe_use_anisotropy) {
defines += "\n#define USE_ANISOTROPY\n";
@@ -3936,21 +4290,25 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) {
actions.renames["QUARTER_RES_COLOR"] = "quarter_res_color";
actions.renames["RADIANCE"] = "radiance";
actions.renames["LIGHT0_ENABLED"] = "directional_lights.data[0].enabled";
- actions.renames["LIGHT0_DIRECTION"] = "directional_lights.data[0].direction";
- actions.renames["LIGHT0_ENERGY"] = "directional_lights.data[0].energy";
- actions.renames["LIGHT0_COLOR"] = "directional_lights.data[0].color";
+ actions.renames["LIGHT0_DIRECTION"] = "directional_lights.data[0].direction_energy.xyz";
+ actions.renames["LIGHT0_ENERGY"] = "directional_lights.data[0].direction_energy.w";
+ actions.renames["LIGHT0_COLOR"] = "directional_lights.data[0].color_size.xyz";
+ actions.renames["LIGHT0_SIZE"] = "directional_lights.data[0].color_size.w";
actions.renames["LIGHT1_ENABLED"] = "directional_lights.data[1].enabled";
- actions.renames["LIGHT1_DIRECTION"] = "directional_lights.data[1].direction";
- actions.renames["LIGHT1_ENERGY"] = "directional_lights.data[1].energy";
- actions.renames["LIGHT1_COLOR"] = "directional_lights.data[1].color";
+ actions.renames["LIGHT1_DIRECTION"] = "directional_lights.data[1].direction_energy.xyz";
+ actions.renames["LIGHT1_ENERGY"] = "directional_lights.data[1].direction_energy.w";
+ actions.renames["LIGHT1_COLOR"] = "directional_lights.data[1].color_size.xyz";
+ actions.renames["LIGHT1_SIZE"] = "directional_lights.data[1].color_size.w";
actions.renames["LIGHT2_ENABLED"] = "directional_lights.data[2].enabled";
- actions.renames["LIGHT2_DIRECTION"] = "directional_lights.data[2].direction";
- actions.renames["LIGHT2_ENERGY"] = "directional_lights.data[2].energy";
- actions.renames["LIGHT2_COLOR"] = "directional_lights.data[2].color";
+ actions.renames["LIGHT2_DIRECTION"] = "directional_lights.data[2].direction_energy.xyz";
+ actions.renames["LIGHT2_ENERGY"] = "directional_lights.data[2].direction_energy.w";
+ actions.renames["LIGHT2_COLOR"] = "directional_lights.data[2].color_size.xyz";
+ actions.renames["LIGHT2_SIZE"] = "directional_lights.data[2].color_size.w";
actions.renames["LIGHT3_ENABLED"] = "directional_lights.data[3].enabled";
- actions.renames["LIGHT3_DIRECTION"] = "directional_lights.data[3].direction";
- actions.renames["LIGHT3_ENERGY"] = "directional_lights.data[3].energy";
- actions.renames["LIGHT3_COLOR"] = "directional_lights.data[3].color";
+ actions.renames["LIGHT3_DIRECTION"] = "directional_lights.data[3].direction_energy.xyz";
+ actions.renames["LIGHT3_ENERGY"] = "directional_lights.data[3].direction_energy.w";
+ actions.renames["LIGHT3_COLOR"] = "directional_lights.data[3].color_size.xyz";
+ actions.renames["LIGHT3_SIZE"] = "directional_lights.data[3].color_size.w";
actions.renames["AT_CUBEMAP_PASS"] = "AT_CUBEMAP_PASS";
actions.renames["AT_HALF_RES_PASS"] = "AT_HALF_RES_PASS";
actions.renames["AT_QUARTER_RES_PASS"] = "AT_QUARTER_RES_PASS";
@@ -3966,6 +4324,7 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) {
actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
+ actions.global_buffer_array_variable = "global_variables.data";
sky_shader.compiler.initialize(actions);
}
@@ -3973,7 +4332,7 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) {
{
// default material and shader for sky shader
sky_shader.default_shader = storage->shader_create();
- storage->shader_set_code(sky_shader.default_shader, "shader_type sky; void fragment() { COLOR = mix(vec3(0.3), vec3(0.2, 0.4, 0.9), smoothstep(0.0, 0.05, EYEDIR.y)); } \n");
+ storage->shader_set_code(sky_shader.default_shader, "shader_type sky; void fragment() { COLOR = vec3(0.0); } \n");
sky_shader.default_material = storage->material_create();
storage->material_set_shader(sky_shader.default_material, sky_shader.default_shader);
@@ -4003,15 +4362,33 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) {
uniforms.push_back(u);
}
+ {
+ RD::Uniform u;
+ u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 1;
+ u.ids.push_back(storage->global_variables_get_storage_buffer());
+ uniforms.push_back(u);
+ }
+
sky_scene_state.sampler_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sky_shader.default_shader_rd, SKY_SET_SAMPLERS);
}
- camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape(int(GLOBAL_GET("rendering/quality/filters/depth_of_field_bokeh_shape"))));
- camera_effects_set_dof_blur_quality(RS::DOFBlurQuality(int(GLOBAL_GET("rendering/quality/filters/depth_of_field_bokeh_quality"))), GLOBAL_GET("rendering/quality/filters/depth_of_field_use_jitter"));
+ camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape(int(GLOBAL_GET("rendering/quality/depth_of_field/depth_of_field_bokeh_shape"))));
+ camera_effects_set_dof_blur_quality(RS::DOFBlurQuality(int(GLOBAL_GET("rendering/quality/depth_of_field/depth_of_field_bokeh_quality"))), GLOBAL_GET("rendering/quality/depth_of_field/depth_of_field_use_jitter"));
environment_set_ssao_quality(RS::EnvironmentSSAOQuality(int(GLOBAL_GET("rendering/quality/ssao/quality"))), GLOBAL_GET("rendering/quality/ssao/half_size"));
- screen_space_roughness_limiter = GLOBAL_GET("rendering/quality/filters/screen_space_roughness_limiter");
- screen_space_roughness_limiter_curve = GLOBAL_GET("rendering/quality/filters/screen_space_roughness_limiter_curve");
+ screen_space_roughness_limiter = GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter");
+ screen_space_roughness_limiter_curve = GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter_curve");
glow_bicubic_upscale = int(GLOBAL_GET("rendering/quality/glow/upscale_mode")) > 0;
+ ssr_roughness_quality = RS::EnvironmentSSRRoughnessQuality(int(GLOBAL_GET("rendering/quality/screen_space_reflection/roughness_quality")));
+ sss_quality = RS::SubSurfaceScatteringQuality(int(GLOBAL_GET("rendering/quality/subsurface_scattering/subsurface_scattering_quality")));
+ sss_scale = GLOBAL_GET("rendering/quality/subsurface_scattering/subsurface_scattering_scale");
+ sss_depth_scale = GLOBAL_GET("rendering/quality/subsurface_scattering/subsurface_scattering_depth_scale");
+ directional_penumbra_shadow_kernel = memnew_arr(float, 128);
+ directional_soft_shadow_kernel = memnew_arr(float, 128);
+ penumbra_shadow_kernel = memnew_arr(float, 128);
+ soft_shadow_kernel = memnew_arr(float, 128);
+ shadows_quality_set(RS::ShadowQuality(int(GLOBAL_GET("rendering/quality/shadows/soft_shadow_quality"))));
+ directional_shadow_quality_set(RS::ShadowQuality(int(GLOBAL_GET("rendering/quality/directional_shadow/soft_shadow_quality"))));
}
RasterizerSceneRD::~RasterizerSceneRD() {
@@ -4040,4 +4417,8 @@ RasterizerSceneRD::~RasterizerSceneRD() {
memdelete_arr(sky_scene_state.last_frame_directional_lights);
storage->free(sky_shader.default_shader);
storage->free(sky_shader.default_material);
+ memdelete_arr(directional_penumbra_shadow_kernel);
+ memdelete_arr(directional_soft_shadow_kernel);
+ memdelete_arr(penumbra_shadow_kernel);
+ memdelete_arr(soft_shadow_kernel);
}
diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h
index e26607aba5..781dbd50cc 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h
+++ b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h
@@ -52,15 +52,15 @@ protected:
// Skys need less info from Directional Lights than the normal shaders
struct SkyDirectionalLightData {
-
float direction[3];
float energy;
float color[3];
+ float size;
uint32_t enabled;
+ uint32_t pad[3];
};
struct SkySceneState {
-
SkyDirectionalLightData *directional_lights;
SkyDirectionalLightData *last_frame_directional_lights;
uint32_t max_directional_lights;
@@ -72,15 +72,15 @@ protected:
} sky_scene_state;
struct RenderBufferData {
-
virtual void configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa) = 0;
virtual ~RenderBufferData() {}
};
virtual RenderBufferData *_create_render_buffer_data() = 0;
- virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_color) = 0;
- virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool use_dp_flip) = 0;
+ virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_color) = 0;
+ virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool use_dp_flip, bool p_use_pancake) = 0;
virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) = 0;
+ virtual void _render_uv2(InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) = 0;
virtual void _debug_giprobe(RID p_gi_probe, RenderingDevice::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha);
@@ -92,10 +92,12 @@ protected:
virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) = 0;
void _process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection);
+ void _process_ssr(RID p_render_buffers, RID p_dest_framebuffer, RID p_normal_buffer, RID p_roughness_buffer, RID p_specular_buffer, RID p_metallic, const Color &p_metallic_mask, RID p_environment, const CameraMatrix &p_projection, bool p_use_additive);
+ void _process_sss(RID p_render_buffers, const CameraMatrix &p_camera);
void _setup_sky(RID p_environment, const Vector3 &p_position, const Size2i p_screen_size);
void _update_sky(RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform);
- void _draw_sky(bool p_can_continue, RID p_fb, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform);
+ void _draw_sky(bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform);
private:
RS::ViewportDebugDraw debug_draw = RS::VIEWPORT_DEBUG_DRAW_DISABLED;
@@ -107,7 +109,6 @@ private:
RasterizerStorageRD *storage;
struct ReflectionData {
-
struct Layer {
struct Mipmap {
RID framebuffers[6];
@@ -187,6 +188,7 @@ private:
virtual void set_code(const String &p_Code);
virtual void set_default_texture_param(const StringName &p_name, RID p_texture);
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
+ virtual void get_instance_param_list(List<RasterizerStorage::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;
@@ -281,7 +283,6 @@ private:
/* REFLECTION ATLAS */
struct ReflectionAtlas {
-
int count = 0;
int size = 0;
@@ -303,7 +304,6 @@ private:
/* REFLECTION PROBE INSTANCE */
struct ReflectionProbeInstance {
-
RID probe;
int atlas_index = -1;
RID atlas;
@@ -322,10 +322,18 @@ private:
mutable RID_Owner<ReflectionProbeInstance> reflection_probe_instance_owner;
+ /* REFLECTION PROBE INSTANCE */
+
+ struct DecalInstance {
+ RID decal;
+ Transform transform;
+ };
+
+ mutable RID_Owner<DecalInstance> decal_instance_owner;
+
/* GIPROBE INSTANCE */
struct GIProbeLight {
-
uint32_t type;
float energy;
float radius;
@@ -342,7 +350,6 @@ private:
};
struct GIProbePushConstant {
-
int32_t limits[3];
uint32_t stack_size;
@@ -358,7 +365,6 @@ private:
};
struct GIProbeDynamicPushConstant {
-
int32_t limits[3];
uint32_t light_count;
int32_t x_dir[3];
@@ -380,7 +386,6 @@ private:
};
struct GIProbeInstance {
-
RID probe;
RID texture;
RID anisotropy[2]; //only if anisotropy is used
@@ -480,7 +485,6 @@ private:
/* SHADOW ATLAS */
struct ShadowAtlas {
-
enum {
QUADRANT_SHIFT = 27,
SHADOW_INDEX_MASK = (1 << QUADRANT_SHIFT) - 1,
@@ -488,7 +492,6 @@ private:
};
struct Quadrant {
-
uint32_t subdivision;
struct Shadow {
@@ -525,11 +528,24 @@ private:
bool _shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow);
+ RS::ShadowQuality shadows_quality = RS::SHADOW_QUALITY_MAX; //So it always updates when first set
+ RS::ShadowQuality directional_shadow_quality = RS::SHADOW_QUALITY_MAX;
+ float shadows_quality_radius = 1.0;
+ float directional_shadow_quality_radius = 1.0;
+
+ float *directional_penumbra_shadow_kernel;
+ float *directional_soft_shadow_kernel;
+ float *penumbra_shadow_kernel;
+ float *soft_shadow_kernel;
+ int directional_penumbra_shadow_samples = 0;
+ int directional_soft_shadow_samples = 0;
+ int penumbra_shadow_samples = 0;
+ int soft_shadow_samples = 0;
+
/* DIRECTIONAL SHADOW */
struct DirectionalShadow {
RID depth;
- RID fb; //for copying
int light_count = 0;
int size = 0;
@@ -539,7 +555,6 @@ private:
/* SHADOW CUBEMAPS */
struct ShadowCubemap {
-
RID cubemap;
RID side_fb[6];
};
@@ -560,18 +575,19 @@ private:
/* LIGHT INSTANCE */
struct LightInstance {
-
struct ShadowTransform {
-
CameraMatrix camera;
Transform transform;
float farplane;
float split;
float bias_scale;
+ float shadow_texel_size;
+ float range_begin;
Rect2 atlas_rect;
+ Vector2 uv_scale;
};
- RS::LightType light_type;
+ RS::LightType light_type = RS::LIGHT_DIRECTIONAL;
ShadowTransform shadow_transform[4];
@@ -581,7 +597,7 @@ private:
Vector3 light_vector;
Vector3 spot_vector;
- float linear_att;
+ float linear_att = 0.0;
uint64_t shadow_pass = 0;
uint64_t last_scene_pass = 0;
@@ -590,7 +606,7 @@ private:
uint32_t light_index = 0;
uint32_t light_directional_index = 0;
- uint32_t current_shadow_atlas_key;
+ uint32_t current_shadow_atlas_key = 0;
Vector2 dp;
@@ -606,7 +622,6 @@ private:
/* ENVIRONMENT */
struct Environent {
-
// BG
RS::EnvironmentBG background = RS::ENV_BG_CLEAR_COLOR;
RID sky;
@@ -657,11 +672,20 @@ private:
float ssao_ao_channel_affect = 0.0;
float ssao_blur_edge_sharpness = 4.0;
RS::EnvironmentSSAOBlur ssao_blur = RS::ENV_SSAO_BLUR_3x3;
+
+ /// SSR
+ ///
+ bool ssr_enabled = false;
+ int ssr_max_steps = 64;
+ float ssr_fade_in = 0.15;
+ float ssr_fade_out = 2.0;
+ float ssr_depth_tolerance = 0.2;
};
RS::EnvironmentSSAOQuality ssao_quality = RS::ENV_SSAO_QUALITY_MEDIUM;
bool ssao_half_size = false;
bool glow_bicubic_upscale = false;
+ RS::EnvironmentSSRRoughnessQuality ssr_roughness_quality = RS::ENV_SSR_ROUGNESS_QUALITY_LOW;
static uint64_t auto_exposure_counter;
@@ -670,7 +694,6 @@ private:
/* CAMERA EFFECTS */
struct CameraEffects {
-
bool dof_blur_far_enabled = false;
float dof_blur_far_distance = 10;
float dof_blur_far_transition = 5;
@@ -688,16 +711,20 @@ private:
RS::DOFBlurQuality dof_blur_quality = RS::DOF_BLUR_QUALITY_MEDIUM;
RS::DOFBokehShape dof_blur_bokeh_shape = RS::DOF_BOKEH_HEXAGON;
bool dof_blur_use_jitter = false;
+ RS::SubSurfaceScatteringQuality sss_quality = RS::SUB_SURFACE_SCATTERING_QUALITY_MEDIUM;
+ float sss_scale = 0.05;
+ float sss_depth_scale = 0.01;
mutable RID_Owner<CameraEffects> camera_effects_owner;
/* RENDER BUFFERS */
struct RenderBuffers {
-
RenderBufferData *data = nullptr;
int width = 0, height = 0;
RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED;
+ RS::ViewportScreenSpaceAA screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED;
+
RID render_target;
uint64_t auto_exposure_version = 1;
@@ -711,7 +738,6 @@ private:
struct Mipmap {
RID texture;
- RID framebuffer;
int width;
int height;
};
@@ -722,7 +748,6 @@ private:
Blur blur[2]; //the second one starts from the first mipmap
struct Luminance {
-
Vector<RID> reduce;
RID current;
} luminance;
@@ -733,6 +758,12 @@ private:
RID ao[2];
RID ao_full; //when using half-size
} ssao;
+
+ struct SSR {
+ RID normal_scaled;
+ RID depth_scaled;
+ RID blur_radius[2];
+ } ssr;
};
bool screen_space_roughness_limiter = false;
@@ -793,6 +824,7 @@ public:
void sky_set_radiance_size(RID p_sky, int p_radiance_size);
void sky_set_mode(RID p_sky, RS::SkyMode p_mode);
void sky_set_material(RID p_sky, RID p_material);
+ Ref<Image> sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size);
RID sky_get_radiance_texture_rd(RID p_sky) const;
RID sky_get_radiance_uniform_set_rd(RID p_sky, RID p_shader, int p_set) const;
@@ -819,8 +851,8 @@ public:
float environment_get_bg_energy(RID p_env) const;
int environment_get_canvas_max_layer(RID p_env) const;
Color environment_get_ambient_light_color(RID p_env) const;
- RS::EnvironmentAmbientSource environment_get_ambient_light_ambient_source(RID p_env) const;
- float environment_get_ambient_light_ambient_energy(RID p_env) const;
+ RS::EnvironmentAmbientSource environment_get_ambient_source(RID p_env) const;
+ float environment_get_ambient_light_energy(RID p_env) const;
float environment_get_ambient_sky_contribution(RID p_env) const;
RS::EnvironmentReflectionSource environment_get_reflection_source(RID p_env) const;
Color environment_get_ao_color(RID p_env) const;
@@ -832,7 +864,7 @@ public:
void environment_set_fog(RID p_env, bool p_enable, float p_begin, float p_end, RID p_gradient_texture) {}
- void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance, bool p_roughness) {}
+ void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance);
void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_bias, float p_light_affect, float p_ao_channel_affect, RS::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness);
void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size);
bool environment_is_ssao_enabled(RID p_env) const;
@@ -840,6 +872,9 @@ public:
float environment_get_ssao_light_affect(RID p_env) const;
bool environment_is_ssr_enabled(RID p_env) const;
+ void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality);
+ RS::EnvironmentSSRRoughnessQuality environment_get_ssr_roughness_quality() const;
+
void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale);
void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp) {}
@@ -847,6 +882,8 @@ public:
void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_end, float p_depth_curve, bool p_transmit, float p_transmit_curve) {}
void environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve) {}
+ virtual Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size);
+
virtual RID camera_effects_create();
virtual void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter);
@@ -857,7 +894,7 @@ public:
RID light_instance_create(RID p_light);
void light_instance_set_transform(RID p_light_instance, const Transform &p_transform);
- void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale = 1.0);
+ void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &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());
void light_instance_mark_visible(RID p_light_instance);
_FORCE_INLINE_ RID light_instance_get_base_light(RID p_light_instance) {
@@ -871,7 +908,6 @@ public:
}
_FORCE_INLINE_ Rect2 light_instance_get_shadow_atlas_rect(RID p_light_instance, RID p_shadow_atlas) {
-
ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
LightInstance *li = light_instance_owner.getornull(p_light_instance);
uint32_t key = shadow_atlas->shadow_owners[li->self];
@@ -898,29 +934,69 @@ public:
}
_FORCE_INLINE_ CameraMatrix light_instance_get_shadow_camera(RID p_light_instance, int p_index) {
-
LightInstance *li = light_instance_owner.getornull(p_light_instance);
return li->shadow_transform[p_index].camera;
}
- _FORCE_INLINE_ Transform light_instance_get_shadow_transform(RID p_light_instance, int p_index) {
+ _FORCE_INLINE_ float light_instance_get_shadow_texel_size(RID p_light_instance, RID p_shadow_atlas) {
+#ifdef DEBUG_ENABLED
+ LightInstance *li = light_instance_owner.getornull(p_light_instance);
+ ERR_FAIL_COND_V(!li->shadow_atlases.has(p_shadow_atlas), 0);
+#endif
+ ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
+ ERR_FAIL_COND_V(!shadow_atlas, 0);
+#ifdef DEBUG_ENABLED
+ ERR_FAIL_COND_V(!shadow_atlas->shadow_owners.has(p_light_instance), 0);
+#endif
+ uint32_t key = shadow_atlas->shadow_owners[p_light_instance];
+
+ uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3;
+ uint32_t quadrant_size = shadow_atlas->size >> 1;
+
+ uint32_t shadow_size = (quadrant_size / shadow_atlas->quadrants[quadrant].subdivision);
+
+ return float(1.0) / shadow_size;
+ }
+
+ _FORCE_INLINE_ Transform
+ light_instance_get_shadow_transform(RID p_light_instance, int p_index) {
LightInstance *li = light_instance_owner.getornull(p_light_instance);
return li->shadow_transform[p_index].transform;
}
+ _FORCE_INLINE_ float light_instance_get_shadow_bias_scale(RID p_light_instance, int p_index) {
+ LightInstance *li = light_instance_owner.getornull(p_light_instance);
+ return li->shadow_transform[p_index].bias_scale;
+ }
+ _FORCE_INLINE_ float light_instance_get_shadow_range(RID p_light_instance, int p_index) {
+ LightInstance *li = light_instance_owner.getornull(p_light_instance);
+ return li->shadow_transform[p_index].farplane;
+ }
+ _FORCE_INLINE_ float light_instance_get_shadow_range_begin(RID p_light_instance, int p_index) {
+ LightInstance *li = light_instance_owner.getornull(p_light_instance);
+ return li->shadow_transform[p_index].range_begin;
+ }
- _FORCE_INLINE_ Rect2 light_instance_get_directional_shadow_atlas_rect(RID p_light_instance, int p_index) {
+ _FORCE_INLINE_ Vector2 light_instance_get_shadow_uv_scale(RID p_light_instance, int p_index) {
+ LightInstance *li = light_instance_owner.getornull(p_light_instance);
+ return li->shadow_transform[p_index].uv_scale;
+ }
+ _FORCE_INLINE_ Rect2 light_instance_get_directional_shadow_atlas_rect(RID p_light_instance, int p_index) {
LightInstance *li = light_instance_owner.getornull(p_light_instance);
return li->shadow_transform[p_index].atlas_rect;
}
_FORCE_INLINE_ float light_instance_get_directional_shadow_split(RID p_light_instance, int p_index) {
-
LightInstance *li = light_instance_owner.getornull(p_light_instance);
return li->shadow_transform[p_index].split;
}
+ _FORCE_INLINE_ float light_instance_get_directional_shadow_texel_size(RID p_light_instance, int p_index) {
+ LightInstance *li = light_instance_owner.getornull(p_light_instance);
+ return li->shadow_transform[p_index].shadow_texel_size;
+ }
+
_FORCE_INLINE_ void light_instance_set_render_pass(RID p_light_instance, uint64_t p_pass) {
LightInstance *li = light_instance_owner.getornull(p_light_instance);
li->last_pass = p_pass;
@@ -1013,6 +1089,19 @@ public:
return rpi->atlas_index;
}
+ virtual RID decal_instance_create(RID p_decal);
+ virtual void decal_instance_set_transform(RID p_decal, const Transform &p_transform);
+
+ _FORCE_INLINE_ RID decal_instance_get_base(RID p_decal) const {
+ DecalInstance *decal = decal_instance_owner.getornull(p_decal);
+ return decal->decal;
+ }
+
+ _FORCE_INLINE_ Transform decal_instance_get_transform(RID p_decal) const {
+ DecalInstance *decal = decal_instance_owner.getornull(p_decal);
+ return decal->transform;
+ }
+
RID gi_probe_instance_create(RID p_base);
void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform);
bool gi_probe_needs_update(RID p_probe) const;
@@ -1073,33 +1162,62 @@ public:
GIProbeQuality gi_probe_get_quality() const;
RID render_buffers_create();
- void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa);
+ 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);
RID render_buffers_get_ao_texture(RID p_render_buffers);
RID render_buffers_get_back_buffer_texture(RID p_render_buffers);
- void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_camera_effects, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
+ void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_shadow_atlas, RID p_camera_effects, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count);
void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region);
- virtual void set_scene_pass(uint64_t p_pass) { scene_pass = p_pass; }
- _FORCE_INLINE_ uint64_t get_scene_pass() { return scene_pass; }
+ virtual void set_scene_pass(uint64_t p_pass) {
+ scene_pass = p_pass;
+ }
+ _FORCE_INLINE_ uint64_t get_scene_pass() {
+ return scene_pass;
+ }
virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_curve);
virtual bool screen_space_roughness_limiter_is_active() const;
virtual float screen_space_roughness_limiter_get_curve() const;
+ virtual void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality);
+ RS::SubSurfaceScatteringQuality sub_surface_scattering_get_quality() const;
+ virtual void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale);
+
+ virtual void shadows_quality_set(RS::ShadowQuality p_quality);
+ virtual void directional_shadow_quality_set(RS::ShadowQuality p_quality);
+ _FORCE_INLINE_ RS::ShadowQuality shadows_quality_get() const { return shadows_quality; }
+ _FORCE_INLINE_ RS::ShadowQuality directional_shadow_quality_get() const { return directional_shadow_quality; }
+ _FORCE_INLINE_ float shadows_quality_radius_get() const { return shadows_quality_radius; }
+ _FORCE_INLINE_ float directional_shadow_quality_radius_get() const { return directional_shadow_quality_radius; }
+
+ _FORCE_INLINE_ float *directional_penumbra_shadow_kernel_get() { return directional_penumbra_shadow_kernel; }
+ _FORCE_INLINE_ float *directional_soft_shadow_kernel_get() { return directional_soft_shadow_kernel; }
+ _FORCE_INLINE_ float *penumbra_shadow_kernel_get() { return penumbra_shadow_kernel; }
+ _FORCE_INLINE_ float *soft_shadow_kernel_get() { return soft_shadow_kernel; }
+
+ _FORCE_INLINE_ int directional_penumbra_shadow_samples_get() const { return directional_penumbra_shadow_samples; }
+ _FORCE_INLINE_ int directional_soft_shadow_samples_get() const { return directional_soft_shadow_samples; }
+ _FORCE_INLINE_ int penumbra_shadow_samples_get() const { return penumbra_shadow_samples; }
+ _FORCE_INLINE_ int soft_shadow_samples_get() const { return soft_shadow_samples; }
+
int get_roughness_layers() const;
bool is_using_radiance_cubemap_array() const;
+ virtual TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size);
+
virtual bool free(RID p_rid);
virtual void update();
virtual void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw);
- _FORCE_INLINE_ RS::ViewportDebugDraw get_debug_draw_mode() const { return debug_draw; }
+ _FORCE_INLINE_ RS::ViewportDebugDraw get_debug_draw_mode() const {
+ return debug_draw;
+ }
virtual void set_time(double p_time, double p_step);
diff --git a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp
index b6b6b5a040..a5151d1ff8 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp
+++ b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp
@@ -31,11 +31,11 @@
#include "rasterizer_storage_rd.h"
#include "core/engine.h"
+#include "core/io/resource_loader.h"
#include "core/project_settings.h"
#include "servers/rendering/shader_language.h"
Ref<Image> RasterizerStorageRD::_validate_texture_format(const Ref<Image> &p_image, TextureToRDFormat &r_format) {
-
Ref<Image> image = p_image->duplicate();
switch (p_image->get_format()) {
@@ -130,7 +130,6 @@ Ref<Image> RasterizerStorageRD::_validate_texture_format(const Ref<Image> &p_ima
image->convert(Image::FORMAT_RGBAF);
}
- r_format.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
@@ -170,7 +169,6 @@ Ref<Image> RasterizerStorageRD::_validate_texture_format(const Ref<Image> &p_ima
image->convert(Image::FORMAT_RGBAH);
}
- r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
@@ -404,7 +402,6 @@ Ref<Image> RasterizerStorageRD::_validate_texture_format(const Ref<Image> &p_ima
} break; //etc2
case Image::FORMAT_ETC2_R11S: {
-
if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11_SNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
r_format.format = RD::DATA_FORMAT_EAC_R11_SNORM_BLOCK;
} else {
@@ -482,7 +479,6 @@ Ref<Image> RasterizerStorageRD::_validate_texture_format(const Ref<Image> &p_ima
r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
} break;
case Image::FORMAT_ETC2_RGB8A1: {
-
if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK;
r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK;
@@ -499,7 +495,6 @@ Ref<Image> RasterizerStorageRD::_validate_texture_format(const Ref<Image> &p_ima
r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
} break;
case Image::FORMAT_ETC2_RA_AS_RG: {
-
if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK;
r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK;
@@ -610,11 +605,116 @@ RID RasterizerStorageRD::texture_2d_create(const Ref<Image> &p_image) {
}
RID RasterizerStorageRD::texture_2d_layered_create(const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) {
+ ERR_FAIL_COND_V(p_layers.size() == 0, RID());
- return RID();
+ ERR_FAIL_COND_V(p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP && p_layers.size() != 6, RID());
+ ERR_FAIL_COND_V(p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP_ARRAY && (p_layers.size() < 6 || (p_layers.size() % 6) != 0), RID());
+
+ TextureToRDFormat ret_format;
+ Vector<Ref<Image>> images;
+ {
+ int valid_width = 0;
+ int valid_height = 0;
+ bool valid_mipmaps = false;
+ Image::Format valid_format = Image::FORMAT_MAX;
+
+ for (int i = 0; i < p_layers.size(); i++) {
+ ERR_FAIL_COND_V(p_layers[i]->empty(), RID());
+
+ if (i == 0) {
+ valid_width = p_layers[i]->get_width();
+ valid_height = p_layers[i]->get_height();
+ valid_format = p_layers[i]->get_format();
+ valid_mipmaps = p_layers[i]->has_mipmaps();
+ } else {
+ ERR_FAIL_COND_V(p_layers[i]->get_width() != valid_width, RID());
+ ERR_FAIL_COND_V(p_layers[i]->get_height() != valid_height, RID());
+ ERR_FAIL_COND_V(p_layers[i]->get_format() != valid_format, RID());
+ ERR_FAIL_COND_V(p_layers[i]->has_mipmaps() != valid_mipmaps, RID());
+ }
+
+ images.push_back(_validate_texture_format(p_layers[i], ret_format));
+ }
+ }
+
+ Texture texture;
+
+ texture.type = Texture::TYPE_LAYERED;
+ texture.layered_type = p_layered_type;
+
+ texture.width = p_layers[0]->get_width();
+ texture.height = p_layers[0]->get_height();
+ texture.layers = p_layers.size();
+ texture.mipmaps = p_layers[0]->get_mipmap_count() + 1;
+ texture.depth = 1;
+ texture.format = p_layers[0]->get_format();
+ texture.validated_format = images[0]->get_format();
+
+ switch (p_layered_type) {
+ case RS::TEXTURE_LAYERED_2D_ARRAY: {
+ texture.rd_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ } break;
+ case RS::TEXTURE_LAYERED_CUBEMAP: {
+ texture.rd_type = RD::TEXTURE_TYPE_CUBE;
+ } break;
+ case RS::TEXTURE_LAYERED_CUBEMAP_ARRAY: {
+ texture.rd_type = RD::TEXTURE_TYPE_CUBE_ARRAY;
+ } break;
+ }
+
+ texture.rd_format = ret_format.format;
+ texture.rd_format_srgb = ret_format.format_srgb;
+
+ RD::TextureFormat rd_format;
+ RD::TextureView rd_view;
+ { //attempt register
+ rd_format.format = texture.rd_format;
+ rd_format.width = texture.width;
+ rd_format.height = texture.height;
+ rd_format.depth = 1;
+ rd_format.array_layers = texture.layers;
+ rd_format.mipmaps = texture.mipmaps;
+ rd_format.type = texture.rd_type;
+ rd_format.samples = RD::TEXTURE_SAMPLES_1;
+ rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
+ if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) {
+ rd_format.shareable_formats.push_back(texture.rd_format);
+ rd_format.shareable_formats.push_back(texture.rd_format_srgb);
+ }
+ }
+ {
+ rd_view.swizzle_r = ret_format.swizzle_r;
+ rd_view.swizzle_g = ret_format.swizzle_g;
+ rd_view.swizzle_b = ret_format.swizzle_b;
+ rd_view.swizzle_a = ret_format.swizzle_a;
+ }
+ Vector<Vector<uint8_t>> data_slices;
+ for (int i = 0; i < images.size(); i++) {
+ Vector<uint8_t> data = images[i]->get_data(); //use image data
+ data_slices.push_back(data);
+ }
+ texture.rd_texture = RD::get_singleton()->texture_create(rd_format, rd_view, data_slices);
+ ERR_FAIL_COND_V(texture.rd_texture.is_null(), RID());
+ if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) {
+ rd_view.format_override = texture.rd_format_srgb;
+ texture.rd_texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, texture.rd_texture);
+ if (texture.rd_texture_srgb.is_null()) {
+ RD::get_singleton()->free(texture.rd_texture);
+ ERR_FAIL_COND_V(texture.rd_texture_srgb.is_null(), RID());
+ }
+ }
+
+ //used for 2D, overridable
+ texture.width_2d = texture.width;
+ texture.height_2d = texture.height;
+ texture.is_render_target = false;
+ texture.rd_view = rd_view;
+ texture.is_proxy = false;
+
+ return texture_owner.make_rid(texture);
}
-RID RasterizerStorageRD::texture_3d_create(const Vector<Ref<Image>> &p_slices) {
+RID RasterizerStorageRD::texture_3d_create(const Vector<Ref<Image>> &p_slices) {
return RID();
}
@@ -642,7 +742,6 @@ RID RasterizerStorageRD::texture_proxy_create(RID p_base) {
}
void RasterizerStorageRD::_texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer, bool p_immediate) {
-
ERR_FAIL_COND(p_image.is_null() || p_image->empty());
Texture *tex = texture_owner.getornull(p_texture);
@@ -667,14 +766,15 @@ void RasterizerStorageRD::_texture_2d_update(RID p_texture, const Ref<Image> &p_
void RasterizerStorageRD::texture_2d_update_immediate(RID p_texture, const Ref<Image> &p_image, int p_layer) {
_texture_2d_update(p_texture, p_image, p_layer, true);
}
+
void RasterizerStorageRD::texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer) {
_texture_2d_update(p_texture, p_image, p_layer, false);
}
+
void RasterizerStorageRD::texture_3d_update(RID p_texture, const Ref<Image> &p_image, int p_depth, int p_mipmap) {
}
void RasterizerStorageRD::texture_proxy_update(RID p_texture, RID p_proxy_to) {
-
Texture *tex = texture_owner.getornull(p_texture);
ERR_FAIL_COND(!tex);
ERR_FAIL_COND(!tex->is_proxy);
@@ -715,7 +815,6 @@ void RasterizerStorageRD::texture_proxy_update(RID p_texture, RID p_proxy_to) {
//these two APIs can be used together or in combination with the others.
RID RasterizerStorageRD::texture_2d_placeholder_create() {
-
//this could be better optimized to reuse an existing image , done this way
//for now to get it working
Ref<Image> image;
@@ -730,17 +829,38 @@ RID RasterizerStorageRD::texture_2d_placeholder_create() {
return texture_2d_create(image);
}
-RID RasterizerStorageRD::texture_2d_layered_placeholder_create() {
- return RID();
+RID RasterizerStorageRD::texture_2d_layered_placeholder_create(RS::TextureLayeredType p_layered_type) {
+ //this could be better optimized to reuse an existing image , done this way
+ //for now to get it working
+ Ref<Image> image;
+ image.instance();
+ image->create(4, 4, false, Image::FORMAT_RGBA8);
+
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+ image->set_pixel(i, j, Color(1, 0, 1, 1));
+ }
+ }
+
+ Vector<Ref<Image>> images;
+ if (p_layered_type == RS::TEXTURE_LAYERED_2D_ARRAY) {
+ images.push_back(image);
+ } else {
+ //cube
+ for (int i = 0; i < 6; i++) {
+ images.push_back(image);
+ }
+ }
+
+ return texture_2d_layered_create(images, p_layered_type);
}
-RID RasterizerStorageRD::texture_3d_placeholder_create() {
+RID RasterizerStorageRD::texture_3d_placeholder_create() {
return RID();
}
Ref<Image> RasterizerStorageRD::texture_2d_get(RID p_texture) const {
-
Texture *tex = texture_owner.getornull(p_texture);
ERR_FAIL_COND_V(!tex, Ref<Image>());
@@ -767,17 +887,16 @@ Ref<Image> RasterizerStorageRD::texture_2d_get(RID p_texture) const {
return image;
}
-Ref<Image> RasterizerStorageRD::texture_2d_layer_get(RID p_texture, int p_layer) const {
+Ref<Image> RasterizerStorageRD::texture_2d_layer_get(RID p_texture, int p_layer) const {
return Ref<Image>();
}
-Ref<Image> RasterizerStorageRD::texture_3d_slice_get(RID p_texture, int p_depth, int p_mipmap) const {
+Ref<Image> RasterizerStorageRD::texture_3d_slice_get(RID p_texture, int p_depth, int p_mipmap) const {
return Ref<Image>();
}
void RasterizerStorageRD::texture_replace(RID p_texture, RID p_by_texture) {
-
Texture *tex = texture_owner.getornull(p_texture);
ERR_FAIL_COND(!tex);
ERR_FAIL_COND(tex->proxy_to.is_valid()); //cant replace proxy
@@ -809,7 +928,14 @@ void RasterizerStorageRD::texture_replace(RID p_texture, RID p_by_texture) {
}
//delete last, so proxies can be updated
texture_owner.free(p_by_texture);
+
+ if (decal_atlas.textures.has(p_texture)) {
+ //belongs to decal atlas..
+
+ decal_atlas.dirty = true; //mark it dirty since it was most likely modified
+ }
}
+
void RasterizerStorageRD::texture_set_size_override(RID p_texture, int p_width, int p_height) {
Texture *tex = texture_owner.getornull(p_texture);
ERR_FAIL_COND(!tex);
@@ -823,6 +949,7 @@ void RasterizerStorageRD::texture_set_path(RID p_texture, const String &p_path)
ERR_FAIL_COND(!tex);
tex->path = p_path;
}
+
String RasterizerStorageRD::texture_get_path(RID p_texture) const {
return String();
}
@@ -833,23 +960,27 @@ void RasterizerStorageRD::texture_set_detect_3d_callback(RID p_texture, RS::Text
tex->detect_3d_callback_ud = p_userdata;
tex->detect_3d_callback = p_callback;
}
+
void RasterizerStorageRD::texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) {
Texture *tex = texture_owner.getornull(p_texture);
ERR_FAIL_COND(!tex);
tex->detect_normal_callback_ud = p_userdata;
tex->detect_normal_callback = p_callback;
}
+
void RasterizerStorageRD::texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) {
Texture *tex = texture_owner.getornull(p_texture);
ERR_FAIL_COND(!tex);
tex->detect_roughness_callback_ud = p_userdata;
tex->detect_roughness_callback = p_callback;
}
+
void RasterizerStorageRD::texture_debug_usage(List<RS::TextureInfo> *r_info) {
}
void RasterizerStorageRD::texture_set_proxy(RID p_proxy, RID p_base) {
}
+
void RasterizerStorageRD::texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) {
}
@@ -860,9 +991,8 @@ Size2 RasterizerStorageRD::texture_size_with_proxy(RID p_proxy) {
/* SHADER API */
RID RasterizerStorageRD::shader_create() {
-
Shader shader;
- shader.data = NULL;
+ shader.data = nullptr;
shader.type = SHADER_TYPE_MAX;
return shader_owner.make_rid(shader);
@@ -876,30 +1006,30 @@ void RasterizerStorageRD::shader_set_code(RID p_shader, const String &p_code) {
String mode_string = ShaderLanguage::get_shader_type(p_code);
ShaderType new_type;
- if (mode_string == "canvas_item")
+ if (mode_string == "canvas_item") {
new_type = SHADER_TYPE_2D;
- else if (mode_string == "particles")
+ } else if (mode_string == "particles") {
new_type = SHADER_TYPE_PARTICLES;
- else if (mode_string == "spatial")
+ } else if (mode_string == "spatial") {
new_type = SHADER_TYPE_3D;
- else if (mode_string == "sky")
+ } else if (mode_string == "sky") {
new_type = SHADER_TYPE_SKY;
- else
+ } else {
new_type = SHADER_TYPE_MAX;
+ }
if (new_type != shader->type) {
if (shader->data) {
memdelete(shader->data);
- shader->data = NULL;
+ shader->data = nullptr;
}
for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) {
-
Material *material = E->get();
material->shader_type = new_type;
if (material->data) {
memdelete(material->data);
- material->data = NULL;
+ material->data = nullptr;
}
}
@@ -915,6 +1045,7 @@ void RasterizerStorageRD::shader_set_code(RID p_shader, const String &p_code) {
Material *material = E->get();
if (shader->data) {
material->data = material_data_request_func[new_type](shader->data);
+ material->data->self = material->self;
material->data->set_next_pass(material->next_pass);
material->data->set_render_priority(material->priority);
}
@@ -938,8 +1069,8 @@ String RasterizerStorageRD::shader_get_code(RID p_shader) const {
ERR_FAIL_COND_V(!shader, String());
return shader->code;
}
-void RasterizerStorageRD::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const {
+void RasterizerStorageRD::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const {
Shader *shader = shader_owner.getornull(p_shader);
ERR_FAIL_COND(!shader);
if (shader->data) {
@@ -948,7 +1079,6 @@ void RasterizerStorageRD::shader_get_param_list(RID p_shader, List<PropertyInfo>
}
void RasterizerStorageRD::shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) {
-
Shader *shader = shader_owner.getornull(p_shader);
ERR_FAIL_COND(!shader);
@@ -973,6 +1103,7 @@ RID RasterizerStorageRD::shader_get_default_texture_param(RID p_shader, const St
return RID();
}
+
Variant RasterizerStorageRD::shader_get_param_default(RID p_shader, const StringName &p_param) const {
Shader *shader = shader_owner.getornull(p_shader);
ERR_FAIL_COND_V(!shader, Variant());
@@ -981,6 +1112,7 @@ Variant RasterizerStorageRD::shader_get_param_default(RID p_shader, const String
}
return Variant();
}
+
void RasterizerStorageRD::shader_set_data_request_function(ShaderType p_shader_type, ShaderDataRequestFunction p_function) {
ERR_FAIL_INDEX(p_shader_type, SHADER_TYPE_MAX);
shader_data_request_func[p_shader_type] = p_function;
@@ -989,12 +1121,11 @@ void RasterizerStorageRD::shader_set_data_request_function(ShaderType p_shader_t
/* COMMON MATERIAL API */
RID RasterizerStorageRD::material_create() {
-
Material material;
- material.data = NULL;
- material.shader = NULL;
+ material.data = nullptr;
+ material.shader = nullptr;
material.shader_type = SHADER_TYPE_MAX;
- material.update_next = NULL;
+ material.update_next = nullptr;
material.update_requested = false;
material.uniform_dirty = false;
material.texture_dirty = false;
@@ -1015,23 +1146,22 @@ void RasterizerStorageRD::_material_queue_update(Material *material, bool p_unif
material->update_next = material_update_list;
material_update_list = material;
material->update_requested = true;
- material->uniform_dirty = p_uniform;
- material->texture_dirty = p_texture;
+ material->uniform_dirty = material->uniform_dirty || p_uniform;
+ material->texture_dirty = material->texture_dirty || p_texture;
}
void RasterizerStorageRD::material_set_shader(RID p_material, RID p_shader) {
-
Material *material = material_owner.getornull(p_material);
ERR_FAIL_COND(!material);
if (material->data) {
memdelete(material->data);
- material->data = NULL;
+ material->data = nullptr;
}
if (material->shader) {
material->shader->owners.erase(material);
- material->shader = NULL;
+ material->shader = nullptr;
material->shader_type = SHADER_TYPE_MAX;
}
@@ -1050,9 +1180,10 @@ void RasterizerStorageRD::material_set_shader(RID p_material, RID p_shader) {
return;
}
- ERR_FAIL_COND(shader->data == NULL);
+ ERR_FAIL_COND(shader->data == nullptr);
material->data = material_data_request_func[shader->type](shader->data);
+ material->data->self = p_material;
material->data->set_next_pass(material->next_pass);
material->data->set_render_priority(material->priority);
//updating happens later
@@ -1061,7 +1192,6 @@ void RasterizerStorageRD::material_set_shader(RID p_material, RID p_shader) {
}
void RasterizerStorageRD::material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) {
-
Material *material = material_owner.getornull(p_material);
ERR_FAIL_COND(!material);
@@ -1104,6 +1234,7 @@ void RasterizerStorageRD::material_set_next_pass(RID p_material, RID p_next_mate
material->instance_dependency.instance_notify_changed(false, true);
}
+
void RasterizerStorageRD::material_set_render_priority(RID p_material, int priority) {
Material *material = material_owner.getornull(p_material);
ERR_FAIL_COND(!material);
@@ -1125,6 +1256,7 @@ bool RasterizerStorageRD::material_is_animated(RID p_material) {
}
return false; //by default nothing is animated
}
+
bool RasterizerStorageRD::material_casts_shadows(RID p_material) {
Material *material = material_owner.getornull(p_material);
ERR_FAIL_COND_V(!material, true);
@@ -1138,6 +1270,18 @@ bool RasterizerStorageRD::material_casts_shadows(RID p_material) {
return true; //by default everything casts shadows
}
+void RasterizerStorageRD::material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) {
+ Material *material = material_owner.getornull(p_material);
+ ERR_FAIL_COND(!material);
+ if (material->shader && material->shader->data) {
+ material->shader->data->get_instance_param_list(r_parameters);
+
+ if (material->next_pass.is_valid()) {
+ material_get_instance_shader_parameters(material->next_pass, r_parameters);
+ }
+ }
+}
+
void RasterizerStorageRD::material_update_dependency(RID p_material, RasterizerScene::InstanceBase *p_instance) {
Material *material = material_owner.getornull(p_material);
ERR_FAIL_COND(!material);
@@ -1155,14 +1299,12 @@ void RasterizerStorageRD::material_set_data_request_function(ShaderType p_shader
_FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataType type, const Variant &value, uint8_t *data, bool p_linear_color) {
switch (type) {
case ShaderLanguage::TYPE_BOOL: {
-
bool v = value;
uint32_t *gui = (uint32_t *)data;
*gui = v ? 1 : 0;
} break;
case ShaderLanguage::TYPE_BVEC2: {
-
int v = value;
uint32_t *gui = (uint32_t *)data;
gui[0] = v & 1 ? 1 : 0;
@@ -1170,7 +1312,6 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
} break;
case ShaderLanguage::TYPE_BVEC3: {
-
int v = value;
uint32_t *gui = (uint32_t *)data;
gui[0] = (v & 1) ? 1 : 0;
@@ -1179,7 +1320,6 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
} break;
case ShaderLanguage::TYPE_BVEC4: {
-
int v = value;
uint32_t *gui = (uint32_t *)data;
gui[0] = (v & 1) ? 1 : 0;
@@ -1189,14 +1329,12 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
} break;
case ShaderLanguage::TYPE_INT: {
-
int v = value;
int32_t *gui = (int32_t *)data;
gui[0] = v;
} break;
case ShaderLanguage::TYPE_IVEC2: {
-
Vector<int> iv = value;
int s = iv.size();
int32_t *gui = (int32_t *)data;
@@ -1204,15 +1342,15 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
const int *r = iv.ptr();
for (int i = 0; i < 2; i++) {
- if (i < s)
+ if (i < s) {
gui[i] = r[i];
- else
+ } else {
gui[i] = 0;
+ }
}
} break;
case ShaderLanguage::TYPE_IVEC3: {
-
Vector<int> iv = value;
int s = iv.size();
int32_t *gui = (int32_t *)data;
@@ -1220,14 +1358,14 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
const int *r = iv.ptr();
for (int i = 0; i < 3; i++) {
- if (i < s)
+ if (i < s) {
gui[i] = r[i];
- else
+ } else {
gui[i] = 0;
+ }
}
} break;
case ShaderLanguage::TYPE_IVEC4: {
-
Vector<int> iv = value;
int s = iv.size();
int32_t *gui = (int32_t *)data;
@@ -1235,21 +1373,20 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
const int *r = iv.ptr();
for (int i = 0; i < 4; i++) {
- if (i < s)
+ if (i < s) {
gui[i] = r[i];
- else
+ } else {
gui[i] = 0;
+ }
}
} break;
case ShaderLanguage::TYPE_UINT: {
-
int v = value;
uint32_t *gui = (uint32_t *)data;
gui[0] = v;
} break;
case ShaderLanguage::TYPE_UVEC2: {
-
Vector<int> iv = value;
int s = iv.size();
uint32_t *gui = (uint32_t *)data;
@@ -1257,10 +1394,11 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
const int *r = iv.ptr();
for (int i = 0; i < 2; i++) {
- if (i < s)
+ if (i < s) {
gui[i] = r[i];
- else
+ } else {
gui[i] = 0;
+ }
}
} break;
case ShaderLanguage::TYPE_UVEC3: {
@@ -1271,10 +1409,11 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
const int *r = iv.ptr();
for (int i = 0; i < 3; i++) {
- if (i < s)
+ if (i < s) {
gui[i] = r[i];
- else
+ } else {
gui[i] = 0;
+ }
}
} break;
@@ -1286,10 +1425,11 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
const int *r = iv.ptr();
for (int i = 0; i < 4; i++) {
- if (i < s)
+ if (i < s) {
gui[i] = r[i];
- else
+ } else {
gui[i] = 0;
+ }
}
} break;
case ShaderLanguage::TYPE_FLOAT: {
@@ -1314,7 +1454,6 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
} break;
case ShaderLanguage::TYPE_VEC4: {
-
float *gui = (float *)data;
if (value.get_type() == Variant::COLOR) {
@@ -1366,7 +1505,6 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
gui[7] = 0;
} break;
case ShaderLanguage::TYPE_MAT3: {
-
Basis v = value;
float *gui = (float *)data;
@@ -1384,7 +1522,6 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
gui[11] = 0;
} break;
case ShaderLanguage::TYPE_MAT4: {
-
Transform v = value;
float *gui = (float *)data;
@@ -1411,22 +1548,18 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
}
_FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type, const Vector<ShaderLanguage::ConstantNode::Value> &value, uint8_t *data) {
-
switch (type) {
case ShaderLanguage::TYPE_BOOL: {
-
uint32_t *gui = (uint32_t *)data;
*gui = value[0].boolean ? 1 : 0;
} break;
case ShaderLanguage::TYPE_BVEC2: {
-
uint32_t *gui = (uint32_t *)data;
gui[0] = value[0].boolean ? 1 : 0;
gui[1] = value[1].boolean ? 1 : 0;
} break;
case ShaderLanguage::TYPE_BVEC3: {
-
uint32_t *gui = (uint32_t *)data;
gui[0] = value[0].boolean ? 1 : 0;
gui[1] = value[1].boolean ? 1 : 0;
@@ -1434,7 +1567,6 @@ _FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type,
} break;
case ShaderLanguage::TYPE_BVEC4: {
-
uint32_t *gui = (uint32_t *)data;
gui[0] = value[0].boolean ? 1 : 0;
gui[1] = value[1].boolean ? 1 : 0;
@@ -1443,13 +1575,11 @@ _FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type,
} break;
case ShaderLanguage::TYPE_INT: {
-
int32_t *gui = (int32_t *)data;
gui[0] = value[0].sint;
} break;
case ShaderLanguage::TYPE_IVEC2: {
-
int32_t *gui = (int32_t *)data;
for (int i = 0; i < 2; i++) {
@@ -1458,7 +1588,6 @@ _FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type,
} break;
case ShaderLanguage::TYPE_IVEC3: {
-
int32_t *gui = (int32_t *)data;
for (int i = 0; i < 3; i++) {
@@ -1467,7 +1596,6 @@ _FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type,
} break;
case ShaderLanguage::TYPE_IVEC4: {
-
int32_t *gui = (int32_t *)data;
for (int i = 0; i < 4; i++) {
@@ -1476,13 +1604,11 @@ _FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type,
} break;
case ShaderLanguage::TYPE_UINT: {
-
uint32_t *gui = (uint32_t *)data;
gui[0] = value[0].uint;
} break;
case ShaderLanguage::TYPE_UVEC2: {
-
int32_t *gui = (int32_t *)data;
for (int i = 0; i < 2; i++) {
@@ -1505,13 +1631,11 @@ _FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type,
}
} break;
case ShaderLanguage::TYPE_FLOAT: {
-
float *gui = (float *)data;
gui[0] = value[0].real;
} break;
case ShaderLanguage::TYPE_VEC2: {
-
float *gui = (float *)data;
for (int i = 0; i < 2; i++) {
@@ -1520,7 +1644,6 @@ _FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type,
} break;
case ShaderLanguage::TYPE_VEC3: {
-
float *gui = (float *)data;
for (int i = 0; i < 3; i++) {
@@ -1529,7 +1652,6 @@ _FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type,
} break;
case ShaderLanguage::TYPE_VEC4: {
-
float *gui = (float *)data;
for (int i = 0; i < 4; i++) {
@@ -1550,7 +1672,6 @@ _FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type,
gui[7] = 0;
} break;
case ShaderLanguage::TYPE_MAT3: {
-
float *gui = (float *)data;
gui[0] = value[0].real;
@@ -1567,7 +1688,6 @@ _FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type,
gui[11] = 0;
} break;
case ShaderLanguage::TYPE_MAT4: {
-
float *gui = (float *)data;
for (int i = 0; i < 16; i++) {
@@ -1580,9 +1700,7 @@ _FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type,
}
_FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type, uint8_t *data) {
-
switch (type) {
-
case ShaderLanguage::TYPE_BOOL:
case ShaderLanguage::TYPE_INT:
case ShaderLanguage::TYPE_UINT:
@@ -1603,15 +1721,12 @@ _FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type,
case ShaderLanguage::TYPE_IVEC4:
case ShaderLanguage::TYPE_UVEC4:
case ShaderLanguage::TYPE_VEC4: {
-
zeromem(data, 16);
} break;
case ShaderLanguage::TYPE_MAT2: {
-
zeromem(data, 32);
} break;
case ShaderLanguage::TYPE_MAT3: {
-
zeromem(data, 48);
} break;
case ShaderLanguage::TYPE_MAT4: {
@@ -1624,11 +1739,35 @@ _FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type,
}
void RasterizerStorageRD::MaterialData::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) {
+ bool uses_global_buffer = false;
for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = p_uniforms.front(); E; E = E->next()) {
-
- if (E->get().order < 0)
+ if (E->get().order < 0) {
continue; // texture, does not go here
+ }
+
+ if (E->get().scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
+ continue; //instance uniforms don't appear in the bufferr
+ }
+
+ if (E->get().scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) {
+ //this is a global variable, get the index to it
+ RasterizerStorageRD *rs = base_singleton;
+
+ GlobalVariables::Variable *gv = rs->global_variables.variables.getptr(E->key());
+ uint32_t index = 0;
+ if (gv) {
+ index = gv->buffer_index;
+ } else {
+ WARN_PRINT("Shader uses global uniform '" + E->key() + "', but it was removed at some point. Material will not display correctly.");
+ }
+
+ uint32_t offset = p_uniform_offsets[E->get().order];
+ uint32_t *intptr = (uint32_t *)&p_buffer[offset];
+ *intptr = index;
+ uses_global_buffer = true;
+ continue;
+ }
//regular uniform
uint32_t offset = p_uniform_offsets[E->get().order];
@@ -1658,10 +1797,41 @@ void RasterizerStorageRD::MaterialData::update_uniform_buffer(const Map<StringNa
}
}
}
+
+ if (uses_global_buffer != (global_buffer_E != nullptr)) {
+ RasterizerStorageRD *rs = base_singleton;
+ if (uses_global_buffer) {
+ global_buffer_E = rs->global_variables.materials_using_buffer.push_back(self);
+ } else {
+ rs->global_variables.materials_using_buffer.erase(global_buffer_E);
+ global_buffer_E = nullptr;
+ }
+ }
}
-void RasterizerStorageRD::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) {
+RasterizerStorageRD::MaterialData::~MaterialData() {
+ if (global_buffer_E) {
+ //unregister global buffers
+ RasterizerStorageRD *rs = base_singleton;
+ rs->global_variables.materials_using_buffer.erase(global_buffer_E);
+ }
+
+ if (global_texture_E) {
+ //unregister global textures
+ RasterizerStorageRD *rs = base_singleton;
+
+ for (Map<StringName, uint64_t>::Element *E = used_global_textures.front(); E; E = E->next()) {
+ GlobalVariables::Variable *v = rs->global_variables.variables.getptr(E->key());
+ if (v) {
+ v->texture_materials.erase(self);
+ }
+ }
+ //unregister material from those using global textures
+ rs->global_variables.materials_using_texture.erase(global_texture_E);
+ }
+}
+void RasterizerStorageRD::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) {
RasterizerStorageRD *singleton = (RasterizerStorageRD *)RasterizerStorage::base_singleton;
#ifdef TOOLS_ENABLED
Texture *roughness_detect_texture = nullptr;
@@ -1669,22 +1839,52 @@ void RasterizerStorageRD::MaterialData::update_textures(const Map<StringName, Va
Texture *normal_detect_texture = nullptr;
#endif
- for (int i = 0; i < p_texture_uniforms.size(); i++) {
+ bool uses_global_textures = false;
+ global_textures_pass++;
+ for (int i = 0; i < p_texture_uniforms.size(); i++) {
const StringName &uniform_name = p_texture_uniforms[i].name;
RID texture;
- const Map<StringName, Variant>::Element *V = p_parameters.find(uniform_name);
- if (V) {
- texture = V->get();
- }
+ if (p_texture_uniforms[i].global) {
+ RasterizerStorageRD *rs = base_singleton;
- if (!texture.is_valid()) {
- const Map<StringName, RID>::Element *W = p_default_textures.find(uniform_name);
- if (W) {
+ uses_global_textures = true;
+
+ GlobalVariables::Variable *v = rs->global_variables.variables.getptr(uniform_name);
+ if (v) {
+ if (v->buffer_index >= 0) {
+ WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it changed type and is no longer a texture!.");
+
+ } else {
+ Map<StringName, uint64_t>::Element *E = used_global_textures.find(uniform_name);
+ if (!E) {
+ E = used_global_textures.insert(uniform_name, global_textures_pass);
+ v->texture_materials.insert(self);
+ } else {
+ E->get() = global_textures_pass;
+ }
+
+ texture = v->override.get_type() != Variant::NIL ? v->override : v->value;
+ }
+
+ } else {
+ WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it was removed at some point. Material will not display correctly.");
+ }
+ } else {
+ if (!texture.is_valid()) {
+ const Map<StringName, Variant>::Element *V = p_parameters.find(uniform_name);
+ if (V) {
+ texture = V->get();
+ }
+ }
- texture = W->get();
+ if (!texture.is_valid()) {
+ const Map<StringName, RID>::Element *W = p_default_textures.find(uniform_name);
+ if (W) {
+ texture = W->get();
+ }
}
}
@@ -1713,7 +1913,6 @@ void RasterizerStorageRD::MaterialData::update_textures(const Map<StringName, Va
Texture *tex = singleton->texture_owner.getornull(texture);
if (tex) {
-
rd_texture = (srgb && tex->rd_texture_srgb.is_valid()) ? tex->rd_texture_srgb : tex->rd_texture;
#ifdef TOOLS_ENABLED
if (tex->detect_3d_callback && p_use_linear_color) {
@@ -1747,6 +1946,36 @@ void RasterizerStorageRD::MaterialData::update_textures(const Map<StringName, Va
roughness_detect_texture->detect_roughness_callback(roughness_detect_texture->detect_roughness_callback_ud, normal_detect_texture->path, roughness_channel);
}
#endif
+ {
+ //for textures no longer used, unregister them
+ List<Map<StringName, uint64_t>::Element *> to_delete;
+ RasterizerStorageRD *rs = base_singleton;
+
+ for (Map<StringName, uint64_t>::Element *E = used_global_textures.front(); E; E = E->next()) {
+ if (E->get() != global_textures_pass) {
+ to_delete.push_back(E);
+
+ GlobalVariables::Variable *v = rs->global_variables.variables.getptr(E->key());
+ if (v) {
+ v->texture_materials.erase(self);
+ }
+ }
+ }
+
+ while (to_delete.front()) {
+ used_global_textures.erase(to_delete.front()->get());
+ to_delete.pop_front();
+ }
+ //handle registering/unregistering global textures
+ if (uses_global_textures != (global_texture_E != nullptr)) {
+ if (uses_global_textures) {
+ global_texture_E = rs->global_variables.materials_using_texture.push_back(self);
+ } else {
+ rs->global_variables.materials_using_texture.erase(global_texture_E);
+ global_texture_E = nullptr;
+ }
+ }
+ }
}
void RasterizerStorageRD::material_force_update_textures(RID p_material, ShaderType p_shader_type) {
@@ -1770,21 +1999,20 @@ void RasterizerStorageRD::_update_queued_materials() {
material->update_requested = false;
material->texture_dirty = false;
material->uniform_dirty = false;
- material->update_next = NULL;
+ material->update_next = nullptr;
material = next;
}
- material_update_list = NULL;
+ material_update_list = nullptr;
}
+
/* MESH API */
RID RasterizerStorageRD::mesh_create() {
-
return mesh_owner.make_rid(Mesh());
}
/// Returns stride
void RasterizerStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) {
-
Mesh *mesh = mesh_owner.getornull(p_mesh);
ERR_FAIL_COND(!mesh);
@@ -1795,17 +2023,12 @@ void RasterizerStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_
#ifdef DEBUG_ENABLED
//do a validation, to catch errors first
{
-
uint32_t stride = 0;
for (int i = 0; i < RS::ARRAY_WEIGHTS; i++) {
-
if ((p_surface.format & (1 << i))) {
-
switch (i) {
-
case RS::ARRAY_VERTEX: {
-
if (p_surface.format & RS::ARRAY_FLAG_USE_2D_VERTICES) {
stride += sizeof(float) * 2;
} else {
@@ -1814,7 +2037,6 @@ void RasterizerStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_
} break;
case RS::ARRAY_NORMAL: {
-
if (p_surface.format & RS::ARRAY_COMPRESS_NORMAL) {
stride += sizeof(int8_t) * 4;
} else {
@@ -1823,7 +2045,6 @@ void RasterizerStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_
} break;
case RS::ARRAY_TANGENT: {
-
if (p_surface.format & RS::ARRAY_COMPRESS_TANGENT) {
stride += sizeof(int8_t) * 4;
} else {
@@ -1832,7 +2053,6 @@ void RasterizerStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_
} break;
case RS::ARRAY_COLOR: {
-
if (p_surface.format & RS::ARRAY_COMPRESS_COLOR) {
stride += sizeof(int8_t) * 4;
} else {
@@ -1841,7 +2061,6 @@ void RasterizerStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_
} break;
case RS::ARRAY_TEX_UV: {
-
if (p_surface.format & RS::ARRAY_COMPRESS_TEX_UV) {
stride += sizeof(int16_t) * 2;
} else {
@@ -1850,7 +2069,6 @@ void RasterizerStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_
} break;
case RS::ARRAY_TEX_UV2: {
-
if (p_surface.format & RS::ARRAY_COMPRESS_TEX_UV2) {
stride += sizeof(int16_t) * 2;
} else {
@@ -1895,7 +2113,6 @@ void RasterizerStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_
s->lod_count = p_surface.lods.size();
for (int i = 0; i < p_surface.lods.size(); i++) {
-
uint32_t indices = p_surface.lods[i].index_data.size() / (is_index_16 ? 2 : 4);
s->lods[i].index_buffer = RD::get_singleton()->index_buffer_create(indices, is_index_16 ? RD::INDEX_BUFFER_FORMAT_UINT16 : RD::INDEX_BUFFER_FORMAT_UINT32, p_surface.lods[i].index_data);
s->lods[i].index_array = RD::get_singleton()->index_array_create(s->lods[i].index_buffer, 0, indices);
@@ -1908,7 +2125,6 @@ void RasterizerStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_
s->bone_aabbs = p_surface.bone_aabbs; //only really useful for returning them.
for (int i = 0; i < p_surface.blend_shapes.size(); i++) {
-
if (p_surface.blend_shapes[i].size() != p_surface.vertex_data.size()) {
memdelete(s);
ERR_FAIL_COND(p_surface.blend_shapes[i].size() != p_surface.vertex_data.size());
@@ -1953,6 +2169,7 @@ void RasterizerStorageRD::mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMo
mesh->blend_shape_mode = p_mode;
}
+
RS::BlendShapeMode RasterizerStorageRD::mesh_get_blend_shape_mode(RID p_mesh) const {
Mesh *mesh = mesh_owner.getornull(p_mesh);
ERR_FAIL_COND_V(!mesh, RS::BLEND_SHAPE_MODE_NORMALIZED);
@@ -1979,6 +2196,7 @@ void RasterizerStorageRD::mesh_surface_set_material(RID p_mesh, int p_surface, R
mesh->instance_dependency.instance_notify_changed(false, true);
mesh->material_cache.clear();
}
+
RID RasterizerStorageRD::mesh_surface_get_material(RID p_mesh, int p_surface) const {
Mesh *mesh = mesh_owner.getornull(p_mesh);
ERR_FAIL_COND_V(!mesh, RID());
@@ -1988,7 +2206,6 @@ RID RasterizerStorageRD::mesh_surface_get_material(RID p_mesh, int p_surface) co
}
RS::SurfaceData RasterizerStorageRD::mesh_get_surface(RID p_mesh, int p_surface) const {
-
Mesh *mesh = mesh_owner.getornull(p_mesh);
ERR_FAIL_COND_V(!mesh, RS::SurfaceData());
ERR_FAIL_UNSIGNED_INDEX_V((uint32_t)p_surface, mesh->surface_count, RS::SurfaceData());
@@ -2034,6 +2251,7 @@ void RasterizerStorageRD::mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) {
ERR_FAIL_COND(!mesh);
mesh->custom_aabb = p_aabb;
}
+
AABB RasterizerStorageRD::mesh_get_custom_aabb(RID p_mesh) const {
Mesh *mesh = mesh_owner.getornull(p_mesh);
ERR_FAIL_COND_V(!mesh, AABB());
@@ -2057,10 +2275,8 @@ AABB RasterizerStorageRD::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
AABB aabb;
for (uint32_t i = 0; i < mesh->surface_count; i++) {
-
AABB laabb;
if ((mesh->surfaces[i]->format & RS::ARRAY_FORMAT_BONES) && mesh->surfaces[i]->bone_aabbs.size()) {
-
int bs = mesh->surfaces[i]->bone_aabbs.size();
const AABB *skbones = mesh->surfaces[i]->bone_aabbs.ptr();
@@ -2072,9 +2288,9 @@ AABB RasterizerStorageRD::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
if (skeleton->use_2d) {
for (int j = 0; j < bs; j++) {
-
- if (skbones[0].size == Vector3())
+ if (skbones[0].size == Vector3()) {
continue; //bone is unused
+ }
const float *dataptr = baseptr + j * 8;
@@ -2099,9 +2315,9 @@ AABB RasterizerStorageRD::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
}
} else {
for (int j = 0; j < bs; j++) {
-
- if (skbones[0].size == Vector3())
+ if (skbones[0].size == Vector3()) {
continue; //bone is unused
+ }
const float *dataptr = baseptr + j * 12;
@@ -2134,7 +2350,6 @@ AABB RasterizerStorageRD::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
laabb = mesh->surfaces[i]->aabb;
}
} else {
-
laabb = mesh->surfaces[i]->aabb;
}
@@ -2149,7 +2364,6 @@ AABB RasterizerStorageRD::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
}
void RasterizerStorageRD::mesh_clear(RID p_mesh) {
-
Mesh *mesh = mesh_owner.getornull(p_mesh);
ERR_FAIL_COND(!mesh);
for (uint32_t i = 0; i < mesh->surface_count; i++) {
@@ -2197,14 +2411,13 @@ void RasterizerStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Su
Mesh::Surface::Version &v = s->versions[version];
- Vector<RD::VertexDescription> attributes;
+ Vector<RD::VertexAttribute> attributes;
Vector<RID> buffers;
uint32_t stride = 0;
for (int i = 0; i < RS::ARRAY_WEIGHTS; i++) {
-
- RD::VertexDescription vd;
+ RD::VertexAttribute vd;
RID buffer;
vd.location = i;
@@ -2212,9 +2425,7 @@ void RasterizerStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Su
// Not supplied by surface, use default value
buffer = mesh_default_rd_buffers[i];
switch (i) {
-
case RS::ARRAY_VERTEX: {
-
vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT;
} break;
@@ -2222,25 +2433,20 @@ void RasterizerStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Su
vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT;
} break;
case RS::ARRAY_TANGENT: {
-
vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
} break;
case RS::ARRAY_COLOR: {
-
vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
} break;
case RS::ARRAY_TEX_UV: {
-
vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
} break;
case RS::ARRAY_TEX_UV2: {
-
vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
} break;
case RS::ARRAY_BONES: {
-
//assumed weights too
vd.format = RD::DATA_FORMAT_R32G32B32A32_UINT;
} break;
@@ -2253,9 +2459,7 @@ void RasterizerStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Su
buffer = s->vertex_buffer;
switch (i) {
-
case RS::ARRAY_VERTEX: {
-
if (s->format & RS::ARRAY_FLAG_USE_2D_VERTICES) {
vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
stride += sizeof(float) * 2;
@@ -2266,7 +2470,6 @@ void RasterizerStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Su
} break;
case RS::ARRAY_NORMAL: {
-
if (s->format & RS::ARRAY_COMPRESS_NORMAL) {
vd.format = RD::DATA_FORMAT_R8G8B8A8_SNORM;
stride += sizeof(int8_t) * 4;
@@ -2277,7 +2480,6 @@ void RasterizerStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Su
} break;
case RS::ARRAY_TANGENT: {
-
if (s->format & RS::ARRAY_COMPRESS_TANGENT) {
vd.format = RD::DATA_FORMAT_R8G8B8A8_SNORM;
stride += sizeof(int8_t) * 4;
@@ -2288,7 +2490,6 @@ void RasterizerStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Su
} break;
case RS::ARRAY_COLOR: {
-
if (s->format & RS::ARRAY_COMPRESS_COLOR) {
vd.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
stride += sizeof(int8_t) * 4;
@@ -2299,7 +2500,6 @@ void RasterizerStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Su
} break;
case RS::ARRAY_TEX_UV: {
-
if (s->format & RS::ARRAY_COMPRESS_TEX_UV) {
vd.format = RD::DATA_FORMAT_R16G16_SFLOAT;
stride += sizeof(int16_t) * 2;
@@ -2310,7 +2510,6 @@ void RasterizerStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Su
} break;
case RS::ARRAY_TEX_UV2: {
-
if (s->format & RS::ARRAY_COMPRESS_TEX_UV2) {
vd.format = RD::DATA_FORMAT_R16G16_SFLOAT;
stride += sizeof(int16_t) * 2;
@@ -2355,12 +2554,10 @@ void RasterizerStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Su
////////////////// MULTIMESH
RID RasterizerStorageRD::multimesh_create() {
-
return multimesh_owner.make_rid(MultiMesh());
}
void RasterizerStorageRD::multimesh_allocate(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors, bool p_use_custom_data) {
-
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
ERR_FAIL_COND(!multimesh);
@@ -2396,7 +2593,6 @@ void RasterizerStorageRD::multimesh_allocate(RID p_multimesh, int p_instances, R
multimesh->visible_instances = MIN(multimesh->visible_instances, multimesh->instances);
if (multimesh->instances) {
-
multimesh->buffer = RD::get_singleton()->storage_buffer_create(multimesh->instances * multimesh->stride_cache * 4);
}
}
@@ -2451,7 +2647,6 @@ void RasterizerStorageRD::_multimesh_make_local(MultiMesh *multimesh) const {
if (multimesh->buffer_set) {
Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer);
{
-
const uint8_t *r = buffer.ptr();
copymem(w, r, buffer.size());
}
@@ -2462,13 +2657,12 @@ void RasterizerStorageRD::_multimesh_make_local(MultiMesh *multimesh) const {
uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
multimesh->data_cache_dirty_regions = memnew_arr(bool, data_cache_dirty_region_count);
for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) {
- multimesh->data_cache_dirty_regions[i] = 0;
+ multimesh->data_cache_dirty_regions[i] = false;
}
multimesh->data_cache_used_dirty_regions = 0;
}
void RasterizerStorageRD::_multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb) {
-
uint32_t region_index = p_index / MULTIMESH_DIRTY_REGION_SIZE;
#ifdef DEBUG_ENABLED
uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
@@ -2514,7 +2708,6 @@ void RasterizerStorageRD::_multimesh_mark_all_dirty(MultiMesh *multimesh, bool p
}
void RasterizerStorageRD::_multimesh_re_create_aabb(MultiMesh *multimesh, const float *p_data, int p_instances) {
-
ERR_FAIL_COND(multimesh->mesh.is_null());
AABB aabb;
AABB mesh_aabb = mesh_get_aabb(multimesh->mesh);
@@ -2523,7 +2716,6 @@ void RasterizerStorageRD::_multimesh_re_create_aabb(MultiMesh *multimesh, const
Transform t;
if (multimesh->xform_format == RS::MULTIMESH_TRANSFORM_3D) {
-
t.basis.elements[0][0] = data[0];
t.basis.elements[0][1] = data[1];
t.basis.elements[0][2] = data[2];
@@ -2538,7 +2730,6 @@ void RasterizerStorageRD::_multimesh_re_create_aabb(MultiMesh *multimesh, const
t.origin.z = data[11];
} else {
-
t.basis.elements[0].x = data[0];
t.basis.elements[1].x = data[1];
t.origin.x = data[3];
@@ -2559,7 +2750,6 @@ void RasterizerStorageRD::_multimesh_re_create_aabb(MultiMesh *multimesh, const
}
void RasterizerStorageRD::multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform) {
-
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
ERR_FAIL_COND(!multimesh);
ERR_FAIL_INDEX(p_index, multimesh->instances);
@@ -2590,7 +2780,6 @@ void RasterizerStorageRD::multimesh_instance_set_transform(RID p_multimesh, int
}
void RasterizerStorageRD::multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) {
-
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
ERR_FAIL_COND(!multimesh);
ERR_FAIL_INDEX(p_index, multimesh->instances);
@@ -2615,8 +2804,8 @@ void RasterizerStorageRD::multimesh_instance_set_transform_2d(RID p_multimesh, i
_multimesh_mark_dirty(multimesh, p_index, true);
}
-void RasterizerStorageRD::multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) {
+void RasterizerStorageRD::multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) {
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
ERR_FAIL_COND(!multimesh);
ERR_FAIL_INDEX(p_index, multimesh->instances);
@@ -2637,6 +2826,7 @@ void RasterizerStorageRD::multimesh_instance_set_color(RID p_multimesh, int p_in
_multimesh_mark_dirty(multimesh, p_index, false);
}
+
void RasterizerStorageRD::multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) {
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
ERR_FAIL_COND(!multimesh);
@@ -2660,7 +2850,6 @@ void RasterizerStorageRD::multimesh_instance_set_custom_data(RID p_multimesh, in
}
RID RasterizerStorageRD::multimesh_get_mesh(RID p_multimesh) const {
-
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
ERR_FAIL_COND_V(!multimesh, RID());
@@ -2668,7 +2857,6 @@ RID RasterizerStorageRD::multimesh_get_mesh(RID p_multimesh) const {
}
Transform RasterizerStorageRD::multimesh_instance_get_transform(RID p_multimesh, int p_index) const {
-
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
ERR_FAIL_COND_V(!multimesh, Transform());
ERR_FAIL_INDEX_V(p_index, multimesh->instances, Transform());
@@ -2698,8 +2886,8 @@ Transform RasterizerStorageRD::multimesh_instance_get_transform(RID p_multimesh,
return t;
}
-Transform2D RasterizerStorageRD::multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const {
+Transform2D RasterizerStorageRD::multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const {
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
ERR_FAIL_COND_V(!multimesh, Transform2D());
ERR_FAIL_INDEX_V(p_index, multimesh->instances, Transform2D());
@@ -2723,8 +2911,8 @@ Transform2D RasterizerStorageRD::multimesh_instance_get_transform_2d(RID p_multi
return t;
}
-Color RasterizerStorageRD::multimesh_instance_get_color(RID p_multimesh, int p_index) const {
+Color RasterizerStorageRD::multimesh_instance_get_color(RID p_multimesh, int p_index) const {
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
ERR_FAIL_COND_V(!multimesh, Color());
ERR_FAIL_INDEX_V(p_index, multimesh->instances, Color());
@@ -2746,8 +2934,8 @@ Color RasterizerStorageRD::multimesh_instance_get_color(RID p_multimesh, int p_i
return c;
}
-Color RasterizerStorageRD::multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const {
+Color RasterizerStorageRD::multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const {
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
ERR_FAIL_COND_V(!multimesh, Color());
ERR_FAIL_INDEX_V(p_index, multimesh->instances, Color());
@@ -2827,7 +3015,6 @@ Vector<float> RasterizerStorageRD::multimesh_get_buffer(RID p_multimesh) const {
}
void RasterizerStorageRD::multimesh_set_visible_instances(RID p_multimesh, int p_visible) {
-
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
ERR_FAIL_COND(!multimesh);
ERR_FAIL_COND(p_visible < -1 || p_visible > multimesh->instances);
@@ -2842,6 +3029,7 @@ void RasterizerStorageRD::multimesh_set_visible_instances(RID p_multimesh, int p
multimesh->visible_instances = p_visible;
}
+
int RasterizerStorageRD::multimesh_get_visible_instances(RID p_multimesh) const {
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
ERR_FAIL_COND_V(!multimesh, 0);
@@ -2858,9 +3046,7 @@ AABB RasterizerStorageRD::multimesh_get_aabb(RID p_multimesh) const {
}
void RasterizerStorageRD::_update_dirty_multimeshes() {
-
while (multimesh_dirty_list) {
-
MultiMesh *multimesh = multimesh_dirty_list;
if (multimesh->data_cache.size()) { //may have been cleared, so only process if it exists
@@ -2869,7 +3055,6 @@ void RasterizerStorageRD::_update_dirty_multimeshes() {
uint32_t visible_instances = multimesh->visible_instances >= 0 ? multimesh->visible_instances : multimesh->instances;
if (multimesh->data_cache_used_dirty_regions) {
-
uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
uint32_t visible_region_count = (visible_instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
@@ -2918,12 +3103,10 @@ void RasterizerStorageRD::_update_dirty_multimeshes() {
/* SKELETON API */
RID RasterizerStorageRD::skeleton_create() {
-
return skeleton_owner.make_rid(Skeleton());
}
void RasterizerStorageRD::_skeleton_make_dirty(Skeleton *skeleton) {
-
if (!skeleton->dirty) {
skeleton->dirty = true;
skeleton->dirty_list = skeleton_dirty_list;
@@ -2932,13 +3115,13 @@ void RasterizerStorageRD::_skeleton_make_dirty(Skeleton *skeleton) {
}
void RasterizerStorageRD::skeleton_allocate(RID p_skeleton, int p_bones, bool p_2d_skeleton) {
-
Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
ERR_FAIL_COND(!skeleton);
ERR_FAIL_COND(p_bones < 0);
- if (skeleton->size == p_bones && skeleton->use_2d == p_2d_skeleton)
+ if (skeleton->size == p_bones && skeleton->use_2d == p_2d_skeleton) {
return;
+ }
skeleton->size = p_bones;
skeleton->use_2d = p_2d_skeleton;
@@ -2951,7 +3134,6 @@ void RasterizerStorageRD::skeleton_allocate(RID p_skeleton, int p_bones, bool p_
}
if (skeleton->size) {
-
skeleton->data.resize(skeleton->size * (skeleton->use_2d ? 8 : 12));
skeleton->buffer = RD::get_singleton()->storage_buffer_create(skeleton->data.size() * sizeof(float));
zeromem(skeleton->data.ptrw(), skeleton->data.size() * sizeof(float));
@@ -2959,8 +3141,8 @@ void RasterizerStorageRD::skeleton_allocate(RID p_skeleton, int p_bones, bool p_
_skeleton_make_dirty(skeleton);
}
}
-int RasterizerStorageRD::skeleton_get_bone_count(RID p_skeleton) const {
+int RasterizerStorageRD::skeleton_get_bone_count(RID p_skeleton) const {
Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
ERR_FAIL_COND_V(!skeleton, 0);
@@ -2968,7 +3150,6 @@ int RasterizerStorageRD::skeleton_get_bone_count(RID p_skeleton) const {
}
void RasterizerStorageRD::skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform &p_transform) {
-
Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
ERR_FAIL_COND(!skeleton);
@@ -2994,7 +3175,6 @@ void RasterizerStorageRD::skeleton_bone_set_transform(RID p_skeleton, int p_bone
}
Transform RasterizerStorageRD::skeleton_bone_get_transform(RID p_skeleton, int p_bone) const {
-
Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
ERR_FAIL_COND_V(!skeleton, Transform());
@@ -3020,8 +3200,8 @@ Transform RasterizerStorageRD::skeleton_bone_get_transform(RID p_skeleton, int p
return t;
}
-void RasterizerStorageRD::skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) {
+void RasterizerStorageRD::skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) {
Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
ERR_FAIL_COND(!skeleton);
@@ -3041,8 +3221,8 @@ void RasterizerStorageRD::skeleton_bone_set_transform_2d(RID p_skeleton, int p_b
_skeleton_make_dirty(skeleton);
}
-Transform2D RasterizerStorageRD::skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const {
+Transform2D RasterizerStorageRD::skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const {
Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
ERR_FAIL_COND_V(!skeleton, Transform2D());
@@ -3063,7 +3243,6 @@ Transform2D RasterizerStorageRD::skeleton_bone_get_transform_2d(RID p_skeleton,
}
void RasterizerStorageRD::skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) {
-
Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
ERR_FAIL_COND(!skeleton->use_2d);
@@ -3072,13 +3251,10 @@ void RasterizerStorageRD::skeleton_set_base_transform_2d(RID p_skeleton, const T
}
void RasterizerStorageRD::_update_dirty_skeletons() {
-
while (skeleton_dirty_list) {
-
Skeleton *skeleton = skeleton_dirty_list;
if (skeleton->size) {
-
RD::get_singleton()->buffer_update(skeleton->buffer, 0, skeleton->data.size() * sizeof(float), skeleton->data.ptr(), false);
}
@@ -3096,7 +3272,6 @@ void RasterizerStorageRD::_update_dirty_skeletons() {
/* LIGHT */
RID RasterizerStorageRD::light_create(RS::LightType p_type) {
-
Light light;
light.type = p_type;
@@ -3104,28 +3279,29 @@ RID RasterizerStorageRD::light_create(RS::LightType p_type) {
light.param[RS::LIGHT_PARAM_INDIRECT_ENERGY] = 1.0;
light.param[RS::LIGHT_PARAM_SPECULAR] = 0.5;
light.param[RS::LIGHT_PARAM_RANGE] = 1.0;
+ light.param[RS::LIGHT_PARAM_SIZE] = 0.0;
light.param[RS::LIGHT_PARAM_SPOT_ANGLE] = 45;
- light.param[RS::LIGHT_PARAM_CONTACT_SHADOW_SIZE] = 45;
light.param[RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE] = 0;
light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET] = 0.1;
light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET] = 0.3;
light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET] = 0.6;
light.param[RS::LIGHT_PARAM_SHADOW_FADE_START] = 0.8;
- light.param[RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] = 0.1;
- light.param[RS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE] = 0.1;
+ light.param[RS::LIGHT_PARAM_SHADOW_BIAS] = 0.02;
+ light.param[RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] = 1.0;
+ light.param[RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE] = 20.0;
+ light.param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS] = 0.05;
return light_owner.make_rid(light);
}
void RasterizerStorageRD::light_set_color(RID p_light, const Color &p_color) {
-
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND(!light);
light->color = p_color;
}
-void RasterizerStorageRD::light_set_param(RID p_light, RS::LightParam p_param, float p_value) {
+void RasterizerStorageRD::light_set_param(RID p_light, RS::LightParam p_param, float p_value) {
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND(!light);
ERR_FAIL_INDEX(p_param, RS::LIGHT_PARAM_MAX);
@@ -3138,8 +3314,8 @@ void RasterizerStorageRD::light_set_param(RID p_light, RS::LightParam p_param, f
case RS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET:
case RS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET:
case RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS:
+ case RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE:
case RS::LIGHT_PARAM_SHADOW_BIAS: {
-
light->version++;
light->instance_dependency.instance_notify_changed(true, false);
} break;
@@ -3149,8 +3325,8 @@ void RasterizerStorageRD::light_set_param(RID p_light, RS::LightParam p_param, f
light->param[p_param] = p_value;
}
-void RasterizerStorageRD::light_set_shadow(RID p_light, bool p_enabled) {
+void RasterizerStorageRD::light_set_shadow(RID p_light, bool p_enabled) {
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND(!light);
light->shadow = p_enabled;
@@ -3160,29 +3336,38 @@ void RasterizerStorageRD::light_set_shadow(RID p_light, bool p_enabled) {
}
void RasterizerStorageRD::light_set_shadow_color(RID p_light, const Color &p_color) {
-
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND(!light);
light->shadow_color = p_color;
}
void RasterizerStorageRD::light_set_projector(RID p_light, RID p_texture) {
-
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND(!light);
+ if (light->projector == p_texture) {
+ return;
+ }
+
+ if (light->type != RS::LIGHT_DIRECTIONAL && light->projector.is_valid()) {
+ texture_remove_from_decal_atlas(light->projector, light->type == RS::LIGHT_OMNI);
+ }
+
light->projector = p_texture;
+
+ if (light->type != RS::LIGHT_DIRECTIONAL && light->projector.is_valid()) {
+ texture_add_to_decal_atlas(light->projector, light->type == RS::LIGHT_OMNI);
+ }
}
void RasterizerStorageRD::light_set_negative(RID p_light, bool p_enable) {
-
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND(!light);
light->negative = p_enable;
}
-void RasterizerStorageRD::light_set_cull_mask(RID p_light, uint32_t p_mask) {
+void RasterizerStorageRD::light_set_cull_mask(RID p_light, uint32_t p_mask) {
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND(!light);
@@ -3193,7 +3378,6 @@ void RasterizerStorageRD::light_set_cull_mask(RID p_light, uint32_t p_mask) {
}
void RasterizerStorageRD::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) {
-
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND(!light);
@@ -3212,8 +3396,8 @@ void RasterizerStorageRD::light_set_use_gi(RID p_light, bool p_enabled) {
light->version++;
light->instance_dependency.instance_notify_changed(true, false);
}
-void RasterizerStorageRD::light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) {
+void RasterizerStorageRD::light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) {
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND(!light);
@@ -3224,7 +3408,6 @@ void RasterizerStorageRD::light_omni_set_shadow_mode(RID p_light, RS::LightOmniS
}
RS::LightOmniShadowMode RasterizerStorageRD::light_omni_get_shadow_mode(RID p_light) {
-
const Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light, RS::LIGHT_OMNI_SHADOW_CUBE);
@@ -3232,7 +3415,6 @@ RS::LightOmniShadowMode RasterizerStorageRD::light_omni_get_shadow_mode(RID p_li
}
void RasterizerStorageRD::light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) {
-
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND(!light);
@@ -3242,7 +3424,6 @@ void RasterizerStorageRD::light_directional_set_shadow_mode(RID p_light, RS::Lig
}
void RasterizerStorageRD::light_directional_set_blend_splits(RID p_light, bool p_enable) {
-
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND(!light);
@@ -3252,7 +3433,6 @@ void RasterizerStorageRD::light_directional_set_blend_splits(RID p_light, bool p
}
bool RasterizerStorageRD::light_directional_get_blend_splits(RID p_light) const {
-
const Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light, false);
@@ -3260,7 +3440,6 @@ bool RasterizerStorageRD::light_directional_get_blend_splits(RID p_light) const
}
RS::LightDirectionalShadowMode RasterizerStorageRD::light_directional_get_shadow_mode(RID p_light) {
-
const Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL);
@@ -3268,7 +3447,6 @@ RS::LightDirectionalShadowMode RasterizerStorageRD::light_directional_get_shadow
}
void RasterizerStorageRD::light_directional_set_shadow_depth_range_mode(RID p_light, RS::LightDirectionalShadowDepthRangeMode p_range_mode) {
-
Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND(!light);
@@ -3276,7 +3454,6 @@ void RasterizerStorageRD::light_directional_set_shadow_depth_range_mode(RID p_li
}
RS::LightDirectionalShadowDepthRangeMode RasterizerStorageRD::light_directional_get_shadow_depth_range_mode(RID p_light) const {
-
const Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE);
@@ -3291,7 +3468,6 @@ bool RasterizerStorageRD::light_get_use_gi(RID p_light) {
}
uint64_t RasterizerStorageRD::light_get_version(RID p_light) const {
-
const Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light, 0);
@@ -3299,25 +3475,20 @@ uint64_t RasterizerStorageRD::light_get_version(RID p_light) const {
}
AABB RasterizerStorageRD::light_get_aabb(RID p_light) const {
-
const Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light, AABB());
switch (light->type) {
-
case RS::LIGHT_SPOT: {
-
float len = light->param[RS::LIGHT_PARAM_RANGE];
float size = Math::tan(Math::deg2rad(light->param[RS::LIGHT_PARAM_SPOT_ANGLE])) * len;
return AABB(Vector3(-size, -size, -len), Vector3(size * 2, size * 2, len));
};
case RS::LIGHT_OMNI: {
-
float r = light->param[RS::LIGHT_PARAM_RANGE];
return AABB(-Vector3(r, r, r), Vector3(r, r, r) * 2);
};
case RS::LIGHT_DIRECTIONAL: {
-
return AABB();
};
}
@@ -3328,12 +3499,10 @@ AABB RasterizerStorageRD::light_get_aabb(RID p_light) const {
/* REFLECTION PROBE */
RID RasterizerStorageRD::reflection_probe_create() {
-
return reflection_probe_owner.make_rid(ReflectionProbe());
}
void RasterizerStorageRD::reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) {
-
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND(!reflection_probe);
@@ -3342,7 +3511,6 @@ void RasterizerStorageRD::reflection_probe_set_update_mode(RID p_probe, RS::Refl
}
void RasterizerStorageRD::reflection_probe_set_intensity(RID p_probe, float p_intensity) {
-
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND(!reflection_probe);
@@ -3350,7 +3518,6 @@ void RasterizerStorageRD::reflection_probe_set_intensity(RID p_probe, float p_in
}
void RasterizerStorageRD::reflection_probe_set_interior_ambient(RID p_probe, const Color &p_ambient) {
-
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND(!reflection_probe);
@@ -3358,7 +3525,6 @@ void RasterizerStorageRD::reflection_probe_set_interior_ambient(RID p_probe, con
}
void RasterizerStorageRD::reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy) {
-
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND(!reflection_probe);
@@ -3366,7 +3532,6 @@ void RasterizerStorageRD::reflection_probe_set_interior_ambient_energy(RID p_pro
}
void RasterizerStorageRD::reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib) {
-
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND(!reflection_probe);
@@ -3374,7 +3539,6 @@ void RasterizerStorageRD::reflection_probe_set_interior_ambient_probe_contributi
}
void RasterizerStorageRD::reflection_probe_set_max_distance(RID p_probe, float p_distance) {
-
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND(!reflection_probe);
@@ -3382,16 +3546,16 @@ void RasterizerStorageRD::reflection_probe_set_max_distance(RID p_probe, float p
reflection_probe->instance_dependency.instance_notify_changed(true, false);
}
-void RasterizerStorageRD::reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) {
+void RasterizerStorageRD::reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) {
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND(!reflection_probe);
reflection_probe->extents = p_extents;
reflection_probe->instance_dependency.instance_notify_changed(true, false);
}
-void RasterizerStorageRD::reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) {
+void RasterizerStorageRD::reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) {
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND(!reflection_probe);
@@ -3400,15 +3564,14 @@ void RasterizerStorageRD::reflection_probe_set_origin_offset(RID p_probe, const
}
void RasterizerStorageRD::reflection_probe_set_as_interior(RID p_probe, bool p_enable) {
-
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND(!reflection_probe);
reflection_probe->interior = p_enable;
reflection_probe->instance_dependency.instance_notify_changed(true, false);
}
-void RasterizerStorageRD::reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) {
+void RasterizerStorageRD::reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) {
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND(!reflection_probe);
@@ -3416,15 +3579,14 @@ void RasterizerStorageRD::reflection_probe_set_enable_box_projection(RID p_probe
}
void RasterizerStorageRD::reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) {
-
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND(!reflection_probe);
reflection_probe->enable_shadows = p_enable;
reflection_probe->instance_dependency.instance_notify_changed(true, false);
}
-void RasterizerStorageRD::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) {
+void RasterizerStorageRD::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) {
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND(!reflection_probe);
@@ -3433,7 +3595,6 @@ void RasterizerStorageRD::reflection_probe_set_cull_mask(RID p_probe, uint32_t p
}
void RasterizerStorageRD::reflection_probe_set_resolution(RID p_probe, int p_resolution) {
-
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND(!reflection_probe);
ERR_FAIL_COND(p_resolution < 32);
@@ -3451,8 +3612,8 @@ AABB RasterizerStorageRD::reflection_probe_get_aabb(RID p_probe) const {
return aabb;
}
-RS::ReflectionProbeUpdateMode RasterizerStorageRD::reflection_probe_get_update_mode(RID p_probe) const {
+RS::ReflectionProbeUpdateMode RasterizerStorageRD::reflection_probe_get_update_mode(RID p_probe) const {
const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND_V(!reflection_probe, RS::REFLECTION_PROBE_UPDATE_ALWAYS);
@@ -3460,7 +3621,6 @@ RS::ReflectionProbeUpdateMode RasterizerStorageRD::reflection_probe_get_update_m
}
uint32_t RasterizerStorageRD::reflection_probe_get_cull_mask(RID p_probe) const {
-
const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND_V(!reflection_probe, 0);
@@ -3468,14 +3628,13 @@ uint32_t RasterizerStorageRD::reflection_probe_get_cull_mask(RID p_probe) const
}
Vector3 RasterizerStorageRD::reflection_probe_get_extents(RID p_probe) const {
-
const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND_V(!reflection_probe, Vector3());
return reflection_probe->extents;
}
-Vector3 RasterizerStorageRD::reflection_probe_get_origin_offset(RID p_probe) const {
+Vector3 RasterizerStorageRD::reflection_probe_get_origin_offset(RID p_probe) const {
const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND_V(!reflection_probe, Vector3());
@@ -3483,7 +3642,6 @@ Vector3 RasterizerStorageRD::reflection_probe_get_origin_offset(RID p_probe) con
}
bool RasterizerStorageRD::reflection_probe_renders_shadows(RID p_probe) const {
-
const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND_V(!reflection_probe, false);
@@ -3491,7 +3649,6 @@ bool RasterizerStorageRD::reflection_probe_renders_shadows(RID p_probe) const {
}
float RasterizerStorageRD::reflection_probe_get_origin_max_distance(RID p_probe) const {
-
const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND_V(!reflection_probe, 0);
@@ -3499,7 +3656,6 @@ float RasterizerStorageRD::reflection_probe_get_origin_max_distance(RID p_probe)
}
int RasterizerStorageRD::reflection_probe_get_resolution(RID p_probe) const {
-
const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND_V(!reflection_probe, 0);
@@ -3507,21 +3663,20 @@ int RasterizerStorageRD::reflection_probe_get_resolution(RID p_probe) const {
}
float RasterizerStorageRD::reflection_probe_get_intensity(RID p_probe) const {
-
const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND_V(!reflection_probe, 0);
return reflection_probe->intensity;
}
-bool RasterizerStorageRD::reflection_probe_is_interior(RID p_probe) const {
+bool RasterizerStorageRD::reflection_probe_is_interior(RID p_probe) const {
const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND_V(!reflection_probe, false);
return reflection_probe->interior;
}
-bool RasterizerStorageRD::reflection_probe_is_box_projection(RID p_probe) const {
+bool RasterizerStorageRD::reflection_probe_is_box_projection(RID p_probe) const {
const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND_V(!reflection_probe, false);
@@ -3529,29 +3684,115 @@ bool RasterizerStorageRD::reflection_probe_is_box_projection(RID p_probe) const
}
Color RasterizerStorageRD::reflection_probe_get_interior_ambient(RID p_probe) const {
-
const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND_V(!reflection_probe, Color());
return reflection_probe->interior_ambient;
}
-float RasterizerStorageRD::reflection_probe_get_interior_ambient_energy(RID p_probe) const {
+float RasterizerStorageRD::reflection_probe_get_interior_ambient_energy(RID p_probe) const {
const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND_V(!reflection_probe, 0);
return reflection_probe->interior_ambient_energy;
}
-float RasterizerStorageRD::reflection_probe_get_interior_ambient_probe_contribution(RID p_probe) const {
+float RasterizerStorageRD::reflection_probe_get_interior_ambient_probe_contribution(RID p_probe) const {
const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
ERR_FAIL_COND_V(!reflection_probe, 0);
return reflection_probe->interior_ambient_probe_contrib;
}
-RID RasterizerStorageRD::gi_probe_create() {
+RID RasterizerStorageRD::decal_create() {
+ return decal_owner.make_rid(Decal());
+}
+
+void RasterizerStorageRD::decal_set_extents(RID p_decal, const Vector3 &p_extents) {
+ Decal *decal = decal_owner.getornull(p_decal);
+ ERR_FAIL_COND(!decal);
+ decal->extents = p_extents;
+ decal->instance_dependency.instance_notify_changed(true, false);
+}
+
+void RasterizerStorageRD::decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) {
+ Decal *decal = decal_owner.getornull(p_decal);
+ ERR_FAIL_COND(!decal);
+ ERR_FAIL_INDEX(p_type, RS::DECAL_TEXTURE_MAX);
+
+ if (decal->textures[p_type] == p_texture) {
+ return;
+ }
+
+ ERR_FAIL_COND(p_texture.is_valid() && !texture_owner.owns(p_texture));
+
+ if (decal->textures[p_type].is_valid() && texture_owner.owns(decal->textures[p_type])) {
+ texture_remove_from_decal_atlas(decal->textures[p_type]);
+ }
+
+ decal->textures[p_type] = p_texture;
+
+ if (decal->textures[p_type].is_valid()) {
+ texture_add_to_decal_atlas(decal->textures[p_type]);
+ }
+
+ decal->instance_dependency.instance_notify_changed(false, true);
+}
+
+void RasterizerStorageRD::decal_set_emission_energy(RID p_decal, float p_energy) {
+ Decal *decal = decal_owner.getornull(p_decal);
+ ERR_FAIL_COND(!decal);
+ decal->emission_energy = p_energy;
+}
+
+void RasterizerStorageRD::decal_set_albedo_mix(RID p_decal, float p_mix) {
+ Decal *decal = decal_owner.getornull(p_decal);
+ ERR_FAIL_COND(!decal);
+ decal->albedo_mix = p_mix;
+}
+
+void RasterizerStorageRD::decal_set_modulate(RID p_decal, const Color &p_modulate) {
+ Decal *decal = decal_owner.getornull(p_decal);
+ ERR_FAIL_COND(!decal);
+ decal->modulate = p_modulate;
+}
+
+void RasterizerStorageRD::decal_set_cull_mask(RID p_decal, uint32_t p_layers) {
+ Decal *decal = decal_owner.getornull(p_decal);
+ ERR_FAIL_COND(!decal);
+ decal->cull_mask = p_layers;
+ decal->instance_dependency.instance_notify_changed(true, false);
+}
+void RasterizerStorageRD::decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) {
+ Decal *decal = decal_owner.getornull(p_decal);
+ ERR_FAIL_COND(!decal);
+ decal->distance_fade = p_enabled;
+ decal->distance_fade_begin = p_begin;
+ decal->distance_fade_length = p_length;
+}
+
+void RasterizerStorageRD::decal_set_fade(RID p_decal, float p_above, float p_below) {
+ Decal *decal = decal_owner.getornull(p_decal);
+ ERR_FAIL_COND(!decal);
+ decal->upper_fade = p_above;
+ decal->lower_fade = p_below;
+}
+
+void RasterizerStorageRD::decal_set_normal_fade(RID p_decal, float p_fade) {
+ Decal *decal = decal_owner.getornull(p_decal);
+ ERR_FAIL_COND(!decal);
+ decal->normal_fade = p_fade;
+}
+
+AABB RasterizerStorageRD::decal_get_aabb(RID p_decal) const {
+ Decal *decal = decal_owner.getornull(p_decal);
+ ERR_FAIL_COND_V(!decal, AABB());
+
+ return AABB(-decal->extents, decal->extents * 2.0);
+}
+
+RID RasterizerStorageRD::gi_probe_create() {
return gi_probe_owner.make_rid(GIProbe());
}
@@ -3693,6 +3934,7 @@ Vector3i RasterizerStorageRD::gi_probe_get_octree_size(RID p_gi_probe) const {
ERR_FAIL_COND_V(!gi_probe, Vector3i());
return gi_probe->octree_size;
}
+
Vector<uint8_t> RasterizerStorageRD::gi_probe_get_octree_cells(RID p_gi_probe) const {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND_V(!gi_probe, Vector<uint8_t>());
@@ -3702,6 +3944,7 @@ Vector<uint8_t> RasterizerStorageRD::gi_probe_get_octree_cells(RID p_gi_probe) c
}
return Vector<uint8_t>();
}
+
Vector<uint8_t> RasterizerStorageRD::gi_probe_get_data_cells(RID p_gi_probe) const {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND_V(!gi_probe, Vector<uint8_t>());
@@ -3711,6 +3954,7 @@ Vector<uint8_t> RasterizerStorageRD::gi_probe_get_data_cells(RID p_gi_probe) con
}
return Vector<uint8_t>();
}
+
Vector<uint8_t> RasterizerStorageRD::gi_probe_get_distance_field(RID p_gi_probe) const {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND_V(!gi_probe, Vector<uint8_t>());
@@ -3720,12 +3964,14 @@ Vector<uint8_t> RasterizerStorageRD::gi_probe_get_distance_field(RID p_gi_probe)
}
return Vector<uint8_t>();
}
+
Vector<int> RasterizerStorageRD::gi_probe_get_level_counts(RID p_gi_probe) const {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND_V(!gi_probe, Vector<int>());
return gi_probe->level_counts;
}
+
Transform RasterizerStorageRD::gi_probe_get_to_cell_xform(RID p_gi_probe) const {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND_V(!gi_probe, Transform());
@@ -3740,6 +3986,7 @@ void RasterizerStorageRD::gi_probe_set_dynamic_range(RID p_gi_probe, float p_ran
gi_probe->dynamic_range = p_range;
gi_probe->version++;
}
+
float RasterizerStorageRD::gi_probe_get_dynamic_range(RID p_gi_probe) const {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND_V(!gi_probe, 0);
@@ -3754,6 +4001,7 @@ void RasterizerStorageRD::gi_probe_set_propagation(RID p_gi_probe, float p_range
gi_probe->propagation = p_range;
gi_probe->version++;
}
+
float RasterizerStorageRD::gi_probe_get_propagation(RID p_gi_probe) const {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND_V(!gi_probe, 0);
@@ -3766,6 +4014,7 @@ void RasterizerStorageRD::gi_probe_set_energy(RID p_gi_probe, float p_energy) {
gi_probe->energy = p_energy;
}
+
float RasterizerStorageRD::gi_probe_get_energy(RID p_gi_probe) const {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND_V(!gi_probe, 0);
@@ -3778,6 +4027,7 @@ void RasterizerStorageRD::gi_probe_set_ao(RID p_gi_probe, float p_ao) {
gi_probe->ao = p_ao;
}
+
float RasterizerStorageRD::gi_probe_get_ao(RID p_gi_probe) const {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND_V(!gi_probe, 0);
@@ -3785,7 +4035,6 @@ float RasterizerStorageRD::gi_probe_get_ao(RID p_gi_probe) const {
}
void RasterizerStorageRD::gi_probe_set_ao_size(RID p_gi_probe, float p_strength) {
-
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND(!gi_probe);
@@ -3804,6 +4053,7 @@ void RasterizerStorageRD::gi_probe_set_bias(RID p_gi_probe, float p_bias) {
gi_probe->bias = p_bias;
}
+
float RasterizerStorageRD::gi_probe_get_bias(RID p_gi_probe) const {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND_V(!gi_probe, 0);
@@ -3816,6 +4066,7 @@ void RasterizerStorageRD::gi_probe_set_normal_bias(RID p_gi_probe, float p_norma
gi_probe->normal_bias = p_normal_bias;
}
+
float RasterizerStorageRD::gi_probe_get_normal_bias(RID p_gi_probe) const {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND_V(!gi_probe, 0);
@@ -3823,7 +4074,6 @@ float RasterizerStorageRD::gi_probe_get_normal_bias(RID p_gi_probe) const {
}
void RasterizerStorageRD::gi_probe_set_anisotropy_strength(RID p_gi_probe, float p_strength) {
-
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND(!gi_probe);
@@ -3876,13 +4126,12 @@ uint32_t RasterizerStorageRD::gi_probe_get_data_version(RID p_gi_probe) {
}
RID RasterizerStorageRD::gi_probe_get_octree_buffer(RID p_gi_probe) const {
-
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND_V(!gi_probe, RID());
return gi_probe->octree_buffer;
}
-RID RasterizerStorageRD::gi_probe_get_data_buffer(RID p_gi_probe) const {
+RID RasterizerStorageRD::gi_probe_get_data_buffer(RID p_gi_probe) const {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND_V(!gi_probe, RID());
return gi_probe->data_buffer;
@@ -3895,10 +4144,182 @@ RID RasterizerStorageRD::gi_probe_get_sdf_texture(RID p_gi_probe) {
return gi_probe->sdf_texture;
}
+/* LIGHTMAP API */
+
+RID RasterizerStorageRD::lightmap_create() {
+ return lightmap_owner.make_rid(Lightmap());
+}
+
+void RasterizerStorageRD::lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) {
+ Lightmap *lm = lightmap_owner.getornull(p_lightmap);
+ ERR_FAIL_COND(!lm);
+
+ lightmap_array_version++;
+
+ //erase lightmap users
+ if (lm->light_texture.is_valid()) {
+ Texture *t = texture_owner.getornull(lm->light_texture);
+ if (t) {
+ t->lightmap_users.erase(p_lightmap);
+ }
+ }
+
+ Texture *t = texture_owner.getornull(p_light);
+ lm->light_texture = p_light;
+ lm->uses_spherical_harmonics = p_uses_spherical_haromics;
+
+ RID default_2d_array = default_rd_textures[DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE];
+ if (!t) {
+ if (using_lightmap_array) {
+ if (lm->array_index >= 0) {
+ lightmap_textures.write[lm->array_index] = default_2d_array;
+ lm->array_index = -1;
+ }
+ }
+
+ return;
+ }
+
+ t->lightmap_users.insert(p_lightmap);
+
+ if (using_lightmap_array) {
+ if (lm->array_index < 0) {
+ //not in array, try to put in array
+ for (int i = 0; i < lightmap_textures.size(); i++) {
+ if (lightmap_textures[i] == default_2d_array) {
+ lm->array_index = i;
+ break;
+ }
+ }
+ }
+ ERR_FAIL_COND_MSG(lm->array_index < 0, "Maximum amount of lightmaps in use (" + itos(lightmap_textures.size()) + ") has been exceeded, lightmap will nod display properly.");
+
+ lightmap_textures.write[lm->array_index] = t->rd_texture;
+ }
+}
+
+void RasterizerStorageRD::lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) {
+ Lightmap *lm = lightmap_owner.getornull(p_lightmap);
+ ERR_FAIL_COND(!lm);
+ lm->bounds = p_bounds;
+}
+
+void RasterizerStorageRD::lightmap_set_probe_interior(RID p_lightmap, bool p_interior) {
+ Lightmap *lm = lightmap_owner.getornull(p_lightmap);
+ ERR_FAIL_COND(!lm);
+ lm->interior = p_interior;
+}
+
+void RasterizerStorageRD::lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) {
+ Lightmap *lm = lightmap_owner.getornull(p_lightmap);
+ ERR_FAIL_COND(!lm);
+
+ if (p_points.size()) {
+ ERR_FAIL_COND(p_points.size() * 9 != p_point_sh.size());
+ ERR_FAIL_COND((p_tetrahedra.size() % 4) != 0);
+ ERR_FAIL_COND((p_bsp_tree.size() % 6) != 0);
+ }
+
+ lm->points = p_points;
+ lm->bsp_tree = p_bsp_tree;
+ lm->point_sh = p_point_sh;
+ lm->tetrahedra = p_tetrahedra;
+}
+
+PackedVector3Array RasterizerStorageRD::lightmap_get_probe_capture_points(RID p_lightmap) const {
+ Lightmap *lm = lightmap_owner.getornull(p_lightmap);
+ ERR_FAIL_COND_V(!lm, PackedVector3Array());
+
+ return lm->points;
+}
+
+PackedColorArray RasterizerStorageRD::lightmap_get_probe_capture_sh(RID p_lightmap) const {
+ Lightmap *lm = lightmap_owner.getornull(p_lightmap);
+ ERR_FAIL_COND_V(!lm, PackedColorArray());
+ return lm->point_sh;
+}
+
+PackedInt32Array RasterizerStorageRD::lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const {
+ Lightmap *lm = lightmap_owner.getornull(p_lightmap);
+ ERR_FAIL_COND_V(!lm, PackedInt32Array());
+ return lm->tetrahedra;
+}
+
+PackedInt32Array RasterizerStorageRD::lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const {
+ Lightmap *lm = lightmap_owner.getornull(p_lightmap);
+ ERR_FAIL_COND_V(!lm, PackedInt32Array());
+ return lm->bsp_tree;
+}
+
+void RasterizerStorageRD::lightmap_set_probe_capture_update_speed(float p_speed) {
+ lightmap_probe_capture_update_speed = p_speed;
+}
+
+void RasterizerStorageRD::lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) {
+ Lightmap *lm = lightmap_owner.getornull(p_lightmap);
+ ERR_FAIL_COND(!lm);
+
+ for (int i = 0; i < 9; i++) {
+ r_sh[i] = Color(0, 0, 0, 0);
+ }
+
+ if (!lm->points.size() || !lm->bsp_tree.size() || !lm->tetrahedra.size()) {
+ return;
+ }
+
+ static_assert(sizeof(Lightmap::BSP) == 24);
+
+ const Lightmap::BSP *bsp = (const Lightmap::BSP *)lm->bsp_tree.ptr();
+ int32_t node = 0;
+ while (node >= 0) {
+ if (Plane(bsp[node].plane[0], bsp[node].plane[1], bsp[node].plane[2], bsp[node].plane[3]).is_point_over(p_point)) {
+#ifdef DEBUG_ENABLED
+ ERR_FAIL_COND(bsp[node].over >= 0 && bsp[node].over < node);
+#endif
+
+ node = bsp[node].over;
+ } else {
+#ifdef DEBUG_ENABLED
+ ERR_FAIL_COND(bsp[node].under >= 0 && bsp[node].under < node);
+#endif
+ node = bsp[node].under;
+ }
+ }
+
+ if (node == Lightmap::BSP::EMPTY_LEAF) {
+ return; //nothing could be done
+ }
+
+ node = ABS(node) - 1;
+
+ uint32_t *tetrahedron = (uint32_t *)&lm->tetrahedra[node * 4];
+ Vector3 points[4] = { lm->points[tetrahedron[0]], lm->points[tetrahedron[1]], lm->points[tetrahedron[2]], lm->points[tetrahedron[3]] };
+ const Color *sh_colors[4]{ &lm->point_sh[tetrahedron[0] * 9], &lm->point_sh[tetrahedron[1] * 9], &lm->point_sh[tetrahedron[2] * 9], &lm->point_sh[tetrahedron[3] * 9] };
+ Color barycentric = Geometry3D::tetrahedron_get_barycentric_coords(points[0], points[1], points[2], points[3], p_point);
+
+ for (int i = 0; i < 4; i++) {
+ float c = CLAMP(barycentric[i], 0.0, 1.0);
+ for (int j = 0; j < 9; j++) {
+ r_sh[j] += sh_colors[i][j] * c;
+ }
+ }
+}
+
+bool RasterizerStorageRD::lightmap_is_interior(RID p_lightmap) const {
+ const Lightmap *lm = lightmap_owner.getornull(p_lightmap);
+ ERR_FAIL_COND_V(!lm, false);
+ return lm->interior;
+}
+
+AABB RasterizerStorageRD::lightmap_get_aabb(RID p_lightmap) const {
+ const Lightmap *lm = lightmap_owner.getornull(p_lightmap);
+ ERR_FAIL_COND_V(!lm, AABB());
+ return lm->bounds;
+}
+
/* RENDER TARGET API */
void RasterizerStorageRD::_clear_render_target(RenderTarget *rt) {
-
//free in reverse dependency order
if (rt->framebuffer.is_valid()) {
RD::get_singleton()->free(rt->framebuffer);
@@ -3911,7 +4332,6 @@ void RasterizerStorageRD::_clear_render_target(RenderTarget *rt) {
if (rt->backbuffer.is_valid()) {
RD::get_singleton()->free(rt->backbuffer);
rt->backbuffer = RID();
- rt->backbuffer_fb = RID();
for (int i = 0; i < rt->backbuffer_mipmaps.size(); i++) {
//just erase copies, since the rest are erased by dependency
RD::get_singleton()->free(rt->backbuffer_mipmaps[i].mipmap_copy);
@@ -3928,7 +4348,6 @@ void RasterizerStorageRD::_clear_render_target(RenderTarget *rt) {
}
void RasterizerStorageRD::_update_render_target(RenderTarget *rt) {
-
if (rt->texture.is_null()) {
//create a placeholder until updated
rt->texture = texture_2d_placeholder_create();
@@ -4025,27 +4444,17 @@ void RasterizerStorageRD::_create_render_target_backbuffer(RenderTarget *rt) {
tf.width = rt->size.width;
tf.height = rt->size.height;
tf.type = RD::TEXTURE_TYPE_2D;
- tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
+ tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
tf.mipmaps = mipmaps_required;
rt->backbuffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
-
- {
- Vector<RID> backbuffer_att;
- RID backbuffer_fb_tex = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rt->backbuffer, 0, 0);
- backbuffer_att.push_back(backbuffer_fb_tex);
- rt->backbuffer_fb = RD::get_singleton()->framebuffer_create(backbuffer_att);
- }
+ rt->backbuffer_mipmap0 = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rt->backbuffer, 0, 0);
//create mipmaps
for (uint32_t i = 1; i < mipmaps_required; i++) {
-
RenderTarget::BackbufferMipmap mm;
{
mm.mipmap = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rt->backbuffer, 0, i);
- Vector<RID> mm_fb_at;
- mm_fb_at.push_back(mm.mipmap);
- mm.mipmap_fb = RD::get_singleton()->framebuffer_create(mm_fb_at);
}
{
@@ -4057,9 +4466,6 @@ void RasterizerStorageRD::_create_render_target_backbuffer(RenderTarget *rt) {
mmtf.mipmaps = 1;
mm.mipmap_copy = RD::get_singleton()->texture_create(mmtf, RD::TextureView());
- Vector<RID> mm_fb_at;
- mm_fb_at.push_back(mm.mipmap_copy);
- mm.mipmap_copy_fb = RD::get_singleton()->framebuffer_create(mm_fb_at);
}
rt->backbuffer_mipmaps.push_back(mm);
@@ -4109,14 +4515,12 @@ void RasterizerStorageRD::render_target_set_flag(RID p_render_target, RenderTarg
}
bool RasterizerStorageRD::render_target_was_used(RID p_render_target) {
-
RenderTarget *rt = render_target_owner.getornull(p_render_target);
ERR_FAIL_COND_V(!rt, false);
return rt->was_used;
}
void RasterizerStorageRD::render_target_set_as_unused(RID p_render_target) {
-
RenderTarget *rt = render_target_owner.getornull(p_render_target);
ERR_FAIL_COND(!rt);
rt->was_used = false;
@@ -4136,6 +4540,13 @@ RID RasterizerStorageRD::render_target_get_rd_framebuffer(RID p_render_target) {
return rt->framebuffer;
}
+RID RasterizerStorageRD::render_target_get_rd_texture(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ ERR_FAIL_COND_V(!rt, RID());
+
+ return rt->color;
+}
+
void RasterizerStorageRD::render_target_request_clear(RID p_render_target, const Color &p_clear_color) {
RenderTarget *rt = render_target_owner.getornull(p_render_target);
ERR_FAIL_COND(!rt);
@@ -4150,21 +4561,18 @@ bool RasterizerStorageRD::render_target_is_clear_requested(RID p_render_target)
}
Color RasterizerStorageRD::render_target_get_clear_request_color(RID p_render_target) {
-
RenderTarget *rt = render_target_owner.getornull(p_render_target);
ERR_FAIL_COND_V(!rt, Color());
return rt->clear_color;
}
void RasterizerStorageRD::render_target_disable_clear_request(RID p_render_target) {
-
RenderTarget *rt = render_target_owner.getornull(p_render_target);
ERR_FAIL_COND(!rt);
rt->clear_requested = false;
}
void RasterizerStorageRD::render_target_do_clear_request(RID p_render_target) {
-
RenderTarget *rt = render_target_owner.getornull(p_render_target);
ERR_FAIL_COND(!rt);
if (!rt->clear_requested) {
@@ -4185,27 +4593,25 @@ void RasterizerStorageRD::render_target_copy_to_back_buffer(RID p_render_target,
}
Rect2i region = p_region;
- Rect2 blur_region;
if (region == Rect2i()) {
region.size = rt->size;
- } else {
- blur_region = region;
- blur_region.position /= rt->size;
- blur_region.size /= rt->size;
}
//single texture copy for backbuffer
- RD::get_singleton()->texture_copy(rt->color, rt->backbuffer, Vector3(region.position.x, region.position.y, 0), Vector3(region.position.x, region.position.y, 0), Vector3(region.size.x, region.size.y, 1), 0, 0, 0, 0, true);
+ RD::get_singleton()->texture_copy(rt->color, rt->backbuffer_mipmap0, Vector3(region.position.x, region.position.y, 0), Vector3(region.position.x, region.position.y, 0), Vector3(region.size.x, region.size.y, 1), 0, 0, 0, 0, true);
//effects.copy(rt->color, rt->backbuffer_fb, blur_region);
//then mipmap blur
RID prev_texture = rt->color; //use color, not backbuffer, as bb has mipmaps.
- Vector2 pixel_size = Vector2(1.0 / rt->size.width, 1.0 / rt->size.height);
for (int i = 0; i < rt->backbuffer_mipmaps.size(); i++) {
- pixel_size *= 2.0; //go halfway
+ region.position.x >>= 1;
+ region.position.y >>= 1;
+ region.size.x = MAX(1, region.size.x >> 1);
+ region.size.y = MAX(1, region.size.y >> 1);
+
const RenderTarget::BackbufferMipmap &mm = rt->backbuffer_mipmaps[i];
- effects.gaussian_blur(prev_texture, mm.mipmap_copy_fb, mm.mipmap_copy, mm.mipmap_fb, pixel_size, blur_region);
+ effects.gaussian_blur(prev_texture, mm.mipmap, mm.mipmap_copy, region, true);
prev_texture = mm.mipmap;
}
}
@@ -4241,7 +4647,6 @@ void RasterizerStorageRD::base_update_dependency(RID p_base, RasterizerScene::In
Mesh *mesh = mesh_owner.getornull(p_base);
p_instance->update_dependency(&mesh->instance_dependency);
} else if (multimesh_owner.owns(p_base)) {
-
MultiMesh *multimesh = multimesh_owner.getornull(p_base);
p_instance->update_dependency(&multimesh->instance_dependency);
if (multimesh->mesh.is_valid()) {
@@ -4250,9 +4655,15 @@ void RasterizerStorageRD::base_update_dependency(RID p_base, RasterizerScene::In
} else if (reflection_probe_owner.owns(p_base)) {
ReflectionProbe *rp = reflection_probe_owner.getornull(p_base);
p_instance->update_dependency(&rp->instance_dependency);
+ } else if (decal_owner.owns(p_base)) {
+ Decal *decal = decal_owner.getornull(p_base);
+ p_instance->update_dependency(&decal->instance_dependency);
} else if (gi_probe_owner.owns(p_base)) {
GIProbe *gip = gi_probe_owner.getornull(p_base);
p_instance->update_dependency(&gip->instance_dependency);
+ } else if (lightmap_owner.owns(p_base)) {
+ Lightmap *lm = lightmap_owner.getornull(p_base);
+ p_instance->update_dependency(&lm->instance_dependency);
} else if (light_owner.owns(p_base)) {
Light *l = light_owner.getornull(p_base);
p_instance->update_dependency(&l->instance_dependency);
@@ -4260,7 +4671,6 @@ void RasterizerStorageRD::base_update_dependency(RID p_base, RasterizerScene::In
}
void RasterizerStorageRD::skeleton_update_dependency(RID p_skeleton, RasterizerScene::InstanceBase *p_instance) {
-
Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
ERR_FAIL_COND(!skeleton);
@@ -4268,7 +4678,6 @@ void RasterizerStorageRD::skeleton_update_dependency(RID p_skeleton, RasterizerS
}
RS::InstanceType RasterizerStorageRD::get_base_type(RID p_rid) const {
-
if (mesh_owner.owns(p_rid)) {
return RS::INSTANCE_MESH;
}
@@ -4278,23 +4687,924 @@ RS::InstanceType RasterizerStorageRD::get_base_type(RID p_rid) const {
if (reflection_probe_owner.owns(p_rid)) {
return RS::INSTANCE_REFLECTION_PROBE;
}
+ if (decal_owner.owns(p_rid)) {
+ return RS::INSTANCE_DECAL;
+ }
if (gi_probe_owner.owns(p_rid)) {
return RS::INSTANCE_GI_PROBE;
}
if (light_owner.owns(p_rid)) {
return RS::INSTANCE_LIGHT;
}
+ if (lightmap_owner.owns(p_rid)) {
+ return RS::INSTANCE_LIGHTMAP;
+ }
return RS::INSTANCE_NONE;
}
+
+void RasterizerStorageRD::texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp) {
+ if (!decal_atlas.textures.has(p_texture)) {
+ DecalAtlas::Texture t;
+ t.users = 1;
+ t.panorama_to_dp_users = p_panorama_to_dp ? 1 : 0;
+ decal_atlas.textures[p_texture] = t;
+ decal_atlas.dirty = true;
+ } else {
+ DecalAtlas::Texture *t = decal_atlas.textures.getptr(p_texture);
+ t->users++;
+ if (p_panorama_to_dp) {
+ t->panorama_to_dp_users++;
+ }
+ }
+}
+
+void RasterizerStorageRD::texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp) {
+ DecalAtlas::Texture *t = decal_atlas.textures.getptr(p_texture);
+ ERR_FAIL_COND(!t);
+ t->users--;
+ if (p_panorama_to_dp) {
+ ERR_FAIL_COND(t->panorama_to_dp_users == 0);
+ t->panorama_to_dp_users--;
+ }
+ if (t->users == 0) {
+ decal_atlas.textures.erase(p_texture);
+ //do not mark it dirty, there is no need to since it remains working
+ }
+}
+
+RID RasterizerStorageRD::decal_atlas_get_texture() const {
+ return decal_atlas.texture;
+}
+
+RID RasterizerStorageRD::decal_atlas_get_texture_srgb() const {
+ return decal_atlas.texture;
+}
+
+void RasterizerStorageRD::_update_decal_atlas() {
+ if (!decal_atlas.dirty) {
+ return; //nothing to do
+ }
+
+ decal_atlas.dirty = false;
+
+ if (decal_atlas.texture.is_valid()) {
+ RD::get_singleton()->free(decal_atlas.texture);
+ decal_atlas.texture = RID();
+ decal_atlas.texture_srgb = RID();
+ decal_atlas.texture_mipmaps.clear();
+ }
+
+ int border = 1 << decal_atlas.mipmaps;
+
+ if (decal_atlas.textures.size()) {
+ //generate atlas
+ Vector<DecalAtlas::SortItem> itemsv;
+ itemsv.resize(decal_atlas.textures.size());
+ int base_size = 8;
+ const RID *K = nullptr;
+
+ int idx = 0;
+ while ((K = decal_atlas.textures.next(K))) {
+ DecalAtlas::SortItem &si = itemsv.write[idx];
+
+ Texture *src_tex = texture_owner.getornull(*K);
+
+ si.size.width = (src_tex->width / border) + 1;
+ si.size.height = (src_tex->height / border) + 1;
+ si.pixel_size = Size2i(src_tex->width, src_tex->height);
+
+ if (base_size < si.size.width) {
+ base_size = nearest_power_of_2_templated(si.size.width);
+ }
+
+ si.texture = *K;
+ idx++;
+ }
+
+ //sort items by size
+ itemsv.sort();
+
+ //attempt to create atlas
+ int item_count = itemsv.size();
+ DecalAtlas::SortItem *items = itemsv.ptrw();
+
+ int atlas_height = 0;
+
+ while (true) {
+ Vector<int> v_offsetsv;
+ v_offsetsv.resize(base_size);
+
+ int *v_offsets = v_offsetsv.ptrw();
+ zeromem(v_offsets, sizeof(int) * base_size);
+
+ int max_height = 0;
+
+ for (int i = 0; i < item_count; i++) {
+ //best fit
+ DecalAtlas::SortItem &si = items[i];
+ int best_idx = -1;
+ int best_height = 0x7FFFFFFF;
+ for (int j = 0; j <= base_size - si.size.width; j++) {
+ int height = 0;
+ for (int k = 0; k < si.size.width; k++) {
+ int h = v_offsets[k + j];
+ if (h > height) {
+ height = h;
+ if (height > best_height) {
+ break; //already bad
+ }
+ }
+ }
+
+ if (height < best_height) {
+ best_height = height;
+ best_idx = j;
+ }
+ }
+
+ //update
+ for (int k = 0; k < si.size.width; k++) {
+ v_offsets[k + best_idx] = best_height + si.size.height;
+ }
+
+ si.pos.x = best_idx;
+ si.pos.y = best_height;
+
+ if (si.pos.y + si.size.height > max_height) {
+ max_height = si.pos.y + si.size.height;
+ }
+ }
+
+ if (max_height <= base_size * 2) {
+ atlas_height = max_height;
+ break; //good ratio, break;
+ }
+
+ base_size *= 2;
+ }
+
+ decal_atlas.size.width = base_size * border;
+ decal_atlas.size.height = nearest_power_of_2_templated(atlas_height * border);
+
+ for (int i = 0; i < item_count; i++) {
+ DecalAtlas::Texture *t = decal_atlas.textures.getptr(items[i].texture);
+ t->uv_rect.position = items[i].pos * border + Vector2i(border / 2, border / 2);
+ t->uv_rect.size = items[i].pixel_size;
+
+ t->uv_rect.position /= Size2(decal_atlas.size);
+ t->uv_rect.size /= Size2(decal_atlas.size);
+ }
+ } else {
+ //use border as size, so it at least has enough mipmaps
+ decal_atlas.size.width = border;
+ decal_atlas.size.height = border;
+ }
+
+ //blit textures
+
+ RD::TextureFormat tformat;
+ tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ tformat.width = decal_atlas.size.width;
+ tformat.height = decal_atlas.size.height;
+ tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
+ tformat.type = RD::TEXTURE_TYPE_2D;
+ tformat.mipmaps = decal_atlas.mipmaps;
+ tformat.shareable_formats.push_back(RD::DATA_FORMAT_R8G8B8A8_UNORM);
+ tformat.shareable_formats.push_back(RD::DATA_FORMAT_R8G8B8A8_SRGB);
+
+ decal_atlas.texture = RD::get_singleton()->texture_create(tformat, RD::TextureView());
+
+ {
+ //create the framebuffer
+
+ Size2i s = decal_atlas.size;
+
+ for (int i = 0; i < decal_atlas.mipmaps; i++) {
+ DecalAtlas::MipMap mm;
+ mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), decal_atlas.texture, 0, i);
+ Vector<RID> fb;
+ fb.push_back(mm.texture);
+ mm.fb = RD::get_singleton()->framebuffer_create(fb);
+ mm.size = s;
+ decal_atlas.texture_mipmaps.push_back(mm);
+
+ s.width = MAX(1, s.width >> 1);
+ s.height = MAX(1, s.height >> 1);
+ }
+ {
+ //create the SRGB variant
+ RD::TextureView rd_view;
+ rd_view.format_override = RD::DATA_FORMAT_R8G8B8A8_SRGB;
+ decal_atlas.texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, decal_atlas.texture);
+ }
+ }
+
+ RID prev_texture;
+ for (int i = 0; i < decal_atlas.texture_mipmaps.size(); i++) {
+ const DecalAtlas::MipMap &mm = decal_atlas.texture_mipmaps[i];
+
+ Color clear_color(0, 0, 0, 0);
+
+ if (decal_atlas.textures.size()) {
+ if (i == 0) {
+ Vector<Color> cc;
+ cc.push_back(clear_color);
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(mm.fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, cc);
+
+ const RID *K = nullptr;
+ while ((K = decal_atlas.textures.next(K))) {
+ DecalAtlas::Texture *t = decal_atlas.textures.getptr(*K);
+ Texture *src_tex = texture_owner.getornull(*K);
+ effects.copy_to_atlas_fb(src_tex->rd_texture, mm.fb, t->uv_rect, draw_list, false, t->panorama_to_dp_users > 0);
+ }
+
+ RD::get_singleton()->draw_list_end();
+
+ prev_texture = mm.texture;
+ } else {
+ effects.copy_to_fb_rect(prev_texture, mm.fb, Rect2i(Point2i(), mm.size));
+ prev_texture = mm.texture;
+ }
+ } else {
+ RD::get_singleton()->texture_clear(mm.texture, clear_color, 0, 1, 0, 1, false);
+ }
+ }
+}
+
+int32_t RasterizerStorageRD::_global_variable_allocate(uint32_t p_elements) {
+ int32_t idx = 0;
+ while (idx + p_elements <= global_variables.buffer_size) {
+ if (global_variables.buffer_usage[idx].elements == 0) {
+ bool valid = true;
+ for (uint32_t i = 1; i < p_elements; i++) {
+ if (global_variables.buffer_usage[idx + i].elements > 0) {
+ valid = false;
+ idx += i + global_variables.buffer_usage[idx + i].elements;
+ break;
+ }
+ }
+
+ if (!valid) {
+ continue; //if not valid, idx is in new position
+ }
+
+ return idx;
+ } else {
+ idx += global_variables.buffer_usage[idx].elements;
+ }
+ }
+
+ return -1;
+}
+
+void RasterizerStorageRD::_global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value) {
+ switch (p_type) {
+ case RS::GLOBAL_VAR_TYPE_BOOL: {
+ GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ bool b = p_value;
+ bv.x = b ? 1.0 : 0.0;
+ bv.y = 0.0;
+ bv.z = 0.0;
+ bv.w = 0.0;
+
+ } break;
+ case RS::GLOBAL_VAR_TYPE_BVEC2: {
+ GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ uint32_t bvec = p_value;
+ bv.x = (bvec & 1) ? 1.0 : 0.0;
+ bv.y = (bvec & 2) ? 1.0 : 0.0;
+ bv.z = 0.0;
+ bv.w = 0.0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_BVEC3: {
+ GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ uint32_t bvec = p_value;
+ bv.x = (bvec & 1) ? 1.0 : 0.0;
+ bv.y = (bvec & 2) ? 1.0 : 0.0;
+ bv.z = (bvec & 4) ? 1.0 : 0.0;
+ bv.w = 0.0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_BVEC4: {
+ GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ uint32_t bvec = p_value;
+ bv.x = (bvec & 1) ? 1.0 : 0.0;
+ bv.y = (bvec & 2) ? 1.0 : 0.0;
+ bv.z = (bvec & 4) ? 1.0 : 0.0;
+ bv.w = (bvec & 8) ? 1.0 : 0.0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_INT: {
+ GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ int32_t v = p_value;
+ bv.x = v;
+ bv.y = 0;
+ bv.z = 0;
+ bv.w = 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_IVEC2: {
+ GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ Vector2i v = p_value;
+ bv.x = v.x;
+ bv.y = v.y;
+ bv.z = 0;
+ bv.w = 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_IVEC3: {
+ GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ Vector3i v = p_value;
+ bv.x = v.x;
+ bv.y = v.y;
+ bv.z = v.z;
+ bv.w = 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_IVEC4: {
+ GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ Vector<int32_t> v = p_value;
+ bv.x = v.size() >= 1 ? v[0] : 0;
+ bv.y = v.size() >= 2 ? v[1] : 0;
+ bv.z = v.size() >= 3 ? v[2] : 0;
+ bv.w = v.size() >= 4 ? v[3] : 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_RECT2I: {
+ GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ Rect2i v = p_value;
+ bv.x = v.position.x;
+ bv.y = v.position.y;
+ bv.z = v.size.x;
+ bv.w = v.size.y;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_UINT: {
+ GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
+ uint32_t v = p_value;
+ bv.x = v;
+ bv.y = 0;
+ bv.z = 0;
+ bv.w = 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_UVEC2: {
+ GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
+ Vector2i v = p_value;
+ bv.x = v.x;
+ bv.y = v.y;
+ bv.z = 0;
+ bv.w = 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_UVEC3: {
+ GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
+ Vector3i v = p_value;
+ bv.x = v.x;
+ bv.y = v.y;
+ bv.z = v.z;
+ bv.w = 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_UVEC4: {
+ GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
+ Vector<int32_t> v = p_value;
+ bv.x = v.size() >= 1 ? v[0] : 0;
+ bv.y = v.size() >= 2 ? v[1] : 0;
+ bv.z = v.size() >= 3 ? v[2] : 0;
+ bv.w = v.size() >= 4 ? v[3] : 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_FLOAT: {
+ GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ float v = p_value;
+ bv.x = v;
+ bv.y = 0;
+ bv.z = 0;
+ bv.w = 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_VEC2: {
+ GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ Vector2 v = p_value;
+ bv.x = v.x;
+ bv.y = v.y;
+ bv.z = 0;
+ bv.w = 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_VEC3: {
+ GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ Vector3 v = p_value;
+ bv.x = v.x;
+ bv.y = v.y;
+ bv.z = v.z;
+ bv.w = 0;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_VEC4: {
+ GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ Plane v = p_value;
+ bv.x = v.normal.x;
+ bv.y = v.normal.y;
+ bv.z = v.normal.z;
+ bv.w = v.d;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_COLOR: {
+ GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ Color v = p_value;
+ bv.x = v.r;
+ bv.y = v.g;
+ bv.z = v.b;
+ bv.w = v.a;
+
+ GlobalVariables::Value &bv_linear = global_variables.buffer_values[p_index + 1];
+ v = v.to_linear();
+ bv_linear.x = v.r;
+ bv_linear.y = v.g;
+ bv_linear.z = v.b;
+ bv_linear.w = v.a;
+
+ } break;
+ case RS::GLOBAL_VAR_TYPE_RECT2: {
+ GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ Rect2 v = p_value;
+ bv.x = v.position.x;
+ bv.y = v.position.y;
+ bv.z = v.size.x;
+ bv.w = v.size.y;
+ } break;
+ case RS::GLOBAL_VAR_TYPE_MAT2: {
+ GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+ Vector<float> m2 = p_value;
+ if (m2.size() < 4) {
+ m2.resize(4);
+ }
+ bv[0].x = m2[0];
+ bv[0].y = m2[1];
+ bv[0].z = 0;
+ bv[0].w = 0;
+
+ bv[1].x = m2[2];
+ bv[1].y = m2[3];
+ bv[1].z = 0;
+ bv[1].w = 0;
+
+ } break;
+ case RS::GLOBAL_VAR_TYPE_MAT3: {
+ GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+ Basis v = p_value;
+ bv[0].x = v.elements[0][0];
+ bv[0].y = v.elements[1][0];
+ bv[0].z = v.elements[2][0];
+ bv[0].w = 0;
+
+ bv[1].x = v.elements[0][1];
+ bv[1].y = v.elements[1][1];
+ bv[1].z = v.elements[2][1];
+ bv[1].w = 0;
+
+ bv[2].x = v.elements[0][2];
+ bv[2].y = v.elements[1][2];
+ bv[2].z = v.elements[2][2];
+ bv[2].w = 0;
+
+ } break;
+ case RS::GLOBAL_VAR_TYPE_MAT4: {
+ GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+
+ Vector<float> m2 = p_value;
+ if (m2.size() < 16) {
+ m2.resize(16);
+ }
+
+ bv[0].x = m2[0];
+ bv[0].y = m2[1];
+ bv[0].z = m2[2];
+ bv[0].w = m2[3];
+
+ bv[1].x = m2[4];
+ bv[1].y = m2[5];
+ bv[1].z = m2[6];
+ bv[1].w = m2[7];
+
+ bv[2].x = m2[8];
+ bv[2].y = m2[9];
+ bv[2].z = m2[10];
+ bv[2].w = m2[11];
+
+ bv[3].x = m2[12];
+ bv[3].y = m2[13];
+ bv[3].z = m2[14];
+ bv[3].w = m2[15];
+
+ } break;
+ case RS::GLOBAL_VAR_TYPE_TRANSFORM_2D: {
+ GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+ Transform2D v = p_value;
+ bv[0].x = v.elements[0][0];
+ bv[0].y = v.elements[0][1];
+ bv[0].z = 0;
+ bv[0].w = 0;
+
+ bv[1].x = v.elements[1][0];
+ bv[1].y = v.elements[1][1];
+ bv[1].z = 0;
+ bv[1].w = 0;
+
+ bv[2].x = v.elements[2][0];
+ bv[2].y = v.elements[2][1];
+ bv[2].z = 1;
+ bv[2].w = 0;
+
+ } break;
+ case RS::GLOBAL_VAR_TYPE_TRANSFORM: {
+ GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+ Transform v = p_value;
+ bv[0].x = v.basis.elements[0][0];
+ bv[0].y = v.basis.elements[1][0];
+ bv[0].z = v.basis.elements[2][0];
+ bv[0].w = 0;
+
+ bv[1].x = v.basis.elements[0][1];
+ bv[1].y = v.basis.elements[1][1];
+ bv[1].z = v.basis.elements[2][1];
+ bv[1].w = 0;
+
+ bv[2].x = v.basis.elements[0][2];
+ bv[2].y = v.basis.elements[1][2];
+ bv[2].z = v.basis.elements[2][2];
+ bv[2].w = 0;
+
+ bv[3].x = v.origin.x;
+ bv[3].y = v.origin.y;
+ bv[3].z = v.origin.z;
+ bv[3].w = 1;
+
+ } break;
+ default: {
+ ERR_FAIL();
+ }
+ }
+}
+
+void RasterizerStorageRD::_global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements) {
+ int32_t prev_chunk = -1;
+
+ for (int32_t i = 0; i < p_elements; i++) {
+ int32_t chunk = (p_index + i) / GlobalVariables::BUFFER_DIRTY_REGION_SIZE;
+ if (chunk != prev_chunk) {
+ if (!global_variables.buffer_dirty_regions[chunk]) {
+ global_variables.buffer_dirty_regions[chunk] = true;
+ global_variables.buffer_dirty_region_count++;
+ }
+ }
+
+ prev_chunk = chunk;
+ }
+}
+
+void RasterizerStorageRD::global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) {
+ ERR_FAIL_COND(global_variables.variables.has(p_name));
+ GlobalVariables::Variable gv;
+ gv.type = p_type;
+ gv.value = p_value;
+ gv.buffer_index = -1;
+
+ if (p_type >= RS::GLOBAL_VAR_TYPE_SAMPLER2D) {
+ //is texture
+ global_variables.must_update_texture_materials = true; //normally ther are no
+ } else {
+ gv.buffer_elements = 1;
+ if (p_type == RS::GLOBAL_VAR_TYPE_COLOR || p_type == RS::GLOBAL_VAR_TYPE_MAT2) {
+ //color needs to elements to store srgb and linear
+ gv.buffer_elements = 2;
+ }
+ if (p_type == RS::GLOBAL_VAR_TYPE_MAT3 || p_type == RS::GLOBAL_VAR_TYPE_TRANSFORM_2D) {
+ //color needs to elements to store srgb and linear
+ gv.buffer_elements = 3;
+ }
+ if (p_type == RS::GLOBAL_VAR_TYPE_MAT4 || p_type == RS::GLOBAL_VAR_TYPE_TRANSFORM) {
+ //color needs to elements to store srgb and linear
+ gv.buffer_elements = 4;
+ }
+
+ //is vector, allocate in buffer and update index
+ gv.buffer_index = _global_variable_allocate(gv.buffer_elements);
+ ERR_FAIL_COND_MSG(gv.buffer_index < 0, vformat("Failed allocating global variable '%s' out of buffer memory. Consider increasing it in the Project Settings.", String(p_name)));
+ global_variables.buffer_usage[gv.buffer_index].elements = gv.buffer_elements;
+ _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value);
+ _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
+
+ global_variables.must_update_buffer_materials = true; //normally ther are no
+ }
+
+ global_variables.variables[p_name] = gv;
+}
+
+void RasterizerStorageRD::global_variable_remove(const StringName &p_name) {
+ if (!global_variables.variables.has(p_name)) {
+ return;
+ }
+ GlobalVariables::Variable &gv = global_variables.variables[p_name];
+
+ if (gv.buffer_index >= 0) {
+ global_variables.buffer_usage[gv.buffer_index].elements = 0;
+ global_variables.must_update_buffer_materials = true;
+ } else {
+ global_variables.must_update_texture_materials = true;
+ }
+
+ global_variables.variables.erase(p_name);
+}
+
+Vector<StringName> RasterizerStorageRD::global_variable_get_list() const {
+ if (!Engine::get_singleton()->is_editor_hint()) {
+ ERR_FAIL_V_MSG(Vector<StringName>(), "This function should never be used outside the editor, it can severely damage performance.");
+ }
+
+ const StringName *K = nullptr;
+ Vector<StringName> names;
+ while ((K = global_variables.variables.next(K))) {
+ names.push_back(*K);
+ }
+ names.sort_custom<StringName::AlphCompare>();
+ return names;
+}
+
+void RasterizerStorageRD::global_variable_set(const StringName &p_name, const Variant &p_value) {
+ ERR_FAIL_COND(!global_variables.variables.has(p_name));
+ GlobalVariables::Variable &gv = global_variables.variables[p_name];
+ gv.value = p_value;
+ if (gv.override.get_type() == Variant::NIL) {
+ if (gv.buffer_index >= 0) {
+ //buffer
+ _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value);
+ _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
+ } else {
+ //texture
+ for (Set<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) {
+ Material *material = material_owner.getornull(E->get());
+ ERR_CONTINUE(!material);
+ _material_queue_update(material, false, true);
+ }
+ }
+ }
+}
+
+void RasterizerStorageRD::global_variable_set_override(const StringName &p_name, const Variant &p_value) {
+ if (!global_variables.variables.has(p_name)) {
+ return; //variable may not exist
+ }
+ GlobalVariables::Variable &gv = global_variables.variables[p_name];
+
+ gv.override = p_value;
+
+ if (gv.buffer_index >= 0) {
+ //buffer
+ if (gv.override.get_type() == Variant::NIL) {
+ _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value);
+ } else {
+ _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.override);
+ }
+
+ _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
+ } else {
+ //texture
+ //texture
+ for (Set<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) {
+ Material *material = material_owner.getornull(E->get());
+ ERR_CONTINUE(!material);
+ _material_queue_update(material, false, true);
+ }
+ }
+}
+
+Variant RasterizerStorageRD::global_variable_get(const StringName &p_name) const {
+ if (!Engine::get_singleton()->is_editor_hint()) {
+ ERR_FAIL_V_MSG(Variant(), "This function should never be used outside the editor, it can severely damage performance.");
+ }
+
+ if (!global_variables.variables.has(p_name)) {
+ return Variant();
+ }
+
+ return global_variables.variables[p_name].value;
+}
+
+RS::GlobalVariableType RasterizerStorageRD::global_variable_get_type_internal(const StringName &p_name) const {
+ if (!global_variables.variables.has(p_name)) {
+ return RS::GLOBAL_VAR_TYPE_MAX;
+ }
+
+ return global_variables.variables[p_name].type;
+}
+
+RS::GlobalVariableType RasterizerStorageRD::global_variable_get_type(const StringName &p_name) const {
+ if (!Engine::get_singleton()->is_editor_hint()) {
+ ERR_FAIL_V_MSG(RS::GLOBAL_VAR_TYPE_MAX, "This function should never be used outside the editor, it can severely damage performance.");
+ }
+
+ return global_variable_get_type_internal(p_name);
+}
+
+void RasterizerStorageRD::global_variables_load_settings(bool p_load_textures) {
+ List<PropertyInfo> settings;
+ ProjectSettings::get_singleton()->get_property_list(&settings);
+
+ for (List<PropertyInfo>::Element *E = settings.front(); E; E = E->next()) {
+ if (E->get().name.begins_with("shader_globals/")) {
+ StringName name = E->get().name.get_slice("/", 1);
+ Dictionary d = ProjectSettings::get_singleton()->get(E->get().name);
+
+ ERR_CONTINUE(!d.has("type"));
+ ERR_CONTINUE(!d.has("value"));
+
+ String type = d["type"];
+
+ static const char *global_var_type_names[RS::GLOBAL_VAR_TYPE_MAX] = {
+ "bool",
+ "bvec2",
+ "bvec3",
+ "bvec4",
+ "int",
+ "ivec2",
+ "ivec3",
+ "ivec4",
+ "rect2i",
+ "uint",
+ "uvec2",
+ "uvec3",
+ "uvec4",
+ "float",
+ "vec2",
+ "vec3",
+ "vec4",
+ "color",
+ "rect2",
+ "mat2",
+ "mat3",
+ "mat4",
+ "transform_2d",
+ "transform",
+ "sampler2D",
+ "sampler2DArray",
+ "sampler3D",
+ "samplerCube",
+ };
+
+ RS::GlobalVariableType gvtype = RS::GLOBAL_VAR_TYPE_MAX;
+
+ for (int i = 0; i < RS::GLOBAL_VAR_TYPE_MAX; i++) {
+ if (global_var_type_names[i] == type) {
+ gvtype = RS::GlobalVariableType(i);
+ break;
+ }
+ }
+
+ ERR_CONTINUE(gvtype == RS::GLOBAL_VAR_TYPE_MAX); //type invalid
+
+ Variant value = d["value"];
+
+ if (gvtype >= RS::GLOBAL_VAR_TYPE_SAMPLER2D) {
+ //textire
+ if (!p_load_textures) {
+ value = RID();
+ continue;
+ }
+
+ String path = value;
+ RES resource = ResourceLoader::load(path);
+ ERR_CONTINUE(resource.is_null());
+ value = resource;
+ }
+
+ if (global_variables.variables.has(name)) {
+ //has it, update it
+ global_variable_set(name, value);
+ } else {
+ global_variable_add(name, gvtype, value);
+ }
+ }
+ }
+}
+
+void RasterizerStorageRD::global_variables_clear() {
+ global_variables.variables.clear(); //not right but for now enough
+}
+
+RID RasterizerStorageRD::global_variables_get_storage_buffer() const {
+ return global_variables.buffer;
+}
+
+int32_t RasterizerStorageRD::global_variables_instance_allocate(RID p_instance) {
+ ERR_FAIL_COND_V(global_variables.instance_buffer_pos.has(p_instance), -1);
+ int32_t pos = _global_variable_allocate(ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES);
+ global_variables.instance_buffer_pos[p_instance] = pos; //save anyway
+ ERR_FAIL_COND_V_MSG(pos < 0, -1, "Too many instances using shader instance variables. Increase buffer size in Project Settings.");
+ global_variables.buffer_usage[pos].elements = ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES;
+ return pos;
+}
+
+void RasterizerStorageRD::global_variables_instance_free(RID p_instance) {
+ ERR_FAIL_COND(!global_variables.instance_buffer_pos.has(p_instance));
+ int32_t pos = global_variables.instance_buffer_pos[p_instance];
+ if (pos >= 0) {
+ global_variables.buffer_usage[pos].elements = 0;
+ }
+ global_variables.instance_buffer_pos.erase(p_instance);
+}
+
+void RasterizerStorageRD::global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) {
+ if (!global_variables.instance_buffer_pos.has(p_instance)) {
+ return; //just not allocated, ignore
+ }
+ int32_t pos = global_variables.instance_buffer_pos[p_instance];
+
+ if (pos < 0) {
+ return; //again, not allocated, ignore
+ }
+ ERR_FAIL_INDEX(p_index, ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES);
+ ERR_FAIL_COND_MSG(p_value.get_type() > Variant::COLOR, "Unsupported variant type for instance parameter: " + Variant::get_type_name(p_value.get_type())); //anything greater not supported
+
+ ShaderLanguage::DataType datatype_from_value[Variant::COLOR + 1] = {
+ ShaderLanguage::TYPE_MAX, //nil
+ ShaderLanguage::TYPE_BOOL, //bool
+ ShaderLanguage::TYPE_INT, //int
+ ShaderLanguage::TYPE_FLOAT, //float
+ ShaderLanguage::TYPE_MAX, //string
+ ShaderLanguage::TYPE_VEC2, //vec2
+ ShaderLanguage::TYPE_IVEC2, //vec2i
+ ShaderLanguage::TYPE_VEC4, //rect2
+ ShaderLanguage::TYPE_IVEC4, //rect2i
+ ShaderLanguage::TYPE_VEC3, // vec3
+ ShaderLanguage::TYPE_IVEC3, //vec3i
+ ShaderLanguage::TYPE_MAX, //xform2d not supported here
+ ShaderLanguage::TYPE_VEC4, //plane
+ ShaderLanguage::TYPE_VEC4, //quat
+ ShaderLanguage::TYPE_MAX, //aabb not supported here
+ ShaderLanguage::TYPE_MAX, //basis not supported here
+ ShaderLanguage::TYPE_MAX, //xform not supported here
+ ShaderLanguage::TYPE_VEC4 //color
+ };
+
+ ShaderLanguage::DataType datatype = datatype_from_value[p_value.get_type()];
+
+ ERR_FAIL_COND_MSG(datatype == ShaderLanguage::TYPE_MAX, "Unsupported variant type for instance parameter: " + Variant::get_type_name(p_value.get_type())); //anything greater not supported
+
+ pos += p_index;
+
+ _fill_std140_variant_ubo_value(datatype, p_value, (uint8_t *)&global_variables.buffer_values[pos], true); //instances always use linear color in this renderer
+ _global_variable_mark_buffer_dirty(pos, 1);
+}
+
+void RasterizerStorageRD::_update_global_variables() {
+ if (global_variables.buffer_dirty_region_count > 0) {
+ uint32_t total_regions = global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE;
+ if (total_regions / global_variables.buffer_dirty_region_count <= 4) {
+ // 25% of regions dirty, just update all buffer
+ RD::get_singleton()->buffer_update(global_variables.buffer, 0, sizeof(GlobalVariables::Value) * global_variables.buffer_size, global_variables.buffer_values);
+ zeromem(global_variables.buffer_dirty_regions, sizeof(bool) * total_regions);
+ } else {
+ uint32_t region_byte_size = sizeof(GlobalVariables::Value) * GlobalVariables::BUFFER_DIRTY_REGION_SIZE;
+
+ for (uint32_t i = 0; i < total_regions; i++) {
+ if (global_variables.buffer_dirty_regions[i]) {
+ RD::get_singleton()->buffer_update(global_variables.buffer, i * region_byte_size, region_byte_size, global_variables.buffer_values);
+
+ global_variables.buffer_dirty_regions[i] = false;
+ }
+ }
+ }
+
+ global_variables.buffer_dirty_region_count = 0;
+ }
+
+ if (global_variables.must_update_buffer_materials) {
+ // only happens in the case of a buffer variable added or removed,
+ // so not often.
+ for (List<RID>::Element *E = global_variables.materials_using_buffer.front(); E; E = E->next()) {
+ Material *material = material_owner.getornull(E->get());
+ ERR_CONTINUE(!material); //wtf
+
+ _material_queue_update(material, true, false);
+ }
+
+ global_variables.must_update_buffer_materials = false;
+ }
+
+ if (global_variables.must_update_texture_materials) {
+ // only happens in the case of a buffer variable added or removed,
+ // so not often.
+ for (List<RID>::Element *E = global_variables.materials_using_texture.front(); E; E = E->next()) {
+ Material *material = material_owner.getornull(E->get());
+ ERR_CONTINUE(!material); //wtf
+
+ _material_queue_update(material, false, true);
+ print_line("update material texture?");
+ }
+
+ global_variables.must_update_texture_materials = false;
+ }
+}
+
void RasterizerStorageRD::update_dirty_resources() {
+ _update_global_variables(); //must do before materials, so it can queue them for update
_update_queued_materials();
_update_dirty_multimeshes();
_update_dirty_skeletons();
+ _update_decal_atlas();
}
bool RasterizerStorageRD::has_os_feature(const String &p_feature) const {
-
if (p_feature == "rgtc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC5_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) {
return true;
}
@@ -4317,8 +5627,8 @@ bool RasterizerStorageRD::has_os_feature(const String &p_feature) const {
return false;
}
-bool RasterizerStorageRD::free(RID p_rid) {
+bool RasterizerStorageRD::free(RID p_rid) {
if (texture_owner.owns(p_rid)) {
Texture *t = texture_owner.getornull(p_rid);
@@ -4339,6 +5649,11 @@ bool RasterizerStorageRD::free(RID p_rid) {
}
}
+ if (decal_atlas.textures.has(p_rid)) {
+ decal_atlas.textures.erase(p_rid);
+ //there is not much a point of making it dirty, just let it be.
+ }
+
for (int i = 0; i < t->proxies.size(); i++) {
Texture *p = texture_owner.getornull(t->proxies[i]);
ERR_CONTINUE(!p);
@@ -4389,14 +5704,28 @@ bool RasterizerStorageRD::free(RID p_rid) {
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_rid);
reflection_probe->instance_dependency.instance_notify_deleted(p_rid);
reflection_probe_owner.free(p_rid);
+ } else if (decal_owner.owns(p_rid)) {
+ Decal *decal = decal_owner.getornull(p_rid);
+ for (int i = 0; i < RS::DECAL_TEXTURE_MAX; i++) {
+ if (decal->textures[i].is_valid() && texture_owner.owns(decal->textures[i])) {
+ texture_remove_from_decal_atlas(decal->textures[i]);
+ }
+ }
+ decal->instance_dependency.instance_notify_deleted(p_rid);
+ decal_owner.free(p_rid);
} else if (gi_probe_owner.owns(p_rid)) {
gi_probe_allocate(p_rid, Transform(), AABB(), Vector3i(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<int>()); //deallocate
GIProbe *gi_probe = gi_probe_owner.getornull(p_rid);
gi_probe->instance_dependency.instance_notify_deleted(p_rid);
gi_probe_owner.free(p_rid);
+ } else if (lightmap_owner.owns(p_rid)) {
+ lightmap_set_textures(p_rid, RID(), false);
+ Lightmap *lightmap = lightmap_owner.getornull(p_rid);
+ lightmap->instance_dependency.instance_notify_deleted(p_rid);
+ lightmap_owner.free(p_rid);
} else if (light_owner.owns(p_rid)) {
-
+ light_set_projector(p_rid, RID()); //clear projector
// delete the texture
Light *light = light_owner.getornull(p_rid);
light->instance_dependency.instance_notify_deleted(p_rid);
@@ -4436,6 +5765,7 @@ void RasterizerStorageRD::capture_timestamp(const String &p_name) {
uint32_t RasterizerStorageRD::get_captured_timestamps_count() const {
return RD::get_singleton()->get_captured_timestamps_count();
}
+
uint64_t RasterizerStorageRD::get_captured_timestamps_frame() const {
return RD::get_singleton()->get_captured_timestamps_frame();
}
@@ -4443,20 +5773,36 @@ uint64_t RasterizerStorageRD::get_captured_timestamps_frame() const {
uint64_t RasterizerStorageRD::get_captured_timestamp_gpu_time(uint32_t p_index) const {
return RD::get_singleton()->get_captured_timestamp_gpu_time(p_index);
}
+
uint64_t RasterizerStorageRD::get_captured_timestamp_cpu_time(uint32_t p_index) const {
return RD::get_singleton()->get_captured_timestamp_cpu_time(p_index);
}
+
String RasterizerStorageRD::get_captured_timestamp_name(uint32_t p_index) const {
return RD::get_singleton()->get_captured_timestamp_name(p_index);
}
+RasterizerStorageRD *RasterizerStorageRD::base_singleton = nullptr;
+
RasterizerStorageRD::RasterizerStorageRD() {
+ base_singleton = this;
for (int i = 0; i < SHADER_TYPE_MAX; i++) {
- shader_data_request_func[i] = NULL;
+ shader_data_request_func[i] = nullptr;
}
- material_update_list = NULL;
+ static_assert(sizeof(GlobalVariables::Value) == 16);
+
+ global_variables.buffer_size = GLOBAL_GET("rendering/high_end/global_shader_variables_buffer_size");
+ global_variables.buffer_size = MAX(4096, global_variables.buffer_size);
+ global_variables.buffer_values = memnew_arr(GlobalVariables::Value, global_variables.buffer_size);
+ zeromem(global_variables.buffer_values, sizeof(GlobalVariables::Value) * global_variables.buffer_size);
+ global_variables.buffer_usage = memnew_arr(GlobalVariables::ValueUsage, global_variables.buffer_size);
+ global_variables.buffer_dirty_regions = memnew_arr(bool, global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE);
+ zeromem(global_variables.buffer_dirty_regions, sizeof(bool) * global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE);
+ global_variables.buffer = RD::get_singleton()->storage_buffer_create(sizeof(GlobalVariables::Value) * global_variables.buffer_size);
+
+ material_update_list = nullptr;
{ //create default textures
RD::TextureFormat tformat;
@@ -4492,6 +5838,10 @@ RasterizerStorageRD::RasterizerStorageRD() {
Vector<Vector<uint8_t>> vpv;
vpv.push_back(pv);
default_rd_textures[DEFAULT_RD_TEXTURE_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
+
+ //take the chance and initialize decal atlas to something
+ decal_atlas.texture = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
+ decal_atlas.texture_srgb = decal_atlas.texture;
}
for (int i = 0; i < 16; i++) {
@@ -4612,6 +5962,32 @@ RasterizerStorageRD::RasterizerStorageRD() {
}
}
+ { //create default array
+
+ RD::TextureFormat tformat;
+ tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ tformat.width = 4;
+ tformat.height = 4;
+ tformat.array_layers = 1;
+ tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
+ tformat.type = RD::TEXTURE_TYPE_2D_ARRAY;
+
+ Vector<uint8_t> pv;
+ pv.resize(16 * 4);
+ for (int i = 0; i < 16; 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_2D_ARRAY_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
+ }
+ }
+
//default samplers
for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
@@ -4623,7 +5999,6 @@ RasterizerStorageRD::RasterizerStorageRD() {
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;
@@ -4644,14 +6019,14 @@ RasterizerStorageRD::RasterizerStorageRD() {
sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
sampler_state.use_anisotropy = true;
- sampler_state.anisotropy_max = GLOBAL_GET("rendering/quality/filters/max_anisotropy");
+ sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/quality/texture_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;
sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
sampler_state.use_anisotropy = true;
- sampler_state.anisotropy_max = GLOBAL_GET("rendering/quality/filters/max_anisotropy");
+ sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/quality/texture_filters/anisotropic_filtering_level"));
} break;
default: {
@@ -4659,7 +6034,6 @@ RasterizerStorageRD::RasterizerStorageRD() {
}
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;
@@ -4682,126 +6056,138 @@ RasterizerStorageRD::RasterizerStorageRD() {
//default rd buffers
{
+ Vector<uint8_t> buffer;
+ {
+ buffer.resize(sizeof(float) * 3);
+ {
+ uint8_t *w = buffer.ptrw();
+ float *fptr = (float *)w;
+ fptr[0] = 0.0;
+ fptr[1] = 0.0;
+ fptr[2] = 0.0;
+ }
+ mesh_default_rd_buffers[DEFAULT_RD_BUFFER_VERTEX] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
+ }
- { //vertex
+ { //normal
+ buffer.resize(sizeof(float) * 3);
+ {
+ uint8_t *w = buffer.ptrw();
+ float *fptr = (float *)w;
+ fptr[0] = 1.0;
+ fptr[1] = 0.0;
+ fptr[2] = 0.0;
+ }
+ mesh_default_rd_buffers[DEFAULT_RD_BUFFER_NORMAL] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
+ }
- Vector<uint8_t> buffer;
- buffer.resize(sizeof(float) * 3);
- {
- uint8_t *w = buffer.ptrw();
- float *fptr = (float *)w;
- fptr[0] = 0.0;
- fptr[1] = 0.0;
- fptr[2] = 0.0;
- }
- mesh_default_rd_buffers[DEFAULT_RD_BUFFER_VERTEX] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
-}
+ { //tangent
+ buffer.resize(sizeof(float) * 4);
+ {
+ uint8_t *w = buffer.ptrw();
+ float *fptr = (float *)w;
+ fptr[0] = 1.0;
+ fptr[1] = 0.0;
+ fptr[2] = 0.0;
+ fptr[3] = 0.0;
+ }
+ mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TANGENT] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
+ }
-{ //normal
- Vector<uint8_t> buffer;
- buffer.resize(sizeof(float) * 3);
- {
- uint8_t *w = buffer.ptrw();
- float *fptr = (float *)w;
- fptr[0] = 1.0;
- fptr[1] = 0.0;
- fptr[2] = 0.0;
- }
- mesh_default_rd_buffers[DEFAULT_RD_BUFFER_NORMAL] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
-}
+ { //color
+ buffer.resize(sizeof(float) * 4);
+ {
+ uint8_t *w = buffer.ptrw();
+ float *fptr = (float *)w;
+ fptr[0] = 1.0;
+ fptr[1] = 1.0;
+ fptr[2] = 1.0;
+ fptr[3] = 1.0;
+ }
+ mesh_default_rd_buffers[DEFAULT_RD_BUFFER_COLOR] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
+ }
-{ //tangent
- Vector<uint8_t> buffer;
- buffer.resize(sizeof(float) * 4);
- {
- uint8_t *w = buffer.ptrw();
- float *fptr = (float *)w;
- fptr[0] = 1.0;
- fptr[1] = 0.0;
- fptr[2] = 0.0;
- fptr[3] = 0.0;
- }
- mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TANGENT] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
-}
+ { //tex uv 1
+ buffer.resize(sizeof(float) * 2);
+ {
+ uint8_t *w = buffer.ptrw();
+ float *fptr = (float *)w;
+ fptr[0] = 0.0;
+ fptr[1] = 0.0;
+ }
+ mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TEX_UV] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
+ }
+ { //tex uv 2
+ buffer.resize(sizeof(float) * 2);
+ {
+ uint8_t *w = buffer.ptrw();
+ float *fptr = (float *)w;
+ fptr[0] = 0.0;
+ fptr[1] = 0.0;
+ }
+ mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TEX_UV2] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
+ }
-{ //color
- Vector<uint8_t> buffer;
- buffer.resize(sizeof(float) * 4);
- {
- uint8_t *w = buffer.ptrw();
- float *fptr = (float *)w;
- fptr[0] = 1.0;
- fptr[1] = 1.0;
- fptr[2] = 1.0;
- fptr[3] = 1.0;
- }
- mesh_default_rd_buffers[DEFAULT_RD_BUFFER_COLOR] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
-}
+ { //bones
+ buffer.resize(sizeof(uint32_t) * 4);
+ {
+ uint8_t *w = buffer.ptrw();
+ uint32_t *fptr = (uint32_t *)w;
+ fptr[0] = 0;
+ fptr[1] = 0;
+ fptr[2] = 0;
+ fptr[3] = 0;
+ }
+ mesh_default_rd_buffers[DEFAULT_RD_BUFFER_BONES] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
+ }
-{ //tex uv 1
- Vector<uint8_t> buffer;
- buffer.resize(sizeof(float) * 2);
- {
- uint8_t *w = buffer.ptrw();
- float *fptr = (float *)w;
- fptr[0] = 0.0;
- fptr[1] = 0.0;
- }
- mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TEX_UV] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
-}
-{ //tex uv 2
- Vector<uint8_t> buffer;
- buffer.resize(sizeof(float) * 2);
- {
- uint8_t *w = buffer.ptrw();
- float *fptr = (float *)w;
- fptr[0] = 0.0;
- fptr[1] = 0.0;
+ { //weights
+ buffer.resize(sizeof(float) * 4);
+ {
+ uint8_t *w = buffer.ptrw();
+ float *fptr = (float *)w;
+ fptr[0] = 0.0;
+ fptr[1] = 0.0;
+ fptr[2] = 0.0;
+ fptr[3] = 0.0;
+ }
+ mesh_default_rd_buffers[DEFAULT_RD_BUFFER_WEIGHTS] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
+ }
}
- mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TEX_UV2] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
-}
-{ //bones
- Vector<uint8_t> buffer;
- buffer.resize(sizeof(uint32_t) * 4);
{
- uint8_t *w = buffer.ptrw();
- uint32_t *fptr = (uint32_t *)w;
- fptr[0] = 0;
- fptr[1] = 0;
- fptr[2] = 0;
- fptr[3] = 0;
+ Vector<String> sdf_versions;
+ sdf_versions.push_back(""); //one only
+ giprobe_sdf_shader.initialize(sdf_versions);
+ giprobe_sdf_shader_version = giprobe_sdf_shader.version_create();
+ giprobe_sdf_shader.version_set_compute_code(giprobe_sdf_shader_version, "", "", "", Vector<String>());
+ giprobe_sdf_shader_version_shader = giprobe_sdf_shader.version_get_shader(giprobe_sdf_shader_version, 0);
+ giprobe_sdf_shader_pipeline = RD::get_singleton()->compute_pipeline_create(giprobe_sdf_shader_version_shader);
}
- mesh_default_rd_buffers[DEFAULT_RD_BUFFER_BONES] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
-}
-{ //weights
- Vector<uint8_t> buffer;
- buffer.resize(sizeof(float) * 4);
- {
- uint8_t *w = buffer.ptrw();
- float *fptr = (float *)w;
- fptr[0] = 0.0;
- fptr[1] = 0.0;
- fptr[2] = 0.0;
- fptr[3] = 0.0;
+ using_lightmap_array = true; // high end
+ if (using_lightmap_array) {
+ uint32_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE);
+
+ if (textures_per_stage <= 256) {
+ lightmap_textures.resize(32);
+ } else {
+ lightmap_textures.resize(1024);
+ }
+
+ for (int i = 0; i < lightmap_textures.size(); i++) {
+ lightmap_textures.write[i] = default_rd_textures[DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE];
+ }
}
- mesh_default_rd_buffers[DEFAULT_RD_BUFFER_WEIGHTS] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
-}
-}
-{
- Vector<String> sdf_versions;
- sdf_versions.push_back(""); //one only
- giprobe_sdf_shader.initialize(sdf_versions);
- giprobe_sdf_shader_version = giprobe_sdf_shader.version_create();
- giprobe_sdf_shader.version_set_compute_code(giprobe_sdf_shader_version, "", "", "", Vector<String>());
- giprobe_sdf_shader_version_shader = giprobe_sdf_shader.version_get_shader(giprobe_sdf_shader_version, 0);
- giprobe_sdf_shader_pipeline = RD::get_singleton()->compute_pipeline_create(giprobe_sdf_shader_version_shader);
-}
+ lightmap_probe_capture_update_speed = GLOBAL_GET("rendering/lightmapper/probe_capture_update_speed");
}
RasterizerStorageRD::~RasterizerStorageRD() {
+ memdelete_arr(global_variables.buffer_values);
+ memdelete_arr(global_variables.buffer_usage);
+ memdelete_arr(global_variables.buffer_dirty_regions);
+ RD::get_singleton()->free(global_variables.buffer);
//def textures
for (int i = 0; i < DEFAULT_RD_TEXTURE_MAX; i++) {
@@ -4820,4 +6206,12 @@ RasterizerStorageRD::~RasterizerStorageRD() {
RD::get_singleton()->free(mesh_default_rd_buffers[i]);
}
giprobe_sdf_shader.version_free(giprobe_sdf_shader_version);
+
+ if (decal_atlas.textures.size()) {
+ ERR_PRINT("Decal Atlas: " + itos(decal_atlas.textures.size()) + " textures were not removed from the atlas.");
+ }
+
+ if (decal_atlas.texture.is_valid()) {
+ RD::get_singleton()->free(decal_atlas.texture);
+ }
}
diff --git a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h
index e69be644d7..fe9377192e 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h
+++ b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h
@@ -52,6 +52,8 @@ public:
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 get_param_list(List<PropertyInfo> *p_param_list) const = 0;
+
+ virtual void get_instance_param_list(List<InstanceShaderParam> *p_param_list) const = 0;
virtual bool is_param_texture(const StringName &p_param) const = 0;
virtual bool is_animated() const = 0;
virtual bool casts_shadows() const = 0;
@@ -62,14 +64,21 @@ public:
typedef ShaderData *(*ShaderDataRequestFunction)();
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);
virtual void set_render_priority(int p_priority) = 0;
virtual void set_next_pass(RID p_pass) = 0;
virtual void update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) = 0;
- virtual ~MaterialData() {}
+ virtual ~MaterialData();
+
+ private:
+ friend class RasterizerStorageRD;
+ RID self;
+ List<RID>::Element *global_buffer_E = nullptr;
+ List<RID>::Element *global_texture_E = nullptr;
+ uint64_t global_textures_pass = 0;
+ Map<StringName, uint64_t> used_global_textures;
};
typedef MaterialData *(*MaterialDataRequestFunction)(ShaderData *);
@@ -82,6 +91,7 @@ public:
DEFAULT_RD_TEXTURE_CUBEMAP_BLACK,
DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK,
DEFAULT_RD_TEXTURE_3D_WHITE,
+ DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE,
DEFAULT_RD_TEXTURE_MAX
};
@@ -100,7 +110,6 @@ public:
private:
/* TEXTURE API */
struct Texture {
-
enum Type {
TYPE_2D,
TYPE_LAYERED,
@@ -108,6 +117,7 @@ private:
};
Type type;
+ RS::TextureLayeredType layered_type = RS::TEXTURE_LAYERED_2D_ARRAY;
RenderingDevice::TextureType rd_type;
RID rd_texture;
@@ -137,6 +147,7 @@ private:
RID proxy_to;
Vector<RID> proxies;
+ Set<RID> lightmap_users;
RS::TextureDetectCallback detect_3d_callback = nullptr;
void *detect_3d_callback_ud = nullptr;
@@ -173,6 +184,50 @@ 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];
+ /* DECAL ATLAS */
+
+ struct DecalAtlas {
+ struct Texture {
+ int panorama_to_dp_users;
+ int users;
+ Rect2 uv_rect;
+ };
+
+ struct SortItem {
+ RID texture;
+ Size2i pixel_size;
+ Size2i size;
+ Point2i pos;
+
+ bool operator<(const SortItem &p_item) const {
+ //sort larger to smaller
+ if (size.height == p_item.size.height) {
+ return size.width > p_item.size.width;
+ } else {
+ return size.height > p_item.size.height;
+ }
+ }
+ };
+
+ HashMap<RID, Texture> textures;
+ bool dirty = true;
+ int mipmaps = 5;
+
+ RID texture;
+ RID texture_srgb;
+ struct MipMap {
+ RID fb;
+ RID texture;
+ Size2i size;
+ };
+ Vector<MipMap> texture_mipmaps;
+
+ Size2i size;
+
+ } decal_atlas;
+
+ void _update_decal_atlas();
+
/* SHADER */
struct Material;
@@ -216,9 +271,8 @@ private:
/* Mesh */
struct Mesh {
-
struct Surface {
- RS::PrimitiveType primitive;
+ RS::PrimitiveType primitive = RS::PRIMITIVE_POINTS;
uint32_t format = 0;
RID vertex_buffer;
@@ -232,8 +286,8 @@ private:
// cache-efficient structure.
struct Version {
- uint32_t input_mask;
- RD::VertexFormatID vertex_format;
+ uint32_t input_mask = 0;
+ RD::VertexFormatID vertex_format = 0;
RID vertex_array;
};
@@ -246,7 +300,7 @@ private:
uint32_t index_count = 0;
struct LOD {
- float edge_length;
+ float edge_length = 0.0;
RID index_buffer;
RID index_array;
};
@@ -358,7 +412,6 @@ private:
/* LIGHT */
struct Light {
-
RS::LightType type;
float param[RS::LIGHT_PARAM_MAX];
Color color = Color(1, 1, 1, 1);
@@ -383,7 +436,6 @@ private:
/* REFLECTION PROBE */
struct ReflectionProbe {
-
RS::ReflectionProbeUpdateMode update_mode = RS::REFLECTION_PROBE_UPDATE_ONCE;
int resolution = 256;
float intensity = 1.0;
@@ -403,10 +455,30 @@ private:
mutable RID_Owner<ReflectionProbe> reflection_probe_owner;
+ /* DECAL */
+
+ struct Decal {
+ Vector3 extents = Vector3(1, 1, 1);
+ RID textures[RS::DECAL_TEXTURE_MAX];
+ float emission_energy = 1.0;
+ float albedo_mix = 1.0;
+ Color modulate = Color(1, 1, 1, 1);
+ uint32_t cull_mask = (1 << 20) - 1;
+ float upper_fade = 0.3;
+ float lower_fade = 0.3;
+ bool distance_fade = false;
+ float distance_fade_begin = 10;
+ float distance_fade_length = 1;
+ float normal_fade = 0.0;
+
+ RasterizerScene::InstanceDependency instance_dependency;
+ };
+
+ mutable RID_Owner<Decal> decal_owner;
+
/* GI PROBE */
struct GIProbe {
-
RID octree_buffer;
RID data_buffer;
RID sdf_texture;
@@ -447,29 +519,59 @@ private:
mutable RID_Owner<GIProbe> gi_probe_owner;
+ /* REFLECTION PROBE */
+
+ struct Lightmap {
+ RID light_texture;
+ bool uses_spherical_harmonics = false;
+ bool interior = false;
+ AABB bounds = AABB(Vector3(), Vector3(1, 1, 1));
+ int32_t array_index = -1; //unassigned
+ PackedVector3Array points;
+ PackedColorArray point_sh;
+ PackedInt32Array tetrahedra;
+ PackedInt32Array bsp_tree;
+
+ struct BSP {
+ static const int32_t EMPTY_LEAF = INT32_MIN;
+ float plane[4];
+ int32_t over = EMPTY_LEAF, under = EMPTY_LEAF;
+ };
+
+ RasterizerScene::InstanceDependency instance_dependency;
+ };
+
+ bool using_lightmap_array; //high end uses this
+ /* for high end */
+
+ Vector<RID> lightmap_textures;
+
+ uint64_t lightmap_array_version = 0;
+
+ mutable RID_Owner<Lightmap> lightmap_owner;
+
+ float lightmap_probe_capture_update_speed = 4;
+
/* RENDER TARGET */
struct RenderTarget {
-
Size2i size;
RID framebuffer;
RID color;
//used for retrieving from CPU
- RD::DataFormat color_format;
- RD::DataFormat color_format_srgb;
- Image::Format image_format;
+ RD::DataFormat color_format = RD::DATA_FORMAT_R4G4_UNORM_PACK8;
+ RD::DataFormat color_format_srgb = RD::DATA_FORMAT_R4G4_UNORM_PACK8;
+ Image::Format image_format = Image::FORMAT_L8;
bool flags[RENDER_TARGET_FLAG_MAX];
RID backbuffer; //used for effects
- RID backbuffer_fb;
+ RID backbuffer_mipmap0;
struct BackbufferMipmap {
RID mipmap;
- RID mipmap_fb;
RID mipmap_copy;
- RID mipmap_copy_fb;
};
Vector<BackbufferMipmap> backbuffer_mipmaps;
@@ -490,6 +592,72 @@ private:
void _update_render_target(RenderTarget *rt);
void _create_render_target_backbuffer(RenderTarget *rt);
+ /* GLOBAL SHADER VARIABLES */
+
+ struct GlobalVariables {
+ enum {
+ BUFFER_DIRTY_REGION_SIZE = 1024
+ };
+ struct Variable {
+ Set<RID> texture_materials; // materials using this
+
+ RS::GlobalVariableType type;
+ Variant value;
+ Variant override;
+ int32_t buffer_index; //for vectors
+ int32_t buffer_elements; //for vectors
+ };
+
+ HashMap<StringName, Variable> variables;
+
+ struct Value {
+ float x;
+ float y;
+ float z;
+ float w;
+ };
+
+ struct ValueInt {
+ int32_t x;
+ int32_t y;
+ int32_t z;
+ int32_t w;
+ };
+
+ struct ValueUInt {
+ uint32_t x;
+ uint32_t y;
+ uint32_t z;
+ uint32_t w;
+ };
+
+ struct ValueUsage {
+ uint32_t elements = 0;
+ };
+
+ List<RID> materials_using_buffer;
+ List<RID> materials_using_texture;
+
+ RID buffer;
+ Value *buffer_values;
+ ValueUsage *buffer_usage;
+ bool *buffer_dirty_regions;
+ uint32_t buffer_dirty_region_count = 0;
+
+ uint32_t buffer_size;
+
+ bool must_update_texture_materials = false;
+ bool must_update_buffer_materials = false;
+
+ HashMap<RID, int32_t> instance_buffer_pos;
+
+ } global_variables;
+
+ int32_t _global_variable_allocate(uint32_t p_elements);
+ void _global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value);
+ void _global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements);
+
+ void _update_global_variables();
/* EFFECTS */
RasterizerEffectsRD effects;
@@ -511,7 +679,7 @@ public:
//these two APIs can be used together or in combination with the others.
virtual RID texture_2d_placeholder_create();
- virtual RID texture_2d_layered_placeholder_create();
+ virtual RID texture_2d_layered_placeholder_create(RenderingServer::TextureLayeredType p_layered_type);
virtual RID texture_3d_placeholder_create();
virtual Ref<Image> texture_2d_get(RID p_texture) const;
@@ -535,6 +703,20 @@ public:
virtual Size2 texture_size_with_proxy(RID p_proxy);
+ virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false);
+ virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false);
+
+ RID decal_atlas_get_texture() const;
+ RID decal_atlas_get_texture_srgb() const;
+ _FORCE_INLINE_ Rect2 decal_atlas_get_texture_rect(RID p_texture) {
+ DecalAtlas::Texture *t = decal_atlas.textures.getptr(p_texture);
+ if (!t) {
+ return Rect2();
+ }
+
+ return t->uv_rect;
+ }
+
//internal usage
_FORCE_INLINE_ RID texture_get_rd_texture(RID p_texture, bool p_srgb = false) {
@@ -596,6 +778,8 @@ public:
bool material_is_animated(RID p_material);
bool material_casts_shadows(RID p_material);
+ void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters);
+
void material_update_dependency(RID p_material, RasterizerScene::InstanceBase *p_instance);
void material_force_update_textures(RID p_material, ShaderType p_shader_type);
@@ -604,7 +788,7 @@ public:
_FORCE_INLINE_ MaterialData *material_get_data(RID p_material, ShaderType p_shader_type) {
Material *material = material_owner.getornull(p_material);
if (!material || material->shader_type != p_shader_type) {
- return NULL;
+ return nullptr;
} else {
return material->data;
}
@@ -640,10 +824,10 @@ public:
_FORCE_INLINE_ const RID *mesh_get_surface_count_and_materials(RID p_mesh, uint32_t &r_surface_count) {
Mesh *mesh = mesh_owner.getornull(p_mesh);
- ERR_FAIL_COND_V(!mesh, NULL);
+ ERR_FAIL_COND_V(!mesh, nullptr);
r_surface_count = mesh->surface_count;
if (r_surface_count == 0) {
- return NULL;
+ return nullptr;
}
if (mesh->material_cache.empty()) {
mesh->material_cache.resize(mesh->surface_count);
@@ -879,15 +1063,20 @@ public:
AABB light_get_aabb(RID p_light) const;
_FORCE_INLINE_ float light_get_param(RID p_light, RS::LightParam p_param) {
-
const Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light, 0);
return light->param[p_param];
}
- _FORCE_INLINE_ Color light_get_color(RID p_light) {
+ _FORCE_INLINE_ RID light_get_projector(RID p_light) {
+ const Light *light = light_owner.getornull(p_light);
+ ERR_FAIL_COND_V(!light, RID());
+
+ return light->projector;
+ }
+ _FORCE_INLINE_ Color light_get_color(RID p_light) {
const Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light, Color());
@@ -895,7 +1084,6 @@ public:
}
_FORCE_INLINE_ Color light_get_shadow_color(RID p_light) {
-
const Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light, Color());
@@ -903,7 +1091,6 @@ public:
}
_FORCE_INLINE_ uint32_t light_get_cull_mask(RID p_light) {
-
const Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light, 0);
@@ -911,7 +1098,6 @@ public:
}
_FORCE_INLINE_ bool light_has_shadow(RID p_light) const {
-
const Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL);
@@ -919,13 +1105,19 @@ public:
}
_FORCE_INLINE_ bool light_is_negative(RID p_light) const {
-
const Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL);
return light->negative;
}
+ _FORCE_INLINE_ float light_get_transmittance_bias(RID p_light) const {
+ const Light *light = light_owner.getornull(p_light);
+ ERR_FAIL_COND_V(!light, 0.0);
+
+ return light->param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS];
+ }
+
bool light_get_use_gi(RID p_light);
uint64_t light_get_version(RID p_light) const;
@@ -966,6 +1158,81 @@ public:
void base_update_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance);
void skeleton_update_dependency(RID p_skeleton, RasterizerScene::InstanceBase *p_instance);
+ /* DECAL API */
+
+ virtual RID decal_create();
+ virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents);
+ virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture);
+ virtual void decal_set_emission_energy(RID p_decal, float p_energy);
+ virtual void decal_set_albedo_mix(RID p_decal, float p_mix);
+ virtual void decal_set_modulate(RID p_decal, const Color &p_modulate);
+ virtual void decal_set_cull_mask(RID p_decal, uint32_t p_layers);
+ virtual void decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length);
+ virtual void decal_set_fade(RID p_decal, float p_above, float p_below);
+ virtual void decal_set_normal_fade(RID p_decal, float p_fade);
+
+ _FORCE_INLINE_ Vector3 decal_get_extents(RID p_decal) {
+ const Decal *decal = decal_owner.getornull(p_decal);
+ return decal->extents;
+ }
+
+ _FORCE_INLINE_ RID decal_get_texture(RID p_decal, RS::DecalTexture p_texture) {
+ const Decal *decal = decal_owner.getornull(p_decal);
+ return decal->textures[p_texture];
+ }
+
+ _FORCE_INLINE_ Color decal_get_modulate(RID p_decal) {
+ const Decal *decal = decal_owner.getornull(p_decal);
+ return decal->modulate;
+ }
+
+ _FORCE_INLINE_ float decal_get_emission_energy(RID p_decal) {
+ const Decal *decal = decal_owner.getornull(p_decal);
+ return decal->emission_energy;
+ }
+
+ _FORCE_INLINE_ float decal_get_albedo_mix(RID p_decal) {
+ const Decal *decal = decal_owner.getornull(p_decal);
+ return decal->albedo_mix;
+ }
+
+ _FORCE_INLINE_ uint32_t decal_get_cull_mask(RID p_decal) {
+ const Decal *decal = decal_owner.getornull(p_decal);
+ return decal->cull_mask;
+ }
+
+ _FORCE_INLINE_ float decal_get_upper_fade(RID p_decal) {
+ const Decal *decal = decal_owner.getornull(p_decal);
+ return decal->upper_fade;
+ }
+
+ _FORCE_INLINE_ float decal_get_lower_fade(RID p_decal) {
+ const Decal *decal = decal_owner.getornull(p_decal);
+ return decal->lower_fade;
+ }
+
+ _FORCE_INLINE_ float decal_get_normal_fade(RID p_decal) {
+ const Decal *decal = decal_owner.getornull(p_decal);
+ return decal->normal_fade;
+ }
+
+ _FORCE_INLINE_ bool decal_is_distance_fade_enabled(RID p_decal) {
+ const Decal *decal = decal_owner.getornull(p_decal);
+ return decal->distance_fade;
+ }
+
+ _FORCE_INLINE_ float decal_get_distance_fade_begin(RID p_decal) {
+ const Decal *decal = decal_owner.getornull(p_decal);
+ return decal->distance_fade_begin;
+ }
+
+ _FORCE_INLINE_ float decal_get_distance_fade_length(RID p_decal) {
+ const Decal *decal = decal_owner.getornull(p_decal);
+ return decal->distance_fade_length;
+ }
+
+ virtual AABB decal_get_aabb(RID p_decal) const;
+
/* GI PROBE API */
RID gi_probe_create();
@@ -1021,23 +1288,47 @@ public:
/* LIGHTMAP CAPTURE */
- void lightmap_capture_set_bounds(RID p_capture, const AABB &p_bounds) {}
- AABB lightmap_capture_get_bounds(RID p_capture) const { return AABB(); }
- void lightmap_capture_set_octree(RID p_capture, const Vector<uint8_t> &p_octree) {}
- RID lightmap_capture_create() {
- return RID();
+ virtual RID lightmap_create();
+
+ virtual void lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics);
+ virtual void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds);
+ virtual void lightmap_set_probe_interior(RID p_lightmap, bool p_interior);
+ virtual void lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree);
+ virtual PackedVector3Array lightmap_get_probe_capture_points(RID p_lightmap) const;
+ virtual PackedColorArray lightmap_get_probe_capture_sh(RID p_lightmap) const;
+ virtual PackedInt32Array lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const;
+ virtual PackedInt32Array lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const;
+ virtual AABB lightmap_get_aabb(RID p_lightmap) const;
+ virtual bool lightmap_is_interior(RID p_lightmap) const;
+ virtual void lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh);
+ virtual void lightmap_set_probe_capture_update_speed(float p_speed);
+ _FORCE_INLINE_ float lightmap_get_probe_capture_update_speed() const {
+ return lightmap_probe_capture_update_speed;
+ }
+
+ _FORCE_INLINE_ int32_t lightmap_get_array_index(RID p_lightmap) const {
+ ERR_FAIL_COND_V(!using_lightmap_array, -1); //only for arrays
+ const Lightmap *lm = lightmap_owner.getornull(p_lightmap);
+ return lm->array_index;
+ }
+ _FORCE_INLINE_ bool lightmap_uses_spherical_harmonics(RID p_lightmap) const {
+ ERR_FAIL_COND_V(!using_lightmap_array, false); //only for arrays
+ const Lightmap *lm = lightmap_owner.getornull(p_lightmap);
+ return lm->uses_spherical_harmonics;
}
- Vector<uint8_t> lightmap_capture_get_octree(RID p_capture) const {
- return Vector<uint8_t>();
+ _FORCE_INLINE_ uint64_t lightmap_array_get_version() const {
+ ERR_FAIL_COND_V(!using_lightmap_array, 0); //only for arrays
+ return lightmap_array_version;
}
- void lightmap_capture_set_octree_cell_transform(RID p_capture, const Transform &p_xform) {}
- Transform lightmap_capture_get_octree_cell_transform(RID p_capture) const { return Transform(); }
- void lightmap_capture_set_octree_cell_subdiv(RID p_capture, int p_subdiv) {}
- int lightmap_capture_get_octree_cell_subdiv(RID p_capture) const { return 0; }
- void lightmap_capture_set_energy(RID p_capture, float p_energy) {}
- float lightmap_capture_get_energy(RID p_capture) const { return 0.0; }
- const Vector<LightmapCaptureOctree> *lightmap_capture_get_octree_ptr(RID p_capture) const {
- return NULL;
+
+ _FORCE_INLINE_ int lightmap_array_get_size() const {
+ ERR_FAIL_COND_V(!using_lightmap_array, 0); //only for arrays
+ return lightmap_textures.size();
+ }
+
+ _FORCE_INLINE_ const Vector<RID> &lightmap_array_get_textures() const {
+ ERR_FAIL_COND_V(!using_lightmap_array, lightmap_textures); //only for arrays
+ return lightmap_textures;
}
/* PARTICLES */
@@ -1076,6 +1367,27 @@ public:
virtual bool particles_is_inactive(RID p_particles) const { return false; }
+ /* GLOBAL VARIABLES API */
+
+ virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value);
+ virtual void global_variable_remove(const StringName &p_name);
+ virtual Vector<StringName> global_variable_get_list() const;
+
+ virtual void global_variable_set(const StringName &p_name, const Variant &p_value);
+ virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value);
+ virtual Variant global_variable_get(const StringName &p_name) const;
+ virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const;
+ RS::GlobalVariableType global_variable_get_type_internal(const StringName &p_name) const;
+
+ virtual void global_variables_load_settings(bool p_load_textures = true);
+ virtual void global_variables_clear();
+
+ virtual int32_t global_variables_instance_allocate(RID p_instance);
+ virtual void global_variables_instance_free(RID p_instance);
+ virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value);
+
+ RID global_variables_get_storage_buffer() const;
+
/* RENDER TARGET API */
RID render_target_create();
@@ -1097,6 +1409,7 @@ public:
Size2 render_target_get_size(RID p_render_target);
RID render_target_get_rd_framebuffer(RID p_render_target);
+ RID render_target_get_rd_texture(RID p_render_target);
RS::InstanceType get_base_type(RID p_rid) const;
@@ -1124,7 +1437,7 @@ public:
virtual uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const;
virtual String get_captured_timestamp_name(uint32_t p_index) const;
- static RasterizerStorage *base_singleton;
+ static RasterizerStorageRD *base_singleton;
RasterizerEffectsRD *get_effects();
diff --git a/servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.cpp b/servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.cpp
index 4ee020aa69..5cc3da8d4e 100644
--- a/servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.cpp
+++ b/servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.cpp
@@ -31,23 +31,25 @@
#include "render_pipeline_vertex_format_cache_rd.h"
#include "core/os/memory.h"
-RID RenderPipelineVertexFormatCacheRD::_generate_version(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id) {
-
+RID RenderPipelineVertexFormatCacheRD::_generate_version(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id, bool p_wireframe) {
RD::PipelineMultisampleState multisample_state_version = multisample_state;
multisample_state_version.sample_count = RD::get_singleton()->framebuffer_format_get_texture_samples(p_framebuffer_format_id);
- RID pipeline = RD::get_singleton()->render_pipeline_create(shader, p_framebuffer_format_id, p_vertex_format_id, render_primitive, rasterization_state, multisample_state_version, depth_stencil_state, blend_state, dynamic_state_flags);
+ RD::PipelineRasterizationState raster_state_version = rasterization_state;
+ raster_state_version.wireframe = p_wireframe;
+
+ RID pipeline = RD::get_singleton()->render_pipeline_create(shader, p_framebuffer_format_id, p_vertex_format_id, render_primitive, raster_state_version, multisample_state_version, depth_stencil_state, blend_state, dynamic_state_flags);
ERR_FAIL_COND_V(pipeline.is_null(), RID());
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].pipeline = pipeline;
version_count++;
return pipeline;
}
void RenderPipelineVertexFormatCacheRD::_clear() {
-
if (versions) {
for (uint32_t i = 0; i < version_count; i++) {
//shader may be gone, so this may not be valid
@@ -57,7 +59,7 @@ void RenderPipelineVertexFormatCacheRD::_clear() {
}
version_count = 0;
memfree(versions);
- versions = NULL;
+ versions = nullptr;
}
}
@@ -88,7 +90,7 @@ void RenderPipelineVertexFormatCacheRD::clear() {
RenderPipelineVertexFormatCacheRD::RenderPipelineVertexFormatCacheRD() {
version_count = 0;
- versions = NULL;
+ versions = nullptr;
input_mask = 0;
}
diff --git a/servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h b/servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h
index ecb1b42b06..cf15e79586 100644
--- a/servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h
+++ b/servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h
@@ -35,7 +35,6 @@
#include "servers/rendering/rendering_device.h"
class RenderPipelineVertexFormatCacheRD {
-
SpinLock spin_lock;
RID shader;
@@ -51,13 +50,14 @@ class RenderPipelineVertexFormatCacheRD {
struct Version {
RD::VertexFormatID vertex_id;
RD::FramebufferFormatID framebuffer_id;
+ bool wireframe;
RID pipeline;
};
Version *versions;
uint32_t version_count;
- RID _generate_version(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id);
+ RID _generate_version(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id, bool p_wireframe);
void _clear();
@@ -65,7 +65,7 @@ public:
void setup(RID p_shader, RD::RenderPrimitive p_primitive, const RD::PipelineRasterizationState &p_rasterization_state, RD::PipelineMultisampleState p_multisample, const RD::PipelineDepthStencilState &p_depth_stencil_state, const RD::PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags = 0);
void update_shader(RID p_shader);
- _FORCE_INLINE_ RID get_render_pipeline(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id) {
+ _FORCE_INLINE_ RID get_render_pipeline(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id, bool p_wireframe = false) {
#ifdef DEBUG_ENABLED
ERR_FAIL_COND_V_MSG(shader.is_null(), RID(),
"Attempted to use an unused shader variant (shader is null),");
@@ -74,13 +74,13 @@ public:
spin_lock.lock();
RID result;
for (uint32_t i = 0; i < version_count; i++) {
- if (versions[i].vertex_id == p_vertex_format_id && versions[i].framebuffer_id == p_framebuffer_format_id) {
+ if (versions[i].vertex_id == p_vertex_format_id && versions[i].framebuffer_id == p_framebuffer_format_id && versions[i].wireframe == p_wireframe) {
result = versions[i].pipeline;
spin_lock.unlock();
return result;
}
}
- result = _generate_version(p_vertex_format_id, p_framebuffer_format_id);
+ result = _generate_version(p_vertex_format_id, p_framebuffer_format_id, p_wireframe);
spin_lock.unlock();
return result;
}
diff --git a/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp b/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp
index b3a4b0ede8..32321164a1 100644
--- a/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp
+++ b/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp
@@ -32,11 +32,12 @@
#include "core/os/os.h"
#include "core/project_settings.h"
+#include "rasterizer_storage_rd.h"
+#include "servers/rendering_server.h"
#define SL ShaderLanguage
static String _mktab(int p_level) {
-
String tb;
for (int i = 0; i < p_level; i++) {
tb += "\t";
@@ -46,7 +47,6 @@ static String _mktab(int p_level) {
}
static String _typestr(SL::DataType p_type) {
-
String type = ShaderLanguage::get_datatype_name(p_type);
if (ShaderLanguage::is_sampler_type(p_type)) {
type = type.replace("sampler", "texture"); //we use textures instead of samplers
@@ -55,129 +55,200 @@ static String _typestr(SL::DataType p_type) {
}
static int _get_datatype_size(SL::DataType p_type) {
-
switch (p_type) {
-
- case SL::TYPE_VOID: return 0;
- case SL::TYPE_BOOL: return 4;
- case SL::TYPE_BVEC2: return 8;
- case SL::TYPE_BVEC3: return 12;
- case SL::TYPE_BVEC4: return 16;
- case SL::TYPE_INT: return 4;
- case SL::TYPE_IVEC2: return 8;
- case SL::TYPE_IVEC3: return 12;
- case SL::TYPE_IVEC4: return 16;
- case SL::TYPE_UINT: return 4;
- case SL::TYPE_UVEC2: return 8;
- case SL::TYPE_UVEC3: return 12;
- case SL::TYPE_UVEC4: return 16;
- case SL::TYPE_FLOAT: return 4;
- case SL::TYPE_VEC2: return 8;
- case SL::TYPE_VEC3: return 12;
- case SL::TYPE_VEC4: return 16;
+ case SL::TYPE_VOID:
+ return 0;
+ case SL::TYPE_BOOL:
+ return 4;
+ case SL::TYPE_BVEC2:
+ return 8;
+ case SL::TYPE_BVEC3:
+ return 12;
+ case SL::TYPE_BVEC4:
+ return 16;
+ case SL::TYPE_INT:
+ return 4;
+ case SL::TYPE_IVEC2:
+ return 8;
+ case SL::TYPE_IVEC3:
+ return 12;
+ case SL::TYPE_IVEC4:
+ return 16;
+ case SL::TYPE_UINT:
+ return 4;
+ case SL::TYPE_UVEC2:
+ return 8;
+ case SL::TYPE_UVEC3:
+ return 12;
+ case SL::TYPE_UVEC4:
+ return 16;
+ case SL::TYPE_FLOAT:
+ return 4;
+ case SL::TYPE_VEC2:
+ return 8;
+ case SL::TYPE_VEC3:
+ return 12;
+ case SL::TYPE_VEC4:
+ return 16;
case SL::TYPE_MAT2:
return 32; //4 * 4 + 4 * 4
case SL::TYPE_MAT3:
return 48; // 4 * 4 + 4 * 4 + 4 * 4
- case SL::TYPE_MAT4: return 64;
- case SL::TYPE_SAMPLER2D: return 16;
- case SL::TYPE_ISAMPLER2D: return 16;
- case SL::TYPE_USAMPLER2D: return 16;
- case SL::TYPE_SAMPLER2DARRAY: return 16;
- case SL::TYPE_ISAMPLER2DARRAY: return 16;
- case SL::TYPE_USAMPLER2DARRAY: return 16;
- case SL::TYPE_SAMPLER3D: return 16;
- case SL::TYPE_ISAMPLER3D: return 16;
- case SL::TYPE_USAMPLER3D: return 16;
- case SL::TYPE_SAMPLERCUBE: return 16;
- case SL::TYPE_STRUCT: return 0;
+ case SL::TYPE_MAT4:
+ return 64;
+ case SL::TYPE_SAMPLER2D:
+ return 16;
+ case SL::TYPE_ISAMPLER2D:
+ return 16;
+ case SL::TYPE_USAMPLER2D:
+ return 16;
+ case SL::TYPE_SAMPLER2DARRAY:
+ return 16;
+ case SL::TYPE_ISAMPLER2DARRAY:
+ return 16;
+ case SL::TYPE_USAMPLER2DARRAY:
+ return 16;
+ case SL::TYPE_SAMPLER3D:
+ return 16;
+ case SL::TYPE_ISAMPLER3D:
+ return 16;
+ case SL::TYPE_USAMPLER3D:
+ return 16;
+ case SL::TYPE_SAMPLERCUBE:
+ return 16;
+ case SL::TYPE_SAMPLERCUBEARRAY:
+ return 16;
+ case SL::TYPE_STRUCT:
+ return 0;
+
+ case SL::TYPE_MAX: {
+ ERR_FAIL_V(0);
+ };
}
ERR_FAIL_V(0);
}
static int _get_datatype_alignment(SL::DataType p_type) {
-
switch (p_type) {
-
- case SL::TYPE_VOID: return 0;
- case SL::TYPE_BOOL: return 4;
- case SL::TYPE_BVEC2: return 8;
- case SL::TYPE_BVEC3: return 16;
- case SL::TYPE_BVEC4: return 16;
- case SL::TYPE_INT: return 4;
- case SL::TYPE_IVEC2: return 8;
- case SL::TYPE_IVEC3: return 16;
- case SL::TYPE_IVEC4: return 16;
- case SL::TYPE_UINT: return 4;
- case SL::TYPE_UVEC2: return 8;
- case SL::TYPE_UVEC3: return 16;
- case SL::TYPE_UVEC4: return 16;
- case SL::TYPE_FLOAT: return 4;
- case SL::TYPE_VEC2: return 8;
- case SL::TYPE_VEC3: return 16;
- case SL::TYPE_VEC4: return 16;
- case SL::TYPE_MAT2: return 16;
- case SL::TYPE_MAT3: return 16;
- case SL::TYPE_MAT4: return 16;
- case SL::TYPE_SAMPLER2D: return 16;
- case SL::TYPE_ISAMPLER2D: return 16;
- case SL::TYPE_USAMPLER2D: return 16;
- case SL::TYPE_SAMPLER2DARRAY: return 16;
- case SL::TYPE_ISAMPLER2DARRAY: return 16;
- case SL::TYPE_USAMPLER2DARRAY: return 16;
- case SL::TYPE_SAMPLER3D: return 16;
- case SL::TYPE_ISAMPLER3D: return 16;
- case SL::TYPE_USAMPLER3D: return 16;
- case SL::TYPE_SAMPLERCUBE: return 16;
- case SL::TYPE_STRUCT: return 0;
+ case SL::TYPE_VOID:
+ return 0;
+ case SL::TYPE_BOOL:
+ return 4;
+ case SL::TYPE_BVEC2:
+ return 8;
+ case SL::TYPE_BVEC3:
+ return 16;
+ case SL::TYPE_BVEC4:
+ return 16;
+ case SL::TYPE_INT:
+ return 4;
+ case SL::TYPE_IVEC2:
+ return 8;
+ case SL::TYPE_IVEC3:
+ return 16;
+ case SL::TYPE_IVEC4:
+ return 16;
+ case SL::TYPE_UINT:
+ return 4;
+ case SL::TYPE_UVEC2:
+ return 8;
+ case SL::TYPE_UVEC3:
+ return 16;
+ case SL::TYPE_UVEC4:
+ return 16;
+ case SL::TYPE_FLOAT:
+ return 4;
+ case SL::TYPE_VEC2:
+ return 8;
+ case SL::TYPE_VEC3:
+ return 16;
+ case SL::TYPE_VEC4:
+ return 16;
+ case SL::TYPE_MAT2:
+ return 16;
+ case SL::TYPE_MAT3:
+ return 16;
+ case SL::TYPE_MAT4:
+ return 16;
+ case SL::TYPE_SAMPLER2D:
+ return 16;
+ case SL::TYPE_ISAMPLER2D:
+ return 16;
+ case SL::TYPE_USAMPLER2D:
+ return 16;
+ case SL::TYPE_SAMPLER2DARRAY:
+ return 16;
+ case SL::TYPE_ISAMPLER2DARRAY:
+ return 16;
+ case SL::TYPE_USAMPLER2DARRAY:
+ return 16;
+ case SL::TYPE_SAMPLER3D:
+ return 16;
+ case SL::TYPE_ISAMPLER3D:
+ return 16;
+ case SL::TYPE_USAMPLER3D:
+ return 16;
+ case SL::TYPE_SAMPLERCUBE:
+ return 16;
+ case SL::TYPE_SAMPLERCUBEARRAY:
+ return 16;
+ case SL::TYPE_STRUCT:
+ return 0;
+ case SL::TYPE_MAX: {
+ ERR_FAIL_V(0);
+ }
}
ERR_FAIL_V(0);
}
-static String _interpstr(SL::DataInterpolation p_interp) {
+static String _interpstr(SL::DataInterpolation p_interp) {
switch (p_interp) {
- case SL::INTERPOLATION_FLAT: return "flat ";
- case SL::INTERPOLATION_SMOOTH: return "";
+ case SL::INTERPOLATION_FLAT:
+ return "flat ";
+ case SL::INTERPOLATION_SMOOTH:
+ return "";
}
return "";
}
static String _prestr(SL::DataPrecision p_pres) {
-
switch (p_pres) {
- case SL::PRECISION_LOWP: return "lowp ";
- case SL::PRECISION_MEDIUMP: return "mediump ";
- case SL::PRECISION_HIGHP: return "highp ";
- case SL::PRECISION_DEFAULT: return "";
+ case SL::PRECISION_LOWP:
+ return "lowp ";
+ case SL::PRECISION_MEDIUMP:
+ return "mediump ";
+ case SL::PRECISION_HIGHP:
+ return "highp ";
+ case SL::PRECISION_DEFAULT:
+ return "";
}
return "";
}
static String _qualstr(SL::ArgumentQualifier p_qual) {
-
switch (p_qual) {
- case SL::ARGUMENT_QUALIFIER_IN: return "";
- case SL::ARGUMENT_QUALIFIER_OUT: return "out ";
- case SL::ARGUMENT_QUALIFIER_INOUT: return "inout ";
+ case SL::ARGUMENT_QUALIFIER_IN:
+ return "";
+ case SL::ARGUMENT_QUALIFIER_OUT:
+ return "out ";
+ case SL::ARGUMENT_QUALIFIER_INOUT:
+ return "inout ";
}
return "";
}
static String _opstr(SL::Operator p_op) {
-
return SL::get_operator_text(p_op);
}
static String _mkid(const String &p_id) {
-
String id = "m_" + p_id.replace("__", "_dus_");
return id.replace("__", "_dus_"); //doubleunderscore is reserved in glsl
}
static String f2sp0(float p_float) {
-
String num = rtoss(p_float);
if (num.find(".") == -1 && num.find("e") == -1) {
num += ".0";
@@ -186,17 +257,17 @@ static String f2sp0(float p_float) {
}
static String get_constant_text(SL::DataType p_type, const Vector<SL::ConstantNode::Value> &p_values) {
-
switch (p_type) {
- case SL::TYPE_BOOL: return p_values[0].boolean ? "true" : "false";
+ case SL::TYPE_BOOL:
+ return p_values[0].boolean ? "true" : "false";
case SL::TYPE_BVEC2:
case SL::TYPE_BVEC3:
case SL::TYPE_BVEC4: {
-
String text = "bvec" + itos(p_type - SL::TYPE_BOOL + 1) + "(";
for (int i = 0; i < p_values.size(); i++) {
- if (i > 0)
+ if (i > 0) {
text += ",";
+ }
text += p_values[i].boolean ? "true" : "false";
}
@@ -204,15 +275,16 @@ static String get_constant_text(SL::DataType p_type, const Vector<SL::ConstantNo
return text;
}
- case SL::TYPE_INT: return itos(p_values[0].sint);
+ case SL::TYPE_INT:
+ return itos(p_values[0].sint);
case SL::TYPE_IVEC2:
case SL::TYPE_IVEC3:
case SL::TYPE_IVEC4: {
-
String text = "ivec" + itos(p_type - SL::TYPE_INT + 1) + "(";
for (int i = 0; i < p_values.size(); i++) {
- if (i > 0)
+ if (i > 0) {
text += ",";
+ }
text += itos(p_values[i].sint);
}
@@ -220,30 +292,32 @@ static String get_constant_text(SL::DataType p_type, const Vector<SL::ConstantNo
return text;
} break;
- case SL::TYPE_UINT: return itos(p_values[0].uint) + "u";
+ case SL::TYPE_UINT:
+ return itos(p_values[0].uint) + "u";
case SL::TYPE_UVEC2:
case SL::TYPE_UVEC3:
case SL::TYPE_UVEC4: {
-
String text = "uvec" + itos(p_type - SL::TYPE_UINT + 1) + "(";
for (int i = 0; i < p_values.size(); i++) {
- if (i > 0)
+ if (i > 0) {
text += ",";
+ }
text += itos(p_values[i].uint) + "u";
}
text += ")";
return text;
} break;
- case SL::TYPE_FLOAT: return f2sp0(p_values[0].real);
+ case SL::TYPE_FLOAT:
+ return f2sp0(p_values[0].real);
case SL::TYPE_VEC2:
case SL::TYPE_VEC3:
case SL::TYPE_VEC4: {
-
String text = "vec" + itos(p_type - SL::TYPE_FLOAT + 1) + "(";
for (int i = 0; i < p_values.size(); i++) {
- if (i > 0)
+ if (i > 0) {
text += ",";
+ }
text += f2sp0(p_values[i].real);
}
@@ -254,11 +328,11 @@ static String get_constant_text(SL::DataType p_type, const Vector<SL::ConstantNo
case SL::TYPE_MAT2:
case SL::TYPE_MAT3:
case SL::TYPE_MAT4: {
-
String text = "mat" + itos(p_type - SL::TYPE_MAT2 + 2) + "(";
for (int i = 0; i < p_values.size(); i++) {
- if (i > 0)
+ if (i > 0) {
text += ",";
+ }
text += f2sp0(p_values[i].real);
}
@@ -266,7 +340,8 @@ static String get_constant_text(SL::DataType p_type, const Vector<SL::ConstantNo
return text;
} break;
- default: ERR_FAIL_V(String());
+ default:
+ ERR_FAIL_V(String());
}
}
@@ -283,7 +358,6 @@ String ShaderCompilerRD::_get_sampler_name(ShaderLanguage::TextureFilter p_filte
}
void ShaderCompilerRD::_dump_function_deps(const SL::ShaderNode *p_node, const StringName &p_for_func, const Map<StringName, String> &p_func_code, String &r_to_add, Set<StringName> &added) {
-
int fidx = -1;
for (int i = 0; i < p_node->functions.size(); i++) {
@@ -296,14 +370,13 @@ void ShaderCompilerRD::_dump_function_deps(const SL::ShaderNode *p_node, const S
ERR_FAIL_COND(fidx == -1);
for (Set<StringName>::Element *E = p_node->functions[fidx].uses_function.front(); E; E = E->next()) {
-
if (added.has(E->get())) {
continue; //was added already
}
_dump_function_deps(p_node, E->get(), p_func_code, r_to_add, added);
- SL::FunctionNode *fnode = NULL;
+ SL::FunctionNode *fnode = nullptr;
for (int i = 0; i < p_node->functions.size(); i++) {
if (p_node->functions[i].name == E->get()) {
@@ -323,9 +396,9 @@ void ShaderCompilerRD::_dump_function_deps(const SL::ShaderNode *p_node, const S
header = _typestr(fnode->return_type) + " " + _mkid(fnode->name) + "(";
}
for (int i = 0; i < fnode->arguments.size(); i++) {
-
- if (i > 0)
+ if (i > 0) {
header += ", ";
+ }
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 {
@@ -341,20 +414,80 @@ void ShaderCompilerRD::_dump_function_deps(const SL::ShaderNode *p_node, const S
}
}
-String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, GeneratedCode &r_gen_code, IdentifierActions &p_actions, const DefaultIdentifierActions &p_default_actions, bool p_assigning) {
+static String _get_global_variable_from_type_and_index(const String &p_buffer, const String &p_index, ShaderLanguage::DataType p_type) {
+ switch (p_type) {
+ case ShaderLanguage::TYPE_BOOL: {
+ return "(" + p_buffer + "[" + p_index + "].x != 0.0)";
+ }
+ case ShaderLanguage::TYPE_BVEC2: {
+ return "(" + p_buffer + "[" + p_index + "].xy != vec2(0.0))";
+ }
+ case ShaderLanguage::TYPE_BVEC3: {
+ return "(" + p_buffer + "[" + p_index + "].xyz != vec3(0.0))";
+ }
+ case ShaderLanguage::TYPE_BVEC4: {
+ return "(" + p_buffer + "[" + p_index + "].xyzw != vec4(0.0))";
+ }
+ case ShaderLanguage::TYPE_INT: {
+ return "floatBitsToInt(" + p_buffer + "[" + p_index + "].x)";
+ }
+ case ShaderLanguage::TYPE_IVEC2: {
+ return "floatBitsToInt(" + p_buffer + "[" + p_index + "].xy)";
+ }
+ case ShaderLanguage::TYPE_IVEC3: {
+ return "floatBitsToInt(" + p_buffer + "[" + p_index + "].xyz)";
+ }
+ case ShaderLanguage::TYPE_IVEC4: {
+ return "floatBitsToInt(" + p_buffer + "[" + p_index + "].xyzw)";
+ }
+ case ShaderLanguage::TYPE_UINT: {
+ return "floatBitsToUInt(" + p_buffer + "[" + p_index + "].x)";
+ }
+ case ShaderLanguage::TYPE_UVEC2: {
+ return "floatBitsToUInt(" + p_buffer + "[" + p_index + "].xy)";
+ }
+ case ShaderLanguage::TYPE_UVEC3: {
+ return "floatBitsToUInt(" + p_buffer + "[" + p_index + "].xyz)";
+ }
+ case ShaderLanguage::TYPE_UVEC4: {
+ return "floatBitsToUInt(" + p_buffer + "[" + p_index + "].xyzw)";
+ }
+ case ShaderLanguage::TYPE_FLOAT: {
+ return "(" + p_buffer + "[" + p_index + "].x)";
+ }
+ case ShaderLanguage::TYPE_VEC2: {
+ return "(" + p_buffer + "[" + p_index + "].xy)";
+ }
+ case ShaderLanguage::TYPE_VEC3: {
+ return "(" + p_buffer + "[" + p_index + "].xyz)";
+ }
+ case ShaderLanguage::TYPE_VEC4: {
+ return "(" + p_buffer + "[" + p_index + "].xyzw)";
+ }
+ case ShaderLanguage::TYPE_MAT2: {
+ return "mat2(" + p_buffer + "[" + p_index + "].xy," + p_buffer + "[" + p_index + "+1].xy)";
+ }
+ case ShaderLanguage::TYPE_MAT3: {
+ return "mat3(" + p_buffer + "[" + p_index + "].xyz," + p_buffer + "[" + p_index + "+1].xyz," + p_buffer + "[" + p_index + "+2].xyz)";
+ }
+ case ShaderLanguage::TYPE_MAT4: {
+ return "mat4(" + p_buffer + "[" + p_index + "].xyzw," + p_buffer + "[" + p_index + "+1].xyzw," + p_buffer + "[" + p_index + "+2].xyzw," + p_buffer + "[" + p_index + "+3].xyzw)";
+ }
+ default: {
+ ERR_FAIL_V("void");
+ }
+ }
+}
+String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, GeneratedCode &r_gen_code, IdentifierActions &p_actions, const DefaultIdentifierActions &p_default_actions, bool p_assigning, bool p_use_scope) {
String code;
switch (p_node->type) {
-
case SL::Node::TYPE_SHADER: {
-
SL::ShaderNode *pnode = (SL::ShaderNode *)p_node;
for (int i = 0; i < pnode->render_modes.size(); i++) {
-
if (p_default_actions.render_mode_defines.has(pnode->render_modes[i]) && !used_rmode_defines.has(pnode->render_modes[i])) {
-
r_gen_code.defines.push_back(p_default_actions.render_mode_defines[pnode->render_modes[i]]);
used_rmode_defines.insert(pnode->render_modes[i]);
}
@@ -372,7 +505,6 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
// structs
for (int i = 0; i < pnode->vstructs.size(); i++) {
-
SL::StructNode *st = pnode->vstructs[i].shader_struct;
String struct_code;
@@ -408,10 +540,15 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
int max_uniforms = 0;
for (Map<StringName, SL::ShaderNode::Uniform>::Element *E = pnode->uniforms.front(); E; E = E->next()) {
- if (SL::is_sampler_type(E->get().type))
+ if (SL::is_sampler_type(E->get().type)) {
max_texture_uniforms++;
- else
+ } else {
+ if (E->get().scope == SL::ShaderNode::Uniform::SCOPE_INSTANCE) {
+ continue; //instances are indexed directly, dont need index uniforms
+ }
+
max_uniforms++;
+ }
}
r_gen_code.texture_uniforms.resize(max_texture_uniforms);
@@ -425,15 +562,27 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
bool uses_uniforms = false;
for (Map<StringName, SL::ShaderNode::Uniform>::Element *E = pnode->uniforms.front(); E; E = E->next()) {
-
String ucode;
+ if (E->get().scope == SL::ShaderNode::Uniform::SCOPE_INSTANCE) {
+ //insert, but don't generate any code.
+ p_actions.uniforms->insert(E->key(), E->get());
+ continue; //instances are indexed directly, dont need index uniforms
+ }
if (SL::is_sampler_type(E->get().type)) {
ucode = "layout(set = " + itos(actions.texture_layout_set) + ", binding = " + itos(actions.base_texture_binding_index + E->get().texture_order) + ") uniform ";
}
- ucode += _prestr(E->get().precision);
- ucode += _typestr(E->get().type);
+ bool is_buffer_global = !SL::is_sampler_type(E->get().type) && E->get().scope == SL::ShaderNode::Uniform::SCOPE_GLOBAL;
+
+ if (is_buffer_global) {
+ //this is an integer to index the global table
+ ucode += _typestr(ShaderLanguage::TYPE_UINT);
+ } else {
+ ucode += _prestr(E->get().precision);
+ ucode += _typestr(E->get().type);
+ }
+
ucode += " " + _mkid(E->key());
ucode += ";\n";
if (SL::is_sampler_type(E->get().type)) {
@@ -446,17 +595,26 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
texture.type = E->get().type;
texture.filter = E->get().filter;
texture.repeat = E->get().repeat;
+ texture.global = E->get().scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL;
+ if (texture.global) {
+ r_gen_code.uses_global_textures = true;
+ }
r_gen_code.texture_uniforms.write[E->get().texture_order] = texture;
} else {
if (!uses_uniforms) {
-
r_gen_code.defines.push_back(String("#define USE_MATERIAL_UNIFORMS\n"));
uses_uniforms = true;
}
uniform_defines.write[E->get().order] = ucode;
- uniform_sizes.write[E->get().order] = _get_datatype_size(E->get().type);
- uniform_alignments.write[E->get().order] = _get_datatype_alignment(E->get().type);
+ if (is_buffer_global) {
+ //globals are indices into the global table
+ uniform_sizes.write[E->get().order] = _get_datatype_size(ShaderLanguage::TYPE_UINT);
+ uniform_alignments.write[E->get().order] = _get_datatype_alignment(ShaderLanguage::TYPE_UINT);
+ } else {
+ uniform_sizes.write[E->get().order] = _get_datatype_size(E->get().type);
+ uniform_alignments.write[E->get().order] = _get_datatype_alignment(E->get().type);
+ }
}
p_actions.uniforms->insert(E->key(), E->get());
@@ -470,7 +628,6 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
// add up
int offset = 0;
for (int i = 0; i < uniform_sizes.size(); i++) {
-
int align = offset % uniform_alignments[i];
if (align != 0) {
@@ -490,9 +647,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
#else
// add up
for (int i = 0; i < uniform_sizes.size(); i++) {
-
if (i > 0) {
-
int align = uniform_sizes[i - 1] % uniform_alignments[i];
if (align != 0) {
uniform_sizes[i - 1] += uniform_alignments[i] - align;
@@ -504,7 +659,6 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
//offset
r_gen_code.uniform_offsets.resize(uniform_sizes.size());
for (int i = 0; i < uniform_sizes.size(); i++) {
-
if (i > 0)
r_gen_code.uniform_offsets[i] = uniform_sizes[i - 1];
else
@@ -530,7 +684,6 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
uint32_t index = p_default_actions.base_varying_index;
for (Map<StringName, SL::ShaderNode::Varying>::Element *E = pnode->varyings.front(); E; E = E->next()) {
-
String vcode;
String interp_mode = _interpstr(E->get().interpolation);
vcode += _prestr(E->get().precision);
@@ -547,18 +700,19 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
index++;
}
- for (Map<StringName, SL::ShaderNode::Constant>::Element *E = pnode->constants.front(); E; E = E->next()) {
+ for (int i = 0; i < pnode->vconstants.size(); i++) {
+ const SL::ShaderNode::Constant &cnode = pnode->vconstants[i];
String gcode;
gcode += "const ";
- gcode += _prestr(E->get().precision);
- if (E->get().type == SL::TYPE_STRUCT) {
- gcode += _mkid(E->get().type_str);
+ gcode += _prestr(cnode.precision);
+ if (cnode.type == SL::TYPE_STRUCT) {
+ gcode += _mkid(cnode.type_str);
} else {
- gcode += _typestr(E->get().type);
+ gcode += _typestr(cnode.type);
}
- gcode += " " + _mkid(E->key());
+ gcode += " " + _mkid(String(cnode.name));
gcode += "=";
- gcode += _dump_node_code(E->get().initializer, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
+ gcode += _dump_node_code(cnode.initializer, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
gcode += ";\n";
r_gen_code.vertex_global += gcode;
r_gen_code.fragment_global += gcode;
@@ -572,7 +726,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
function = fnode;
current_func_name = fnode->name;
function_code[fnode->name] = _dump_node_code(fnode->body, p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning);
- function = NULL;
+ function = nullptr;
}
//place functions in actual code
@@ -581,7 +735,6 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
Set<StringName> added_fragment; //share for light
for (int i = 0; i < pnode->functions.size(); i++) {
-
SL::FunctionNode *fnode = pnode->functions[i].function;
function = fnode;
@@ -589,32 +742,27 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
current_func_name = fnode->name;
if (fnode->name == vertex_name) {
-
_dump_function_deps(pnode, fnode->name, function_code, r_gen_code.vertex_global, added_vtx);
r_gen_code.vertex = function_code[vertex_name];
}
if (fnode->name == fragment_name) {
-
_dump_function_deps(pnode, fnode->name, function_code, r_gen_code.fragment_global, added_fragment);
r_gen_code.fragment = function_code[fragment_name];
}
if (fnode->name == light_name) {
-
_dump_function_deps(pnode, fnode->name, function_code, r_gen_code.fragment_global, added_fragment);
r_gen_code.light = function_code[light_name];
}
- function = NULL;
+ function = nullptr;
}
//code+=dump_node_code(pnode->body,p_level);
} break;
case SL::Node::TYPE_STRUCT: {
-
} break;
case SL::Node::TYPE_FUNCTION: {
-
} break;
case SL::Node::TYPE_BLOCK: {
SL::BlockNode *bnode = (SL::BlockNode *)p_node;
@@ -625,7 +773,6 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
}
for (int i = 0; i < bnode->statements.size(); i++) {
-
String scode = _dump_node_code(bnode->statements[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
if (bnode->statements[i]->type == SL::Node::TYPE_CONTROL_FLOW || bnode->single_statement) {
@@ -687,12 +834,32 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
used_flag_pointers.insert(vnode->name);
}
- if (p_default_actions.renames.has(vnode->name))
+ if (p_default_actions.renames.has(vnode->name)) {
code = p_default_actions.renames[vnode->name];
- else {
- code = _mkid(vnode->name);
- if (actions.base_uniform_string != String() && shader->uniforms.has(vnode->name) && shader->uniforms[vnode->name].texture_order < 0) {
- code = actions.base_uniform_string + code;
+ } else {
+ if (shader->uniforms.has(vnode->name)) {
+ //its a uniform!
+ const ShaderLanguage::ShaderNode::Uniform &u = shader->uniforms[vnode->name];
+ if (u.texture_order >= 0) {
+ code = _mkid(vnode->name); //texture, use as is
+ } else {
+ //a scalar or vector
+ if (u.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) {
+ code = actions.base_uniform_string + _mkid(vnode->name); //texture, use as is
+ //global variable, this means the code points to an index to the global table
+ code = _get_global_variable_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
+ } else if (u.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
+ //instance variable, index it as such
+ code = "(" + p_default_actions.instance_uniform_index_variable + "+" + itos(u.instance_index) + ")";
+ code = _get_global_variable_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
+ } else {
+ //regular uniform, index from UBO
+ code = actions.base_uniform_string + _mkid(vnode->name);
+ }
+ }
+
+ } else {
+ code = _mkid(vnode->name); //its something else (local var most likely) use as is
}
}
@@ -727,7 +894,6 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
code += ")";
} break;
case SL::Node::TYPE_ARRAY_DECLARATION: {
-
SL::ArrayDeclarationNode *adnode = (SL::ArrayDeclarationNode *)p_node;
String declaration;
if (adnode->is_const) {
@@ -793,17 +959,18 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
used_flag_pointers.insert(anode->name);
}
- if (p_default_actions.renames.has(anode->name))
+ if (p_default_actions.renames.has(anode->name)) {
code = p_default_actions.renames[anode->name];
- else
+ } else {
code = _mkid(anode->name);
+ }
- if (anode->call_expression != NULL) {
+ if (anode->call_expression != nullptr) {
code += ".";
- code += _dump_node_code(anode->call_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
+ code += _dump_node_code(anode->call_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning, false);
}
- if (anode->index_expression != NULL) {
+ if (anode->index_expression != nullptr) {
code += "[";
code += _dump_node_code(anode->index_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
code += "]";
@@ -828,7 +995,6 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
SL::OperatorNode *onode = (SL::OperatorNode *)p_node;
switch (onode->op) {
-
case SL::OP_ASSIGN:
case SL::OP_ASSIGN_ADD:
case SL::OP_ASSIGN_SUB:
@@ -856,7 +1022,6 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
case SL::OP_CALL:
case SL::OP_STRUCT:
case SL::OP_CONSTRUCT: {
-
ERR_FAIL_COND_V(onode->arguments[0]->type != SL::Node::TYPE_VARIABLE, String());
SL::VariableNode *vnode = (SL::VariableNode *)onode->arguments[0];
@@ -867,7 +1032,6 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
} else if (onode->op == SL::OP_CONSTRUCT) {
code += String(vnode->name);
} else {
-
if (internal_functions.has(vnode->name)) {
code += vnode->name;
is_texture_func = texture_functions.has(vnode->name);
@@ -881,11 +1045,11 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
code += "(";
for (int i = 1; i < onode->arguments.size(); i++) {
- if (i > 1)
+ if (i > 1) {
code += ", ";
+ }
String node_code = _dump_node_code(onode->arguments[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
if (is_texture_func && i == 1 && onode->arguments[i]->type == SL::Node::TYPE_VARIABLE) {
-
//need to map from texture to sampler in order to sample
const SL::VariableNode *varnode = static_cast<const SL::VariableNode *>(onode->arguments[i]);
@@ -931,7 +1095,6 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
code += ")";
} break;
case SL::OP_INDEX: {
-
code += _dump_node_code(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
code += "[";
code += _dump_node_code(onode->arguments[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
@@ -939,7 +1102,6 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
} break;
case SL::OP_SELECT_IF: {
-
code += "(";
code += _dump_node_code(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
code += "?";
@@ -951,8 +1113,13 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
} break;
default: {
-
- code = "(" + _dump_node_code(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + _opstr(onode->op) + _dump_node_code(onode->arguments[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ")";
+ if (p_use_scope) {
+ code += "(";
+ }
+ code += _dump_node_code(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + _opstr(onode->op) + _dump_node_code(onode->arguments[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
+ if (p_use_scope) {
+ code += ")";
+ }
break;
}
}
@@ -961,37 +1128,29 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
case SL::Node::TYPE_CONTROL_FLOW: {
SL::ControlFlowNode *cfnode = (SL::ControlFlowNode *)p_node;
if (cfnode->flow_op == SL::FLOW_OP_IF) {
-
code += _mktab(p_level) + "if (" + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ")\n";
code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning);
if (cfnode->blocks.size() == 2) {
-
code += _mktab(p_level) + "else\n";
code += _dump_node_code(cfnode->blocks[1], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning);
}
} else if (cfnode->flow_op == SL::FLOW_OP_SWITCH) {
-
code += _mktab(p_level) + "switch (" + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ")\n";
code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning);
} else if (cfnode->flow_op == SL::FLOW_OP_CASE) {
-
code += _mktab(p_level) + "case " + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ":\n";
code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning);
} else if (cfnode->flow_op == SL::FLOW_OP_DEFAULT) {
-
code += _mktab(p_level) + "default:\n";
code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning);
} else if (cfnode->flow_op == SL::FLOW_OP_DO) {
-
code += _mktab(p_level) + "do";
code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning);
code += _mktab(p_level) + "while (" + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ");";
} else if (cfnode->flow_op == SL::FLOW_OP_WHILE) {
-
code += _mktab(p_level) + "while (" + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ")\n";
code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning);
} else if (cfnode->flow_op == SL::FLOW_OP_FOR) {
-
String left = _dump_node_code(cfnode->blocks[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
String middle = _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
String right = _dump_node_code(cfnode->expressions[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
@@ -999,14 +1158,12 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
code += _dump_node_code(cfnode->blocks[1], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning);
} else if (cfnode->flow_op == SL::FLOW_OP_RETURN) {
-
if (cfnode->expressions.size()) {
code = "return " + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ";";
} else {
code = "return;";
}
} else if (cfnode->flow_op == SL::FLOW_OP_DISCARD) {
-
if (p_actions.usage_flag_pointers.has("DISCARD") && !used_flag_pointers.has("DISCARD")) {
*p_actions.usage_flag_pointers["DISCARD"] = true;
used_flag_pointers.insert("DISCARD");
@@ -1014,10 +1171,8 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
code = "discard;";
} else if (cfnode->flow_op == SL::FLOW_OP_CONTINUE) {
-
code = "continue;";
} else if (cfnode->flow_op == SL::FLOW_OP_BREAK) {
-
code = "break;";
}
@@ -1025,7 +1180,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
case SL::Node::TYPE_MEMBER: {
SL::MemberNode *mnode = (SL::MemberNode *)p_node;
code = _dump_node_code(mnode->owner, p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + "." + mnode->name;
- if (mnode->index_expression != NULL) {
+ if (mnode->index_expression != nullptr) {
code += "[";
code += _dump_node_code(mnode->index_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
code += "]";
@@ -1037,18 +1192,21 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
return code;
}
-Error ShaderCompilerRD::compile(RS::ShaderMode p_mode, const String &p_code, IdentifierActions *p_actions, const String &p_path, GeneratedCode &r_gen_code) {
+ShaderLanguage::DataType ShaderCompilerRD::_get_variable_type(const StringName &p_type) {
+ RS::GlobalVariableType gvt = ((RasterizerStorageRD *)(RasterizerStorage::base_singleton))->global_variable_get_type_internal(p_type);
+ return RS::global_variable_type_get_shader_datatype(gvt);
+}
- Error err = parser.compile(p_code, ShaderTypes::get_singleton()->get_functions(p_mode), ShaderTypes::get_singleton()->get_modes(p_mode), ShaderTypes::get_singleton()->get_types());
+Error ShaderCompilerRD::compile(RS::ShaderMode p_mode, const String &p_code, IdentifierActions *p_actions, const String &p_path, GeneratedCode &r_gen_code) {
+ Error err = parser.compile(p_code, ShaderTypes::get_singleton()->get_functions(p_mode), ShaderTypes::get_singleton()->get_modes(p_mode), ShaderTypes::get_singleton()->get_types(), _get_variable_type);
if (err != OK) {
-
Vector<String> shader = p_code.split("\n");
for (int i = 0; i < shader.size(); i++) {
print_line(itos(i + 1) + " " + shader[i]);
}
- _err_print_error(NULL, 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(), ERR_HANDLER_SHADER);
return err;
}
@@ -1060,13 +1218,14 @@ Error ShaderCompilerRD::compile(RS::ShaderMode p_mode, const String &p_code, Ide
r_gen_code.light = String();
r_gen_code.uses_fragment_time = false;
r_gen_code.uses_vertex_time = false;
+ r_gen_code.uses_global_textures = false;
used_name_defines.clear();
used_rmode_defines.clear();
used_flag_pointers.clear();
shader = parser.get_shader();
- function = NULL;
+ function = nullptr;
_dump_node_code(shader, 1, r_gen_code, *p_actions, actions, false);
return OK;
diff --git a/servers/rendering/rasterizer_rd/shader_compiler_rd.h b/servers/rendering/rasterizer_rd/shader_compiler_rd.h
index 7d78469e9c..ce94fb743f 100644
--- a/servers/rendering/rasterizer_rd/shader_compiler_rd.h
+++ b/servers/rendering/rasterizer_rd/shader_compiler_rd.h
@@ -39,7 +39,6 @@
class ShaderCompilerRD {
public:
struct IdentifierActions {
-
Map<StringName, Pair<int *, int>> render_mode_values;
Map<StringName, bool *> render_mode_flags;
Map<StringName, bool *> usage_flag_pointers;
@@ -49,7 +48,6 @@ public:
};
struct GeneratedCode {
-
Vector<String> defines;
struct Texture {
StringName name;
@@ -57,6 +55,7 @@ public:
ShaderLanguage::ShaderNode::Uniform::Hint hint;
ShaderLanguage::TextureFilter filter;
ShaderLanguage::TextureRepeat repeat;
+ bool global;
};
Vector<Texture> texture_uniforms;
@@ -70,12 +69,12 @@ public:
String fragment;
String light;
+ bool uses_global_textures;
bool uses_fragment_time;
bool uses_vertex_time;
};
struct DefaultIdentifierActions {
-
Map<StringName, String> renames;
Map<StringName, String> render_mode_defines;
Map<StringName, String> usage_defines;
@@ -86,6 +85,8 @@ public:
int base_texture_binding_index = 0;
int texture_layout_set = 0;
String base_uniform_string;
+ String global_buffer_array_variable;
+ String instance_uniform_index_variable;
uint32_t base_varying_index = 0;
};
@@ -95,7 +96,7 @@ private:
String _get_sampler_name(ShaderLanguage::TextureFilter p_filter, ShaderLanguage::TextureRepeat p_repeat);
void _dump_function_deps(const ShaderLanguage::ShaderNode *p_node, const StringName &p_for_func, const Map<StringName, String> &p_func_code, String &r_to_add, Set<StringName> &added);
- String _dump_node_code(const ShaderLanguage::Node *p_node, int p_level, GeneratedCode &r_gen_code, IdentifierActions &p_actions, const DefaultIdentifierActions &p_default_actions, bool p_assigning);
+ String _dump_node_code(const ShaderLanguage::Node *p_node, int p_level, GeneratedCode &r_gen_code, IdentifierActions &p_actions, const DefaultIdentifierActions &p_default_actions, bool p_assigning, bool p_scope = true);
const ShaderLanguage::ShaderNode *shader;
const ShaderLanguage::FunctionNode *function;
@@ -113,6 +114,8 @@ private:
DefaultIdentifierActions actions;
+ static ShaderLanguage::DataType _get_variable_type(const StringName &p_type);
+
public:
Error compile(RS::ShaderMode p_mode, const String &p_code, IdentifierActions *p_actions, const String &p_path, GeneratedCode &r_gen_code);
diff --git a/servers/rendering/rasterizer_rd/shader_rd.cpp b/servers/rendering/rasterizer_rd/shader_rd.cpp
index 3dcfd0faf9..8c57651263 100644
--- a/servers/rendering/rasterizer_rd/shader_rd.cpp
+++ b/servers/rendering/rasterizer_rd/shader_rd.cpp
@@ -35,7 +35,6 @@
#include "servers/rendering/rendering_device.h"
void ShaderRD::setup(const char *p_vertex_code, const char *p_fragment_code, const char *p_compute_code, const char *p_name) {
-
name = p_name;
//split vertex and shader code (thank you, shader compiler programmers from you know what company).
if (p_vertex_code) {
@@ -64,7 +63,6 @@ void ShaderRD::setup(const char *p_vertex_code, const char *p_fragment_code, con
if (cpos == -1) {
vertex_code1 = code.ascii();
} else {
-
vertex_code1 = code.substr(0, cpos).ascii();
String code2 = code.substr(cpos + globals_tag.length(), code.length());
@@ -72,7 +70,6 @@ void ShaderRD::setup(const char *p_vertex_code, const char *p_fragment_code, con
if (cpos == -1) {
vertex_code2 = code2.ascii();
} else {
-
vertex_code2 = code2.substr(0, cpos).ascii();
vertex_code3 = code2.substr(cpos + code_tag.length(), code2.length()).ascii();
}
@@ -106,7 +103,6 @@ void ShaderRD::setup(const char *p_vertex_code, const char *p_fragment_code, con
if (cpos == -1) {
fragment_code1 = code.ascii();
} else {
-
fragment_code1 = code.substr(0, cpos).ascii();
//print_line("CODE1:\n"+String(fragment_code1.get_data()));
@@ -116,7 +112,6 @@ void ShaderRD::setup(const char *p_vertex_code, const char *p_fragment_code, con
if (cpos == -1) {
fragment_code2 = code2.ascii();
} else {
-
fragment_code2 = code2.substr(0, cpos).ascii();
//print_line("CODE2:\n"+String(fragment_code2.get_data()));
@@ -126,7 +121,6 @@ void ShaderRD::setup(const char *p_vertex_code, const char *p_fragment_code, con
if (cpos == -1) {
fragment_code3 = code3.ascii();
} else {
-
fragment_code3 = code3.substr(0, cpos).ascii();
//print_line("CODE3:\n"+String(fragment_code3.get_data()));
fragment_code4 = code3.substr(cpos + code_tag.length(), code3.length()).ascii();
@@ -165,7 +159,6 @@ void ShaderRD::setup(const char *p_vertex_code, const char *p_fragment_code, con
if (cpos == -1) {
compute_code1 = code.ascii();
} else {
-
compute_code1 = code.substr(0, cpos).ascii();
String code2 = code.substr(cpos + globals_tag.length(), code.length());
@@ -173,7 +166,6 @@ void ShaderRD::setup(const char *p_vertex_code, const char *p_fragment_code, con
if (cpos == -1) {
compute_code2 = code2.ascii();
} else {
-
compute_code2 = code2.substr(0, cpos).ascii();
compute_code3 = code2.substr(cpos + code_tag.length(), code2.length()).ascii();
}
@@ -183,7 +175,6 @@ void ShaderRD::setup(const char *p_vertex_code, const char *p_fragment_code, con
}
RID ShaderRD::version_create() {
-
//initialize() was never called
ERR_FAIL_COND_V(variant_defines.size() == 0, RID());
@@ -191,7 +182,7 @@ RID ShaderRD::version_create() {
version.dirty = true;
version.valid = false;
version.initialize_needed = true;
- version.variants = NULL;
+ version.variants = nullptr;
return version_owner.make_rid(version);
}
@@ -203,12 +194,11 @@ void ShaderRD::_clear_version(Version *p_version) {
}
memdelete_arr(p_version->variants);
- p_version->variants = NULL;
+ p_version->variants = nullptr;
}
}
void ShaderRD::_compile_variant(uint32_t p_variant, Version *p_version) {
-
Vector<RD::ShaderStageData> stages;
String error;
@@ -250,7 +240,6 @@ void ShaderRD::_compile_variant(uint32_t p_variant, Version *p_version) {
if (stage.spir_v.size() == 0) {
build_ok = false;
} else {
-
stage.shader_stage = RD::SHADER_STAGE_VERTEX;
stages.push_back(stage);
}
@@ -295,7 +284,6 @@ void ShaderRD::_compile_variant(uint32_t p_variant, Version *p_version) {
if (stage.spir_v.size() == 0) {
build_ok = false;
} else {
-
stage.shader_stage = RD::SHADER_STAGE_FRAGMENT;
stages.push_back(stage);
}
@@ -336,7 +324,6 @@ void ShaderRD::_compile_variant(uint32_t p_variant, Version *p_version) {
if (stage.spir_v.size() == 0) {
build_ok = false;
} else {
-
stage.shader_stage = RD::SHADER_STAGE_COMPUTE;
stages.push_back(stage);
}
@@ -361,7 +348,6 @@ void ShaderRD::_compile_variant(uint32_t p_variant, Version *p_version) {
}
void ShaderRD::_compile_version(Version *p_version) {
-
_clear_version(p_version);
p_version->valid = false;
@@ -373,7 +359,6 @@ void ShaderRD::_compile_version(Version *p_version) {
RasterizerRD::thread_work_pool.do_work(variant_defines.size(), this, &ShaderRD::_compile_variant, p_version);
#else
for (int i = 0; i < variant_defines.size(); i++) {
-
_compile_variant(i, p_version);
}
#endif
@@ -394,7 +379,7 @@ void ShaderRD::_compile_version(Version *p_version) {
}
}
memdelete_arr(p_version->variants);
- p_version->variants = NULL;
+ p_version->variants = nullptr;
return;
}
@@ -402,7 +387,6 @@ void ShaderRD::_compile_version(Version *p_version) {
}
void ShaderRD::version_set_code(RID p_version, const String &p_uniforms, const String &p_vertex_globals, const String &p_vertex_code, const String &p_fragment_globals, const String &p_fragment_light, const String &p_fragment_code, const Vector<String> &p_custom_defines) {
-
ERR_FAIL_COND(is_compute);
Version *version = version_owner.getornull(p_version);
@@ -427,7 +411,6 @@ void ShaderRD::version_set_code(RID p_version, const String &p_uniforms, const S
}
void ShaderRD::version_set_compute_code(RID p_version, const String &p_uniforms, const String &p_compute_globals, const String &p_compute_code, const Vector<String> &p_custom_defines) {
-
ERR_FAIL_COND(!is_compute);
Version *version = version_owner.getornull(p_version);
@@ -460,7 +443,6 @@ bool ShaderRD::version_is_valid(RID p_version) {
}
bool ShaderRD::version_free(RID p_version) {
-
if (version_owner.owns(p_version)) {
Version *version = version_owner.getornull(p_version);
_clear_version(version);
@@ -477,7 +459,6 @@ void ShaderRD::initialize(const Vector<String> &p_variant_defines, const String
ERR_FAIL_COND(p_variant_defines.size() == 0);
general_defines = p_general_defines.utf8();
for (int i = 0; i < p_variant_defines.size(); i++) {
-
variant_defines.push_back(p_variant_defines[i].utf8());
}
}
diff --git a/servers/rendering/rasterizer_rd/shader_rd.h b/servers/rendering/rasterizer_rd/shader_rd.h
index 6635b08cc8..d9bb068ba6 100644
--- a/servers/rendering/rasterizer_rd/shader_rd.h
+++ b/servers/rendering/rasterizer_rd/shader_rd.h
@@ -43,7 +43,6 @@
*/
class ShaderRD {
-
//versions
CharString general_defines;
Vector<CharString> variant_defines;
diff --git a/servers/rendering/rasterizer_rd/shaders/SCsub b/servers/rendering/rasterizer_rd/shaders/SCsub
index 6e852e2dc5..a454d144aa 100644
--- a/servers/rendering/rasterizer_rd/shaders/SCsub
+++ b/servers/rendering/rasterizer_rd/shaders/SCsub
@@ -5,14 +5,15 @@ Import("env")
if "RD_GLSL" in env["BUILDERS"]:
env.RD_GLSL("canvas.glsl")
env.RD_GLSL("canvas_occlusion.glsl")
- env.RD_GLSL("blur.glsl")
+ env.RD_GLSL("copy.glsl")
+ env.RD_GLSL("copy_to_fb.glsl")
env.RD_GLSL("cubemap_roughness.glsl")
env.RD_GLSL("cubemap_downsampler.glsl")
env.RD_GLSL("cubemap_filter.glsl")
env.RD_GLSL("scene_high_end.glsl")
env.RD_GLSL("sky.glsl")
env.RD_GLSL("tonemap.glsl")
- env.RD_GLSL("copy.glsl")
+ env.RD_GLSL("cube_to_dp.glsl")
env.RD_GLSL("giprobe.glsl")
env.RD_GLSL("giprobe_debug.glsl")
env.RD_GLSL("giprobe_sdf.glsl")
@@ -22,3 +23,8 @@ if "RD_GLSL" in env["BUILDERS"]:
env.RD_GLSL("ssao_minify.glsl")
env.RD_GLSL("ssao_blur.glsl")
env.RD_GLSL("roughness_limiter.glsl")
+ env.RD_GLSL("screen_space_reflection.glsl")
+ env.RD_GLSL("screen_space_reflection_filter.glsl")
+ env.RD_GLSL("screen_space_reflection_scale.glsl")
+ env.RD_GLSL("subsurface_scattering.glsl")
+ env.RD_GLSL("specular_merge.glsl")
diff --git a/servers/rendering/rasterizer_rd/shaders/blur.glsl b/servers/rendering/rasterizer_rd/shaders/blur.glsl
deleted file mode 100644
index 87c20ebaef..0000000000
--- a/servers/rendering/rasterizer_rd/shaders/blur.glsl
+++ /dev/null
@@ -1,294 +0,0 @@
-/* clang-format off */
-[vertex]
-
-#version 450
-
-VERSION_DEFINES
-
-#include "blur_inc.glsl"
-
-layout(location = 0) out vec2 uv_interp;
-/* clang-format on */
-
-void main() {
-
- vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
- uv_interp = base_arr[gl_VertexIndex];
-
- if (bool(blur.flags & FLAG_USE_BLUR_SECTION)) {
- uv_interp = blur.section.xy + uv_interp * blur.section.zw;
- }
-
- gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0);
-
- if (bool(blur.flags & FLAG_FLIP_Y)) {
- uv_interp.y = 1.0 - uv_interp.y;
- }
-}
-
-/* clang-format off */
-[fragment]
-
-#version 450
-
-VERSION_DEFINES
-
-#include "blur_inc.glsl"
-
-layout(location = 0) in vec2 uv_interp;
-/* clang-format on */
-
-layout(set = 0, binding = 0) uniform sampler2D source_color;
-
-#ifdef MODE_SSAO_MERGE
-layout(set = 1, binding = 0) uniform sampler2D source_ssao;
-#endif
-
-#ifdef GLOW_USE_AUTO_EXPOSURE
-layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure;
-#endif
-
-layout(location = 0) out vec4 frag_color;
-
-//DOF
-#if defined(MODE_DOF_FAR_BLUR) || defined(MODE_DOF_NEAR_BLUR)
-
-layout(set = 1, binding = 0) uniform sampler2D dof_source_depth;
-
-#ifdef DOF_NEAR_BLUR_MERGE
-layout(set = 2, binding = 0) uniform sampler2D source_dof_original;
-#endif
-
-#ifdef DOF_QUALITY_LOW
-const int dof_kernel_size = 5;
-const int dof_kernel_from = 2;
-const float dof_kernel[5] = float[](0.153388, 0.221461, 0.250301, 0.221461, 0.153388);
-#endif
-
-#ifdef DOF_QUALITY_MEDIUM
-const int dof_kernel_size = 11;
-const int dof_kernel_from = 5;
-const float dof_kernel[11] = float[](0.055037, 0.072806, 0.090506, 0.105726, 0.116061, 0.119726, 0.116061, 0.105726, 0.090506, 0.072806, 0.055037);
-
-#endif
-
-#ifdef DOF_QUALITY_HIGH
-const int dof_kernel_size = 21;
-const int dof_kernel_from = 10;
-const float dof_kernel[21] = float[](0.028174, 0.032676, 0.037311, 0.041944, 0.046421, 0.050582, 0.054261, 0.057307, 0.059587, 0.060998, 0.061476, 0.060998, 0.059587, 0.057307, 0.054261, 0.050582, 0.046421, 0.041944, 0.037311, 0.032676, 0.028174);
-#endif
-
-#endif
-
-void main() {
-
-#ifdef MODE_MIPMAP
-
- vec2 pix_size = blur.pixel_size;
- vec4 color = texture(source_color, uv_interp + vec2(-0.5, -0.5) * pix_size);
- color += texture(source_color, uv_interp + vec2(0.5, -0.5) * pix_size);
- color += texture(source_color, uv_interp + vec2(0.5, 0.5) * pix_size);
- color += texture(source_color, uv_interp + vec2(-0.5, 0.5) * pix_size);
- frag_color = color / 4.0;
-
-#endif
-
-#ifdef MODE_GAUSSIAN_BLUR
-
- //Simpler blur uses SIGMA2 for the gaussian kernel for a stronger effect
-
- if (bool(blur.flags & FLAG_HORIZONTAL)) {
-
- vec2 pix_size = blur.pixel_size;
- pix_size *= 0.5; //reading from larger buffer, so use more samples
- vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.214607;
- color += texture(source_color, uv_interp + vec2(1.0, 0.0) * pix_size) * 0.189879;
- color += texture(source_color, uv_interp + vec2(2.0, 0.0) * pix_size) * 0.131514;
- color += texture(source_color, uv_interp + vec2(3.0, 0.0) * pix_size) * 0.071303;
- color += texture(source_color, uv_interp + vec2(-1.0, 0.0) * pix_size) * 0.189879;
- color += texture(source_color, uv_interp + vec2(-2.0, 0.0) * pix_size) * 0.131514;
- color += texture(source_color, uv_interp + vec2(-3.0, 0.0) * pix_size) * 0.071303;
- frag_color = color;
- } else {
-
- vec2 pix_size = blur.pixel_size;
- vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.38774;
- color += texture(source_color, uv_interp + vec2(0.0, 1.0) * pix_size) * 0.24477;
- color += texture(source_color, uv_interp + vec2(0.0, 2.0) * pix_size) * 0.06136;
- color += texture(source_color, uv_interp + vec2(0.0, -1.0) * pix_size) * 0.24477;
- color += texture(source_color, uv_interp + vec2(0.0, -2.0) * pix_size) * 0.06136;
- frag_color = color;
- }
-#endif
-
-#ifdef MODE_GAUSSIAN_GLOW
-
- //Glow uses larger sigma 1 for a more rounded blur effect
-
-#define GLOW_ADD(m_ofs, m_mult) \
- { \
- vec2 ofs = uv_interp + m_ofs * pix_size; \
- vec4 c = texture(source_color, ofs) * m_mult; \
- if (any(lessThan(ofs, vec2(0.0))) || any(greaterThan(ofs, vec2(1.0)))) { \
- c *= 0.0; \
- } \
- color += c; \
- }
-
- if (bool(blur.flags & FLAG_HORIZONTAL)) {
-
- vec2 pix_size = blur.pixel_size;
- pix_size *= 0.5; //reading from larger buffer, so use more samples
- vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.174938;
- GLOW_ADD(vec2(1.0, 0.0), 0.165569);
- GLOW_ADD(vec2(2.0, 0.0), 0.140367);
- GLOW_ADD(vec2(3.0, 0.0), 0.106595);
- GLOW_ADD(vec2(-1.0, 0.0), 0.165569);
- GLOW_ADD(vec2(-2.0, 0.0), 0.140367);
- GLOW_ADD(vec2(-3.0, 0.0), 0.106595);
- color *= blur.glow_strength;
- frag_color = color;
- } else {
-
- vec2 pix_size = blur.pixel_size;
- vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.288713;
- GLOW_ADD(vec2(0.0, 1.0), 0.233062);
- GLOW_ADD(vec2(0.0, 2.0), 0.122581);
- GLOW_ADD(vec2(0.0, -1.0), 0.233062);
- GLOW_ADD(vec2(0.0, -2.0), 0.122581);
- color *= blur.glow_strength;
- frag_color = color;
- }
-
-#undef GLOW_ADD
-
- if (bool(blur.flags & FLAG_GLOW_FIRST_PASS)) {
-#ifdef GLOW_USE_AUTO_EXPOSURE
-
- frag_color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / blur.glow_auto_exposure_grey;
-#endif
- frag_color *= blur.glow_exposure;
-
- float luminance = max(frag_color.r, max(frag_color.g, frag_color.b));
- float feedback = max(smoothstep(blur.glow_hdr_threshold, blur.glow_hdr_threshold + blur.glow_hdr_scale, luminance), blur.glow_bloom);
-
- frag_color = min(frag_color * feedback, vec4(blur.glow_luminance_cap));
- }
-
-#endif
-
-#ifdef MODE_DOF_FAR_BLUR
-
- vec4 color_accum = vec4(0.0);
-
- float depth = texture(dof_source_depth, uv_interp, 0.0).r;
- depth = depth * 2.0 - 1.0;
-
- if (bool(blur.flags & FLAG_USE_ORTHOGONAL_PROJECTION)) {
- depth = ((depth + (blur.camera_z_far + blur.camera_z_near) / (blur.camera_z_far - blur.camera_z_near)) * (blur.camera_z_far - blur.camera_z_near)) / 2.0;
- } else {
- depth = 2.0 * blur.camera_z_near * blur.camera_z_far / (blur.camera_z_far + blur.camera_z_near - depth * (blur.camera_z_far - blur.camera_z_near));
- }
-
- float amount = smoothstep(blur.dof_begin, blur.dof_end, depth);
- float k_accum = 0.0;
-
- for (int i = 0; i < dof_kernel_size; i++) {
-
- int int_ofs = i - dof_kernel_from;
- vec2 tap_uv = uv_interp + blur.dof_dir * float(int_ofs) * amount * blur.dof_radius;
-
- float tap_k = dof_kernel[i];
-
- float tap_depth = texture(dof_source_depth, tap_uv, 0.0).r;
- tap_depth = tap_depth * 2.0 - 1.0;
-
- if (bool(blur.flags & FLAG_USE_ORTHOGONAL_PROJECTION)) {
-
- tap_depth = ((tap_depth + (blur.camera_z_far + blur.camera_z_near) / (blur.camera_z_far - blur.camera_z_near)) * (blur.camera_z_far - blur.camera_z_near)) / 2.0;
- } else {
- tap_depth = 2.0 * blur.camera_z_near * blur.camera_z_far / (blur.camera_z_far + blur.camera_z_near - tap_depth * (blur.camera_z_far - blur.camera_z_near));
- }
-
- float tap_amount = mix(smoothstep(blur.dof_begin, blur.dof_end, tap_depth), 1.0, int_ofs == 0);
- tap_amount *= tap_amount * tap_amount; //prevent undesired glow effect
-
- vec4 tap_color = texture(source_color, tap_uv, 0.0) * tap_k;
-
- k_accum += tap_k * tap_amount;
- color_accum += tap_color * tap_amount;
- }
-
- if (k_accum > 0.0) {
- color_accum /= k_accum;
- }
-
- frag_color = color_accum; ///k_accum;
-
-#endif
-
-#ifdef MODE_DOF_NEAR_BLUR
-
- vec4 color_accum = vec4(0.0);
-
- float max_accum = 0.0;
-
- for (int i = 0; i < dof_kernel_size; i++) {
-
- int int_ofs = i - dof_kernel_from;
- vec2 tap_uv = uv_interp + blur.dof_dir * float(int_ofs) * blur.dof_radius;
- float ofs_influence = max(0.0, 1.0 - float(abs(int_ofs)) / float(dof_kernel_from));
-
- float tap_k = dof_kernel[i];
-
- vec4 tap_color = texture(source_color, tap_uv, 0.0);
-
- float tap_depth = texture(dof_source_depth, tap_uv, 0.0).r;
- tap_depth = tap_depth * 2.0 - 1.0;
- if (bool(blur.flags & FLAG_USE_ORTHOGONAL_PROJECTION)) {
-
- tap_depth = ((tap_depth + (blur.camera_z_far + blur.camera_z_near) / (blur.camera_z_far - blur.camera_z_near)) * (blur.camera_z_far - blur.camera_z_near)) / 2.0;
- } else {
- tap_depth = 2.0 * blur.camera_z_near * blur.camera_z_far / (blur.camera_z_far + blur.camera_z_near - tap_depth * (blur.camera_z_far - blur.camera_z_near));
- }
- float tap_amount = 1.0 - smoothstep(blur.dof_end, blur.dof_begin, tap_depth);
- tap_amount *= tap_amount * tap_amount; //prevent undesired glow effect
-
- if (bool(blur.flags & FLAG_DOF_NEAR_FIRST_TAP)) {
- tap_color.a = 1.0 - smoothstep(blur.dof_end, blur.dof_begin, tap_depth);
- }
-
- max_accum = max(max_accum, tap_amount * ofs_influence);
-
- color_accum += tap_color * tap_k;
- }
-
- color_accum.a = max(color_accum.a, sqrt(max_accum));
-
-#ifdef DOF_NEAR_BLUR_MERGE
- {
- vec4 original = texture(source_dof_original, uv_interp, 0.0);
- color_accum = mix(original, color_accum, color_accum.a);
- }
-#endif
-
- if (bool(blur.flags & FLAG_DOF_NEAR_FIRST_TAP)) {
- frag_color = color_accum;
- }
-#endif
-
-#ifdef MODE_SIMPLE_COPY
- vec4 color = texture(source_color, uv_interp, 0.0);
- if (bool(blur.flags & FLAG_COPY_FORCE_LUMINANCE)) {
- color.rgb = vec3(max(max(color.r, color.g), color.b));
- }
- frag_color = color;
-#endif
-
-#ifdef MODE_SSAO_MERGE
- vec4 color = texture(source_color, uv_interp, 0.0);
- float ssao = texture(source_ssao, uv_interp, 0.0).r;
- frag_color = vec4(mix(color.rgb, color.rgb * mix(blur.ssao_color.rgb, vec3(1.0), ssao), color.a), 1.0);
-
-#endif
-}
diff --git a/servers/rendering/rasterizer_rd/shaders/blur_inc.glsl b/servers/rendering/rasterizer_rd/shaders/blur_inc.glsl
deleted file mode 100644
index 33ba9de7bb..0000000000
--- a/servers/rendering/rasterizer_rd/shaders/blur_inc.glsl
+++ /dev/null
@@ -1,35 +0,0 @@
-#define FLAG_HORIZONTAL (1 << 0)
-#define FLAG_USE_BLUR_SECTION (1 << 1)
-#define FLAG_USE_ORTHOGONAL_PROJECTION (1 << 2)
-#define FLAG_DOF_NEAR_FIRST_TAP (1 << 3)
-#define FLAG_GLOW_FIRST_PASS (1 << 4)
-#define FLAG_FLIP_Y (1 << 5)
-#define FLAG_COPY_FORCE_LUMINANCE (1 << 6)
-
-layout(push_constant, binding = 1, std430) uniform Blur {
- vec4 section;
- vec2 pixel_size;
- uint flags;
- uint pad;
- // Glow.
- float glow_strength;
- float glow_bloom;
- float glow_hdr_threshold;
- float glow_hdr_scale;
- float glow_exposure;
- float glow_white;
- float glow_luminance_cap;
- float glow_auto_exposure_grey;
- // DOF.
- float dof_begin;
- float dof_end;
- float dof_radius;
- float dof_pad;
-
- vec2 dof_dir;
- float camera_z_far;
- float camera_z_near;
-
- vec4 ssao_color;
-}
-blur;
diff --git a/servers/rendering/rasterizer_rd/shaders/bokeh_dof.glsl b/servers/rendering/rasterizer_rd/shaders/bokeh_dof.glsl
index 7153fe6b17..63f086a83d 100644
--- a/servers/rendering/rasterizer_rd/shaders/bokeh_dof.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/bokeh_dof.glsl
@@ -1,5 +1,4 @@
-/* clang-format off */
-[compute]
+#[compute]
#version 450
@@ -8,7 +7,6 @@ VERSION_DEFINES
#define BLOCK_SIZE 8
layout(local_size_x = BLOCK_SIZE, local_size_y = BLOCK_SIZE, local_size_z = 1) in;
-/* clang-format on */
#ifdef MODE_GEN_BLUR_SIZE
layout(rgba16f, set = 0, binding = 0) uniform restrict image2D color_image;
@@ -69,7 +67,6 @@ float get_depth_at_pos(vec2 uv) {
}
float get_blur_size(float depth) {
-
if (params.blur_near_active && depth < params.blur_near_begin) {
return -(1.0 - smoothstep(params.blur_near_end, params.blur_near_begin, depth)) * params.blur_size - DEPTH_GAP; //near blur is negative
}
@@ -95,7 +92,6 @@ float hash12n(vec2 p) {
#if defined(MODE_BOKEH_BOX) || defined(MODE_BOKEH_HEXAGONAL)
vec4 weighted_filter_dir(vec2 dir, vec2 uv, vec2 pixel_size) {
-
dir *= pixel_size;
vec4 color = texture(color_texture, uv);
@@ -109,7 +105,6 @@ vec4 weighted_filter_dir(vec2 dir, vec2 uv, vec2 pixel_size) {
}
for (int i = -params.blur_steps; i <= params.blur_steps; i++) {
-
if (i == 0) {
continue;
}
@@ -141,7 +136,6 @@ vec4 weighted_filter_dir(vec2 dir, vec2 uv, vec2 pixel_size) {
#endif
void main() {
-
ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
if (any(greaterThan(pos, params.size))) { //too large, do nothing
@@ -218,7 +212,6 @@ void main() {
float radius = params.blur_scale;
for (float ang = 0.0; radius < params.blur_size; ang += GOLDEN_ANGLE) {
-
vec2 suv = uv + vec2(cos(ang), sin(ang)) * pixel_size * radius;
vec4 sample_color = texture(color_texture, suv);
float sample_size = abs(sample_color.a);
diff --git a/servers/rendering/rasterizer_rd/shaders/canvas.glsl b/servers/rendering/rasterizer_rd/shaders/canvas.glsl
index 28135fce31..e33b3face9 100644
--- a/servers/rendering/rasterizer_rd/shaders/canvas.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/canvas.glsl
@@ -1,5 +1,4 @@
-/* clang-format off */
-[vertex]
+#[vertex]
#version 450
@@ -7,7 +6,6 @@ VERSION_DEFINES
#ifdef USE_ATTRIBUTES
layout(location = 0) in vec2 vertex_attrib;
-/* clang-format on */
layout(location = 3) in vec4 color_attrib;
layout(location = 4) in vec2 uv_attrib;
@@ -40,7 +38,6 @@ VERTEX_SHADER_GLOBALS
/* clang-format on */
void main() {
-
vec4 instance_custom = vec4(0.0);
#ifdef USE_PRIMITIVE
@@ -88,7 +85,6 @@ void main() {
#if 0
if (draw_data.flags & FLAGS_INSTANCING_ENABLED) {
-
uint offset = draw_data.flags & FLAGS_INSTANCING_STRIDE_MASK;
offset *= gl_InstanceIndex;
mat4 instance_xform = mat4(
@@ -149,7 +145,6 @@ VERTEX_SHADER_CODE
color_interp = color;
if (bool(draw_data.flags & FLAGS_USE_PIXEL_SNAP)) {
-
vertex = floor(vertex + 0.5);
// precision issue on some hardware creates artifacts within texture
// offset uv by a small amount to avoid
@@ -160,7 +155,6 @@ VERTEX_SHADER_CODE
#if 0
if (bool(draw_data.flags & FLAGS_USE_SKELETON) && bone_weights != vec4(0.0)) { //must be a valid bone
//skeleton transform
-
ivec4 bone_indicesi = ivec4(bone_indices);
uvec2 tex_ofs = bone_indicesi.x * 2;
@@ -211,8 +205,7 @@ VERTEX_SHADER_CODE
#endif
}
-/* clang-format off */
-[fragment]
+#[fragment]
#version 450
@@ -221,7 +214,6 @@ VERSION_DEFINES
#include "canvas_uniforms_inc.glsl"
layout(location = 0) in vec2 uv_interp;
-/* clang-format on */
layout(location = 1) in vec4 color_interp;
layout(location = 2) in vec2 vertex_interp;
@@ -258,7 +250,6 @@ vec4 light_compute(
vec2 screen_uv,
vec2 uv,
vec4 color) {
-
vec4 light = vec4(0.0);
/* clang-format off */
LIGHT_SHADER_CODE
@@ -271,7 +262,6 @@ LIGHT_SHADER_CODE
#ifdef USE_NINEPATCH
float map_ninepatch_axis(float pixel, float draw_size, float tex_pixel_size, float margin_begin, float margin_end, int np_repeat, inout int draw_center) {
-
float tex_size = 1.0 / tex_pixel_size;
if (pixel < margin_begin) {
@@ -313,7 +303,6 @@ float map_ninepatch_axis(float pixel, float draw_size, float tex_pixel_size, flo
#endif
void main() {
-
vec4 color = color_interp;
vec2 uv = uv_interp;
vec2 vertex = vertex_interp;
@@ -335,7 +324,6 @@ void main() {
#endif
if (bool(draw_data.flags & FLAGS_CLIP_RECT_UV)) {
-
uv = clamp(uv, draw_data.src_rect.xy, draw_data.src_rect.xy + abs(draw_data.src_rect.zw));
}
@@ -348,7 +336,6 @@ void main() {
vec3 normal;
#if defined(NORMAL_USED)
-
bool normal_used = true;
#else
bool normal_used = false;
@@ -458,7 +445,6 @@ FRAGMENT_SHADER_CODE
light_color.rgb *= light_base_color.rgb * light_base_color.a;
if (normal_used) {
-
vec3 light_pos = vec3(light_array.data[light_base].position, light_array.data[light_base].height);
vec3 pos = light_vertex;
vec3 light_vec = normalize(light_pos - pos);
@@ -490,7 +476,6 @@ FRAGMENT_SHADER_CODE
}
if (bool(light_array.data[light_base].flags & LIGHT_FLAGS_HAS_SHADOW)) {
-
vec2 shadow_pos = (vec4(shadow_vertex, 0.0, 1.0) * mat4(light_array.data[light_base].shadow_matrix[0], light_array.data[light_base].shadow_matrix[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))).xy; //multiply inverse given its transposed. Optimizer removes useless operations.
vec2 pos_norm = normalize(shadow_pos);
diff --git a/servers/rendering/rasterizer_rd/shaders/canvas_occlusion.glsl b/servers/rendering/rasterizer_rd/shaders/canvas_occlusion.glsl
index 7b30cc8fe9..99e70a1976 100644
--- a/servers/rendering/rasterizer_rd/shaders/canvas_occlusion.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/canvas_occlusion.glsl
@@ -1,13 +1,10 @@
-/* clang-format off */
-[vertex]
+#[vertex]
#version 450
layout(location = 0) in highp vec3 vertex;
-/* clang-format on */
layout(push_constant, binding = 0, std430) uniform Constants {
-
mat4 projection;
mat2x4 modelview;
vec2 direction;
@@ -18,23 +15,19 @@ constants;
layout(location = 0) out highp float depth;
void main() {
-
highp vec4 vtx = vec4(vertex, 1.0) * mat4(constants.modelview[0], constants.modelview[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));
depth = dot(constants.direction, vtx.xy);
gl_Position = constants.projection * vtx;
}
-/* clang-format off */
-[fragment]
+#[fragment]
#version 450
layout(location = 0) in highp float depth;
-/* clang-format on */
layout(location = 0) out highp float distance_buf;
void main() {
-
distance_buf = depth;
}
diff --git a/servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl b/servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl
index 1ac43480cd..a39866004b 100644
--- a/servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl
@@ -132,6 +132,11 @@ layout(set = 2, binding = 6) uniform sampler shadow_sampler;
#endif
+layout(set = 2, binding = 7, std430) restrict readonly buffer GlobalVariableData {
+ vec4 data[];
+}
+global_variables;
+
/* SET3: Render Target Data */
#ifdef SCREEN_TEXTURE_USED
diff --git a/servers/rendering/rasterizer_rd/shaders/copy.glsl b/servers/rendering/rasterizer_rd/shaders/copy.glsl
index cbb9b546a3..eb39c28fa9 100644
--- a/servers/rendering/rasterizer_rd/shaders/copy.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/copy.glsl
@@ -1,86 +1,240 @@
-/* clang-format off */
-[vertex]
+#[compute]
#version 450
VERSION_DEFINES
-layout(location = 0) out vec2 uv_interp;
-/* clang-format on */
+layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
+
+#define FLAG_HORIZONTAL (1 << 0)
+#define FLAG_USE_BLUR_SECTION (1 << 1)
+#define FLAG_USE_ORTHOGONAL_PROJECTION (1 << 2)
+#define FLAG_DOF_NEAR_FIRST_TAP (1 << 3)
+#define FLAG_GLOW_FIRST_PASS (1 << 4)
+#define FLAG_FLIP_Y (1 << 5)
+#define FLAG_FORCE_LUMINANCE (1 << 6)
+#define FLAG_COPY_ALL_SOURCE (1 << 7)
+
+layout(push_constant, binding = 1, std430) uniform Params {
+ ivec4 section;
+ ivec2 target;
+ uint flags;
+ uint pad;
+ // Glow.
+ float glow_strength;
+ float glow_bloom;
+ float glow_hdr_threshold;
+ float glow_hdr_scale;
+
+ float glow_exposure;
+ float glow_white;
+ float glow_luminance_cap;
+ float glow_auto_exposure_grey;
+ // DOF.
+ float camera_z_far;
+ float camera_z_near;
+ uint pad2[2];
+}
+params;
+
+#ifdef MODE_CUBEMAP_ARRAY_TO_PANORAMA
+layout(set = 0, binding = 0) uniform samplerCubeArray source_color;
+#elif defined(MODE_CUBEMAP_TO_PANORAMA)
+layout(set = 0, binding = 0) uniform samplerCube source_color;
+#else
+layout(set = 0, binding = 0) uniform sampler2D source_color;
+#endif
+
+#ifdef GLOW_USE_AUTO_EXPOSURE
+layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure;
+#endif
+
+#if defined(MODE_LINEARIZE_DEPTH_COPY) || defined(MODE_SIMPLE_COPY_DEPTH)
+layout(r32f, set = 3, binding = 0) uniform restrict writeonly image2D dest_buffer;
+#elif defined(DST_IMAGE_8BIT)
+layout(rgba8, set = 3, binding = 0) uniform restrict writeonly image2D dest_buffer;
+#else
+layout(rgba32f, set = 3, binding = 0) uniform restrict writeonly image2D dest_buffer;
+#endif
void main() {
+ // Pixel being shaded
+ ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
+ if (any(greaterThanEqual(pos, params.section.zw))) { //too large, do nothing
+ return;
+ }
- vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
- uv_interp = base_arr[gl_VertexIndex];
+#ifdef MODE_MIPMAP
- gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0);
-}
+ ivec2 base_pos = (pos + params.section.xy) << 1;
+ vec4 color = texelFetch(source_color, base_pos, 0);
+ color += texelFetch(source_color, base_pos + ivec2(0, 1), 0);
+ color += texelFetch(source_color, base_pos + ivec2(1, 0), 0);
+ color += texelFetch(source_color, base_pos + ivec2(1, 1), 0);
+ color /= 4.0;
-/* clang-format off */
-[fragment]
+ imageStore(dest_buffer, pos + params.target, color);
+#endif
-#version 450
+#ifdef MODE_GAUSSIAN_BLUR
-VERSION_DEFINES
+ //Simpler blur uses SIGMA2 for the gaussian kernel for a stronger effect
-layout(location = 0) in vec2 uv_interp;
-/* clang-format on */
+ if (bool(params.flags & FLAG_HORIZONTAL)) {
+ ivec2 base_pos = (pos + params.section.xy) << 1;
+ vec4 color = texelFetch(source_color, base_pos + ivec2(0, 0), 0) * 0.214607;
+ color += texelFetch(source_color, base_pos + ivec2(1, 0), 0) * 0.189879;
+ color += texelFetch(source_color, base_pos + ivec2(2, 0), 0) * 0.131514;
+ color += texelFetch(source_color, base_pos + ivec2(3, 0), 0) * 0.071303;
+ color += texelFetch(source_color, base_pos + ivec2(-1, 0), 0) * 0.189879;
+ color += texelFetch(source_color, base_pos + ivec2(-2, 0), 0) * 0.131514;
+ color += texelFetch(source_color, base_pos + ivec2(-3, 0), 0) * 0.071303;
+ imageStore(dest_buffer, pos + params.target, color);
+ } else {
+ ivec2 base_pos = (pos + params.section.xy);
+ vec4 color = texelFetch(source_color, base_pos + ivec2(0, 0), 0) * 0.38774;
+ color += texelFetch(source_color, base_pos + ivec2(0, 1), 0) * 0.24477;
+ color += texelFetch(source_color, base_pos + ivec2(0, 2), 0) * 0.06136;
+ color += texelFetch(source_color, base_pos + ivec2(0, -1), 0) * 0.24477;
+ color += texelFetch(source_color, base_pos + ivec2(0, -2), 0) * 0.06136;
+ imageStore(dest_buffer, pos + params.target, color);
+ }
+#endif
-#ifdef MODE_CUBE_TO_DP
+#ifdef MODE_GAUSSIAN_GLOW
-layout(set = 0, binding = 0) uniform samplerCube source_cube;
+ //Glow uses larger sigma 1 for a more rounded blur effect
-layout(push_constant, binding = 0, std430) uniform Params {
- float bias;
- float z_far;
- float z_near;
- bool z_flip;
-}
-params;
+#define GLOW_ADD(m_ofs, m_mult) \
+ { \
+ ivec2 ofs = base_pos + m_ofs; \
+ if (all(greaterThanEqual(ofs, section_begin)) && all(lessThan(ofs, section_end))) { \
+ color += texelFetch(source_color, ofs, 0) * m_mult; \
+ } \
+ }
+
+ vec4 color = vec4(0.0);
+
+ if (bool(params.flags & FLAG_HORIZONTAL)) {
+ ivec2 base_pos = (pos + params.section.xy) << 1;
+ ivec2 section_begin = params.section.xy << 1;
+ ivec2 section_end = section_begin + (params.section.zw << 1);
+
+ GLOW_ADD(ivec2(0, 0), 0.174938);
+ GLOW_ADD(ivec2(1, 0), 0.165569);
+ GLOW_ADD(ivec2(2, 0), 0.140367);
+ GLOW_ADD(ivec2(3, 0), 0.106595);
+ GLOW_ADD(ivec2(-1, 0), 0.165569);
+ GLOW_ADD(ivec2(-2, 0), 0.140367);
+ GLOW_ADD(ivec2(-3, 0), 0.106595);
+ color *= params.glow_strength;
+ } else {
+ ivec2 base_pos = pos + params.section.xy;
+ ivec2 section_begin = params.section.xy;
+ ivec2 section_end = section_begin + params.section.zw;
+
+ GLOW_ADD(ivec2(0, 0), 0.288713);
+ GLOW_ADD(ivec2(0, 1), 0.233062);
+ GLOW_ADD(ivec2(0, 2), 0.122581);
+ GLOW_ADD(ivec2(0, -1), 0.233062);
+ GLOW_ADD(ivec2(0, -2), 0.122581);
+ color *= params.glow_strength;
+ }
+
+#undef GLOW_ADD
-layout(location = 0) out float depth_buffer;
+ if (bool(params.flags & FLAG_GLOW_FIRST_PASS)) {
+#ifdef GLOW_USE_AUTO_EXPOSURE
+ color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / params.glow_auto_exposure_grey;
#endif
+ color *= params.glow_exposure;
-void main() {
+ float luminance = max(color.r, max(color.g, color.b));
+ float feedback = max(smoothstep(params.glow_hdr_threshold, params.glow_hdr_threshold + params.glow_hdr_scale, luminance), params.glow_bloom);
-#ifdef MODE_CUBE_TO_DP
+ color = min(color * feedback, vec4(params.glow_luminance_cap));
+ }
- vec3 normal = vec3(uv_interp * 2.0 - 1.0, 0.0);
+ imageStore(dest_buffer, pos + params.target, color);
- normal.z = 0.5 - 0.5 * ((normal.x * normal.x) + (normal.y * normal.y));
- normal = normalize(normal);
+#endif
- normal.y = -normal.y; //needs to be flipped to match projection matrix
- if (!params.z_flip) {
- normal.z = -normal.z;
- }
+#ifdef MODE_SIMPLE_COPY
- float depth = texture(source_cube, normal).r;
+ vec4 color;
+ if (bool(params.flags & FLAG_COPY_ALL_SOURCE)) {
+ vec2 uv = vec2(pos) / vec2(params.section.zw);
+ if (bool(params.flags & FLAG_FLIP_Y)) {
+ uv.y = 1.0 - uv.y;
+ }
+ color = textureLod(source_color, uv, 0.0);
- // absolute values for direction cosines, bigger value equals closer to basis axis
- vec3 unorm = abs(normal);
+ if (bool(params.flags & FLAG_FORCE_LUMINANCE)) {
+ color.rgb = vec3(max(max(color.r, color.g), color.b));
+ }
+ imageStore(dest_buffer, pos + params.target, color);
- if ((unorm.x >= unorm.y) && (unorm.x >= unorm.z)) {
- // x code
- unorm = normal.x > 0.0 ? vec3(1.0, 0.0, 0.0) : vec3(-1.0, 0.0, 0.0);
- } else if ((unorm.y > unorm.x) && (unorm.y >= unorm.z)) {
- // y code
- unorm = normal.y > 0.0 ? vec3(0.0, 1.0, 0.0) : vec3(0.0, -1.0, 0.0);
- } else if ((unorm.z > unorm.x) && (unorm.z > unorm.y)) {
- // z code
- unorm = normal.z > 0.0 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 0.0, -1.0);
} else {
- // oh-no we messed up code
- // has to be
- unorm = vec3(1.0, 0.0, 0.0);
+ color = texelFetch(source_color, pos + params.section.xy, 0);
+
+ if (bool(params.flags & FLAG_FORCE_LUMINANCE)) {
+ color.rgb = vec3(max(max(color.r, color.g), color.b));
+ }
+
+ if (bool(params.flags & FLAG_FLIP_Y)) {
+ pos.y = params.section.w - pos.y - 1;
+ }
+
+ imageStore(dest_buffer, pos + params.target, color);
}
- float depth_fix = 1.0 / dot(normal, unorm);
+#endif
+
+#ifdef MODE_SIMPLE_COPY_DEPTH
+
+ vec4 color = texelFetch(source_color, pos + params.section.xy, 0);
- depth = 2.0 * depth - 1.0;
- float linear_depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near));
- depth_buffer = (linear_depth * depth_fix + params.bias) / params.z_far;
+ if (bool(params.flags & FLAG_FLIP_Y)) {
+ pos.y = params.section.w - pos.y - 1;
+ }
+
+ imageStore(dest_buffer, pos + params.target, vec4(color.r));
#endif
+
+#ifdef MODE_LINEARIZE_DEPTH_COPY
+
+ float depth = texelFetch(source_color, pos + params.section.xy, 0).r;
+ depth = depth * 2.0 - 1.0;
+ depth = 2.0 * params.camera_z_near * params.camera_z_far / (params.camera_z_far + params.camera_z_near - depth * (params.camera_z_far - params.camera_z_near));
+ vec4 color = vec4(depth / params.camera_z_far);
+
+ if (bool(params.flags & FLAG_FLIP_Y)) {
+ pos.y = params.section.w - pos.y - 1;
+ }
+
+ imageStore(dest_buffer, pos + params.target, color);
+#endif
+
+#if defined(MODE_CUBEMAP_TO_PANORAMA) || defined(MODE_CUBEMAP_ARRAY_TO_PANORAMA)
+
+ const float PI = 3.14159265359;
+ vec2 uv = vec2(pos) / vec2(params.section.zw);
+ uv.y = 1.0 - uv.y;
+ float phi = uv.x * 2.0 * PI;
+ float theta = uv.y * PI;
+
+ vec3 normal;
+ normal.x = sin(phi) * sin(theta) * -1.0;
+ normal.y = cos(theta);
+ normal.z = cos(phi) * sin(theta) * -1.0;
+
+#ifdef MODE_CUBEMAP_TO_PANORAMA
+ vec4 color = textureLod(source_color, normal, params.camera_z_far); //the biggest the lod the least the acne
+#else
+ vec4 color = textureLod(source_color, vec4(normal, params.camera_z_far), 0.0); //the biggest the lod the least the acne
+#endif
+ imageStore(dest_buffer, pos + params.target, color);
+#endif
}
diff --git a/servers/rendering/rasterizer_rd/shaders/copy_to_fb.glsl b/servers/rendering/rasterizer_rd/shaders/copy_to_fb.glsl
new file mode 100644
index 0000000000..b1cfe1e91e
--- /dev/null
+++ b/servers/rendering/rasterizer_rd/shaders/copy_to_fb.glsl
@@ -0,0 +1,99 @@
+#[vertex]
+
+#version 450
+
+VERSION_DEFINES
+
+layout(location = 0) out vec2 uv_interp;
+
+layout(push_constant, binding = 1, std430) uniform Params {
+ vec4 section;
+ vec2 pixel_size;
+ bool flip_y;
+ bool use_section;
+
+ bool force_luminance;
+ uint pad[3];
+}
+params;
+
+void main() {
+ vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
+ uv_interp = base_arr[gl_VertexIndex];
+
+ vec2 vpos = uv_interp;
+ if (params.use_section) {
+ vpos = params.section.xy + vpos * params.section.zw;
+ }
+
+ gl_Position = vec4(vpos * 2.0 - 1.0, 0.0, 1.0);
+
+ if (params.flip_y) {
+ uv_interp.y = 1.0 - uv_interp.y;
+ }
+}
+
+#[fragment]
+
+#version 450
+
+VERSION_DEFINES
+
+layout(push_constant, binding = 1, std430) uniform Params {
+ vec4 section;
+ vec2 pixel_size;
+ bool flip_y;
+ bool use_section;
+
+ bool force_luminance;
+ bool alpha_to_zero;
+ uint pad[2];
+}
+params;
+
+layout(location = 0) in vec2 uv_interp;
+
+layout(set = 0, binding = 0) uniform sampler2D source_color;
+
+layout(location = 0) out vec4 frag_color;
+
+void main() {
+ vec2 uv = uv_interp;
+
+#ifdef MODE_PANORAMA_TO_DP
+
+ //obtain normal from dual paraboloid uv
+#define M_PI 3.14159265359
+
+ float side;
+ uv.y = modf(uv.y * 2.0, side);
+ side = side * 2.0 - 1.0;
+ vec3 normal = vec3(uv * 2.0 - 1.0, 0.0);
+ normal.z = 0.5 - 0.5 * ((normal.x * normal.x) + (normal.y * normal.y));
+ normal *= -side;
+ normal = normalize(normal);
+
+ //now convert normal to panorama uv
+
+ vec2 st = vec2(atan(normal.x, normal.z), acos(normal.y));
+
+ if (st.x < 0.0) {
+ st.x += M_PI * 2.0;
+ }
+
+ uv = st / vec2(M_PI * 2.0, M_PI);
+
+ if (side < 0.0) {
+ //uv.y = 1.0 - uv.y;
+ uv = 1.0 - uv;
+ }
+#endif
+ vec4 color = textureLod(source_color, uv, 0.0);
+ if (params.force_luminance) {
+ color.rgb = vec3(max(max(color.r, color.g), color.b));
+ }
+ if (params.alpha_to_zero) {
+ color.rgb *= color.a;
+ }
+ frag_color = color;
+}
diff --git a/servers/rendering/rasterizer_rd/shaders/cube_to_dp.glsl b/servers/rendering/rasterizer_rd/shaders/cube_to_dp.glsl
new file mode 100644
index 0000000000..54d67db6c6
--- /dev/null
+++ b/servers/rendering/rasterizer_rd/shaders/cube_to_dp.glsl
@@ -0,0 +1,69 @@
+#[compute]
+
+#version 450
+
+VERSION_DEFINES
+
+layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
+
+layout(set = 0, binding = 0) uniform samplerCube source_cube;
+
+layout(push_constant, binding = 1, std430) uniform Params {
+ ivec2 screen_size;
+ ivec2 offset;
+ float bias;
+ float z_far;
+ float z_near;
+ bool z_flip;
+}
+params;
+
+layout(r32f, set = 1, binding = 0) uniform restrict writeonly image2D depth_buffer;
+
+void main() {
+ ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
+ if (any(greaterThan(pos, params.screen_size))) { //too large, do nothing
+ return;
+ }
+
+ vec2 pixel_size = 1.0 / vec2(params.screen_size);
+ vec2 uv = (vec2(pos) + 0.5) * pixel_size;
+
+ vec3 normal = vec3(uv * 2.0 - 1.0, 0.0);
+
+ normal.z = 0.5 - 0.5 * ((normal.x * normal.x) + (normal.y * normal.y));
+ normal = normalize(normal);
+
+ normal.y = -normal.y; //needs to be flipped to match projection matrix
+ if (!params.z_flip) {
+ normal.z = -normal.z;
+ }
+
+ float depth = texture(source_cube, normal).r;
+
+ // absolute values for direction cosines, bigger value equals closer to basis axis
+ vec3 unorm = abs(normal);
+
+ if ((unorm.x >= unorm.y) && (unorm.x >= unorm.z)) {
+ // x code
+ unorm = normal.x > 0.0 ? vec3(1.0, 0.0, 0.0) : vec3(-1.0, 0.0, 0.0);
+ } else if ((unorm.y > unorm.x) && (unorm.y >= unorm.z)) {
+ // y code
+ unorm = normal.y > 0.0 ? vec3(0.0, 1.0, 0.0) : vec3(0.0, -1.0, 0.0);
+ } else if ((unorm.z > unorm.x) && (unorm.z > unorm.y)) {
+ // z code
+ unorm = normal.z > 0.0 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 0.0, -1.0);
+ } else {
+ // oh-no we messed up code
+ // has to be
+ unorm = vec3(1.0, 0.0, 0.0);
+ }
+
+ float depth_fix = 1.0 / dot(normal, unorm);
+
+ depth = 2.0 * depth - 1.0;
+ float linear_depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near));
+ depth = (linear_depth * depth_fix) / params.z_far;
+
+ imageStore(depth_buffer, pos + params.offset, vec4(depth));
+}
diff --git a/servers/rendering/rasterizer_rd/shaders/cubemap_downsampler.glsl b/servers/rendering/rasterizer_rd/shaders/cubemap_downsampler.glsl
index 9f3ecf6053..7f269b7af3 100644
--- a/servers/rendering/rasterizer_rd/shaders/cubemap_downsampler.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/cubemap_downsampler.glsl
@@ -18,8 +18,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
-/* clang-format off */
-[compute]
+#[compute]
#version 450
@@ -28,7 +27,6 @@ VERSION_DEFINES
#define BLOCK_SIZE 8
layout(local_size_x = BLOCK_SIZE, local_size_y = BLOCK_SIZE, local_size_z = 1) in;
-/* clang-format on */
layout(set = 0, binding = 0) uniform samplerCube source_cubemap;
@@ -46,26 +44,31 @@ void get_dir_0(out vec3 dir, in float u, in float v) {
dir[1] = v;
dir[2] = -u;
}
+
void get_dir_1(out vec3 dir, in float u, in float v) {
dir[0] = -1.0;
dir[1] = v;
dir[2] = u;
}
+
void get_dir_2(out vec3 dir, in float u, in float v) {
dir[0] = u;
dir[1] = 1.0;
dir[2] = -v;
}
+
void get_dir_3(out vec3 dir, in float u, in float v) {
dir[0] = u;
dir[1] = -1.0;
dir[2] = v;
}
+
void get_dir_4(out vec3 dir, in float u, in float v) {
dir[0] = u;
dir[1] = v;
dir[2] = 1.0;
}
+
void get_dir_5(out vec3 dir, in float u, in float v) {
dir[0] = -u;
dir[1] = v;
diff --git a/servers/rendering/rasterizer_rd/shaders/cubemap_filter.glsl b/servers/rendering/rasterizer_rd/shaders/cubemap_filter.glsl
index 193d0a8a3c..987545fb76 100644
--- a/servers/rendering/rasterizer_rd/shaders/cubemap_filter.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/cubemap_filter.glsl
@@ -18,8 +18,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
-/* clang-format off */
-[compute]
+#[compute]
#version 450
@@ -28,7 +27,6 @@ VERSION_DEFINES
#define GROUP_SIZE 64
layout(local_size_x = GROUP_SIZE, local_size_y = 1, local_size_z = 1) in;
-/* clang-format on */
layout(set = 0, binding = 0) uniform samplerCube source_cubemap;
layout(rgba16f, set = 2, binding = 0) uniform restrict writeonly imageCube dest_cubemap0;
diff --git a/servers/rendering/rasterizer_rd/shaders/cubemap_roughness.glsl b/servers/rendering/rasterizer_rd/shaders/cubemap_roughness.glsl
index e85996fa1a..5cbb00baa4 100644
--- a/servers/rendering/rasterizer_rd/shaders/cubemap_roughness.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/cubemap_roughness.glsl
@@ -1,5 +1,4 @@
-/* clang-format off */
-[compute]
+#[compute]
#version 450
@@ -8,7 +7,6 @@ VERSION_DEFINES
#define GROUP_SIZE 8
layout(local_size_x = GROUP_SIZE, local_size_y = GROUP_SIZE, local_size_z = 1) in;
-/* clang-format on */
layout(set = 0, binding = 0) uniform samplerCube source_cube;
@@ -119,10 +117,8 @@ void main() {
//vec4 color = color_interp;
if (params.use_direct_write) {
-
imageStore(dest_cubemap, ivec3(id), vec4(texture(source_cube, N).rgb, 1.0));
} else {
-
vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);
for (uint sampleNum = 0u; sampleNum < params.sample_count; sampleNum++) {
@@ -135,7 +131,6 @@ void main() {
float ndotl = clamp(dot(N, L), 0.0, 1.0);
if (ndotl > 0.0) {
-
sum.rgb += textureLod(source_cube, L, 0.0).rgb * ndotl;
sum.a += ndotl;
}
diff --git a/servers/rendering/rasterizer_rd/shaders/giprobe.glsl b/servers/rendering/rasterizer_rd/shaders/giprobe.glsl
index fd09f96a57..ea4237a45e 100644
--- a/servers/rendering/rasterizer_rd/shaders/giprobe.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/giprobe.glsl
@@ -1,5 +1,4 @@
-/* clang-format off */
-[compute]
+#[compute]
#version 450
@@ -10,7 +9,6 @@ layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
#else
layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
#endif
-/* clang-format on */
#ifndef MODE_DYNAMIC
@@ -47,7 +45,6 @@ cell_data;
#if defined(MODE_COMPUTE_LIGHT) || defined(MODE_DYNAMIC_LIGHTING)
struct Light {
-
uint type;
float energy;
float radius;
@@ -191,7 +188,6 @@ layout(r16ui, set = 0, binding = 13) uniform restrict writeonly uimage3D aniso_n
#if defined(MODE_COMPUTE_LIGHT) || defined(MODE_DYNAMIC_LIGHTING)
float raymarch(float distance, float distance_adv, vec3 from, vec3 direction) {
-
vec3 cell_size = 1.0 / vec3(params.limits);
float occlusion = 1.0;
while (distance > 0.5) { //use this to avoid precision errors
@@ -213,14 +209,11 @@ float raymarch(float distance, float distance_adv, vec3 from, vec3 direction) {
}
bool compute_light_vector(uint light, vec3 pos, out float attenuation, out vec3 light_pos) {
-
if (lights.data[light].type == LIGHT_TYPE_DIRECTIONAL) {
-
light_pos = pos - lights.data[light].direction * length(vec3(params.limits));
attenuation = 1.0;
} else {
-
light_pos = lights.data[light].position;
float distance = length(pos - light_pos);
if (distance >= lights.data[light].radius) {
@@ -230,7 +223,6 @@ bool compute_light_vector(uint light, vec3 pos, out float attenuation, out vec3
attenuation = pow(clamp(1.0 - distance / lights.data[light].radius, 0.0001, 1.0), lights.data[light].attenuation);
if (lights.data[light].type == LIGHT_TYPE_SPOT) {
-
vec3 rel = normalize(pos - light_pos);
float angle = acos(dot(rel, lights.data[light].direction));
if (angle > lights.data[light].spot_angle_radians) {
@@ -246,7 +238,6 @@ bool compute_light_vector(uint light, vec3 pos, out float attenuation, out vec3
}
float get_normal_advance(vec3 p_normal) {
-
vec3 normal = p_normal;
vec3 unorm = abs(normal);
@@ -269,7 +260,6 @@ float get_normal_advance(vec3 p_normal) {
}
void clip_segment(vec4 plane, vec3 begin, inout vec3 end) {
-
vec3 segment = begin - end;
float den = dot(plane.xyz, segment);
@@ -302,7 +292,6 @@ bool compute_light_at_pos(uint index, vec3 pos, vec3 normal, inout vec3 light, i
}
if (lights.data[index].has_shadow) {
-
float distance_adv = get_normal_advance(light_dir);
vec3 to = pos;
@@ -352,7 +341,6 @@ bool compute_light_at_pos(uint index, vec3 pos, vec3 normal, inout vec3 light, i
#endif // MODE COMPUTE LIGHT
void main() {
-
#ifndef MODE_DYNAMIC
uint cell_index = gl_GlobalInvocationID.x;
@@ -383,7 +371,6 @@ void main() {
#endif
for (uint i = 0; i < params.light_count; i++) {
-
vec3 light;
vec3 light_dir;
if (!compute_light_at_pos(i, pos, normal.xyz, light, light_dir)) {
@@ -394,7 +381,6 @@ void main() {
#ifdef MODE_ANISOTROPIC
for (uint j = 0; j < 6; j++) {
-
accum[j] += max(0.0, dot(accum_dirs[j], -light_dir)) * light;
}
#else
@@ -461,7 +447,6 @@ void main() {
#endif
if (length(normal.xyz) > 0.2) {
-
vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);
vec3 tangent = normalize(cross(v0, normal.xyz));
vec3 bitangent = normalize(cross(tangent, normal.xyz));
@@ -481,11 +466,9 @@ void main() {
float tan_half_angle = 0.577;
for (int i = 0; i < MAX_CONE_DIRS; i++) {
-
vec3 direction = normal_mat * cone_dirs[i];
vec4 color = vec4(0.0);
{
-
float dist = 1.5;
float max_distance = length(vec3(params.limits));
vec3 cell_size = 1.0 / vec3(params.limits);
@@ -519,7 +502,6 @@ void main() {
color *= cone_weights[i] * vec4(albedo.rgb, 1.0) * params.dynamic_range; //restore range
#ifdef MODE_ANISOTROPIC
for (uint j = 0; j < 6; j++) {
-
accum[j] += max(0.0, dot(accum_dirs[j], direction)) * color.rgb;
}
#else
@@ -594,7 +576,6 @@ void main() {
#ifdef MODE_WRITE_TEXTURE
{
-
#ifdef MODE_ANISOTROPIC
vec3 accum_total = vec3(0.0);
accum_total += outputs.data[cell_index * 6 + 0].rgb;
@@ -665,7 +646,6 @@ void main() {
vec3 accum = vec3(0.0);
for (uint i = 0; i < params.light_count; i++) {
-
vec3 light;
vec3 light_dir;
if (!compute_light_at_pos(i, vec3(pos) * params.pos_multiplier, normal, light, light_dir)) {
diff --git a/servers/rendering/rasterizer_rd/shaders/giprobe_debug.glsl b/servers/rendering/rasterizer_rd/shaders/giprobe_debug.glsl
index b1784e7eee..515cc35507 100644
--- a/servers/rendering/rasterizer_rd/shaders/giprobe_debug.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/giprobe_debug.glsl
@@ -1,5 +1,4 @@
-/* clang-format off */
-[vertex]
+#[vertex]
#version 450
@@ -11,7 +10,6 @@ struct CellData {
uint emission; //rgb normalized with e as multiplier
uint normal; //RGB normal encoded
};
-/* clang-format on */
layout(set = 0, binding = 1, std140) buffer CellDataBuffer {
CellData data[];
@@ -28,7 +26,6 @@ layout(set = 0, binding = 5) uniform texture3D aniso_neg_tex;
#endif
layout(push_constant, binding = 0, std430) uniform Params {
-
mat4 projection;
uint cell_offset;
float dynamic_range;
@@ -42,7 +39,6 @@ params;
layout(location = 0) out vec4 color_interp;
void main() {
-
const vec3 cube_triangles[36] = vec3[](
vec3(-1.0f, -1.0f, -1.0f),
vec3(-1.0f, -1.0f, 1.0f),
@@ -130,12 +126,24 @@ void main() {
float strength = 0.0;
switch (side) {
- case POS_X: strength = aniso_pos.x; break;
- case POS_Y: strength = aniso_pos.y; break;
- case POS_Z: strength = aniso_pos.z; break;
- case NEG_X: strength = aniso_neg.x; break;
- case NEG_Y: strength = aniso_neg.y; break;
- case NEG_Z: strength = aniso_neg.z; break;
+ case POS_X:
+ strength = aniso_pos.x;
+ break;
+ case POS_Y:
+ strength = aniso_pos.y;
+ break;
+ case POS_Z:
+ strength = aniso_pos.z;
+ break;
+ case NEG_X:
+ strength = aniso_neg.x;
+ break;
+ case NEG_Y:
+ strength = aniso_neg.y;
+ break;
+ case NEG_Z:
+ strength = aniso_neg.z;
+ break;
}
color_interp.xyz *= strength;
@@ -160,19 +168,16 @@ void main() {
#endif
}
-/* clang-format off */
-[fragment]
+#[fragment]
#version 450
VERSION_DEFINES
layout(location = 0) in vec4 color_interp;
-/* clang-format on */
layout(location = 0) out vec4 frag_color;
void main() {
-
frag_color = color_interp;
#ifdef MODE_DEBUG_LIGHT_FULL
@@ -184,22 +189,38 @@ void main() {
int index = x + y * 4;
float limit = 0.0;
if (x < 8) {
- if (index == 0) limit = 0.0625;
- if (index == 1) limit = 0.5625;
- if (index == 2) limit = 0.1875;
- if (index == 3) limit = 0.6875;
- if (index == 4) limit = 0.8125;
- if (index == 5) limit = 0.3125;
- if (index == 6) limit = 0.9375;
- if (index == 7) limit = 0.4375;
- if (index == 8) limit = 0.25;
- if (index == 9) limit = 0.75;
- if (index == 10) limit = 0.125;
- if (index == 11) limit = 0.625;
- if (index == 12) limit = 1.0;
- if (index == 13) limit = 0.5;
- if (index == 14) limit = 0.875;
- if (index == 15) limit = 0.375;
+ if (index == 0)
+ limit = 0.0625;
+ if (index == 1)
+ limit = 0.5625;
+ if (index == 2)
+ limit = 0.1875;
+ if (index == 3)
+ limit = 0.6875;
+ if (index == 4)
+ limit = 0.8125;
+ if (index == 5)
+ limit = 0.3125;
+ if (index == 6)
+ limit = 0.9375;
+ if (index == 7)
+ limit = 0.4375;
+ if (index == 8)
+ limit = 0.25;
+ if (index == 9)
+ limit = 0.75;
+ if (index == 10)
+ limit = 0.125;
+ if (index == 11)
+ limit = 0.625;
+ if (index == 12)
+ limit = 1.0;
+ if (index == 13)
+ limit = 0.5;
+ if (index == 14)
+ limit = 0.875;
+ if (index == 15)
+ limit = 0.375;
}
if (frag_color.a < limit) {
discard;
diff --git a/servers/rendering/rasterizer_rd/shaders/giprobe_sdf.glsl b/servers/rendering/rasterizer_rd/shaders/giprobe_sdf.glsl
index d089236723..5b3dec0ee7 100644
--- a/servers/rendering/rasterizer_rd/shaders/giprobe_sdf.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/giprobe_sdf.glsl
@@ -1,12 +1,10 @@
-/* clang-format off */
-[compute]
+#[compute]
#version 450
VERSION_DEFINES
layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in;
-/* clang-format on */
#define MAX_DISTANCE 100000
@@ -45,7 +43,6 @@ layout(push_constant, binding = 0, std430) uniform Params {
params;
void main() {
-
vec3 pos = vec3(gl_GlobalInvocationID);
float closest_dist = 100000.0;
@@ -71,19 +68,17 @@ void main() {
#if 0
layout(push_constant, binding = 0, std430) uniform Params {
-
ivec3 limits;
uint stack_size;
-} params;
+}
+params;
float distance_to_aabb(ivec3 pos, ivec3 aabb_pos, ivec3 aabb_size) {
-
vec3 delta = vec3(max(ivec3(0), max(aabb_pos - pos, pos - (aabb_pos + aabb_size - ivec3(1)))));
return length(delta);
}
void main() {
-
ivec3 pos = ivec3(gl_GlobalInvocationID);
uint stack[10] = uint[](0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@@ -107,7 +102,6 @@ void main() {
int stack_pos = 0;
while (true) {
-
uint index = stack_indices[stack_pos] >> 24;
if (index == 8) {
diff --git a/servers/rendering/rasterizer_rd/shaders/giprobe_write.glsl b/servers/rendering/rasterizer_rd/shaders/giprobe_write.glsl
index c832223b1e..9c794f1bcc 100644
--- a/servers/rendering/rasterizer_rd/shaders/giprobe_write.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/giprobe_write.glsl
@@ -1,12 +1,10 @@
-/* clang-format off */
-[compute]
+#[compute]
#version 450
VERSION_DEFINES
layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
-/* clang-format on */
#define NO_CHILDREN 0xFFFFFFFF
#define GREY_VEC vec3(0.33333, 0.33333, 0.33333)
@@ -84,24 +82,20 @@ output;
#ifdef MODE_COMPUTE_LIGHT
uint raymarch(float distance, float distance_adv, vec3 from, vec3 direction) {
-
uint result = NO_CHILDREN;
ivec3 size = ivec3(max(max(params.limits.x, params.limits.y), params.limits.z));
while (distance > -distance_adv) { //use this to avoid precision errors
-
uint cell = 0;
ivec3 pos = ivec3(from);
if (all(greaterThanEqual(pos, ivec3(0))) && all(lessThan(pos, size))) {
-
ivec3 ofs = ivec3(0);
ivec3 half_size = size / 2;
for (int i = 0; i < params.stack_size - 1; i++) {
-
bvec3 greater = greaterThanEqual(pos, ofs + half_size);
ofs += mix(ivec3(0), half_size, greater);
@@ -118,8 +112,9 @@ uint raymarch(float distance, float distance_adv, vec3 from, vec3 direction) {
}
cell = cell_children.data[cell].children[child];
- if (cell == NO_CHILDREN)
+ if (cell == NO_CHILDREN) {
break;
+ }
half_size >>= ivec3(1);
}
@@ -137,14 +132,10 @@ uint raymarch(float distance, float distance_adv, vec3 from, vec3 direction) {
}
bool compute_light_vector(uint light, uint cell, vec3 pos, out float attenuation, out vec3 light_pos) {
-
if (lights.data[light].type == LIGHT_TYPE_DIRECTIONAL) {
-
light_pos = pos - lights.data[light].direction * length(vec3(params.limits));
attenuation = 1.0;
-
} else {
-
light_pos = lights.data[light].position;
float distance = length(pos - light_pos);
if (distance >= lights.data[light].radius) {
@@ -154,7 +145,6 @@ bool compute_light_vector(uint light, uint cell, vec3 pos, out float attenuation
attenuation = pow(clamp(1.0 - distance / lights.data[light].radius, 0.0001, 1.0), lights.data[light].attenuation);
if (lights.data[light].type == LIGHT_TYPE_SPOT) {
-
vec3 rel = normalize(pos - light_pos);
float angle = acos(dot(rel, lights.data[light].direction));
if (angle > lights.data[light].spot_angle_radians) {
@@ -170,7 +160,6 @@ bool compute_light_vector(uint light, uint cell, vec3 pos, out float attenuation
}
float get_normal_advance(vec3 p_normal) {
-
vec3 normal = p_normal;
vec3 unorm = abs(normal);
@@ -195,7 +184,6 @@ float get_normal_advance(vec3 p_normal) {
#endif
void main() {
-
uint cell_index = gl_GlobalInvocationID.x;
if (cell_index >= params.cell_count) {
return;
@@ -220,7 +208,6 @@ void main() {
#endif
for (uint i = 0; i < params.light_count; i++) {
-
float attenuation;
vec3 light_pos;
@@ -237,7 +224,6 @@ void main() {
}
if (lights.data[i].has_shadow) {
-
float distance_adv = get_normal_advance(light_dir);
distance += distance_adv - mod(distance, distance_adv); //make it reach the center of the box always
diff --git a/servers/rendering/rasterizer_rd/shaders/luminance_reduce.glsl b/servers/rendering/rasterizer_rd/shaders/luminance_reduce.glsl
index 4bf5b7e7f1..8a11c35b78 100644
--- a/servers/rendering/rasterizer_rd/shaders/luminance_reduce.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/luminance_reduce.glsl
@@ -1,5 +1,4 @@
-/* clang-format off */
-[compute]
+#[compute]
#version 450
@@ -8,7 +7,6 @@ VERSION_DEFINES
#define BLOCK_SIZE 8
layout(local_size_x = BLOCK_SIZE, local_size_y = BLOCK_SIZE, local_size_z = 1) in;
-/* clang-format on */
shared float tmp_data[BLOCK_SIZE * BLOCK_SIZE];
@@ -40,12 +38,10 @@ layout(push_constant, binding = 1, std430) uniform Params {
params;
void main() {
-
uint t = gl_LocalInvocationID.y * BLOCK_SIZE + gl_LocalInvocationID.x;
ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
if (any(lessThan(pos, params.source_size))) {
-
#ifdef READ_TEXTURE
vec3 v = texelFetch(source_texture, pos, 0).rgb;
tmp_data[t] = max(v.r, max(v.g, v.b));
@@ -69,7 +65,6 @@ void main() {
barrier();
size >>= 1;
-
} while (size >= 1);
if (t == 0) {
diff --git a/servers/rendering/rasterizer_rd/shaders/roughness_limiter.glsl b/servers/rendering/rasterizer_rd/shaders/roughness_limiter.glsl
index 3637b1abb2..464895928a 100644
--- a/servers/rendering/rasterizer_rd/shaders/roughness_limiter.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/roughness_limiter.glsl
@@ -1,12 +1,10 @@
-/* clang-format off */
-[compute]
+#[compute]
#version 450
VERSION_DEFINES
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
-/* clang-format on */
layout(set = 0, binding = 0) uniform sampler2D source_normal;
layout(r8, set = 1, binding = 0) uniform restrict writeonly image2D dest_roughness;
@@ -21,7 +19,6 @@ params;
#define HALF_PI 1.5707963267948966
void main() {
-
// Pixel being shaded
ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
if (any(greaterThan(pos, params.screen_size))) { //too large, do nothing
@@ -53,14 +50,14 @@ void main() {
float kappa = (3.0f * r - r * r2) / (1.0f - r2);
float variance = 0.25f / kappa;
limit = sqrt(min(2.0f * variance, threshold * threshold));
-//*/
+ */
/*
//Formula based on probability distribution graph
float width = acos(max(0.0,r)); // convert to angle (width)
float roughness = pow(width,1.7)*0.854492; //approximate (crappy) formula to convert to roughness
limit = min(sqrt(roughness), threshold); //convert to perceptual roughness and apply threshold
-//*/
+ */
limit = min(sqrt(pow(acos(max(0.0, r)) / HALF_PI, params.curve)), threshold); //convert to perceptual roughness and apply threshold
diff --git a/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl b/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl
index 07f4770b14..9f42b0f814 100644
--- a/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl
@@ -1,5 +1,4 @@
-/* clang-format off */
-[vertex]
+#[vertex]
#version 450
@@ -10,7 +9,6 @@ VERSION_DEFINES
/* INPUT ATTRIBS */
layout(location = 0) in vec3 vertex_attrib;
-/* clang-format on */
layout(location = 1) in vec3 normal_attrib;
#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED)
layout(location = 2) in vec4 tangent_attrib;
@@ -20,11 +18,9 @@ layout(location = 2) in vec4 tangent_attrib;
layout(location = 3) in vec4 color_attrib;
#endif
-#if defined(UV_USED)
layout(location = 4) in vec2 uv_attrib;
-#endif
-#if defined(UV2_USED) || defined(USE_LIGHTMAP)
+#if defined(UV2_USED) || defined(USE_LIGHTMAP) || defined(MODE_RENDER_MATERIAL)
layout(location = 5) in vec2 uv2_attrib;
#endif
@@ -39,9 +35,7 @@ layout(location = 1) out vec3 normal_interp;
layout(location = 2) out vec4 color_interp;
#endif
-#if defined(UV_USED)
layout(location = 3) out vec2 uv_interp;
-#endif
#if defined(UV2_USED) || defined(USE_LIGHTMAP)
layout(location = 4) out vec2 uv2_interp;
@@ -53,7 +47,7 @@ layout(location = 6) out vec3 binormal_interp;
#endif
#ifdef USE_MATERIAL_UNIFORMS
-layout(set = 5, binding = 0, std140) uniform MaterialUniforms{
+layout(set = MATERIAL_UNIFORM_SET, binding = 0, std140) uniform MaterialUniforms{
/* clang-format off */
MATERIAL_UNIFORMS
/* clang-format on */
@@ -66,8 +60,6 @@ VERTEX_SHADER_GLOBALS
/* clang-format on */
-// FIXME: This triggers a Mesa bug that breaks rendering, so disabled for now.
-// See GH-13450 and https://bugs.freedesktop.org/show_bug.cgi?id=100316
invariant gl_Position;
layout(location = 7) flat out uint instance_index;
@@ -79,7 +71,6 @@ layout(location = 8) out float dp_clip;
#endif
void main() {
-
instance_index = draw_call.instance_index;
vec4 instance_custom = vec4(0.0);
#if defined(COLOR_USED)
@@ -157,9 +148,7 @@ void main() {
#endif
}
-#if defined(UV_USED)
uv_interp = uv_attrib;
-#endif
#if defined(UV2_USED) || defined(USE_LIGHTMAP)
uv2_interp = uv2_attrib;
@@ -244,19 +233,13 @@ VERTEX_SHADER_CODE
//for dual paraboloid shadow mapping, this is the fastest but least correct way, as it curves straight edges
- vec3 vtx = vertex_interp + normalize(vertex_interp) * scene_data.z_offset;
+ vec3 vtx = vertex_interp;
float distance = length(vtx);
vtx = normalize(vtx);
vtx.xy /= 1.0 - vtx.z;
vtx.z = (distance / scene_data.z_far);
vtx.z = vtx.z * 2.0 - 1.0;
-
vertex_interp = vtx;
-#else
-
- float z_ofs = scene_data.z_offset;
- z_ofs += max(0.0, 1.0 - abs(normalize(normal_interp).z)) * scene_data.z_slope_scale;
- vertex_interp.z -= z_ofs;
#endif
@@ -267,10 +250,25 @@ VERTEX_SHADER_CODE
#else
gl_Position = projection_matrix * vec4(vertex_interp, 1.0);
#endif
+
+#ifdef MODE_RENDER_DEPTH
+ if (scene_data.pancake_shadows) {
+ if (gl_Position.z <= 0.00001) {
+ gl_Position.z = 0.00001;
+ }
+ }
+#endif
+
+#ifdef MODE_RENDER_MATERIAL
+ if (scene_data.material_uv2_mode) {
+ gl_Position.xy = (uv2_attrib.xy + draw_call.bake_uv2_offset) * 2.0 - 1.0;
+ gl_Position.z = 0.00001;
+ gl_Position.w = 1.0;
+ }
+#endif
}
-/* clang-format off */
-[fragment]
+#[fragment]
#version 450
@@ -281,16 +279,13 @@ VERSION_DEFINES
/* Varyings */
layout(location = 0) in vec3 vertex_interp;
-/* clang-format on */
layout(location = 1) in vec3 normal_interp;
#if defined(COLOR_USED)
layout(location = 2) in vec4 color_interp;
#endif
-#if defined(UV_USED)
layout(location = 3) in vec2 uv_interp;
-#endif
#if defined(UV2_USED) || defined(USE_LIGHTMAP)
layout(location = 4) in vec2 uv2_interp;
@@ -315,8 +310,13 @@ layout(location = 8) in float dp_clip;
#define world_normal_matrix instances.data[instance_index].normal_transform
#define projection_matrix scene_data.projection_matrix
+#if defined(ENABLE_SSS) && defined(ENABLE_TRANSMITTANCE)
+//both required for transmittance to be enabled
+#define LIGHT_TRANSMITTANCE_USED
+#endif
+
#ifdef USE_MATERIAL_UNIFORMS
-layout(set = 5, binding = 0, std140) uniform MaterialUniforms{
+layout(set = MATERIAL_UNIFORM_SET, binding = 0, std140) uniform MaterialUniforms{
/* clang-format off */
MATERIAL_UNIFORMS
/* clang-format on */
@@ -421,7 +421,8 @@ float SchlickFresnel(float u) {
}
float GTR1(float NdotH, float a) {
- if (a >= 1.0) return 1.0 / M_PI;
+ if (a >= 1.0)
+ return 1.0 / M_PI;
float a2 = a * a;
float t = 1.0 + (a2 - 1.0) * NdotH * NdotH;
return (a2 - 1.0) / (M_PI * log(a2) * t);
@@ -434,9 +435,16 @@ vec3 F0(float metallic, float specular, vec3 albedo) {
return mix(vec3(dielectric), albedo, vec3(metallic));
}
-void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, vec3 attenuation, vec3 diffuse_color, float roughness, float metallic, float specular, float specular_blob_intensity,
-#ifdef LIGHT_TRANSMISSION_USED
- vec3 transmission,
+void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float attenuation, vec3 shadow_attenuation, vec3 diffuse_color, float roughness, float metallic, float specular, float specular_blob_intensity,
+#ifdef LIGHT_BACKLIGHT_USED
+ vec3 backlight,
+#endif
+#ifdef LIGHT_TRANSMITTANCE_USED
+ vec4 transmittance_color,
+ float transmittance_depth,
+ float transmittance_curve,
+ float transmittance_boost,
+ float transmittance_z,
#endif
#ifdef LIGHT_RIM_USED
float rim, float rim_tint,
@@ -467,7 +475,7 @@ LIGHT_SHADER_CODE
/* clang-format on */
#else
- float NdotL = dot(N, L);
+ float NdotL = min(A + dot(N, L), 1.0);
float cNdotL = max(NdotL, 0.0); // clamped NdotL
float NdotV = dot(N, V);
float cNdotV = max(NdotV, 0.0);
@@ -477,11 +485,11 @@ LIGHT_SHADER_CODE
#endif
#if defined(SPECULAR_BLINN) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_CLEARCOAT_USED)
- float cNdotH = max(dot(N, H), 0.0);
+ float cNdotH = clamp(A + dot(N, H), 0.0, 1.0);
#endif
#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_CLEARCOAT_USED)
- float cLdotH = max(dot(L, H), 0.0);
+ float cLdotH = clamp(A + dot(L, H), 0.0, 1.0);
#endif
if (metallic < 1.0) {
@@ -538,16 +546,48 @@ LIGHT_SHADER_CODE
diffuse_brdf_NL = cNdotL * (1.0 / M_PI);
#endif
- diffuse_light += light_color * diffuse_color * diffuse_brdf_NL * attenuation;
+ diffuse_light += light_color * diffuse_color * shadow_attenuation * diffuse_brdf_NL * attenuation;
-#if defined(LIGHT_TRANSMISSION_USED)
- diffuse_light += light_color * diffuse_color * (vec3(1.0 / M_PI) - diffuse_brdf_NL) * transmission * attenuation;
+#if defined(LIGHT_BACKLIGHT_USED)
+ diffuse_light += light_color * diffuse_color * (vec3(1.0 / M_PI) - diffuse_brdf_NL) * backlight * attenuation;
#endif
#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), diffuse_color, rim_tint) * light_color;
#endif
+
+#ifdef LIGHT_TRANSMITTANCE_USED
+
+#ifdef SSS_MODE_SKIN
+
+ {
+ float scale = 8.25 / transmittance_depth;
+ 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);
+
+ diffuse_light += profile * transmittance_color.a * diffuse_color * light_color * clamp(transmittance_boost - NdotL, 0.0, 1.0) * (1.0 / M_PI) * attenuation;
+ }
+#else
+
+ if (transmittance_depth > 0.0) {
+ float fade = clamp(abs(transmittance_z / transmittance_depth), 0.0, 1.0);
+
+ fade = pow(max(0.0, 1.0 - fade), transmittance_curve);
+ fade *= clamp(transmittance_boost - NdotL, 0.0, 1.0);
+
+ diffuse_light += diffuse_color * transmittance_color.rgb * light_color * (1.0 / M_PI) * transmittance_color.a * fade * attenuation;
+ }
+
+#endif //SSS_MODE_SKIN
+
+#endif //LIGHT_TRANSMITTANCE_USED
}
if (roughness > 0.0) { // FIXME: roughness == 0 should not disable specular light entirely
@@ -562,18 +602,18 @@ LIGHT_SHADER_CODE
blinn *= (shininess + 8.0) * (1.0 / (8.0 * M_PI));
float intensity = blinn;
- specular_light += light_color * intensity * specular_blob_intensity * attenuation;
+ specular_light += light_color * shadow_attenuation * intensity * specular_blob_intensity * attenuation;
#elif defined(SPECULAR_PHONG)
vec3 R = normalize(-reflect(L, N));
- float cRdotV = max(0.0, dot(R, V));
+ float cRdotV = clamp(A + dot(R, V), 0.0, 1.0);
float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25;
float phong = pow(cRdotV, shininess);
phong *= (shininess + 8.0) * (1.0 / (8.0 * M_PI));
float intensity = (phong) / max(4.0 * cNdotV * cNdotL, 0.75);
- specular_light += light_color * intensity * specular_blob_intensity * attenuation;
+ specular_light += light_color * shadow_attenuation * intensity * specular_blob_intensity * attenuation;
#elif defined(SPECULAR_TOON)
@@ -582,7 +622,7 @@ LIGHT_SHADER_CODE
float mid = 1.0 - roughness;
mid *= mid;
float intensity = smoothstep(mid - roughness * 0.5, mid + roughness * 0.5, RdotV) * mid;
- diffuse_light += light_color * intensity * specular_blob_intensity * attenuation; // write to diffuse_light, as in toon shading you generally want no reflection
+ diffuse_light += light_color * shadow_attenuation * intensity * specular_blob_intensity * attenuation; // write to diffuse_light, as in toon shading you generally want no reflection
#elif defined(SPECULAR_DISABLED)
// none..
@@ -613,7 +653,7 @@ LIGHT_SHADER_CODE
vec3 specular_brdf_NL = cNdotL * D * F * G;
- specular_light += specular_brdf_NL * light_color * specular_blob_intensity * attenuation;
+ specular_light += specular_brdf_NL * light_color * shadow_attenuation * specular_blob_intensity * attenuation;
#endif
#if defined(LIGHT_CLEARCOAT_USED)
@@ -627,12 +667,12 @@ LIGHT_SHADER_CODE
float clearcoat_specular_brdf_NL = 0.25 * clearcoat * Gr * Fr * Dr * cNdotL;
- specular_light += clearcoat_specular_brdf_NL * light_color * specular_blob_intensity * attenuation;
+ specular_light += clearcoat_specular_brdf_NL * light_color * shadow_attenuation * specular_blob_intensity * attenuation;
#endif
}
#ifdef USE_SHADOW_TO_OPACITY
- alpha = min(alpha, clamp(1.0 - length(attenuation), 0.0, 1.0));
+ alpha = min(alpha, clamp(1.0 - length(shadow_attenuation * attenuation), 0.0, 1.0));
#endif
#endif //defined(USE_LIGHT_SHADER_CODE)
@@ -640,53 +680,116 @@ LIGHT_SHADER_CODE
#ifndef USE_NO_SHADOWS
-float sample_shadow(texture2D shadow, vec2 shadow_pixel_size, vec4 coord) {
+// Produces cheap but low-quality white noise, nothing special
+float quick_hash(vec2 pos) {
+ return fract(sin(dot(pos * 19.19, vec2(49.5791, 97.413))) * 49831.189237);
+}
- //todo optimize
+float sample_directional_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec4 coord) {
vec2 pos = coord.xy;
float depth = coord.z;
-#ifdef SHADOW_MODE_PCF_13
+ //if only one sample is taken, take it from the center
+ if (scene_data.directional_soft_shadow_samples == 1) {
+ return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
+ }
- float avg = textureProj(shadow, vec4(pos, depth, 1.0));
- avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, 0.0), depth, 1.0));
- avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, 0.0), depth, 1.0));
- avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y), depth, 1.0));
- avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y), depth, 1.0));
- avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, shadow_pixel_size.y), depth, 1.0));
- avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, shadow_pixel_size.y), depth, 1.0));
- avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, -shadow_pixel_size.y), depth, 1.0));
- avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, -shadow_pixel_size.y), depth, 1.0));
- avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x * 2.0, 0.0), depth, 1.0));
- avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x * 2.0, 0.0), depth, 1.0));
- avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y * 2.0), depth, 1.0));
- avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y * 2.0), depth, 1.0));
- return avg * (1.0 / 13.0);
-#endif
+ mat2 disk_rotation;
+ {
+ float r = quick_hash(gl_FragCoord.xy) * 2.0 * M_PI;
+ float sr = sin(r);
+ float cr = cos(r);
+ disk_rotation = mat2(vec2(cr, -sr), vec2(sr, cr));
+ }
-#ifdef SHADOW_MODE_PCF_5
+ float avg = 0.0;
- float avg = textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
- avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, 0.0), depth, 1.0));
- avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, 0.0), depth, 1.0));
- avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y), depth, 1.0));
- avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y), depth, 1.0));
- return avg * (1.0 / 5.0);
+ for (uint i = 0; i < scene_data.directional_soft_shadow_samples; i++) {
+ avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + shadow_pixel_size * (disk_rotation * scene_data.directional_soft_shadow_kernel[i].xy), depth, 1.0));
+ }
-#endif
+ return avg * (1.0 / float(scene_data.directional_soft_shadow_samples));
+}
-#if !defined(SHADOW_MODE_PCF_5) || !defined(SHADOW_MODE_PCF_13)
+float sample_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec4 coord) {
+ vec2 pos = coord.xy;
+ float depth = coord.z;
- return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
+ //if only one sample is taken, take it from the center
+ if (scene_data.soft_shadow_samples == 1) {
+ return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
+ }
-#endif
+ mat2 disk_rotation;
+ {
+ float r = quick_hash(gl_FragCoord.xy) * 2.0 * M_PI;
+ float sr = sin(r);
+ float cr = cos(r);
+ disk_rotation = mat2(vec2(cr, -sr), vec2(sr, cr));
+ }
+
+ float avg = 0.0;
+
+ for (uint i = 0; i < scene_data.soft_shadow_samples; i++) {
+ avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + shadow_pixel_size * (disk_rotation * scene_data.soft_shadow_kernel[i].xy), depth, 1.0));
+ }
+
+ return avg * (1.0 / float(scene_data.soft_shadow_samples));
+}
+
+float sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex_scale) {
+ //find blocker
+ float blocker_count = 0.0;
+ float blocker_average = 0.0;
+
+ mat2 disk_rotation;
+ {
+ float r = quick_hash(gl_FragCoord.xy) * 2.0 * M_PI;
+ float sr = sin(r);
+ float cr = cos(r);
+ disk_rotation = mat2(vec2(cr, -sr), vec2(sr, cr));
+ }
+
+ for (uint i = 0; i < scene_data.directional_penumbra_shadow_samples; i++) {
+ vec2 suv = pssm_coord.xy + (disk_rotation * scene_data.directional_penumbra_shadow_kernel[i].xy) * tex_scale;
+ float d = textureLod(sampler2D(shadow, material_samplers[SAMPLER_LINEAR_CLAMP]), suv, 0.0).r;
+ if (d < pssm_coord.z) {
+ blocker_average += d;
+ blocker_count += 1.0;
+ }
+ }
+
+ if (blocker_count > 0.0) {
+ //blockers found, do soft shadow
+ blocker_average /= blocker_count;
+ float penumbra = (pssm_coord.z - blocker_average) / blocker_average;
+ tex_scale *= penumbra;
+
+ float s = 0.0;
+ for (uint i = 0; i < scene_data.directional_penumbra_shadow_samples; i++) {
+ vec2 suv = pssm_coord.xy + (disk_rotation * scene_data.directional_penumbra_shadow_kernel[i].xy) * tex_scale;
+ s += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(suv, pssm_coord.z, 1.0));
+ }
+
+ return s / float(scene_data.directional_penumbra_shadow_samples);
+
+ } else {
+ //no blockers found, so no shadow
+ return 1.0;
+ }
}
#endif //USE_NO_SHADOWS
-void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 albedo, float roughness, float metallic, float specular, float p_blob_intensity,
-#ifdef LIGHT_TRANSMISSION_USED
- vec3 transmission,
+void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 albedo, float roughness, float metallic, float specular, float p_blob_intensity,
+#ifdef LIGHT_BACKLIGHT_USED
+ vec3 backlight,
+#endif
+#ifdef LIGHT_TRANSMITTANCE_USED
+ vec4 transmittance_color,
+ float transmittance_depth,
+ float transmittance_curve,
+ float transmittance_boost,
#endif
#ifdef LIGHT_RIM_USED
float rim, float rim_tint,
@@ -707,45 +810,249 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
float normalized_distance = light_length * lights.data[idx].inv_radius;
vec2 attenuation_energy = unpackHalf2x16(lights.data[idx].attenuation_energy);
float omni_attenuation = pow(max(1.0 - normalized_distance, 0.0), attenuation_energy.x);
- vec3 light_attenuation = vec3(omni_attenuation);
+ float light_attenuation = omni_attenuation;
+ vec3 shadow_attenuation = vec3(1.0);
vec4 color_specular = unpackUnorm4x8(lights.data[idx].color_specular);
color_specular.rgb *= attenuation_energy.y;
+ float size_A = 0.0;
+
+ if (lights.data[idx].size > 0.0) {
+ float t = lights.data[idx].size / max(0.001, light_length);
+ size_A = max(0.0, 1.0 - 1 / sqrt(1 + t * t));
+ }
+
+#ifdef LIGHT_TRANSMITTANCE_USED
+ float transmittance_z = transmittance_depth; //no transmittance by default
+#endif
#ifndef USE_NO_SHADOWS
vec4 shadow_color_enabled = unpackUnorm4x8(lights.data[idx].shadow_color_enabled);
if (shadow_color_enabled.w > 0.5) {
// there is a shadowmap
- vec4 splane = (lights.data[idx].shadow_matrix * vec4(vertex, 1.0));
- float shadow_len = length(splane);
- splane = normalize(splane);
- vec4 clamp_rect = lights.data[idx].atlas_rect;
+ vec4 v = vec4(vertex, 1.0);
+
+ vec4 splane = (lights.data[idx].shadow_matrix * v);
+ float shadow_len = length(splane.xyz); //need to remember shadow len from here
+
+ {
+ vec3 nofs = normal_interp * lights.data[idx].shadow_normal_bias / lights.data[idx].inv_radius;
+ nofs *= (1.0 - max(0.0, dot(normalize(light_rel_vec), normalize(normal_interp))));
+ v.xyz += nofs;
+ splane = (lights.data[idx].shadow_matrix * v);
+ }
+
+ float shadow;
- if (splane.z >= 0.0) {
+ if (lights.data[idx].soft_shadow_size > 0.0) {
+ //soft shadow
- splane.z += 1.0;
+ //find blocker
- clamp_rect.y += clamp_rect.w;
+ float blocker_count = 0.0;
+ float blocker_average = 0.0;
+ mat2 disk_rotation;
+ {
+ float r = quick_hash(gl_FragCoord.xy) * 2.0 * M_PI;
+ float sr = sin(r);
+ float cr = cos(r);
+ disk_rotation = mat2(vec2(cr, -sr), vec2(sr, cr));
+ }
+
+ vec3 normal = normalize(splane.xyz);
+ vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);
+ vec3 tangent = normalize(cross(v0, normal));
+ vec3 bitangent = normalize(cross(tangent, normal));
+ float z_norm = shadow_len * lights.data[idx].inv_radius;
+
+ tangent *= lights.data[idx].soft_shadow_size * lights.data[idx].soft_shadow_scale;
+ bitangent *= lights.data[idx].soft_shadow_size * lights.data[idx].soft_shadow_scale;
+
+ for (uint i = 0; i < scene_data.penumbra_shadow_samples; i++) {
+ vec2 disk = disk_rotation * scene_data.penumbra_shadow_kernel[i].xy;
+
+ vec3 pos = splane.xyz + tangent * disk.x + bitangent * disk.y;
+
+ pos = normalize(pos);
+ vec4 uv_rect = lights.data[idx].atlas_rect;
+
+ if (pos.z >= 0.0) {
+ pos.z += 1.0;
+ uv_rect.y += uv_rect.w;
+ } else {
+ pos.z = 1.0 - pos.z;
+ }
+
+ pos.xy /= pos.z;
+
+ pos.xy = pos.xy * 0.5 + 0.5;
+ pos.xy = uv_rect.xy + pos.xy * uv_rect.zw;
+
+ float d = textureLod(sampler2D(shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), pos.xy, 0.0).r;
+ if (d < z_norm) {
+ blocker_average += d;
+ blocker_count += 1.0;
+ }
+ }
+
+ if (blocker_count > 0.0) {
+ //blockers found, do soft shadow
+ blocker_average /= blocker_count;
+ float penumbra = (z_norm - blocker_average) / blocker_average;
+ tangent *= penumbra;
+ bitangent *= penumbra;
+
+ z_norm -= lights.data[idx].inv_radius * lights.data[idx].shadow_bias;
+
+ shadow = 0.0;
+ for (uint i = 0; i < scene_data.penumbra_shadow_samples; i++) {
+ vec2 disk = disk_rotation * scene_data.penumbra_shadow_kernel[i].xy;
+ vec3 pos = splane.xyz + tangent * disk.x + bitangent * disk.y;
+
+ pos = normalize(pos);
+ vec4 uv_rect = lights.data[idx].atlas_rect;
+
+ if (pos.z >= 0.0) {
+ pos.z += 1.0;
+ uv_rect.y += uv_rect.w;
+ } else {
+ pos.z = 1.0 - pos.z;
+ }
+
+ pos.xy /= pos.z;
+
+ pos.xy = pos.xy * 0.5 + 0.5;
+ pos.xy = uv_rect.xy + pos.xy * uv_rect.zw;
+ shadow += textureProj(sampler2DShadow(shadow_atlas, shadow_sampler), vec4(pos.xy, z_norm, 1.0));
+ }
+
+ shadow /= float(scene_data.penumbra_shadow_samples);
+
+ } else {
+ //no blockers found, so no shadow
+ shadow = 1.0;
+ }
} else {
+ splane.xyz = normalize(splane.xyz);
+ vec4 clamp_rect = lights.data[idx].atlas_rect;
- splane.z = 1.0 - splane.z;
+ if (splane.z >= 0.0) {
+ splane.z += 1.0;
+
+ 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 - lights.data[idx].shadow_bias) * lights.data[idx].inv_radius;
+ splane.xy = clamp_rect.xy + splane.xy * clamp_rect.zw;
+ splane.w = 1.0; //needed? i think it should be 1 already
+ shadow = sample_pcf_shadow(shadow_atlas, lights.data[idx].soft_shadow_scale * scene_data.shadow_atlas_pixel_size, splane);
}
- splane.xy /= splane.z;
- splane.xy = splane.xy * 0.5 + 0.5;
- splane.z = shadow_len * lights.data[idx].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 shadow = sample_shadow(shadow_atlas, scene_data.shadow_atlas_pixel_size, splane);
+#ifdef LIGHT_TRANSMITTANCE_USED
+ {
+ vec4 clamp_rect = lights.data[idx].atlas_rect;
+
+ //redo shadowmapping, but shrink the model a bit to avoid arctifacts
+ splane = (lights.data[idx].shadow_matrix * vec4(vertex - normalize(normal_interp) * lights.data[idx].transmittance_bias, 1.0));
+
+ shadow_len = length(splane.xyz);
+ splane = normalize(splane.xyz);
- light_attenuation *= mix(shadow_color_enabled.rgb, vec3(1.0), shadow);
+ if (splane.z >= 0.0) {
+ splane.z += 1.0;
+
+ } else {
+ splane.z = 1.0 - splane.z;
+ }
+
+ splane.xy /= splane.z;
+ splane.xy = splane.xy * 0.5 + 0.5;
+ splane.z = shadow_len * lights.data[idx].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 shadow_z = textureLod(sampler2D(shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), splane.xy, 0.0).r;
+ transmittance_z = (splane.z - shadow_z) / lights.data[idx].inv_radius;
+ }
+#endif
+
+ vec3 no_shadow = vec3(1.0);
+
+ if (lights.data[idx].projector_rect != vec4(0.0)) {
+ vec3 local_v = (lights.data[idx].shadow_matrix * vec4(vertex, 1.0)).xyz;
+ local_v = normalize(local_v);
+
+ vec4 atlas_rect = lights.data[idx].projector_rect;
+
+ if (local_v.z >= 0.0) {
+ local_v.z += 1.0;
+ atlas_rect.y += atlas_rect.w;
+
+ } else {
+ local_v.z = 1.0 - local_v.z;
+ }
+
+ local_v.xy /= local_v.z;
+ local_v.xy = local_v.xy * 0.5 + 0.5;
+ vec2 proj_uv = local_v.xy * atlas_rect.zw;
+
+ vec2 proj_uv_ddx;
+ vec2 proj_uv_ddy;
+ {
+ vec3 local_v_ddx = (lights.data[idx].shadow_matrix * vec4(vertex + vertex_ddx, 1.0)).xyz;
+ local_v_ddx = normalize(local_v_ddx);
+
+ if (local_v_ddx.z >= 0.0) {
+ local_v_ddx.z += 1.0;
+ } else {
+ local_v_ddx.z = 1.0 - local_v_ddx.z;
+ }
+
+ local_v_ddx.xy /= local_v_ddx.z;
+ local_v_ddx.xy = local_v_ddx.xy * 0.5 + 0.5;
+
+ proj_uv_ddx = local_v_ddx.xy * atlas_rect.zw - proj_uv;
+
+ vec3 local_v_ddy = (lights.data[idx].shadow_matrix * vec4(vertex + vertex_ddy, 1.0)).xyz;
+ local_v_ddy = normalize(local_v_ddy);
+
+ if (local_v_ddy.z >= 0.0) {
+ local_v_ddy.z += 1.0;
+ } else {
+ local_v_ddy.z = 1.0 - local_v_ddy.z;
+ }
+
+ local_v_ddy.xy /= local_v_ddy.z;
+ local_v_ddy.xy = local_v_ddy.xy * 0.5 + 0.5;
+
+ proj_uv_ddy = local_v_ddy.xy * atlas_rect.zw - proj_uv;
+ }
+
+ vec4 proj = textureGrad(sampler2D(decal_atlas_srgb, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), proj_uv + atlas_rect.xy, proj_uv_ddx, proj_uv_ddy);
+ no_shadow = mix(no_shadow, proj.rgb, proj.a);
+ }
+
+ shadow_attenuation = mix(shadow_color_enabled.rgb, no_shadow, shadow);
}
#endif //USE_NO_SHADOWS
- light_compute(normal, normalize(light_rel_vec), eye_vec, color_specular.rgb, light_attenuation, albedo, roughness, metallic, specular, color_specular.a * p_blob_intensity,
-#ifdef LIGHT_TRANSMISSION_USED
- transmission,
+ light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color_specular.rgb, light_attenuation, shadow_attenuation, albedo, roughness, metallic, specular, color_specular.a * p_blob_intensity,
+#ifdef LIGHT_BACKLIGHT_USED
+ backlight,
+#endif
+#ifdef LIGHT_TRANSMITTANCE_USED
+ transmittance_color,
+ transmittance_depth,
+ transmittance_curve,
+ transmittance_boost,
+ transmittance_z,
#endif
#ifdef LIGHT_RIM_USED
rim * omni_attenuation, rim_tint,
@@ -763,9 +1070,15 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
specular_light);
}
-void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 albedo, float roughness, float metallic, float specular, float p_blob_intensity,
-#ifdef LIGHT_TRANSMISSION_USED
- vec3 transmission,
+void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 albedo, float roughness, float metallic, float specular, float p_blob_intensity,
+#ifdef LIGHT_BACKLIGHT_USED
+ vec3 backlight,
+#endif
+#ifdef LIGHT_TRANSMITTANCE_USED
+ vec4 transmittance_color,
+ float transmittance_depth,
+ float transmittance_curve,
+ float transmittance_boost,
#endif
#ifdef LIGHT_RIM_USED
float rim, float rim_tint,
@@ -792,31 +1105,157 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
float scos = max(dot(-normalize(light_rel_vec), spot_dir), spot_att_angle.y);
float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_att_angle.y));
spot_attenuation *= 1.0 - pow(spot_rim, spot_att_angle.x);
- vec3 light_attenuation = vec3(spot_attenuation);
+ float light_attenuation = spot_attenuation;
+ vec3 shadow_attenuation = vec3(1.0);
vec4 color_specular = unpackUnorm4x8(lights.data[idx].color_specular);
color_specular.rgb *= attenuation_energy.y;
+ float size_A = 0.0;
+
+ if (lights.data[idx].size > 0.0) {
+ float t = lights.data[idx].size / max(0.001, light_length);
+ size_A = max(0.0, 1.0 - 1 / sqrt(1 + t * t));
+ }
/*
if (lights.data[idx].atlas_rect!=vec4(0.0)) {
//use projector texture
}
*/
+#ifdef LIGHT_TRANSMITTANCE_USED
+ float transmittance_z = transmittance_depth;
+#endif
+
#ifndef USE_NO_SHADOWS
vec4 shadow_color_enabled = unpackUnorm4x8(lights.data[idx].shadow_color_enabled);
if (shadow_color_enabled.w > 0.5) {
//there is a shadowmap
- vec4 splane = (lights.data[idx].shadow_matrix * vec4(vertex, 1.0));
+ vec4 v = vec4(vertex, 1.0);
+
+ v.xyz -= spot_dir * lights.data[idx].shadow_bias;
+
+ float z_norm = dot(spot_dir, -light_rel_vec) * lights.data[idx].inv_radius;
+
+ float depth_bias_scale = 1.0 / (max(0.0001, z_norm)); //the closer to the light origin, the more you have to offset to reach 1px in the map
+ vec3 normal_bias = normalize(normal_interp) * (1.0 - max(0.0, dot(spot_dir, -normalize(normal_interp)))) * lights.data[idx].shadow_normal_bias * depth_bias_scale;
+ normal_bias -= spot_dir * dot(spot_dir, normal_bias); //only XY, no Z
+ v.xyz += normal_bias;
+
+ //adjust with bias
+ z_norm = dot(spot_dir, v.xyz - lights.data[idx].position) * lights.data[idx].inv_radius;
+
+ float shadow;
+
+ vec4 splane = (lights.data[idx].shadow_matrix * v);
splane /= splane.w;
- float shadow = sample_shadow(shadow_atlas, scene_data.shadow_atlas_pixel_size, splane);
- light_attenuation *= mix(shadow_color_enabled.rgb, vec3(1.0), shadow);
+ if (lights.data[idx].soft_shadow_size > 0.0) {
+ //soft shadow
+
+ //find blocker
+
+ vec2 shadow_uv = splane.xy * lights.data[idx].atlas_rect.zw + lights.data[idx].atlas_rect.xy;
+
+ float blocker_count = 0.0;
+ float blocker_average = 0.0;
+
+ mat2 disk_rotation;
+ {
+ float r = quick_hash(gl_FragCoord.xy) * 2.0 * M_PI;
+ float sr = sin(r);
+ float cr = cos(r);
+ disk_rotation = mat2(vec2(cr, -sr), vec2(sr, cr));
+ }
+
+ float uv_size = lights.data[idx].soft_shadow_size * z_norm * lights.data[idx].soft_shadow_scale;
+ vec2 clamp_max = lights.data[idx].atlas_rect.xy + lights.data[idx].atlas_rect.zw;
+ for (uint i = 0; i < scene_data.penumbra_shadow_samples; i++) {
+ vec2 suv = shadow_uv + (disk_rotation * scene_data.penumbra_shadow_kernel[i].xy) * uv_size;
+ suv = clamp(suv, lights.data[idx].atlas_rect.xy, clamp_max);
+ float d = textureLod(sampler2D(shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), suv, 0.0).r;
+ if (d < z_norm) {
+ blocker_average += d;
+ blocker_count += 1.0;
+ }
+ }
+
+ if (blocker_count > 0.0) {
+ //blockers found, do soft shadow
+ blocker_average /= blocker_count;
+ float penumbra = (z_norm - blocker_average) / blocker_average;
+ uv_size *= penumbra;
+
+ shadow = 0.0;
+ for (uint i = 0; i < scene_data.penumbra_shadow_samples; i++) {
+ vec2 suv = shadow_uv + (disk_rotation * scene_data.penumbra_shadow_kernel[i].xy) * uv_size;
+ suv = clamp(suv, lights.data[idx].atlas_rect.xy, clamp_max);
+ shadow += textureProj(sampler2DShadow(shadow_atlas, shadow_sampler), vec4(suv, z_norm, 1.0));
+ }
+
+ shadow /= float(scene_data.penumbra_shadow_samples);
+
+ } else {
+ //no blockers found, so no shadow
+ shadow = 1.0;
+ }
+
+ } else {
+ //hard shadow
+ vec4 shadow_uv = vec4(splane.xy * lights.data[idx].atlas_rect.zw + lights.data[idx].atlas_rect.xy, z_norm, 1.0);
+
+ shadow = sample_pcf_shadow(shadow_atlas, lights.data[idx].soft_shadow_scale * scene_data.shadow_atlas_pixel_size, shadow_uv);
+ }
+
+ vec3 no_shadow = vec3(1.0);
+
+ if (lights.data[idx].projector_rect != vec4(0.0)) {
+ splane = (lights.data[idx].shadow_matrix * vec4(vertex, 1.0));
+ splane /= splane.w;
+
+ vec2 proj_uv = splane.xy * lights.data[idx].projector_rect.zw;
+
+ //ensure we have proper mipmaps
+ vec4 splane_ddx = (lights.data[idx].shadow_matrix * vec4(vertex + vertex_ddx, 1.0));
+ splane_ddx /= splane_ddx.w;
+ vec2 proj_uv_ddx = splane_ddx.xy * lights.data[idx].projector_rect.zw - proj_uv;
+
+ vec4 splane_ddy = (lights.data[idx].shadow_matrix * vec4(vertex + vertex_ddy, 1.0));
+ splane_ddy /= splane_ddy.w;
+ vec2 proj_uv_ddy = splane_ddy.xy * lights.data[idx].projector_rect.zw - proj_uv;
+
+ vec4 proj = textureGrad(sampler2D(decal_atlas_srgb, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), proj_uv + lights.data[idx].projector_rect.xy, proj_uv_ddx, proj_uv_ddy);
+ no_shadow = mix(no_shadow, proj.rgb, proj.a);
+ }
+
+ shadow_attenuation = mix(shadow_color_enabled.rgb, no_shadow, shadow);
+
+#ifdef LIGHT_TRANSMITTANCE_USED
+ {
+ splane = (lights.data[idx].shadow_matrix * vec4(vertex - normalize(normal_interp) * lights.data[idx].transmittance_bias, 1.0));
+ splane /= splane.w;
+ splane.xy = splane.xy * lights.data[idx].atlas_rect.zw + lights.data[idx].atlas_rect.xy;
+
+ float shadow_z = textureLod(sampler2D(shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), splane.xy, 0.0).r;
+ //reconstruct depth
+ shadow_z / lights.data[idx].inv_radius;
+ //distance to light plane
+ float z = dot(spot_dir, -light_rel_vec);
+ transmittance_z = z - shadow_z;
+ }
+#endif //LIGHT_TRANSMITTANCE_USED
}
#endif //USE_NO_SHADOWS
- light_compute(normal, normalize(light_rel_vec), eye_vec, color_specular.rgb, light_attenuation, albedo, roughness, metallic, specular, color_specular.a * p_blob_intensity,
-#ifdef LIGHT_TRANSMISSION_USED
- transmission,
+ light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color_specular.rgb, light_attenuation, shadow_attenuation, albedo, roughness, metallic, specular, color_specular.a * p_blob_intensity,
+#ifdef LIGHT_BACKLIGHT_USED
+ backlight,
+#endif
+#ifdef LIGHT_TRANSMITTANCE_USED
+ transmittance_color,
+ transmittance_depth,
+ transmittance_curve,
+ transmittance_boost,
+ transmittance_z,
#endif
#ifdef LIGHT_RIM_USED
rim * spot_attenuation, rim_tint,
@@ -834,7 +1273,6 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
}
void reflection_process(uint ref_index, vec3 vertex, vec3 normal, float roughness, vec3 ambient_light, vec3 specular_light, inout vec4 ambient_accum, inout vec4 reflection_accum) {
-
vec3 box_extents = reflections.data[ref_index].box_extents;
vec3 local_pos = (reflections.data[ref_index].local_matrix * vec4(vertex, 1.0)).xyz;
@@ -901,7 +1339,6 @@ void reflection_process(uint ref_index, vec3 vertex, vec3 normal, float roughnes
ambient_out.rgb *= ambient_out.a;
ambient_accum += ambient_out;
} else {
-
vec4 ambient_out;
ambient_out.a = blend;
ambient_out.rgb = reflections.data[ref_index].ambient.rgb;
@@ -918,7 +1355,6 @@ void reflection_process(uint ref_index, vec3 vertex, vec3 normal, float roughnes
//standard voxel cone trace
vec4 voxel_cone_trace(texture3D probe, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias) {
-
float dist = p_bias;
vec4 color = vec4(0.0);
@@ -945,7 +1381,6 @@ vec4 voxel_cone_trace(texture3D probe, vec3 cell_size, vec3 pos, vec3 direction,
#ifdef GI_PROBE_USE_ANISOTROPY
vec4 voxel_cone_trace_anisotropic_45_degrees(texture3D probe, texture3D aniso_pos, texture3D aniso_neg, vec3 normal, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias) {
-
float dist = p_bias;
vec4 color = vec4(0.0);
float radius = max(0.5, tan_half_angle * dist);
@@ -977,7 +1412,6 @@ vec4 voxel_cone_trace_anisotropic_45_degrees(texture3D probe, texture3D aniso_po
#else
vec4 voxel_cone_trace_45_degrees(texture3D probe, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias) {
-
float dist = p_bias;
vec4 color = vec4(0.0);
float radius = max(0.5, tan_half_angle * dist);
@@ -1009,7 +1443,6 @@ vec4 voxel_cone_trace_45_degrees(texture3D probe, vec3 cell_size, vec3 pos, vec3
//standard voxel cone trace
vec4 voxel_cone_trace_anisotropic(texture3D probe, texture3D aniso_pos, texture3D aniso_neg, vec3 normal, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias) {
-
float dist = p_bias;
vec4 color = vec4(0.0);
@@ -1040,7 +1473,6 @@ vec4 voxel_cone_trace_anisotropic(texture3D probe, texture3D aniso_pos, texture3
#endif
void gi_probe_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3 normal_xform, float roughness, vec3 ambient, vec3 environment, inout vec4 out_spec, inout vec4 out_diff) {
-
position = (gi_probes.data[index].xform * vec4(position, 1.0)).xyz;
ref_vec = normalize((gi_probes.data[index].xform * vec4(ref_vec, 0.0)).xyz);
normal = normalize((gi_probes.data[index].xform * vec4(normal, 0.0)).xyz);
@@ -1101,7 +1533,6 @@ void gi_probe_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3
vec3 light = vec3(0.0);
for (int i = 0; i < MAX_CONE_DIRS; i++) {
-
vec3 dir = normalize((gi_probes.data[index].xform * vec4(normal_xform * cone_dirs[i], 0.0)).xyz);
#if defined(GI_PROBE_HIGH_QUALITY) || defined(GI_PROBE_LOW_QUALITY)
@@ -1133,7 +1564,6 @@ void gi_probe_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3
light *= gi_probes.data[index].dynamic_range;
if (gi_probes.data[index].ambient_occlusion > 0.001) {
-
float size = 1.0 + gi_probes.data[index].ambient_occlusion_size * 7.0;
float taps, blend;
@@ -1174,7 +1604,6 @@ void gi_probe_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3
#endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
void main() {
-
#ifdef MODE_DUAL_PARABOLOID
if (dp_clip > 0.0)
@@ -1185,7 +1614,11 @@ void main() {
vec3 vertex = vertex_interp;
vec3 view = -normalize(vertex_interp);
vec3 albedo = vec3(1.0);
- vec3 transmission = vec3(0.0);
+ vec3 backlight = vec3(0.0);
+ vec4 transmittance_color = vec4(0.0);
+ float transmittance_depth = 0.0;
+ float transmittance_curve = 1.0;
+ float transmittance_boost = 0.0;
float metallic = 0.0;
float specular = 0.5;
vec3 emission = vec3(0.0);
@@ -1223,9 +1656,7 @@ void main() {
}
#endif
-#if defined(UV_USED)
vec2 uv = uv_interp;
-#endif
#if defined(UV2_USED) || defined(USE_LIGHTMAP)
vec2 uv2 = uv2_interp;
@@ -1254,6 +1685,14 @@ FRAGMENT_SHADER_CODE
/* clang-format on */
}
+#if defined(LIGHT_TRANSMITTANCE_USED)
+#ifdef SSS_MODE_SKIN
+ transmittance_color.a = sss_strength;
+#else
+ transmittance_color.a *= sss_strength;
+#endif
+#endif
+
#if !defined(USE_SHADOW_TO_OPACITY)
#if defined(ALPHA_SCISSOR_USED)
@@ -1299,7 +1738,78 @@ FRAGMENT_SHADER_CODE
discard;
}
#endif
+ /////////////////////// DECALS ////////////////////////////////
+
+#ifndef MODE_RENDER_DEPTH
+
+ uvec4 cluster_cell = texture(usampler3D(cluster_texture, material_samplers[SAMPLER_NEAREST_CLAMP]), vec3(screen_uv, (abs(vertex.z) - scene_data.z_near) / (scene_data.z_far - scene_data.z_near)));
+ //used for interpolating anything cluster related
+ vec3 vertex_ddx = dFdx(vertex);
+ vec3 vertex_ddy = dFdy(vertex);
+
+ { // process decals
+
+ uint decal_count = cluster_cell.w >> CLUSTER_COUNTER_SHIFT;
+ uint decal_pointer = cluster_cell.w & CLUSTER_POINTER_MASK;
+
+ //do outside for performance and avoiding arctifacts
+
+ for (uint i = 0; i < decal_count; i++) {
+ uint decal_index = cluster_data.indices[decal_pointer + i];
+ if (!bool(decals.data[decal_index].mask & instances.data[instance_index].layer_mask)) {
+ continue; //not masked
+ }
+
+ vec3 uv_local = (decals.data[decal_index].xform * vec4(vertex, 1.0)).xyz;
+ if (any(lessThan(uv_local, vec3(0.0, -1.0, 0.0))) || any(greaterThan(uv_local, vec3(1.0)))) {
+ continue; //out of decal
+ }
+
+ //we need ddx/ddy for mipmaps, so simulate them
+ vec2 ddx = (decals.data[decal_index].xform * vec4(vertex_ddx, 0.0)).xz;
+ vec2 ddy = (decals.data[decal_index].xform * vec4(vertex_ddy, 0.0)).xz;
+
+ float fade = pow(1.0 - (uv_local.y > 0.0 ? uv_local.y : -uv_local.y), uv_local.y > 0.0 ? decals.data[decal_index].upper_fade : decals.data[decal_index].lower_fade);
+
+ if (decals.data[decal_index].normal_fade > 0.0) {
+ fade *= smoothstep(decals.data[decal_index].normal_fade, 1.0, dot(normal_interp, decals.data[decal_index].normal) * 0.5 + 0.5);
+ }
+
+ if (decals.data[decal_index].albedo_rect != vec4(0.0)) {
+ //has albedo
+ vec4 decal_albedo = textureGrad(sampler2D(decal_atlas_srgb, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uv_local.xz * decals.data[decal_index].albedo_rect.zw + decals.data[decal_index].albedo_rect.xy, ddx * decals.data[decal_index].albedo_rect.zw, ddy * decals.data[decal_index].albedo_rect.zw);
+ decal_albedo *= decals.data[decal_index].modulate;
+ decal_albedo.a *= fade;
+ albedo = mix(albedo, decal_albedo.rgb, decal_albedo.a * decals.data[decal_index].albedo_mix);
+
+ if (decals.data[decal_index].normal_rect != vec4(0.0)) {
+ vec3 decal_normal = textureGrad(sampler2D(decal_atlas, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uv_local.xz * decals.data[decal_index].normal_rect.zw + decals.data[decal_index].normal_rect.xy, ddx * decals.data[decal_index].normal_rect.zw, ddy * decals.data[decal_index].normal_rect.zw).xyz;
+ decal_normal.xy = decal_normal.xy * vec2(2.0, -2.0) - vec2(1.0, -1.0); //users prefer flipped y normal maps in most authoring software
+ decal_normal.z = sqrt(max(0.0, 1.0 - dot(decal_normal.xy, decal_normal.xy)));
+ //convert to view space, use xzy because y is up
+ decal_normal = (decals.data[decal_index].normal_xform * decal_normal.xzy).xyz;
+
+ normal = normalize(mix(normal, decal_normal, decal_albedo.a));
+ }
+
+ if (decals.data[decal_index].orm_rect != vec4(0.0)) {
+ vec3 decal_orm = textureGrad(sampler2D(decal_atlas, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uv_local.xz * decals.data[decal_index].orm_rect.zw + decals.data[decal_index].orm_rect.xy, ddx * decals.data[decal_index].orm_rect.zw, ddy * decals.data[decal_index].orm_rect.zw).xyz;
+#if defined(AO_USED)
+ ao = mix(ao, decal_orm.r, decal_albedo.a);
+#endif
+ roughness = mix(roughness, decal_orm.g, decal_albedo.a);
+ metallic = mix(metallic, decal_orm.b, decal_albedo.a);
+ }
+ }
+
+ if (decals.data[decal_index].emission_rect != vec4(0.0)) {
+ //emission is additive, so its independent from albedo
+ emission += textureGrad(sampler2D(decal_atlas_srgb, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, ddx * decals.data[decal_index].emission_rect.zw, ddy * decals.data[decal_index].emission_rect.zw).xyz * decals.data[decal_index].emission_energy * fade;
+ }
+ }
+ }
+#endif //not render depth
/////////////////////// LIGHTING //////////////////////////////
//apply energy conservation
@@ -1316,7 +1826,6 @@ FRAGMENT_SHADER_CODE
}
if (scene_data.use_reflection_cubemap) {
-
vec3 ref_vec = reflect(-view, normal);
ref_vec = scene_data.radiance_inverse_xform * ref_vec;
#ifdef USE_RADIANCE_CUBEMAP_ARRAY
@@ -1336,7 +1845,6 @@ FRAGMENT_SHADER_CODE
#ifndef USE_LIGHTMAP
//lightmap overrides everything
if (scene_data.use_ambient_light) {
-
ambient_light = scene_data.ambient_light_color_energy.rgb;
if (scene_data.use_ambient_cubemap) {
@@ -1365,47 +1873,98 @@ FRAGMENT_SHADER_CODE
#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
//gi probes
+#ifdef USE_LIGHTMAP
+
//lightmap
+ if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE)) { //has lightmap capture
+ uint index = instances.data[instance_index].gi_offset;
+
+ vec3 wnormal = mat3(scene_data.camera_matrix) * normal;
+ const float c1 = 0.429043;
+ const float c2 = 0.511664;
+ const float c3 = 0.743125;
+ 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);
+
+ } 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);
+ uint ofs = instances.data[instance_index].gi_offset & 0xFFF;
+ vec3 uvw;
+ uvw.xy = uv2 * instances.data[instance_index].lightmap_uv_scale.zw + instances.data[instance_index].lightmap_uv_scale.xy;
+ uvw.z = float((instances.data[instance_index].gi_offset >> 12) & 0xFF);
+
+ if (uses_sh) {
+ uvw.z *= 4.0; //SH textures use 4 times more data
+ vec3 lm_light_l0 = textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw + vec3(0.0, 0.0, 0.0), 0.0).rgb;
+ vec3 lm_light_l1n1 = textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw + vec3(0.0, 0.0, 1.0), 0.0).rgb;
+ vec3 lm_light_l1_0 = textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw + vec3(0.0, 0.0, 2.0), 0.0).rgb;
+ vec3 lm_light_l1p1 = textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw + vec3(0.0, 0.0, 3.0), 0.0).rgb;
+
+ uint idx = instances.data[instance_index].gi_offset >> 20;
+ vec3 n = normalize(lightmaps.data[idx].normal_xform * normal);
+
+ ambient_light += lm_light_l0 * 0.282095f;
+ ambient_light += lm_light_l1n1 * 0.32573 * n.y;
+ ambient_light += lm_light_l1_0 * 0.32573 * n.z;
+ ambient_light += lm_light_l1p1 * 0.32573 * n.x;
+ if (metallic > 0.01) { // since the more direct bounced light is lost, we can kind of fake it with this trick
+ vec3 r = reflect(normalize(-vertex), normal);
+ specular_light += lm_light_l1n1 * 0.32573 * r.y;
+ specular_light += lm_light_l1_0 * 0.32573 * r.z;
+ specular_light += lm_light_l1p1 * 0.32573 * r.x;
+ }
+ } else {
+ ambient_light += textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw, 0.0).rgb;
+ }
+ }
+#endif
//lightmap capture
#ifdef USE_VOXEL_CONE_TRACING
- { // process giprobes
- uint index1 = instances.data[instance_index].gi_offset & 0xFFFF;
- if (index1 != 0xFFFF) {
- vec3 ref_vec = normalize(reflect(normalize(vertex), normal));
- //find arbitrary tangent and bitangent, then build a matrix
- vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);
- vec3 tangent = normalize(cross(v0, normal));
- vec3 bitangent = normalize(cross(tangent, normal));
- mat3 normal_mat = mat3(tangent, bitangent, normal);
+ if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_GIPROBE)) { // process giprobes
- vec4 amb_accum = vec4(0.0);
- vec4 spec_accum = vec4(0.0);
- gi_probe_compute(index1, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum);
+ uint index1 = instances.data[instance_index].gi_offset & 0xFFFF;
+ vec3 ref_vec = normalize(reflect(normalize(vertex), normal));
+ //find arbitrary tangent and bitangent, then build a matrix
+ vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);
+ vec3 tangent = normalize(cross(v0, normal));
+ vec3 bitangent = normalize(cross(tangent, normal));
+ mat3 normal_mat = mat3(tangent, bitangent, normal);
- uint index2 = instances.data[instance_index].gi_offset >> 16;
+ vec4 amb_accum = vec4(0.0);
+ vec4 spec_accum = vec4(0.0);
+ gi_probe_compute(index1, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum);
- if (index2 != 0xFFFF) {
- gi_probe_compute(index2, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum);
- }
+ uint index2 = instances.data[instance_index].gi_offset >> 16;
- if (amb_accum.a > 0.0) {
- amb_accum.rgb /= amb_accum.a;
- }
+ if (index2 != 0xFFFF) {
+ gi_probe_compute(index2, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum);
+ }
- if (spec_accum.a > 0.0) {
- spec_accum.rgb /= spec_accum.a;
- }
+ if (amb_accum.a > 0.0) {
+ amb_accum.rgb /= amb_accum.a;
+ }
- specular_light = spec_accum.rgb;
- ambient_light = amb_accum.rgb;
+ if (spec_accum.a > 0.0) {
+ spec_accum.rgb /= spec_accum.a;
}
+
+ specular_light = spec_accum.rgb;
+ ambient_light = amb_accum.rgb;
}
#endif
- uvec4 cluster_cell = texture(usampler3D(cluster_texture, material_samplers[SAMPLER_NEAREST_CLAMP]), vec3(screen_uv, (abs(vertex.z) - scene_data.z_near) / (scene_data.z_far - scene_data.z_near)));
-
{ // process reflections
vec4 reflection_accum = vec4(0.0, 0.0, 0.0, 0.0);
@@ -1415,7 +1974,6 @@ FRAGMENT_SHADER_CODE
uint reflection_probe_pointer = cluster_cell.z & CLUSTER_POINTER_MASK;
for (uint i = 0; i < reflection_probe_count; i++) {
-
uint ref_index = cluster_data.indices[reflection_probe_pointer + i];
reflection_process(ref_index, vertex, normal, roughness, ambient_light, specular_light, ambient_accum, reflection_accum);
}
@@ -1432,7 +1990,6 @@ FRAGMENT_SHADER_CODE
}
{
-
#if defined(DIFFUSE_TOON)
//simplify for toon, as
specular_light *= specular * metallic * albedo * 2.0;
@@ -1457,63 +2014,250 @@ FRAGMENT_SHADER_CODE
{ //directional light
for (uint i = 0; i < scene_data.directional_light_count; i++) {
-
if (!bool(directional_lights.data[i].mask & instances.data[instance_index].layer_mask)) {
continue; //not masked
}
- vec3 light_attenuation = vec3(1.0);
+ vec3 shadow_attenuation = vec3(1.0);
+
+#ifdef LIGHT_TRANSMITTANCE_USED
+ float transmittance_z = transmittance_depth;
+#endif
if (directional_lights.data[i].shadow_enabled) {
float depth_z = -vertex.z;
vec4 pssm_coord;
+ vec3 shadow_color = vec3(0.0);
+ vec3 light_dir = directional_lights.data[i].direction;
+
+#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); \
+ m_var.xyz += normal_bias;
+
+ float shadow = 0.0;
if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
- pssm_coord = (directional_lights.data[i].shadow_matrix1 * vec4(vertex, 1.0));
+ vec4 v = vec4(vertex, 1.0);
+
+ BIAS_FUNC(v, 0)
+
+ pssm_coord = (directional_lights.data[i].shadow_matrix1 * v);
+ pssm_coord /= pssm_coord.w;
+
+ if (directional_lights.data[i].softshadow_angle > 0) {
+ float range_pos = dot(directional_lights.data[i].direction, v.xyz);
+ float range_begin = directional_lights.data[i].shadow_range_begin.x;
+ 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);
+ } else {
+ shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
+ }
+
+ shadow_color = directional_lights.data[i].shadow_color1.rgb;
+
+#ifdef LIGHT_TRANSMITTANCE_USED
+ {
+ vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.x, 1.0);
+ vec4 trans_coord = directional_lights.data[i].shadow_matrix1 * trans_vertex;
+ trans_coord /= trans_coord.w;
+
+ float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
+ shadow_z *= directional_lights.data[i].shadow_transmittance_z_scale.x;
+ float z = trans_coord.z * directional_lights.data[i].shadow_transmittance_z_scale.x;
+
+ transmittance_z = z - shadow_z;
+ }
+#endif
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
- pssm_coord = (directional_lights.data[i].shadow_matrix2 * vec4(vertex, 1.0));
+ vec4 v = vec4(vertex, 1.0);
+
+ BIAS_FUNC(v, 1)
+
+ pssm_coord = (directional_lights.data[i].shadow_matrix2 * v);
+ pssm_coord /= pssm_coord.w;
+
+ if (directional_lights.data[i].softshadow_angle > 0) {
+ float range_pos = dot(directional_lights.data[i].direction, v.xyz);
+ float range_begin = directional_lights.data[i].shadow_range_begin.y;
+ float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
+ vec2 tex_scale = directional_lights.data[i].uv_scale2 * test_radius;
+ shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
+ } else {
+ shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
+ }
+
+ shadow_color = directional_lights.data[i].shadow_color2.rgb;
+#ifdef LIGHT_TRANSMITTANCE_USED
+ {
+ vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.y, 1.0);
+ vec4 trans_coord = directional_lights.data[i].shadow_matrix2 * trans_vertex;
+ trans_coord /= trans_coord.w;
+
+ float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
+ shadow_z *= directional_lights.data[i].shadow_transmittance_z_scale.y;
+ float z = trans_coord.z * directional_lights.data[i].shadow_transmittance_z_scale.y;
+
+ transmittance_z = z - shadow_z;
+ }
+#endif
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
- pssm_coord = (directional_lights.data[i].shadow_matrix3 * vec4(vertex, 1.0));
+ vec4 v = vec4(vertex, 1.0);
+
+ BIAS_FUNC(v, 2)
+
+ pssm_coord = (directional_lights.data[i].shadow_matrix3 * v);
+ pssm_coord /= pssm_coord.w;
+
+ if (directional_lights.data[i].softshadow_angle > 0) {
+ float range_pos = dot(directional_lights.data[i].direction, v.xyz);
+ float range_begin = directional_lights.data[i].shadow_range_begin.z;
+ float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
+ vec2 tex_scale = directional_lights.data[i].uv_scale3 * test_radius;
+ shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
+ } else {
+ shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
+ }
+
+ shadow_color = directional_lights.data[i].shadow_color3.rgb;
+#ifdef LIGHT_TRANSMITTANCE_USED
+ {
+ vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.z, 1.0);
+ vec4 trans_coord = directional_lights.data[i].shadow_matrix3 * trans_vertex;
+ trans_coord /= trans_coord.w;
+
+ float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
+ shadow_z *= directional_lights.data[i].shadow_transmittance_z_scale.z;
+ float z = trans_coord.z * directional_lights.data[i].shadow_transmittance_z_scale.z;
+
+ transmittance_z = z - shadow_z;
+ }
+#endif
+
} else {
- pssm_coord = (directional_lights.data[i].shadow_matrix4 * vec4(vertex, 1.0));
- }
+ vec4 v = vec4(vertex, 1.0);
+
+ BIAS_FUNC(v, 3)
- pssm_coord /= pssm_coord.w;
+ pssm_coord = (directional_lights.data[i].shadow_matrix4 * v);
+ pssm_coord /= pssm_coord.w;
- float shadow = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, pssm_coord);
+ if (directional_lights.data[i].softshadow_angle > 0) {
+ float range_pos = dot(directional_lights.data[i].direction, v.xyz);
+ float range_begin = directional_lights.data[i].shadow_range_begin.w;
+ float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
+ vec2 tex_scale = directional_lights.data[i].uv_scale4 * test_radius;
+ shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
+ } else {
+ shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
+ }
- if (directional_lights.data[i].blend_splits) {
+ shadow_color = directional_lights.data[i].shadow_color4.rgb;
+
+#ifdef LIGHT_TRANSMITTANCE_USED
+ {
+ vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.w, 1.0);
+ vec4 trans_coord = directional_lights.data[i].shadow_matrix4 * trans_vertex;
+ trans_coord /= trans_coord.w;
+ float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
+ shadow_z *= directional_lights.data[i].shadow_transmittance_z_scale.w;
+ float z = trans_coord.z * directional_lights.data[i].shadow_transmittance_z_scale.w;
+
+ transmittance_z = z - shadow_z;
+ }
+#endif
+ }
+
+ if (directional_lights.data[i].blend_splits) {
+ vec3 shadow_color_blend = vec3(0.0);
float pssm_blend;
+ float shadow2;
if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
- pssm_coord = (directional_lights.data[i].shadow_matrix2 * vec4(vertex, 1.0));
+ vec4 v = vec4(vertex, 1.0);
+ BIAS_FUNC(v, 1)
+ pssm_coord = (directional_lights.data[i].shadow_matrix2 * v);
+ pssm_coord /= pssm_coord.w;
+
+ if (directional_lights.data[i].softshadow_angle > 0) {
+ float range_pos = dot(directional_lights.data[i].direction, v.xyz);
+ float range_begin = directional_lights.data[i].shadow_range_begin.y;
+ float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
+ vec2 tex_scale = directional_lights.data[i].uv_scale2 * test_radius;
+ shadow2 = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
+ } else {
+ shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
+ }
+
pssm_blend = smoothstep(0.0, directional_lights.data[i].shadow_split_offsets.x, depth_z);
+ shadow_color_blend = directional_lights.data[i].shadow_color2.rgb;
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
- pssm_coord = (directional_lights.data[i].shadow_matrix3 * vec4(vertex, 1.0));
+ vec4 v = vec4(vertex, 1.0);
+ BIAS_FUNC(v, 2)
+ pssm_coord = (directional_lights.data[i].shadow_matrix3 * v);
+ pssm_coord /= pssm_coord.w;
+
+ if (directional_lights.data[i].softshadow_angle > 0) {
+ float range_pos = dot(directional_lights.data[i].direction, v.xyz);
+ float range_begin = directional_lights.data[i].shadow_range_begin.z;
+ float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
+ vec2 tex_scale = directional_lights.data[i].uv_scale3 * test_radius;
+ shadow2 = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
+ } else {
+ shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
+ }
+
pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.x, directional_lights.data[i].shadow_split_offsets.y, depth_z);
+
+ shadow_color_blend = directional_lights.data[i].shadow_color3.rgb;
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
- pssm_coord = (directional_lights.data[i].shadow_matrix4 * vec4(vertex, 1.0));
+ vec4 v = vec4(vertex, 1.0);
+ BIAS_FUNC(v, 3)
+ pssm_coord = (directional_lights.data[i].shadow_matrix4 * v);
+ pssm_coord /= pssm_coord.w;
+ if (directional_lights.data[i].softshadow_angle > 0) {
+ float range_pos = dot(directional_lights.data[i].direction, v.xyz);
+ float range_begin = directional_lights.data[i].shadow_range_begin.w;
+ float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
+ vec2 tex_scale = directional_lights.data[i].uv_scale4 * test_radius;
+ shadow2 = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
+ } else {
+ shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
+ }
+
pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.y, directional_lights.data[i].shadow_split_offsets.z, depth_z);
+ shadow_color_blend = directional_lights.data[i].shadow_color4.rgb;
} else {
pssm_blend = 0.0; //if no blend, same coord will be used (divide by z will result in same value, and already cached)
}
- pssm_coord /= pssm_coord.w;
+ pssm_blend = sqrt(pssm_blend);
- float shadow2 = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, pssm_coord);
shadow = mix(shadow, shadow2, pssm_blend);
+ shadow_color = mix(shadow_color, shadow_color_blend, 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
- light_attenuation = mix(directional_lights.data[i].shadow_color, vec3(1.0), shadow);
+ shadow_attenuation = mix(shadow_color, vec3(1.0), shadow);
+
+#undef BIAS_FUNC
}
- light_compute(normal, directional_lights.data[i].direction, normalize(view), directional_lights.data[i].color * directional_lights.data[i].energy, light_attenuation, albedo, roughness, metallic, specular, directional_lights.data[i].specular * specular_blob_intensity,
-#ifdef LIGHT_TRANSMISSION_USED
- transmission,
+ light_compute(normal, directional_lights.data[i].direction, normalize(view), directional_lights.data[i].size, directional_lights.data[i].color * directional_lights.data[i].energy, 1.0, shadow_attenuation, albedo, roughness, metallic, specular, directional_lights.data[i].specular * specular_blob_intensity,
+#ifdef LIGHT_BACKLIGHT_USED
+ backlight,
+#endif
+#ifdef LIGHT_TRANSMITTANCE_USED
+ transmittance_color,
+ transmittance_depth,
+ transmittance_curve,
+ transmittance_boost,
+ transmittance_z,
#endif
#ifdef LIGHT_RIM_USED
rim, rim_tint,
@@ -1538,16 +2282,21 @@ FRAGMENT_SHADER_CODE
uint omni_light_pointer = cluster_cell.x & CLUSTER_POINTER_MASK;
for (uint i = 0; i < omni_light_count; i++) {
-
uint light_index = cluster_data.indices[omni_light_pointer + i];
if (!bool(lights.data[light_index].mask & instances.data[instance_index].layer_mask)) {
continue; //not masked
}
- light_process_omni(light_index, vertex, view, normal, albedo, roughness, metallic, specular, specular_blob_intensity,
-#ifdef LIGHT_TRANSMISSION_USED
- transmission,
+ light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, albedo, roughness, metallic, specular, specular_blob_intensity,
+#ifdef LIGHT_BACKLIGHT_USED
+ backlight,
+#endif
+#ifdef LIGHT_TRANSMITTANCE_USED
+ transmittance_color,
+ transmittance_depth,
+ transmittance_curve,
+ transmittance_boost,
#endif
#ifdef LIGHT_RIM_USED
rim,
@@ -1571,16 +2320,21 @@ FRAGMENT_SHADER_CODE
uint spot_light_pointer = cluster_cell.y & CLUSTER_POINTER_MASK;
for (uint i = 0; i < spot_light_count; i++) {
-
uint light_index = cluster_data.indices[spot_light_pointer + i];
if (!bool(lights.data[light_index].mask & instances.data[instance_index].layer_mask)) {
continue; //not masked
}
- light_process_spot(light_index, vertex, view, normal, albedo, roughness, metallic, specular, specular_blob_intensity,
-#ifdef LIGHT_TRANSMISSION_USED
- transmission,
+ light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, albedo, roughness, metallic, specular, specular_blob_intensity,
+#ifdef LIGHT_BACKLIGHT_USED
+ backlight,
+#endif
+#ifdef LIGHT_TRANSMITTANCE_USED
+ transmittance_color,
+ transmittance_depth,
+ transmittance_curve,
+ transmittance_boost,
#endif
#ifdef LIGHT_RIM_USED
rim,
@@ -1670,7 +2424,6 @@ FRAGMENT_SHADER_CODE
ao_light_affect = mix(1.0, ao, ao_light_affect);
specular_light = mix(scene_data.ao_color.rgb, specular_light, ao_light_affect);
diffuse_light = mix(scene_data.ao_color.rgb, diffuse_light, ao_light_affect);
-
#else
if (scene_data.ssao_enabled) {
@@ -1697,6 +2450,9 @@ FRAGMENT_SHADER_CODE
#else
+#ifdef SSS_MODE_SKIN
+ sss_strength = -sss_strength;
+#endif
diffuse_buffer = vec4(emission + diffuse_light + ambient_light, sss_strength);
specular_buffer = vec4(specular_light, metallic);
diff --git a/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl b/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl
index baef1e060f..1cac12406a 100644
--- a/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl
@@ -3,7 +3,8 @@
layout(push_constant, binding = 0, std430) uniform DrawCall {
uint instance_index;
- uint pad[3]; //16 bits minimum size
+ uint pad; //16 bits minimum size
+ vec2 bake_uv2_offset; //used for bake to uv2, ignored otherwise
}
draw_call;
@@ -27,7 +28,6 @@ layout(set = 0, binding = 1) uniform sampler material_samplers[12];
layout(set = 0, binding = 2) uniform sampler shadow_sampler;
layout(set = 0, binding = 3, std140) uniform SceneData {
-
mat4 projection_matrix;
mat4 inv_projection_matrix;
@@ -37,13 +37,23 @@ layout(set = 0, binding = 3, std140) uniform SceneData {
vec2 viewport_size;
vec2 screen_pixel_size;
- //used for shadow mapping only
- float z_offset;
- float z_slope_scale;
-
float time;
float reflection_multiplier; // one normally, zero when rendering reflections
+ bool pancake_shadows;
+ uint pad;
+
+ //use vec4s because std140 doesnt play nice with vec2s, z and w are wasted
+ vec4 directional_penumbra_shadow_kernel[32];
+ vec4 directional_soft_shadow_kernel[32];
+ vec4 penumbra_shadow_kernel[32];
+ vec4 soft_shadow_kernel[32];
+
+ uint directional_penumbra_shadow_samples;
+ uint directional_soft_shadow_samples;
+ uint penumbra_shadow_samples;
+ uint soft_shadow_samples;
+
vec4 ambient_light_color_energy;
float ambient_color_sky_mix;
@@ -67,6 +77,10 @@ layout(set = 0, binding = 3, std140) uniform SceneData {
bool roughness_limiter_enabled;
vec4 ao_color;
+ bool material_uv2_mode;
+ uint pad_material0;
+ uint pad_material1;
+ uint pad_material2;
#if 0
vec4 ambient_light_color;
@@ -103,13 +117,13 @@ layout(set = 0, binding = 3, std140) uniform SceneData {
float fog_height_curve;
#endif
}
-scene_data;
-#define INSTANCE_FLAGS_FORWARD_MASK 0x7
-#define INSTANCE_FLAGS_FORWARD_OMNI_LIGHT_SHIFT 3
-#define INSTANCE_FLAGS_FORWARD_SPOT_LIGHT_SHIFT 6
-#define INSTANCE_FLAGS_FORWARD_DECAL_SHIFT 9
+scene_data;
+#define INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE (1 << 8)
+#define INSTANCE_FLAGS_USE_LIGHTMAP (1 << 9)
+#define INSTANCE_FLAGS_USE_SH_LIGHTMAP (1 << 10)
+#define INSTANCE_FLAGS_USE_GIPROBE (1 << 11)
#define INSTANCE_FLAGS_MULTIMESH (1 << 12)
#define INSTANCE_FLAGS_MULTIMESH_FORMAT_2D (1 << 13)
#define INSTANCE_FLAGS_MULTIMESH_HAS_COLOR (1 << 14)
@@ -124,36 +138,44 @@ struct InstanceData {
mat4 transform;
mat4 normal_transform;
uint flags;
- uint instance_ofs; //instance_offset in instancing/skeleton buffer
- uint gi_offset; //GI information when using lightmapping (VCT or lightmap)
+ uint instance_uniforms_ofs; //base offset in global buffer for instance variables
+ uint gi_offset; //GI information when using lightmapping (VCT or lightmap index)
uint layer_mask;
+ vec4 lightmap_uv_scale;
};
-layout(set = 0, binding = 4, std430) buffer Instances {
+layout(set = 0, binding = 4, std430) restrict readonly buffer Instances {
InstanceData data[];
}
instances;
-struct LightData { //this structure needs to be 128 bits
+struct LightData { //this structure needs to be as packed as possible
vec3 position;
float inv_radius;
vec3 direction;
+ float size;
uint attenuation_energy; //attenuation
uint color_specular; //rgb color, a specular (8 bit unorm)
uint cone_attenuation_angle; // attenuation and angle, (16bit float)
- uint mask;
uint shadow_color_enabled; //shadow rgb color, a>0.5 enabled (8bit unorm)
- vec4 atlas_rect; //used for shadow atlas uv on omni, and for projection atlas on spot
+ vec4 atlas_rect; // rect in the shadow atlas
mat4 shadow_matrix;
+ float shadow_bias;
+ float shadow_normal_bias;
+ float transmittance_bias;
+ float soft_shadow_size; // for spot, it's the size in uv coordinates of the light, for omni it's the span angle
+ float soft_shadow_scale; // scales the shadow kernel for blurrier shadows
+ uint mask;
+ uint pad[2];
+ vec4 projector_rect; //projector rect in srgb decal atlas
};
-layout(set = 0, binding = 5, std140) uniform Lights {
- LightData data[MAX_LIGHT_DATA_STRUCTS];
+layout(set = 0, binding = 5, std430) restrict readonly buffer Lights {
+ LightData data[];
}
lights;
struct ReflectionData {
-
vec3 box_extents;
float index;
vec3 box_offset;
@@ -173,18 +195,33 @@ struct DirectionalLightData {
vec3 direction;
float energy;
vec3 color;
+ float size;
float specular;
- vec3 shadow_color;
uint mask;
+ float softshadow_angle;
+ float soft_shadow_scale;
bool blend_splits;
bool shadow_enabled;
float fade_from;
float fade_to;
+ vec4 shadow_bias;
+ vec4 shadow_normal_bias;
+ vec4 shadow_transmittance_bias;
+ vec4 shadow_transmittance_z_scale;
+ vec4 shadow_range_begin;
vec4 shadow_split_offsets;
mat4 shadow_matrix1;
mat4 shadow_matrix2;
mat4 shadow_matrix3;
mat4 shadow_matrix4;
+ vec4 shadow_color1;
+ vec4 shadow_color2;
+ vec4 shadow_color3;
+ vec4 shadow_color4;
+ vec2 uv_scale1;
+ vec2 uv_scale2;
+ vec2 uv_scale3;
+ vec2 uv_scale4;
};
layout(set = 0, binding = 7, std140) uniform DirectionalLights {
@@ -215,18 +252,72 @@ gi_probes;
layout(set = 0, binding = 9) uniform texture3D gi_probe_textures[MAX_GI_PROBE_TEXTURES];
+#define LIGHTMAP_FLAG_USE_DIRECTION 1
+#define LIGHTMAP_FLAG_USE_SPECULAR_DIRECTION 2
+
+struct Lightmap {
+ mat3 normal_xform;
+};
+
+layout(set = 0, binding = 10, std140) restrict readonly buffer Lightmaps {
+ Lightmap data[];
+}
+lightmaps;
+
+layout(set = 0, binding = 11) uniform texture2DArray lightmap_textures[MAX_LIGHTMAP_TEXTURES];
+
+struct LightmapCapture {
+ vec4 sh[9];
+};
+
+layout(set = 0, binding = 12, std140) restrict readonly buffer LightmapCaptures {
+ LightmapCapture data[];
+}
+lightmap_captures;
+
#define CLUSTER_COUNTER_SHIFT 20
#define CLUSTER_POINTER_MASK ((1 << CLUSTER_COUNTER_SHIFT) - 1)
#define CLUSTER_COUNTER_MASK 0xfff
-layout(set = 0, binding = 10) uniform utexture3D cluster_texture;
+layout(set = 0, binding = 13) uniform texture2D decal_atlas;
+layout(set = 0, binding = 14) uniform texture2D decal_atlas_srgb;
+
+struct DecalData {
+ mat4 xform; //to decal transform
+ vec3 inv_extents;
+ float albedo_mix;
+ vec4 albedo_rect;
+ vec4 normal_rect;
+ vec4 orm_rect;
+ vec4 emission_rect;
+ vec4 modulate;
+ float emission_energy;
+ uint mask;
+ float upper_fade;
+ float lower_fade;
+ mat3x4 normal_xform;
+ vec3 normal;
+ float normal_fade;
+};
+
+layout(set = 0, binding = 15, std430) restrict readonly buffer Decals {
+ DecalData data[];
+}
+decals;
+
+layout(set = 0, binding = 16) uniform utexture3D cluster_texture;
-layout(set = 0, binding = 11, std430) buffer ClusterData {
+layout(set = 0, binding = 17, std430) restrict readonly buffer ClusterData {
uint indices[];
}
cluster_data;
-layout(set = 0, binding = 12) uniform texture2D directional_shadow_atlas;
+layout(set = 0, binding = 18) uniform texture2D directional_shadow_atlas;
+
+layout(set = 0, binding = 19, std430) restrict readonly buffer GlobalVariableData {
+ vec4 data[];
+}
+global_variables;
// decal atlas
@@ -248,7 +339,7 @@ layout(set = 2, binding = 0) uniform textureCubeArray reflection_atlas;
layout(set = 2, binding = 1) uniform texture2D shadow_atlas;
-/* Set 1, Render Buffers */
+/* Set 3, Render Buffers */
layout(set = 3, binding = 0) uniform texture2D depth_buffer;
layout(set = 3, binding = 1) uniform texture2D color_buffer;
@@ -258,7 +349,7 @@ layout(set = 3, binding = 4) uniform texture2D ao_buffer;
/* Set 4 Skeleton & Instancing (Multimesh) */
-layout(set = 4, binding = 0, std430) buffer Transforms {
+layout(set = 4, binding = 0, std430) restrict readonly buffer Transforms {
vec4 data[];
}
transforms;
diff --git a/servers/rendering/rasterizer_rd/shaders/screen_space_reflection.glsl b/servers/rendering/rasterizer_rd/shaders/screen_space_reflection.glsl
new file mode 100644
index 0000000000..084f28d932
--- /dev/null
+++ b/servers/rendering/rasterizer_rd/shaders/screen_space_reflection.glsl
@@ -0,0 +1,252 @@
+#[compute]
+
+#version 450
+
+VERSION_DEFINES
+
+layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
+
+layout(rgba16f, set = 0, binding = 0) uniform restrict readonly image2D source_diffuse;
+layout(r32f, set = 0, binding = 1) uniform restrict readonly image2D source_depth;
+layout(rgba16f, set = 1, binding = 0) uniform restrict writeonly image2D ssr_image;
+#ifdef MODE_ROUGH
+layout(r8, set = 1, binding = 1) uniform restrict writeonly image2D blur_radius_image;
+#endif
+layout(rgba8, set = 2, binding = 0) uniform restrict readonly image2D source_normal;
+layout(set = 3, binding = 0) uniform sampler2D source_metallic;
+#ifdef MODE_ROUGH
+layout(set = 3, binding = 1) uniform sampler2D source_roughness;
+#endif
+
+layout(push_constant, binding = 2, std430) uniform Params {
+ vec4 proj_info;
+
+ ivec2 screen_size;
+ float camera_z_near;
+ float camera_z_far;
+
+ int num_steps;
+ float depth_tolerance;
+ float distance_fade;
+ float curve_fade_in;
+
+ bool orthogonal;
+ float filter_mipmap_levels;
+ bool use_half_res;
+ uint metallic_mask;
+
+ mat4 projection;
+}
+params;
+
+vec2 view_to_screen(vec3 view_pos, out float w) {
+ vec4 projected = params.projection * vec4(view_pos, 1.0);
+ projected.xyz /= projected.w;
+ projected.xy = projected.xy * 0.5 + 0.5;
+ w = projected.w;
+ return projected.xy;
+}
+
+#define M_PI 3.14159265359
+
+vec3 reconstructCSPosition(vec2 S, float z) {
+ if (params.orthogonal) {
+ return vec3((S.xy * params.proj_info.xy + params.proj_info.zw), z);
+ } else {
+ return vec3((S.xy * params.proj_info.xy + params.proj_info.zw) * z, z);
+ }
+}
+
+void main() {
+ // Pixel being shaded
+ ivec2 ssC = ivec2(gl_GlobalInvocationID.xy);
+
+ if (any(greaterThanEqual(ssC, params.screen_size))) { //too large, do nothing
+ return;
+ }
+
+ vec2 pixel_size = 1.0 / vec2(params.screen_size);
+ vec2 uv = vec2(ssC) * pixel_size;
+
+ uv += pixel_size * 0.5;
+
+ float base_depth = imageLoad(source_depth, ssC).r;
+
+ // World space point being shaded
+ vec3 vertex = reconstructCSPosition(uv * vec2(params.screen_size), base_depth);
+
+ vec3 normal = imageLoad(source_normal, ssC).xyz * 2.0 - 1.0;
+ normal = normalize(normal);
+ normal.y = -normal.y; //because this code reads flipped
+
+ vec3 view_dir = normalize(vertex);
+ vec3 ray_dir = normalize(reflect(view_dir, normal));
+
+ if (dot(ray_dir, normal) < 0.001) {
+ imageStore(ssr_image, ssC, vec4(0.0));
+ return;
+ }
+ //ray_dir = normalize(view_dir - normal * dot(normal,view_dir) * 2.0);
+ //ray_dir = normalize(vec3(1.0, 1.0, -1.0));
+
+ ////////////////
+
+ // make ray length and clip it against the near plane (don't want to trace beyond visible)
+ float ray_len = (vertex.z + ray_dir.z * params.camera_z_far) > -params.camera_z_near ? (-params.camera_z_near - vertex.z) / ray_dir.z : params.camera_z_far;
+ vec3 ray_end = vertex + ray_dir * ray_len;
+
+ float w_begin;
+ vec2 vp_line_begin = view_to_screen(vertex, w_begin);
+ float w_end;
+ vec2 vp_line_end = view_to_screen(ray_end, w_end);
+ vec2 vp_line_dir = vp_line_end - vp_line_begin;
+
+ // we need to interpolate w along the ray, to generate perspective correct reflections
+ w_begin = 1.0 / w_begin;
+ w_end = 1.0 / w_end;
+
+ float z_begin = vertex.z * w_begin;
+ float z_end = ray_end.z * w_end;
+
+ vec2 line_begin = vp_line_begin / pixel_size;
+ vec2 line_dir = vp_line_dir / pixel_size;
+ float z_dir = z_end - z_begin;
+ float w_dir = w_end - w_begin;
+
+ // clip the line to the viewport edges
+
+ float scale_max_x = min(1.0, 0.99 * (1.0 - vp_line_begin.x) / max(1e-5, vp_line_dir.x));
+ float scale_max_y = min(1.0, 0.99 * (1.0 - vp_line_begin.y) / max(1e-5, vp_line_dir.y));
+ float scale_min_x = min(1.0, 0.99 * vp_line_begin.x / max(1e-5, -vp_line_dir.x));
+ float scale_min_y = min(1.0, 0.99 * vp_line_begin.y / max(1e-5, -vp_line_dir.y));
+ float line_clip = min(scale_max_x, scale_max_y) * min(scale_min_x, scale_min_y);
+ line_dir *= line_clip;
+ z_dir *= line_clip;
+ w_dir *= line_clip;
+
+ // clip z and w advance to line advance
+ vec2 line_advance = normalize(line_dir); // down to pixel
+ float step_size = length(line_advance) / length(line_dir);
+ float z_advance = z_dir * step_size; // adapt z advance to line advance
+ float w_advance = w_dir * step_size; // adapt w advance to line advance
+
+ // make line advance faster if direction is closer to pixel edges (this avoids sampling the same pixel twice)
+ float advance_angle_adj = 1.0 / max(abs(line_advance.x), abs(line_advance.y));
+ line_advance *= advance_angle_adj; // adapt z advance to line advance
+ z_advance *= advance_angle_adj;
+ w_advance *= advance_angle_adj;
+
+ vec2 pos = line_begin;
+ float z = z_begin;
+ float w = w_begin;
+ float z_from = z / w;
+ float z_to = z_from;
+ float depth;
+ vec2 prev_pos = pos;
+
+ bool found = false;
+
+ float steps_taken = 0.0;
+
+ for (int i = 0; i < params.num_steps; i++) {
+ pos += line_advance;
+ z += z_advance;
+ w += w_advance;
+
+ // convert to linear depth
+
+ depth = imageLoad(source_depth, ivec2(pos - 0.5)).r;
+
+ if (-depth >= params.camera_z_far) { //went beyond camera
+ break;
+ }
+
+ z_from = z_to;
+ z_to = z / w;
+
+ if (depth > z_to) {
+ // if depth was surpassed
+ if (depth <= max(z_to, z_from) + params.depth_tolerance) {
+ // check the depth tolerance
+ //check that normal is valid
+ found = true;
+ }
+ break;
+ }
+
+ steps_taken += 1.0;
+ prev_pos = pos;
+ }
+
+ if (found) {
+ float margin_blend = 1.0;
+
+ vec2 margin = vec2((params.screen_size.x + params.screen_size.y) * 0.5 * 0.05); // make a uniform margin
+ if (any(bvec4(lessThan(pos, -margin), greaterThan(pos, params.screen_size + margin)))) {
+ // clip outside screen + margin
+ imageStore(ssr_image, ssC, vec4(0.0));
+ return;
+ }
+
+ {
+ //blend fading out towards external margin
+ vec2 margin_grad = mix(pos - params.screen_size, -pos, lessThan(pos, vec2(0.0)));
+ margin_blend = 1.0 - smoothstep(0.0, margin.x, max(margin_grad.x, margin_grad.y));
+ //margin_blend = 1.0;
+ }
+
+ vec2 final_pos;
+ float grad;
+ grad = steps_taken / float(params.num_steps);
+ float initial_fade = params.curve_fade_in == 0.0 ? 1.0 : pow(clamp(grad, 0.0, 1.0), params.curve_fade_in);
+ float fade = pow(clamp(1.0 - grad, 0.0, 1.0), params.distance_fade) * initial_fade;
+ final_pos = pos;
+
+ vec4 final_color;
+
+#ifdef MODE_ROUGH
+
+ // if roughness is enabled, do screen space cone tracing
+ float blur_radius = 0.0;
+ float roughness = texelFetch(source_roughness, ssC << 1, 0).r;
+
+ if (roughness > 0.001) {
+ float cone_angle = min(roughness, 0.999) * M_PI * 0.5;
+ float cone_len = length(final_pos - line_begin);
+ float op_len = 2.0 * tan(cone_angle) * cone_len; // opposite side of iso triangle
+ {
+ // fit to sphere inside cone (sphere ends at end of cone), something like this:
+ // ___
+ // \O/
+ // V
+ //
+ // as it avoids bleeding from beyond the reflection as much as possible. As a plus
+ // it also makes the rough reflection more elongated.
+ float a = op_len;
+ float h = cone_len;
+ float a2 = a * a;
+ float fh2 = 4.0f * h * h;
+ blur_radius = (a * (sqrt(a2 + fh2) - a)) / (4.0f * h);
+ }
+ }
+
+ final_color = imageLoad(source_diffuse, ivec2((final_pos - 0.5) * pixel_size));
+
+ imageStore(blur_radius_image, ssC, vec4(blur_radius / 255.0)); //stored in r8
+
+#endif
+
+ final_color = vec4(imageLoad(source_diffuse, ivec2(final_pos - 0.5)).rgb, fade * margin_blend);
+ //change blend by metallic
+ vec4 metallic_mask = unpackUnorm4x8(params.metallic_mask);
+ final_color.a *= dot(metallic_mask, texelFetch(source_metallic, ssC << 1, 0));
+
+ imageStore(ssr_image, ssC, final_color);
+
+ } else {
+#ifdef MODE_ROUGH
+ imageStore(blur_radius_image, ssC, vec4(0.0));
+#endif
+ imageStore(ssr_image, ssC, vec4(0.0));
+ }
+}
diff --git a/servers/rendering/rasterizer_rd/shaders/screen_space_reflection_filter.glsl b/servers/rendering/rasterizer_rd/shaders/screen_space_reflection_filter.glsl
new file mode 100644
index 0000000000..a5afe74cb2
--- /dev/null
+++ b/servers/rendering/rasterizer_rd/shaders/screen_space_reflection_filter.glsl
@@ -0,0 +1,154 @@
+#[compute]
+
+#version 450
+
+VERSION_DEFINES
+
+layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
+
+layout(rgba16f, set = 0, binding = 0) uniform restrict readonly image2D source_ssr;
+layout(r8, set = 0, binding = 1) uniform restrict readonly image2D source_radius;
+layout(rgba8, set = 1, binding = 0) uniform restrict readonly image2D source_normal;
+
+layout(rgba16f, set = 2, binding = 0) uniform restrict writeonly image2D dest_ssr;
+#ifndef VERTICAL_PASS
+layout(r8, set = 2, binding = 1) uniform restrict writeonly image2D dest_radius;
+#endif
+layout(r32f, set = 3, binding = 0) uniform restrict readonly image2D source_depth;
+
+layout(push_constant, binding = 2, std430) uniform Params {
+ vec4 proj_info;
+
+ bool orthogonal;
+ float edge_tolerance;
+ int increment;
+ uint pad;
+
+ ivec2 screen_size;
+ bool vertical;
+ uint steps;
+}
+params;
+
+#define GAUSS_TABLE_SIZE 15
+
+const float gauss_table[GAUSS_TABLE_SIZE + 1] = float[](
+ 0.1847392078702266,
+ 0.16595854345772326,
+ 0.12031364177766891,
+ 0.07038755277896766,
+ 0.03322925565155569,
+ 0.012657819729901945,
+ 0.0038903040680094217,
+ 0.0009646503390864025,
+ 0.00019297087402915717,
+ 0.000031139936308099136,
+ 0.000004053309048174758,
+ 4.255228059965837e-7,
+ 3.602517634249573e-8,
+ 2.4592560765896795e-9,
+ 1.3534945386863618e-10,
+ 0.0 //one more for interpolation
+);
+
+float gauss_weight(float p_val) {
+ float idxf;
+ float c = modf(max(0.0, p_val * float(GAUSS_TABLE_SIZE)), idxf);
+ int idx = int(idxf);
+ if (idx >= GAUSS_TABLE_SIZE + 1) {
+ return 0.0;
+ }
+
+ return mix(gauss_table[idx], gauss_table[idx + 1], c);
+}
+
+#define M_PI 3.14159265359
+
+vec3 reconstructCSPosition(vec2 S, float z) {
+ if (params.orthogonal) {
+ return vec3((S.xy * params.proj_info.xy + params.proj_info.zw), z);
+ } else {
+ return vec3((S.xy * params.proj_info.xy + params.proj_info.zw) * z, z);
+ }
+}
+
+void do_filter(inout vec4 accum, inout float accum_radius, inout float divisor, ivec2 texcoord, ivec2 increment, vec3 p_pos, vec3 normal, float p_limit_radius) {
+ for (int i = 1; i < params.steps; i++) {
+ float d = float(i * params.increment);
+ ivec2 tc = texcoord + increment * i;
+ float depth = imageLoad(source_depth, tc).r;
+ vec3 view_pos = reconstructCSPosition(vec2(tc) + 0.5, depth);
+ vec3 view_normal = normalize(imageLoad(source_normal, tc).rgb * 2.0 - 1.0);
+ view_normal.y = -view_normal.y;
+
+ float r = imageLoad(source_radius, tc).r;
+ float radius = round(r * 255.0);
+
+ float angle_n = 1.0 - abs(dot(normal, view_normal));
+ if (angle_n > params.edge_tolerance) {
+ break;
+ }
+
+ float angle = abs(dot(normal, normalize(view_pos - p_pos)));
+
+ if (angle > params.edge_tolerance) {
+ break;
+ }
+
+ if (d < radius) {
+ float w = gauss_weight(d / radius);
+ accum += imageLoad(source_ssr, tc) * w;
+#ifndef VERTICAL_PASS
+ accum_radius += r * w;
+#endif
+ divisor += w;
+ }
+ }
+}
+
+void main() {
+ // Pixel being shaded
+ ivec2 ssC = ivec2(gl_GlobalInvocationID.xy);
+
+ if (any(greaterThanEqual(ssC, params.screen_size))) { //too large, do nothing
+ return;
+ }
+
+ float base_contrib = gauss_table[0];
+
+ vec4 accum = imageLoad(source_ssr, ssC);
+
+ float accum_radius = imageLoad(source_radius, ssC).r;
+ float radius = accum_radius * 255.0;
+
+ float divisor = gauss_table[0];
+ accum *= divisor;
+ accum_radius *= divisor;
+#ifdef VERTICAL_PASS
+ ivec2 direction = ivec2(0, params.increment);
+#else
+ ivec2 direction = ivec2(params.increment, 0);
+#endif
+ float depth = imageLoad(source_depth, ssC).r;
+ vec3 pos = reconstructCSPosition(vec2(ssC) + 0.5, depth);
+ vec3 normal = imageLoad(source_normal, ssC).xyz * 2.0 - 1.0;
+ normal = normalize(normal);
+ normal.y = -normal.y;
+
+ do_filter(accum, accum_radius, divisor, ssC, direction, pos, normal, radius);
+ do_filter(accum, accum_radius, divisor, ssC, -direction, pos, normal, radius);
+
+ if (divisor > 0.0) {
+ accum /= divisor;
+ accum_radius /= divisor;
+ } else {
+ accum = vec4(0.0);
+ accum_radius = 0.0;
+ }
+
+ imageStore(dest_ssr, ssC, accum);
+
+#ifndef VERTICAL_PASS
+ imageStore(dest_radius, ssC, vec4(accum_radius));
+#endif
+}
diff --git a/servers/rendering/rasterizer_rd/shaders/screen_space_reflection_scale.glsl b/servers/rendering/rasterizer_rd/shaders/screen_space_reflection_scale.glsl
new file mode 100644
index 0000000000..218605a962
--- /dev/null
+++ b/servers/rendering/rasterizer_rd/shaders/screen_space_reflection_scale.glsl
@@ -0,0 +1,87 @@
+#[compute]
+
+#version 450
+
+VERSION_DEFINES
+
+layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
+
+layout(set = 0, binding = 0) uniform sampler2D source_ssr;
+layout(set = 1, binding = 0) uniform sampler2D source_depth;
+layout(set = 1, binding = 1) uniform sampler2D source_normal;
+layout(rgba16f, set = 2, binding = 0) uniform restrict writeonly image2D dest_ssr;
+layout(r32f, set = 3, binding = 0) uniform restrict writeonly image2D dest_depth;
+layout(rgba8, set = 3, binding = 1) uniform restrict writeonly image2D dest_normal;
+
+layout(push_constant, binding = 1, std430) uniform Params {
+ ivec2 screen_size;
+ float camera_z_near;
+ float camera_z_far;
+
+ bool orthogonal;
+ bool filtered;
+ uint pad[2];
+}
+params;
+
+void main() {
+ // Pixel being shaded
+ ivec2 ssC = ivec2(gl_GlobalInvocationID.xy);
+
+ if (any(greaterThanEqual(ssC, params.screen_size))) { //too large, do nothing
+ return;
+ }
+ //do not filter, SSR will generate arctifacts if this is done
+
+ float divisor = 0.0;
+ vec4 color;
+ float depth;
+ vec3 normal;
+
+ if (params.filtered) {
+ color = vec4(0.0);
+ depth = 0.0;
+ normal = vec3(0.0);
+
+ for (int i = 0; i < 4; i++) {
+ ivec2 ofs = ssC << 1;
+ if (bool(i & 1)) {
+ ofs.x += 1;
+ }
+ if (bool(i & 2)) {
+ ofs.y += 1;
+ }
+ color += texelFetch(source_ssr, ofs, 0);
+ float d = texelFetch(source_depth, ofs, 0).r;
+ normal += texelFetch(source_normal, ofs, 0).xyz * 2.0 - 1.0;
+
+ d = d * 2.0 - 1.0;
+ if (params.orthogonal) {
+ d = ((d + (params.camera_z_far + params.camera_z_near) / (params.camera_z_far - params.camera_z_near)) * (params.camera_z_far - params.camera_z_near)) / 2.0;
+ } else {
+ d = 2.0 * params.camera_z_near * params.camera_z_far / (params.camera_z_far + params.camera_z_near - d * (params.camera_z_far - params.camera_z_near));
+ }
+ depth += -d;
+ }
+
+ color /= 4.0;
+ depth /= 4.0;
+ normal = normalize(normal / 4.0) * 0.5 + 0.5;
+ } else {
+ color = texelFetch(source_ssr, ssC << 1, 0);
+ depth = texelFetch(source_depth, ssC << 1, 0).r;
+ normal = texelFetch(source_normal, ssC << 1, 0).xyz;
+
+ depth = depth * 2.0 - 1.0;
+ if (params.orthogonal) {
+ depth = ((depth + (params.camera_z_far + params.camera_z_near) / (params.camera_z_far - params.camera_z_near)) * (params.camera_z_far - params.camera_z_near)) / 2.0;
+ } else {
+ depth = 2.0 * params.camera_z_near * params.camera_z_far / (params.camera_z_far + params.camera_z_near - depth * (params.camera_z_far - params.camera_z_near));
+ }
+ depth = -depth;
+ }
+
+ imageStore(dest_ssr, ssC, color);
+ imageStore(dest_depth, ssC, vec4(depth));
+ imageStore(dest_normal, ssC, vec4(normal, 0.0));
+}
diff --git a/servers/rendering/rasterizer_rd/shaders/sky.glsl b/servers/rendering/rasterizer_rd/shaders/sky.glsl
index 3f433eb2ee..9c59be6841 100644
--- a/servers/rendering/rasterizer_rd/shaders/sky.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/sky.glsl
@@ -1,12 +1,10 @@
-/* clang-format off */
-[vertex]
+#[vertex]
#version 450
VERSION_DEFINES
layout(location = 0) out vec2 uv_interp;
-/* clang-format on */
layout(push_constant, binding = 1, std430) uniform Params {
mat3 orientation;
@@ -17,14 +15,12 @@ layout(push_constant, binding = 1, std430) uniform Params {
params;
void main() {
-
vec2 base_arr[4] = vec2[](vec2(-1.0, -1.0), vec2(-1.0, 1.0), vec2(1.0, 1.0), vec2(1.0, -1.0));
uv_interp = base_arr[gl_VertexIndex];
gl_Position = vec4(uv_interp, 1.0, 1.0);
}
-/* clang-format off */
-[fragment]
+#[fragment]
#version 450
@@ -33,7 +29,6 @@ VERSION_DEFINES
#define M_PI 3.14159265359
layout(location = 0) in vec2 uv_interp;
-/* clang-format on */
layout(push_constant, binding = 1, std430) uniform Params {
mat3 orientation;
@@ -58,6 +53,11 @@ params;
layout(set = 0, binding = 0) uniform sampler material_samplers[12];
+layout(set = 0, binding = 1, std430) restrict readonly buffer GlobalVariableData {
+ vec4 data[];
+}
+global_variables;
+
#ifdef USE_MATERIAL_UNIFORMS
layout(set = 1, binding = 0, std140) uniform MaterialUniforms{
/* clang-format off */
@@ -96,15 +96,15 @@ layout(set = 2, binding = 2) uniform texture2D quarter_res;
#endif
struct DirectionalLightData {
- vec3 direction;
- float energy;
- vec3 color;
+ vec4 direction_energy;
+ vec4 color_size;
bool enabled;
};
layout(set = 3, binding = 0, std140) uniform DirectionalLights {
DirectionalLightData data[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS];
}
+
directional_lights;
/* clang-format off */
@@ -116,7 +116,6 @@ FRAGMENT_SHADER_GLOBALS
layout(location = 0) out vec4 frag_color;
void main() {
-
vec3 cube_normal;
cube_normal.z = -1.0;
cube_normal.x = (cube_normal.z * (-uv_interp.x - params.proj.x)) / params.proj.y;
@@ -141,15 +140,15 @@ void main() {
vec4 quarter_res_color = vec4(1.0);
#ifdef USE_CUBEMAP_PASS
- float using_cubemap = 1.0;
+ vec3 inverted_cube_normal = cube_normal;
+ inverted_cube_normal.z *= -1.0;
#ifdef USES_HALF_RES_COLOR
- half_res_color = texture(samplerCube(half_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), cube_normal);
+ half_res_color = texture(samplerCube(half_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), inverted_cube_normal);
#endif
#ifdef USES_QUARTER_RES_COLOR
- quarter_res_color = texture(samplerCube(quarter_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), cube_normal);
+ quarter_res_color = texture(samplerCube(quarter_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), inverted_cube_normal);
#endif
#else
- float using_cubemap = 0.0;
#ifdef USES_HALF_RES_COLOR
half_res_color = textureLod(sampler2D(half_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0);
#endif
@@ -178,4 +177,10 @@ FRAGMENT_SHADER_CODE
frag_color.rgb = color * params.position_multiplier.w;
frag_color.a = alpha;
+
+ // Blending is disabled for Sky, so alpha doesn't blend
+ // alpha is used for subsurface scattering so make sure it doesn't get applied to Sky
+ if (!AT_CUBEMAP_PASS && !AT_HALF_RES_PASS && !AT_QUARTER_RES_PASS) {
+ frag_color.a = 0.0;
+ }
}
diff --git a/servers/rendering/rasterizer_rd/shaders/specular_merge.glsl b/servers/rendering/rasterizer_rd/shaders/specular_merge.glsl
new file mode 100644
index 0000000000..0b8f406213
--- /dev/null
+++ b/servers/rendering/rasterizer_rd/shaders/specular_merge.glsl
@@ -0,0 +1,53 @@
+#[vertex]
+
+#version 450
+
+VERSION_DEFINES
+
+layout(location = 0) out vec2 uv_interp;
+
+void main() {
+ vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
+ uv_interp = base_arr[gl_VertexIndex];
+
+ gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0);
+}
+
+#[fragment]
+
+#version 450
+
+VERSION_DEFINES
+
+layout(location = 0) in vec2 uv_interp;
+
+layout(set = 0, binding = 0) uniform sampler2D specular;
+
+#ifdef MODE_SSR
+
+layout(set = 1, binding = 0) uniform sampler2D ssr;
+
+#endif
+
+#ifdef MODE_MERGE
+
+layout(set = 2, binding = 0) uniform sampler2D diffuse;
+
+#endif
+
+layout(location = 0) out vec4 frag_color;
+
+void main() {
+ frag_color.rgb = texture(specular, uv_interp).rgb;
+ frag_color.a = 0.0;
+#ifdef MODE_SSR
+
+ vec4 ssr_color = texture(ssr, uv_interp);
+ frag_color.rgb = mix(frag_color.rgb, ssr_color.rgb, ssr_color.a);
+#endif
+
+#ifdef MODE_MERGE
+ frag_color += texture(diffuse, uv_interp);
+#endif
+ //added using additive blend
+}
diff --git a/servers/rendering/rasterizer_rd/shaders/ssao.glsl b/servers/rendering/rasterizer_rd/shaders/ssao.glsl
index c9d7134610..346338181a 100644
--- a/servers/rendering/rasterizer_rd/shaders/ssao.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/ssao.glsl
@@ -1,12 +1,10 @@
-/* clang-format off */
-[compute]
+#[compute]
#version 450
VERSION_DEFINES
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
-/* clang-format on */
#define TWO_PI 6.283185307179586476925286766559
@@ -49,7 +47,6 @@ const int ROTATIONS[] = int[](
29, 21, 19, 27, 31, 29, 21, 18, 17, 29,
31, 31, 23, 18, 25, 26, 25, 23, 19, 34,
19, 27, 21, 25, 39, 29, 17, 21, 27);
-/* clang-format on */
//#define NUM_SPIRAL_TURNS (7)
const int NUM_SPIRAL_TURNS = ROTATIONS[NUM_SAMPLES - 1];
@@ -212,7 +209,7 @@ float sampleAO(in ivec2 ssC, in vec3 C, in vec3 n_C, in float ssDiskRadius, in f
void main() {
// Pixel being shaded
ivec2 ssC = ivec2(gl_GlobalInvocationID.xy);
- if (any(greaterThan(ssC, params.screen_size))) { //too large, do nothing
+ if (any(greaterThanEqual(ssC, params.screen_size))) { //too large, do nothing
return;
}
diff --git a/servers/rendering/rasterizer_rd/shaders/ssao_blur.glsl b/servers/rendering/rasterizer_rd/shaders/ssao_blur.glsl
index e90c788e08..3e63e3cb59 100644
--- a/servers/rendering/rasterizer_rd/shaders/ssao_blur.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/ssao_blur.glsl
@@ -1,12 +1,10 @@
-/* clang-format off */
-[compute]
+#[compute]
#version 450
VERSION_DEFINES
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
-/* clang-format on */
layout(set = 0, binding = 0) uniform sampler2D source_ssao;
layout(set = 1, binding = 0) uniform sampler2D source_depth;
@@ -46,10 +44,9 @@ const float gaussian[R + 1] =
//float[](0.111220, 0.107798, 0.098151, 0.083953, 0.067458, 0.050920, 0.036108); // stddev = 3.0
void main() {
-
// Pixel being shaded
ivec2 ssC = ivec2(gl_GlobalInvocationID.xy);
- if (any(greaterThan(ssC, params.screen_size))) { //too large, do nothing
+ if (any(greaterThanEqual(ssC, params.screen_size))) { //too large, do nothing
return;
}
@@ -122,7 +119,6 @@ void main() {
// We already handled the zero case above. This loop should be unrolled and the static branch optimized out,
// so the IF statement has no runtime cost
if (r != 0) {
-
ivec2 ppos = ssC + params.axis * (r * params.filter_scale);
float value = texelFetch(source_ssao, clamp(ppos, ivec2(0), clamp_limit), 0).r;
ivec2 rpos = clamp(ppos, ivec2(0), clamp_limit);
diff --git a/servers/rendering/rasterizer_rd/shaders/ssao_minify.glsl b/servers/rendering/rasterizer_rd/shaders/ssao_minify.glsl
index 8728154347..263fca386f 100644
--- a/servers/rendering/rasterizer_rd/shaders/ssao_minify.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/ssao_minify.glsl
@@ -1,12 +1,10 @@
-/* clang-format off */
-[compute]
+#[compute]
#version 450
VERSION_DEFINES
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
-/* clang-format on */
layout(push_constant, binding = 1, std430) uniform Params {
vec2 pixel_size;
@@ -26,7 +24,6 @@ layout(r32f, set = 0, binding = 0) uniform restrict readonly image2D source_imag
layout(r32f, set = 1, binding = 0) uniform restrict writeonly image2D dest_image;
void main() {
-
ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
if (any(greaterThan(pos, params.source_size >> 1))) { //too large, do nothing
diff --git a/servers/rendering/rasterizer_rd/shaders/subsurface_scattering.glsl b/servers/rendering/rasterizer_rd/shaders/subsurface_scattering.glsl
new file mode 100644
index 0000000000..88a953562f
--- /dev/null
+++ b/servers/rendering/rasterizer_rd/shaders/subsurface_scattering.glsl
@@ -0,0 +1,189 @@
+#[compute]
+
+#version 450
+
+VERSION_DEFINES
+
+layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
+
+#ifdef USE_25_SAMPLES
+const int kernel_size = 13;
+
+const vec2 kernel[kernel_size] = vec2[](
+ vec2(0.530605, 0.0),
+ vec2(0.0211412, 0.0208333),
+ vec2(0.0402784, 0.0833333),
+ vec2(0.0493588, 0.1875),
+ vec2(0.0410172, 0.333333),
+ vec2(0.0263642, 0.520833),
+ vec2(0.017924, 0.75),
+ vec2(0.0128496, 1.02083),
+ vec2(0.0094389, 1.33333),
+ vec2(0.00700976, 1.6875),
+ vec2(0.00500364, 2.08333),
+ vec2(0.00333804, 2.52083),
+ vec2(0.000973794, 3.0));
+
+const vec4 skin_kernel[kernel_size] = vec4[](
+ vec4(0.530605, 0.613514, 0.739601, 0),
+ vec4(0.0211412, 0.0459286, 0.0378196, 0.0208333),
+ vec4(0.0402784, 0.0657244, 0.04631, 0.0833333),
+ vec4(0.0493588, 0.0367726, 0.0219485, 0.1875),
+ vec4(0.0410172, 0.0199899, 0.0118481, 0.333333),
+ vec4(0.0263642, 0.0119715, 0.00684598, 0.520833),
+ vec4(0.017924, 0.00711691, 0.00347194, 0.75),
+ vec4(0.0128496, 0.00356329, 0.00132016, 1.02083),
+ vec4(0.0094389, 0.00139119, 0.000416598, 1.33333),
+ vec4(0.00700976, 0.00049366, 0.000151938, 1.6875),
+ vec4(0.00500364, 0.00020094, 5.28848e-005, 2.08333),
+ vec4(0.00333804, 7.85443e-005, 1.2945e-005, 2.52083),
+ vec4(0.000973794, 1.11862e-005, 9.43437e-007, 3));
+
+#endif //USE_25_SAMPLES
+
+#ifdef USE_17_SAMPLES
+const int kernel_size = 9;
+const vec2 kernel[kernel_size] = vec2[](
+ vec2(0.536343, 0.0),
+ vec2(0.0324462, 0.03125),
+ vec2(0.0582416, 0.125),
+ vec2(0.0571056, 0.28125),
+ vec2(0.0347317, 0.5),
+ vec2(0.0216301, 0.78125),
+ vec2(0.0144609, 1.125),
+ vec2(0.0100386, 1.53125),
+ vec2(0.00317394, 2.0));
+
+const vec4 skin_kernel[kernel_size] = vec4[](
+ vec4(0.536343, 0.624624, 0.748867, 0),
+ vec4(0.0324462, 0.0656718, 0.0532821, 0.03125),
+ vec4(0.0582416, 0.0659959, 0.0411329, 0.125),
+ vec4(0.0571056, 0.0287432, 0.0172844, 0.28125),
+ vec4(0.0347317, 0.0151085, 0.00871983, 0.5),
+ vec4(0.0216301, 0.00794618, 0.00376991, 0.78125),
+ vec4(0.0144609, 0.00317269, 0.00106399, 1.125),
+ vec4(0.0100386, 0.000914679, 0.000275702, 1.53125),
+ vec4(0.00317394, 0.000134823, 3.77269e-005, 2));
+#endif //USE_17_SAMPLES
+
+#ifdef USE_11_SAMPLES
+const int kernel_size = 6;
+const vec2 kernel[kernel_size] = vec2[](
+ vec2(0.560479, 0.0),
+ vec2(0.0771802, 0.08),
+ vec2(0.0821904, 0.32),
+ vec2(0.03639, 0.72),
+ vec2(0.0192831, 1.28),
+ vec2(0.00471691, 2.0));
+
+const vec4 skin_kernel[kernel_size] = vec4[](
+
+ vec4(0.560479, 0.669086, 0.784728, 0),
+ vec4(0.0771802, 0.113491, 0.0793803, 0.08),
+ vec4(0.0821904, 0.0358608, 0.0209261, 0.32),
+ vec4(0.03639, 0.0130999, 0.00643685, 0.72),
+ vec4(0.0192831, 0.00282018, 0.00084214, 1.28),
+ vec4(0.00471691, 0.000184771, 5.07565e-005, 2));
+
+#endif //USE_11_SAMPLES
+
+layout(push_constant, binding = 1, std430) uniform Params {
+ ivec2 screen_size;
+ float camera_z_far;
+ float camera_z_near;
+
+ bool vertical;
+ bool orthogonal;
+ float unit_size;
+ float scale;
+
+ float depth_scale;
+ uint pad[3];
+}
+params;
+
+layout(set = 0, binding = 0) uniform sampler2D source_image;
+layout(rgba16f, set = 1, binding = 0) uniform restrict writeonly image2D dest_image;
+layout(set = 2, binding = 0) uniform sampler2D source_depth;
+
+void do_filter(inout vec3 color_accum, inout vec3 divisor, vec2 uv, vec2 step, bool p_skin) {
+ // Accumulate the other samples:
+ for (int i = 1; i < kernel_size; i++) {
+ // Fetch color and depth for current sample:
+ vec2 offset = uv + kernel[i].y * step;
+ vec4 color = texture(source_image, offset);
+
+ if (abs(color.a) < 0.001) {
+ break; //mix no more
+ }
+
+ vec3 w;
+ if (p_skin) {
+ //skin
+ w = skin_kernel[i].rgb;
+ } else {
+ w = vec3(kernel[i].x);
+ }
+
+ color_accum += color.rgb * w;
+ divisor += w;
+ }
+}
+
+void main() {
+ // Pixel being shaded
+ ivec2 ssC = ivec2(gl_GlobalInvocationID.xy);
+
+ if (any(greaterThanEqual(ssC, params.screen_size))) { //too large, do nothing
+ return;
+ }
+
+ vec2 uv = (vec2(ssC) + 0.5) / vec2(params.screen_size);
+
+ // Fetch color of current pixel:
+ vec4 base_color = texture(source_image, uv);
+ float strength = abs(base_color.a);
+
+ if (strength > 0.0) {
+ vec2 dir = params.vertical ? vec2(0.0, 1.0) : vec2(1.0, 0.0);
+
+ // Fetch linear depth of current pixel:
+ float depth = texture(source_depth, uv).r * 2.0 - 1.0;
+ float depth_scale;
+
+ if (params.orthogonal) {
+ depth = ((depth + (params.camera_z_far + params.camera_z_near) / (params.camera_z_far - params.camera_z_near)) * (params.camera_z_far - params.camera_z_near)) / 2.0;
+ depth_scale = params.unit_size; //remember depth is negative by default in OpenGL
+ } else {
+ depth = 2.0 * params.camera_z_near * params.camera_z_far / (params.camera_z_far + params.camera_z_near - depth * (params.camera_z_far - params.camera_z_near));
+ depth_scale = params.unit_size / depth; //remember depth is negative by default in OpenGL
+ }
+
+ float scale = mix(params.scale, depth_scale, params.depth_scale);
+
+ // Calculate the final step to fetch the surrounding pixels:
+ vec2 step = scale * dir;
+ step *= strength;
+ step /= 3.0;
+ // Accumulate the center sample:
+
+ vec3 divisor;
+ bool skin = bool(base_color.a < 0.0);
+
+ if (skin) {
+ //skin
+ divisor = skin_kernel[0].rgb;
+ } else {
+ divisor = vec3(kernel[0].x);
+ }
+
+ vec3 color = base_color.rgb * divisor;
+
+ do_filter(color, divisor, uv, step, skin);
+ do_filter(color, divisor, uv, -step, skin);
+
+ base_color.rgb = color / divisor;
+ }
+
+ imageStore(dest_image, ssC, base_color);
+}
diff --git a/servers/rendering/rasterizer_rd/shaders/tonemap.glsl b/servers/rendering/rasterizer_rd/shaders/tonemap.glsl
index 524ca5e2ea..b7c46a7d0e 100644
--- a/servers/rendering/rasterizer_rd/shaders/tonemap.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/tonemap.glsl
@@ -1,29 +1,24 @@
-/* clang-format off */
-[vertex]
+#[vertex]
#version 450
VERSION_DEFINES
layout(location = 0) out vec2 uv_interp;
-/* clang-format on */
void main() {
-
vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
uv_interp = base_arr[gl_VertexIndex];
gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0);
}
-/* clang-format off */
-[fragment]
+#[fragment]
#version 450
VERSION_DEFINES
layout(location = 0) in vec2 uv_interp;
-/* clang-format on */
layout(set = 0, binding = 0) uniform sampler2D source_color;
layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure;
@@ -48,6 +43,10 @@ layout(push_constant, binding = 1, std430) uniform Params {
float exposure;
float white;
float auto_exposure_grey;
+
+ vec2 pixel_size;
+ bool use_fxaa;
+ uint pad;
}
params;
@@ -255,25 +254,74 @@ vec3 apply_color_correction(vec3 color, sampler3D correction_tex) {
return texture(correction_tex, color).rgb;
}
+vec3 do_fxaa(vec3 color, float exposure, vec2 uv_interp) {
+ const float FXAA_REDUCE_MIN = (1.0 / 128.0);
+ const float FXAA_REDUCE_MUL = (1.0 / 8.0);
+ const float FXAA_SPAN_MAX = 8.0;
+
+ vec3 rgbNW = textureLod(source_color, uv_interp + vec2(-1.0, -1.0) * params.pixel_size, 0.0).xyz * exposure;
+ vec3 rgbNE = textureLod(source_color, uv_interp + vec2(1.0, -1.0) * params.pixel_size, 0.0).xyz * exposure;
+ vec3 rgbSW = textureLod(source_color, uv_interp + vec2(-1.0, 1.0) * params.pixel_size, 0.0).xyz * exposure;
+ vec3 rgbSE = textureLod(source_color, uv_interp + vec2(1.0, 1.0) * params.pixel_size, 0.0).xyz * exposure;
+ vec3 rgbM = color;
+ vec3 luma = vec3(0.299, 0.587, 0.114);
+ float lumaNW = dot(rgbNW, luma);
+ float lumaNE = dot(rgbNE, luma);
+ float lumaSW = dot(rgbSW, luma);
+ float lumaSE = dot(rgbSE, luma);
+ float lumaM = dot(rgbM, luma);
+ float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
+ float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));
+
+ vec2 dir;
+ dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));
+ dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));
+
+ float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) *
+ (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;
+
+ vec3 rgbA = 0.5 * (textureLod(source_color, uv_interp + dir * (1.0 / 3.0 - 0.5), 0.0).xyz * exposure + textureLod(source_color, uv_interp + dir * (2.0 / 3.0 - 0.5), 0.0).xyz) * exposure;
+ vec3 rgbB = rgbA * 0.5 + 0.25 * (textureLod(source_color, uv_interp + dir * -0.5, 0.0).xyz * exposure +
+ textureLod(source_color, uv_interp + dir * 0.5, 0.0).xyz * exposure);
+
+ float lumaB = dot(rgbB, luma);
+ if ((lumaB < lumaMin) || (lumaB > lumaMax)) {
+ return rgbA;
+ } else {
+ return rgbB;
+ }
+}
+
void main() {
vec3 color = textureLod(source_color, uv_interp, 0.0f).rgb;
// Exposure
+ float exposure = params.exposure;
+
if (params.use_auto_exposure) {
- color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / params.auto_exposure_grey;
+ exposure *= 1.0 / (texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / params.auto_exposure_grey);
}
- color *= params.exposure;
+ color *= exposure;
// Early Tonemap & SRGB Conversion
if (params.use_glow && params.glow_mode == GLOW_MODE_MIX) {
-
vec3 glow = gather_glow(source_glow, uv_interp);
color.rgb = mix(color.rgb, glow, params.glow_intensity);
}
+ if (params.use_fxaa) {
+ color = do_fxaa(color, exposure, uv_interp);
+ }
color = apply_tonemapping(color, params.white);
color = linear_to_srgb(color); // regular linear -> SRGB conversion
@@ -281,7 +329,6 @@ void main() {
// Glow
if (params.use_glow && params.glow_mode != GLOW_MODE_MIX) {
-
vec3 glow = gather_glow(source_glow, uv_interp) * params.glow_intensity;
// high dynamic range -> SRGB
diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp
index 3c1795161d..55b65d2747 100644
--- a/servers/rendering/rendering_device.cpp
+++ b/servers/rendering/rendering_device.cpp
@@ -29,19 +29,22 @@
/*************************************************************************/
#include "rendering_device.h"
+#include "core/method_bind_ext.gen.inc"
+#include "rendering_device_binds.h"
-RenderingDevice *RenderingDevice::singleton = NULL;
+RenderingDevice *RenderingDevice::singleton = nullptr;
RenderingDevice *RenderingDevice::get_singleton() {
return singleton;
}
-RenderingDevice::ShaderCompileFunction RenderingDevice::compile_function = NULL;
-RenderingDevice::ShaderCacheFunction RenderingDevice::cache_function = NULL;
+RenderingDevice::ShaderCompileFunction RenderingDevice::compile_function = nullptr;
+RenderingDevice::ShaderCacheFunction RenderingDevice::cache_function = nullptr;
void RenderingDevice::shader_set_compile_function(ShaderCompileFunction p_function) {
compile_function = p_function;
}
+
void RenderingDevice::shader_set_cache_function(ShaderCacheFunction p_function) {
cache_function = p_function;
}
@@ -59,6 +62,743 @@ Vector<uint8_t> RenderingDevice::shader_compile_from_source(ShaderStage p_stage,
return compile_function(p_stage, p_source_code, p_language, r_error);
}
+RID RenderingDevice::_texture_create(const Ref<RDTextureFormat> &p_format, const Ref<RDTextureView> &p_view, const TypedArray<PackedByteArray> &p_data) {
+ ERR_FAIL_COND_V(p_format.is_null(), RID());
+ ERR_FAIL_COND_V(p_view.is_null(), RID());
+ Vector<Vector<uint8_t>> data;
+ for (int i = 0; i < p_data.size(); i++) {
+ Vector<uint8_t> byte_slice = p_data[i];
+ ERR_FAIL_COND_V(byte_slice.empty(), RID());
+ data.push_back(byte_slice);
+ }
+ return texture_create(p_format->base, p_view->base, data);
+}
+
+RID RenderingDevice::_texture_create_shared(const Ref<RDTextureView> &p_view, RID p_with_texture) {
+ ERR_FAIL_COND_V(p_view.is_null(), RID());
+
+ return texture_create_shared(p_view->base, p_with_texture);
+}
+
+RID RenderingDevice::_texture_create_shared_from_slice(const Ref<RDTextureView> &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, TextureSliceType p_slice_type) {
+ ERR_FAIL_COND_V(p_view.is_null(), RID());
+
+ return texture_create_shared_from_slice(p_view->base, p_with_texture, p_layer, p_mipmap, p_slice_type);
+}
+
+RenderingDevice::FramebufferFormatID RenderingDevice::_framebuffer_format_create(const TypedArray<RDAttachmentFormat> &p_attachments) {
+ Vector<AttachmentFormat> attachments;
+ attachments.resize(p_attachments.size());
+
+ for (int i = 0; i < p_attachments.size(); i++) {
+ Ref<RDAttachmentFormat> af = p_attachments[i];
+ ERR_FAIL_COND_V(af.is_null(), INVALID_FORMAT_ID);
+ attachments.write[i] = af->base;
+ }
+ return framebuffer_format_create(attachments);
+}
+
+RID RenderingDevice::_framebuffer_create(const Array &p_textures, FramebufferFormatID p_format_check) {
+ Vector<RID> textures = Variant(p_textures);
+ return framebuffer_create(textures, p_format_check);
+}
+
+RID RenderingDevice::_sampler_create(const Ref<RDSamplerState> &p_state) {
+ ERR_FAIL_COND_V(p_state.is_null(), RID());
+
+ return sampler_create(p_state->base);
+}
+
+RenderingDevice::VertexFormatID RenderingDevice::_vertex_format_create(const TypedArray<RDVertexAttribute> &p_vertex_formats) {
+ Vector<VertexAttribute> descriptions;
+ descriptions.resize(p_vertex_formats.size());
+
+ for (int i = 0; i < p_vertex_formats.size(); i++) {
+ Ref<RDVertexAttribute> af = p_vertex_formats[i];
+ ERR_FAIL_COND_V(af.is_null(), INVALID_FORMAT_ID);
+ descriptions.write[i] = af->base;
+ }
+ return vertex_format_create(descriptions);
+}
+
+RID RenderingDevice::_vertex_array_create(uint32_t p_vertex_count, VertexFormatID p_vertex_format, const TypedArray<RID> &p_src_buffers) {
+ Vector<RID> buffers = Variant(p_src_buffers);
+
+ return vertex_array_create(p_vertex_count, p_vertex_format, buffers);
+}
+
+Ref<RDShaderBytecode> RenderingDevice::_shader_compile_from_source(const Ref<RDShaderSource> &p_source, bool p_allow_cache) {
+ ERR_FAIL_COND_V(p_source.is_null(), Ref<RDShaderBytecode>());
+
+ Ref<RDShaderBytecode> bytecode;
+ bytecode.instance();
+ for (int i = 0; i < RD::SHADER_STAGE_MAX; i++) {
+ String error;
+
+ ShaderStage stage = ShaderStage(i);
+ Vector<uint8_t> spirv = shader_compile_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);
+ }
+ return bytecode;
+}
+
+RID RenderingDevice::shader_create_from_bytecode(const Ref<RDShaderBytecode> &p_bytecode) {
+ ERR_FAIL_COND_V(p_bytecode.is_null(), RID());
+
+ Vector<ShaderStageData> stage_data;
+ for (int i = 0; i < RD::SHADER_STAGE_MAX; i++) {
+ ShaderStage stage = ShaderStage(i);
+ ShaderStageData sd;
+ sd.shader_stage = stage;
+ String error = p_bytecode->get_stage_compile_error(stage);
+ ERR_FAIL_COND_V_MSG(error != String(), RID(), "Can't create a shader from an errored bytecode. Check errors in source bytecode.");
+ sd.spir_v = p_bytecode->get_stage_bytecode(stage);
+ if (sd.spir_v.empty()) {
+ continue;
+ }
+ stage_data.push_back(sd);
+ }
+
+ return shader_create(stage_data);
+}
+
+RID RenderingDevice::_uniform_set_create(const Array &p_uniforms, RID p_shader, uint32_t p_shader_set) {
+ Vector<Uniform> uniforms;
+ uniforms.resize(p_uniforms.size());
+ for (int i = 0; i < p_uniforms.size(); i++) {
+ Ref<RDUniform> uniform = p_uniforms[i];
+ ERR_FAIL_COND_V(!uniform.is_valid(), RID());
+ uniforms.write[i] = uniform->base;
+ }
+ return uniform_set_create(uniforms, p_shader, p_shader_set);
+}
+
+Error RenderingDevice::_buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const Vector<uint8_t> &p_data, bool p_sync_with_draw) {
+ return buffer_update(p_buffer, p_offset, p_size, p_data.ptr(), p_sync_with_draw);
+}
+
+RID RenderingDevice::_render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const Ref<RDPipelineRasterizationState> &p_rasterization_state, const Ref<RDPipelineMultisampleState> &p_multisample_state, const Ref<RDPipelineDepthStencilState> &p_depth_stencil_state, const Ref<RDPipelineColorBlendState> &p_blend_state, int p_dynamic_state_flags) {
+ PipelineRasterizationState rasterization_state;
+ if (p_rasterization_state.is_valid()) {
+ rasterization_state = p_rasterization_state->base;
+ }
+
+ PipelineMultisampleState multisample_state;
+ if (p_multisample_state.is_valid()) {
+ multisample_state = p_multisample_state->base;
+ for (int i = 0; i < p_multisample_state->sample_masks.size(); i++) {
+ int64_t mask = p_multisample_state->sample_masks[i];
+ multisample_state.sample_mask.push_back(mask);
+ }
+ }
+
+ PipelineDepthStencilState depth_stencil_state;
+ if (p_depth_stencil_state.is_valid()) {
+ depth_stencil_state = p_depth_stencil_state->base;
+ }
+
+ PipelineColorBlendState color_blend_state;
+ if (p_blend_state.is_valid()) {
+ color_blend_state = p_blend_state->base;
+ for (int i = 0; i < p_blend_state->attachments.size(); i++) {
+ Ref<RDPipelineColorBlendStateAttachment> attachment = p_blend_state->attachments[i];
+ if (attachment.is_valid()) {
+ color_blend_state.attachments.push_back(attachment->base);
+ }
+ }
+ }
+
+ return render_pipeline_create(p_shader, p_framebuffer_format, p_vertex_format, p_render_primitive, rasterization_state, multisample_state, depth_stencil_state, color_blend_state, p_dynamic_state_flags);
+}
+
+Vector<int64_t> RenderingDevice::_draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region) {
+ Vector<DrawListID> splits;
+ splits.resize(p_splits);
+ draw_list_begin_split(p_framebuffer, p_splits, splits.ptrw(), p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, p_region);
+
+ Vector<int64_t> split_ids;
+ split_ids.resize(splits.size());
+ for (int i = 0; i < splits.size(); i++) {
+ split_ids.write[i] = splits[i];
+ }
+
+ return split_ids;
+}
+
+void RenderingDevice::_draw_list_set_push_constant(DrawListID p_list, const Vector<uint8_t> &p_data, uint32_t p_data_size) {
+ ERR_FAIL_COND((uint32_t)p_data.size() > p_data_size);
+ draw_list_set_push_constant(p_list, p_data.ptr(), p_data_size);
+}
+
+void RenderingDevice::_compute_list_set_push_constant(ComputeListID p_list, const Vector<uint8_t> &p_data, uint32_t p_data_size) {
+ ERR_FAIL_COND((uint32_t)p_data.size() > p_data_size);
+ compute_list_set_push_constant(p_list, p_data.ptr(), p_data_size);
+}
+
+void RenderingDevice::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("texture_create", "format", "view", "data"), &RenderingDevice::_texture_create, DEFVAL(Array()));
+ ClassDB::bind_method(D_METHOD("texture_create_shared", "view", "with_texture"), &RenderingDevice::_texture_create_shared);
+ ClassDB::bind_method(D_METHOD("texture_create_shared_from_slice", "view", "with_texture", "layer", "mipmap", "slice_type"), &RenderingDevice::_texture_create_shared_from_slice, DEFVAL(TEXTURE_SLICE_2D));
+
+ ClassDB::bind_method(D_METHOD("texture_update", "texture", "layer", "data", "sync_with_draw"), &RenderingDevice::texture_update, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("texture_get_data", "texture", "layer"), &RenderingDevice::texture_get_data);
+
+ ClassDB::bind_method(D_METHOD("texture_is_format_supported_for_usage", "format", "usage_flags"), &RenderingDevice::texture_is_format_supported_for_usage);
+
+ ClassDB::bind_method(D_METHOD("texture_is_shared", "texture"), &RenderingDevice::texture_is_shared);
+ ClassDB::bind_method(D_METHOD("texture_is_valid", "texture"), &RenderingDevice::texture_is_valid);
+
+ ClassDB::bind_method(D_METHOD("texture_copy", "from_texture", "to_texture", "from_pos", "to_pos", "size", "src_mipmap", "dst_mipmap", "src_layer", "dst_layer", "sync_with_draw"), &RenderingDevice::texture_copy, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("texture_clear", "texture", "color", "base_mipmap", "mipmap_count", "base_layer", "layer_count", "sync_with_draw"), &RenderingDevice::texture_clear, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("texture_resolve_multisample", "from_texture", "to_texture", "sync_with_draw"), &RenderingDevice::texture_resolve_multisample, DEFVAL(false));
+
+ ClassDB::bind_method(D_METHOD("framebuffer_format_create", "attachments"), &RenderingDevice::_framebuffer_format_create);
+ ClassDB::bind_method(D_METHOD("framebuffer_format_get_texture_samples", "format"), &RenderingDevice::framebuffer_format_get_texture_samples);
+ ClassDB::bind_method(D_METHOD("framebuffer_create", "textures", "validate_with_format"), &RenderingDevice::_framebuffer_create, DEFVAL(INVALID_FORMAT_ID));
+ ClassDB::bind_method(D_METHOD("framebuffer_get_format", "framebuffer"), &RenderingDevice::framebuffer_get_format);
+
+ ClassDB::bind_method(D_METHOD("sampler_create", "state"), &RenderingDevice::_sampler_create);
+
+ ClassDB::bind_method(D_METHOD("vertex_buffer_create", "size_bytes", "data"), &RenderingDevice::vertex_buffer_create, DEFVAL(Vector<uint8_t>()));
+ ClassDB::bind_method(D_METHOD("vertex_format_create", "vertex_descriptions"), &RenderingDevice::_vertex_format_create);
+
+ ClassDB::bind_method(D_METHOD("index_buffer_create", "size_indices", "format", "data"), &RenderingDevice::index_buffer_create, DEFVAL(Vector<uint8_t>()), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("index_array_create", "index_buffer", "index_offset", "index_count"), &RenderingDevice::index_array_create);
+
+ ClassDB::bind_method(D_METHOD("shader_compile_from_source", "shader_source", "allow_cache"), &RenderingDevice::_shader_compile_from_source, DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("shader_create", "shader_data"), &RenderingDevice::shader_create_from_bytecode);
+ ClassDB::bind_method(D_METHOD("shader_get_vertex_input_attribute_mask", "shader"), &RenderingDevice::shader_get_vertex_input_attribute_mask);
+
+ ClassDB::bind_method(D_METHOD("uniform_buffer_create", "size_bytes", "data"), &RenderingDevice::uniform_buffer_create, DEFVAL(Vector<uint8_t>()));
+ ClassDB::bind_method(D_METHOD("storage_buffer_create", "size_bytes", "data"), &RenderingDevice::storage_buffer_create, DEFVAL(Vector<uint8_t>()));
+ ClassDB::bind_method(D_METHOD("texture_buffer_create", "size_bytes", "format", "data"), &RenderingDevice::texture_buffer_create, DEFVAL(Vector<uint8_t>()));
+
+ ClassDB::bind_method(D_METHOD("uniform_set_create", "uniforms", "shader", "shader_set"), &RenderingDevice::_uniform_set_create);
+ ClassDB::bind_method(D_METHOD("uniform_set_is_valid", "uniform_set"), &RenderingDevice::uniform_set_is_valid);
+
+ ClassDB::bind_method(D_METHOD("buffer_update", "buffer", "offset", "size_bytes", "data", "sync_with_draw"), &RenderingDevice::_buffer_update, DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("buffer_get_data", "buffer"), &RenderingDevice::buffer_get_data);
+
+ ClassDB::bind_method(D_METHOD("render_pipeline_create", "shader", "framebuffer_format", "vertex_format", "primitive", "rasterization_state", "multisample_state", "stencil_state", "color_blend_state", "dynamic_state_flags"), &RenderingDevice::_render_pipeline_create, DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("render_pipeline_is_valid", "render_pipeline"), &RenderingDevice::render_pipeline_is_valid);
+
+ ClassDB::bind_method(D_METHOD("compute_pipeline_create", "shader"), &RenderingDevice::compute_pipeline_create);
+ ClassDB::bind_method(D_METHOD("compute_pipeline_is_valid", "compute_pieline"), &RenderingDevice::compute_pipeline_is_valid);
+
+ ClassDB::bind_method(D_METHOD("screen_get_width", "screen"), &RenderingDevice::screen_get_width, DEFVAL(DisplayServer::MAIN_WINDOW_ID));
+ ClassDB::bind_method(D_METHOD("screen_get_height", "screen"), &RenderingDevice::screen_get_height, DEFVAL(DisplayServer::MAIN_WINDOW_ID));
+ ClassDB::bind_method(D_METHOD("screen_get_framebuffer_format"), &RenderingDevice::screen_get_framebuffer_format);
+
+ ClassDB::bind_method(D_METHOD("draw_list_begin_for_screen", "screen", "clear_color"), &RenderingDevice::draw_list_begin_for_screen, DEFVAL(DisplayServer::MAIN_WINDOW_ID), DEFVAL(Color()));
+
+ ClassDB::bind_method(D_METHOD("draw_list_begin", "framebuffer", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region"), &RenderingDevice::draw_list_begin, DEFVAL(Vector<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2i()));
+ ClassDB::bind_method(D_METHOD("draw_list_begin_split", "framebuffer", "splits", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region"), &RenderingDevice::_draw_list_begin_split, DEFVAL(Vector<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2i()));
+
+ ClassDB::bind_method(D_METHOD("draw_list_bind_render_pipeline", "draw_list", "render_pipeline"), &RenderingDevice::draw_list_bind_render_pipeline);
+ ClassDB::bind_method(D_METHOD("draw_list_bind_uniform_set", "draw_list", "uniform_set", "set_index"), &RenderingDevice::draw_list_bind_uniform_set);
+ ClassDB::bind_method(D_METHOD("draw_list_bind_vertex_array", "draw_list", "vertex_array"), &RenderingDevice::draw_list_bind_vertex_array);
+ ClassDB::bind_method(D_METHOD("draw_list_bind_index_array", "draw_list", "index_array"), &RenderingDevice::draw_list_bind_index_array);
+ ClassDB::bind_method(D_METHOD("draw_list_set_push_constant", "draw_list", "buffer", "size_bytes"), &RenderingDevice::_draw_list_set_push_constant);
+
+ ClassDB::bind_method(D_METHOD("draw_list_draw", "draw_list", "use_indices", "instances", "procedural_vertex_count"), &RenderingDevice::draw_list_draw, DEFVAL(0));
+
+ ClassDB::bind_method(D_METHOD("draw_list_enable_scissor", "draw_list", "rect"), &RenderingDevice::draw_list_enable_scissor, DEFVAL(Rect2i()));
+ ClassDB::bind_method(D_METHOD("draw_list_disable_scissor", "draw_list"), &RenderingDevice::draw_list_disable_scissor);
+
+ ClassDB::bind_method(D_METHOD("draw_list_end"), &RenderingDevice::draw_list_end);
+
+ ClassDB::bind_method(D_METHOD("compute_list_begin"), &RenderingDevice::compute_list_begin);
+ ClassDB::bind_method(D_METHOD("compute_list_bind_compute_pipeline", "compute_list", "compute_pipeline"), &RenderingDevice::compute_list_bind_compute_pipeline);
+ ClassDB::bind_method(D_METHOD("compute_list_set_push_constant", "compute_list", "buffer", "size_bytes"), &RenderingDevice::_compute_list_set_push_constant);
+ ClassDB::bind_method(D_METHOD("compute_list_bind_uniform_set", "compute_list", "uniform_set", "set_index"), &RenderingDevice::compute_list_bind_uniform_set);
+ ClassDB::bind_method(D_METHOD("compute_list_dispatch", "compute_list", "x_groups", "y_groups", "z_groups"), &RenderingDevice::compute_list_dispatch);
+ ClassDB::bind_method(D_METHOD("compute_list_add_barrier", "compute_list"), &RenderingDevice::compute_list_add_barrier);
+ ClassDB::bind_method(D_METHOD("compute_list_end"), &RenderingDevice::compute_list_end);
+
+ ClassDB::bind_method(D_METHOD("free", "rid"), &RenderingDevice::free);
+
+ ClassDB::bind_method(D_METHOD("capture_timestamp", "name", "sync_to_draw"), &RenderingDevice::capture_timestamp);
+ ClassDB::bind_method(D_METHOD("get_captured_timestamps_count"), &RenderingDevice::get_captured_timestamps_count);
+ ClassDB::bind_method(D_METHOD("get_captured_timestamps_frame"), &RenderingDevice::get_captured_timestamps_frame);
+ ClassDB::bind_method(D_METHOD("get_captured_timestamp_gpu_time", "index"), &RenderingDevice::get_captured_timestamp_gpu_time);
+ ClassDB::bind_method(D_METHOD("get_captured_timestamp_cpu_time", "index"), &RenderingDevice::get_captured_timestamp_cpu_time);
+ ClassDB::bind_method(D_METHOD("get_captured_timestamp_name", "index"), &RenderingDevice::get_captured_timestamp_name);
+
+ ClassDB::bind_method(D_METHOD("limit_get", "limit"), &RenderingDevice::limit_get);
+ ClassDB::bind_method(D_METHOD("get_frame_delay"), &RenderingDevice::get_frame_delay);
+ ClassDB::bind_method(D_METHOD("submit"), &RenderingDevice::submit);
+ ClassDB::bind_method(D_METHOD("sync"), &RenderingDevice::sync);
+
+ ClassDB::bind_method(D_METHOD("create_local_device"), &RenderingDevice::create_local_device);
+
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R4G4_UNORM_PACK8);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R4G4B4A4_UNORM_PACK16);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_B4G4R4A4_UNORM_PACK16);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R5G6B5_UNORM_PACK16);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_B5G6R5_UNORM_PACK16);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R5G5B5A1_UNORM_PACK16);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_B5G5R5A1_UNORM_PACK16);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_A1R5G5B5_UNORM_PACK16);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R8_UNORM);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R8_SNORM);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R8_USCALED);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R8_SSCALED);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R8_UINT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R8_SINT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R8_SRGB);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R8G8_UNORM);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R8G8_SNORM);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R8G8_USCALED);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R8G8_SSCALED);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R8G8_UINT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R8G8_SINT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R8G8_SRGB);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R8G8B8_UNORM);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R8G8B8_SNORM);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R8G8B8_USCALED);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R8G8B8_SSCALED);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R8G8B8_UINT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R8G8B8_SINT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R8G8B8_SRGB);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_B8G8R8_UNORM);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_B8G8R8_SNORM);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_B8G8R8_USCALED);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_B8G8R8_SSCALED);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_B8G8R8_UINT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_B8G8R8_SINT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_B8G8R8_SRGB);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R8G8B8A8_UNORM);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R8G8B8A8_SNORM);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R8G8B8A8_USCALED);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R8G8B8A8_SSCALED);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R8G8B8A8_UINT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R8G8B8A8_SINT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R8G8B8A8_SRGB);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_B8G8R8A8_UNORM);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_B8G8R8A8_SNORM);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_B8G8R8A8_USCALED);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_B8G8R8A8_SSCALED);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_B8G8R8A8_UINT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_B8G8R8A8_SINT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_B8G8R8A8_SRGB);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_A8B8G8R8_UNORM_PACK32);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_A8B8G8R8_SNORM_PACK32);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_A8B8G8R8_USCALED_PACK32);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_A8B8G8R8_SSCALED_PACK32);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_A8B8G8R8_UINT_PACK32);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_A8B8G8R8_SINT_PACK32);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_A8B8G8R8_SRGB_PACK32);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_A2R10G10B10_UNORM_PACK32);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_A2R10G10B10_SNORM_PACK32);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_A2R10G10B10_USCALED_PACK32);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_A2R10G10B10_SSCALED_PACK32);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_A2R10G10B10_UINT_PACK32);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_A2R10G10B10_SINT_PACK32);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_A2B10G10R10_UNORM_PACK32);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_A2B10G10R10_SNORM_PACK32);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_A2B10G10R10_USCALED_PACK32);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_A2B10G10R10_SSCALED_PACK32);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_A2B10G10R10_UINT_PACK32);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_A2B10G10R10_SINT_PACK32);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R16_UNORM);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R16_SNORM);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R16_USCALED);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R16_SSCALED);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R16_UINT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R16_SINT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R16_SFLOAT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R16G16_UNORM);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R16G16_SNORM);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R16G16_USCALED);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R16G16_SSCALED);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R16G16_UINT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R16G16_SINT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R16G16_SFLOAT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R16G16B16_UNORM);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R16G16B16_SNORM);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R16G16B16_USCALED);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R16G16B16_SSCALED);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R16G16B16_UINT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R16G16B16_SINT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R16G16B16_SFLOAT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R16G16B16A16_UNORM);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R16G16B16A16_SNORM);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R16G16B16A16_USCALED);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R16G16B16A16_SSCALED);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R16G16B16A16_UINT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R16G16B16A16_SINT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R16G16B16A16_SFLOAT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R32_UINT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R32_SINT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R32_SFLOAT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R32G32_UINT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R32G32_SINT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R32G32_SFLOAT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R32G32B32_UINT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R32G32B32_SINT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R32G32B32_SFLOAT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R32G32B32A32_UINT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R32G32B32A32_SINT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R32G32B32A32_SFLOAT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R64_UINT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R64_SINT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R64_SFLOAT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R64G64_UINT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R64G64_SINT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R64G64_SFLOAT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R64G64B64_UINT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R64G64B64_SINT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R64G64B64_SFLOAT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R64G64B64A64_UINT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R64G64B64A64_SINT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R64G64B64A64_SFLOAT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_B10G11R11_UFLOAT_PACK32);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_D16_UNORM);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_X8_D24_UNORM_PACK32);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_D32_SFLOAT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_S8_UINT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_D16_UNORM_S8_UINT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_D24_UNORM_S8_UINT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_D32_SFLOAT_S8_UINT);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_BC1_RGB_UNORM_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_BC1_RGB_SRGB_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_BC1_RGBA_UNORM_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_BC1_RGBA_SRGB_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_BC2_UNORM_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_BC2_SRGB_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_BC3_UNORM_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_BC3_SRGB_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_BC4_UNORM_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_BC4_SNORM_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_BC5_UNORM_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_BC5_SNORM_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_BC6H_UFLOAT_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_BC6H_SFLOAT_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_BC7_UNORM_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_BC7_SRGB_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_ETC2_R8G8B8_SRGB_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_EAC_R11_UNORM_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_EAC_R11_SNORM_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_EAC_R11G11_UNORM_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_EAC_R11G11_SNORM_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_4x4_UNORM_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_4x4_SRGB_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_5x4_UNORM_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_5x4_SRGB_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_5x5_UNORM_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_5x5_SRGB_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_6x5_UNORM_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_6x5_SRGB_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_6x6_UNORM_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_6x6_SRGB_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_8x5_UNORM_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_8x5_SRGB_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_8x6_UNORM_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_8x6_SRGB_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_8x8_UNORM_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_8x8_SRGB_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_10x5_UNORM_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_10x5_SRGB_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_10x6_UNORM_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_10x6_SRGB_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_10x8_UNORM_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_10x8_SRGB_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_10x10_UNORM_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_10x10_SRGB_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_12x10_UNORM_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_12x10_SRGB_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_12x12_UNORM_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_ASTC_12x12_SRGB_BLOCK);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_G8B8G8R8_422_UNORM);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_B8G8R8G8_422_UNORM);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_G8_B8_R8_3PLANE_420_UNORM);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_G8_B8R8_2PLANE_420_UNORM);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_G8_B8_R8_3PLANE_422_UNORM);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_G8_B8R8_2PLANE_422_UNORM);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_G8_B8_R8_3PLANE_444_UNORM);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R10X6_UNORM_PACK16);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R10X6G10X6_UNORM_2PACK16);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R12X4_UNORM_PACK16);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R12X4G12X4_UNORM_2PACK16);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_G16B16G16R16_422_UNORM);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_B16G16R16G16_422_UNORM);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_G16_B16_R16_3PLANE_420_UNORM);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_G16_B16R16_2PLANE_420_UNORM);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_G16_B16_R16_3PLANE_422_UNORM);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_G16_B16R16_2PLANE_422_UNORM);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_G16_B16_R16_3PLANE_444_UNORM);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG);
+ BIND_ENUM_CONSTANT(DATA_FORMAT_MAX);
+
+ BIND_ENUM_CONSTANT(TEXTURE_TYPE_1D);
+ BIND_ENUM_CONSTANT(TEXTURE_TYPE_2D);
+ BIND_ENUM_CONSTANT(TEXTURE_TYPE_3D);
+ BIND_ENUM_CONSTANT(TEXTURE_TYPE_CUBE);
+ BIND_ENUM_CONSTANT(TEXTURE_TYPE_1D_ARRAY);
+ BIND_ENUM_CONSTANT(TEXTURE_TYPE_2D_ARRAY);
+ BIND_ENUM_CONSTANT(TEXTURE_TYPE_CUBE_ARRAY);
+ BIND_ENUM_CONSTANT(TEXTURE_TYPE_MAX);
+
+ BIND_ENUM_CONSTANT(TEXTURE_SAMPLES_1);
+ BIND_ENUM_CONSTANT(TEXTURE_SAMPLES_2);
+ BIND_ENUM_CONSTANT(TEXTURE_SAMPLES_4);
+ BIND_ENUM_CONSTANT(TEXTURE_SAMPLES_8);
+ BIND_ENUM_CONSTANT(TEXTURE_SAMPLES_16);
+ BIND_ENUM_CONSTANT(TEXTURE_SAMPLES_32);
+ BIND_ENUM_CONSTANT(TEXTURE_SAMPLES_64);
+ BIND_ENUM_CONSTANT(TEXTURE_SAMPLES_MAX);
+
+ BIND_ENUM_CONSTANT(TEXTURE_USAGE_SAMPLING_BIT);
+ BIND_ENUM_CONSTANT(TEXTURE_USAGE_COLOR_ATTACHMENT_BIT);
+ BIND_ENUM_CONSTANT(TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
+ BIND_ENUM_CONSTANT(TEXTURE_USAGE_STORAGE_BIT);
+ BIND_ENUM_CONSTANT(TEXTURE_USAGE_STORAGE_ATOMIC_BIT);
+ BIND_ENUM_CONSTANT(TEXTURE_USAGE_CPU_READ_BIT);
+ BIND_ENUM_CONSTANT(TEXTURE_USAGE_CAN_UPDATE_BIT);
+ BIND_ENUM_CONSTANT(TEXTURE_USAGE_CAN_COPY_FROM_BIT);
+ BIND_ENUM_CONSTANT(TEXTURE_USAGE_CAN_COPY_TO_BIT);
+ BIND_ENUM_CONSTANT(TEXTURE_USAGE_RESOLVE_ATTACHMENT_BIT);
+
+ BIND_ENUM_CONSTANT(TEXTURE_SWIZZLE_IDENTITY);
+ BIND_ENUM_CONSTANT(TEXTURE_SWIZZLE_ZERO);
+ BIND_ENUM_CONSTANT(TEXTURE_SWIZZLE_ONE);
+ BIND_ENUM_CONSTANT(TEXTURE_SWIZZLE_R);
+ BIND_ENUM_CONSTANT(TEXTURE_SWIZZLE_G);
+ BIND_ENUM_CONSTANT(TEXTURE_SWIZZLE_B);
+ BIND_ENUM_CONSTANT(TEXTURE_SWIZZLE_A);
+ BIND_ENUM_CONSTANT(TEXTURE_SWIZZLE_MAX);
+
+ BIND_ENUM_CONSTANT(TEXTURE_SLICE_2D);
+ BIND_ENUM_CONSTANT(TEXTURE_SLICE_CUBEMAP);
+ BIND_ENUM_CONSTANT(TEXTURE_SLICE_3D);
+
+ BIND_ENUM_CONSTANT(SAMPLER_FILTER_NEAREST);
+ BIND_ENUM_CONSTANT(SAMPLER_FILTER_LINEAR);
+ BIND_ENUM_CONSTANT(SAMPLER_REPEAT_MODE_REPEAT);
+ BIND_ENUM_CONSTANT(SAMPLER_REPEAT_MODE_MIRRORED_REPEAT);
+ BIND_ENUM_CONSTANT(SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE);
+ BIND_ENUM_CONSTANT(SAMPLER_REPEAT_MODE_CLAMP_TO_BORDER);
+ BIND_ENUM_CONSTANT(SAMPLER_REPEAT_MODE_MIRROR_CLAMP_TO_EDGE);
+ BIND_ENUM_CONSTANT(SAMPLER_REPEAT_MODE_MAX);
+
+ BIND_ENUM_CONSTANT(SAMPLER_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK);
+ BIND_ENUM_CONSTANT(SAMPLER_BORDER_COLOR_INT_TRANSPARENT_BLACK);
+ BIND_ENUM_CONSTANT(SAMPLER_BORDER_COLOR_FLOAT_OPAQUE_BLACK);
+ BIND_ENUM_CONSTANT(SAMPLER_BORDER_COLOR_INT_OPAQUE_BLACK);
+ BIND_ENUM_CONSTANT(SAMPLER_BORDER_COLOR_FLOAT_OPAQUE_WHITE);
+ BIND_ENUM_CONSTANT(SAMPLER_BORDER_COLOR_INT_OPAQUE_WHITE);
+ BIND_ENUM_CONSTANT(SAMPLER_BORDER_COLOR_MAX);
+
+ BIND_ENUM_CONSTANT(VERTEX_FREQUENCY_VERTEX);
+ BIND_ENUM_CONSTANT(VERTEX_FREQUENCY_INSTANCE);
+
+ BIND_ENUM_CONSTANT(INDEX_BUFFER_FORMAT_UINT16);
+ BIND_ENUM_CONSTANT(INDEX_BUFFER_FORMAT_UINT32);
+
+ BIND_ENUM_CONSTANT(UNIFORM_TYPE_SAMPLER); //for sampling only (sampler GLSL type)
+ BIND_ENUM_CONSTANT(UNIFORM_TYPE_SAMPLER_WITH_TEXTURE); // for sampling only); but includes a texture); (samplerXX GLSL type)); first a sampler then a texture
+ BIND_ENUM_CONSTANT(UNIFORM_TYPE_TEXTURE); //only texture); (textureXX GLSL type)
+ BIND_ENUM_CONSTANT(UNIFORM_TYPE_IMAGE); // storage image (imageXX GLSL type)); for compute mostly
+ BIND_ENUM_CONSTANT(UNIFORM_TYPE_TEXTURE_BUFFER); // buffer texture (or TBO); textureBuffer type)
+ BIND_ENUM_CONSTANT(UNIFORM_TYPE_SAMPLER_WITH_TEXTURE_BUFFER); // buffer texture with a sampler(or TBO); samplerBuffer type)
+ BIND_ENUM_CONSTANT(UNIFORM_TYPE_IMAGE_BUFFER); //texel buffer); (imageBuffer type)); for compute mostly
+ BIND_ENUM_CONSTANT(UNIFORM_TYPE_UNIFORM_BUFFER); //regular uniform buffer (or UBO).
+ BIND_ENUM_CONSTANT(UNIFORM_TYPE_STORAGE_BUFFER); //storage buffer ("buffer" qualifier) like UBO); but supports storage); for compute mostly
+ BIND_ENUM_CONSTANT(UNIFORM_TYPE_INPUT_ATTACHMENT); //used for sub-pass read/write); for mobile mostly
+ BIND_ENUM_CONSTANT(UNIFORM_TYPE_MAX);
+
+ BIND_ENUM_CONSTANT(RENDER_PRIMITIVE_POINTS);
+ BIND_ENUM_CONSTANT(RENDER_PRIMITIVE_LINES);
+ BIND_ENUM_CONSTANT(RENDER_PRIMITIVE_LINES_WITH_ADJACENCY);
+ BIND_ENUM_CONSTANT(RENDER_PRIMITIVE_LINESTRIPS);
+ BIND_ENUM_CONSTANT(RENDER_PRIMITIVE_LINESTRIPS_WITH_ADJACENCY);
+ BIND_ENUM_CONSTANT(RENDER_PRIMITIVE_TRIANGLES);
+ BIND_ENUM_CONSTANT(RENDER_PRIMITIVE_TRIANGLES_WITH_ADJACENCY);
+ BIND_ENUM_CONSTANT(RENDER_PRIMITIVE_TRIANGLE_STRIPS);
+ BIND_ENUM_CONSTANT(RENDER_PRIMITIVE_TRIANGLE_STRIPS_WITH_AJACENCY);
+ BIND_ENUM_CONSTANT(RENDER_PRIMITIVE_TRIANGLE_STRIPS_WITH_RESTART_INDEX);
+ BIND_ENUM_CONSTANT(RENDER_PRIMITIVE_TESSELATION_PATCH);
+ BIND_ENUM_CONSTANT(RENDER_PRIMITIVE_MAX);
+
+ BIND_ENUM_CONSTANT(POLYGON_CULL_DISABLED);
+ BIND_ENUM_CONSTANT(POLYGON_CULL_FRONT);
+ BIND_ENUM_CONSTANT(POLYGON_CULL_BACK);
+
+ BIND_ENUM_CONSTANT(POLYGON_FRONT_FACE_CLOCKWISE);
+ BIND_ENUM_CONSTANT(POLYGON_FRONT_FACE_COUNTER_CLOCKWISE);
+
+ BIND_ENUM_CONSTANT(STENCIL_OP_KEEP);
+ BIND_ENUM_CONSTANT(STENCIL_OP_ZERO);
+ BIND_ENUM_CONSTANT(STENCIL_OP_REPLACE);
+ BIND_ENUM_CONSTANT(STENCIL_OP_INCREMENT_AND_CLAMP);
+ BIND_ENUM_CONSTANT(STENCIL_OP_DECREMENT_AND_CLAMP);
+ BIND_ENUM_CONSTANT(STENCIL_OP_INVERT);
+ BIND_ENUM_CONSTANT(STENCIL_OP_INCREMENT_AND_WRAP);
+ BIND_ENUM_CONSTANT(STENCIL_OP_DECREMENT_AND_WRAP);
+ BIND_ENUM_CONSTANT(STENCIL_OP_MAX); //not an actual operator); just the amount of operators :D
+
+ BIND_ENUM_CONSTANT(COMPARE_OP_NEVER);
+ BIND_ENUM_CONSTANT(COMPARE_OP_LESS);
+ BIND_ENUM_CONSTANT(COMPARE_OP_EQUAL);
+ BIND_ENUM_CONSTANT(COMPARE_OP_LESS_OR_EQUAL);
+ BIND_ENUM_CONSTANT(COMPARE_OP_GREATER);
+ BIND_ENUM_CONSTANT(COMPARE_OP_NOT_EQUAL);
+ BIND_ENUM_CONSTANT(COMPARE_OP_GREATER_OR_EQUAL);
+ BIND_ENUM_CONSTANT(COMPARE_OP_ALWAYS);
+ BIND_ENUM_CONSTANT(COMPARE_OP_MAX);
+
+ BIND_ENUM_CONSTANT(LOGIC_OP_CLEAR);
+ BIND_ENUM_CONSTANT(LOGIC_OP_AND);
+ BIND_ENUM_CONSTANT(LOGIC_OP_AND_REVERSE);
+ BIND_ENUM_CONSTANT(LOGIC_OP_COPY);
+ BIND_ENUM_CONSTANT(LOGIC_OP_AND_INVERTED);
+ BIND_ENUM_CONSTANT(LOGIC_OP_NO_OP);
+ BIND_ENUM_CONSTANT(LOGIC_OP_XOR);
+ BIND_ENUM_CONSTANT(LOGIC_OP_OR);
+ BIND_ENUM_CONSTANT(LOGIC_OP_NOR);
+ BIND_ENUM_CONSTANT(LOGIC_OP_EQUIVALENT);
+ BIND_ENUM_CONSTANT(LOGIC_OP_INVERT);
+ BIND_ENUM_CONSTANT(LOGIC_OP_OR_REVERSE);
+ BIND_ENUM_CONSTANT(LOGIC_OP_COPY_INVERTED);
+ BIND_ENUM_CONSTANT(LOGIC_OP_OR_INVERTED);
+ BIND_ENUM_CONSTANT(LOGIC_OP_NAND);
+ BIND_ENUM_CONSTANT(LOGIC_OP_SET);
+ BIND_ENUM_CONSTANT(LOGIC_OP_MAX); //not an actual operator); just the amount of operators :D
+
+ BIND_ENUM_CONSTANT(BLEND_FACTOR_ZERO);
+ BIND_ENUM_CONSTANT(BLEND_FACTOR_ONE);
+ BIND_ENUM_CONSTANT(BLEND_FACTOR_SRC_COLOR);
+ BIND_ENUM_CONSTANT(BLEND_FACTOR_ONE_MINUS_SRC_COLOR);
+ BIND_ENUM_CONSTANT(BLEND_FACTOR_DST_COLOR);
+ BIND_ENUM_CONSTANT(BLEND_FACTOR_ONE_MINUS_DST_COLOR);
+ BIND_ENUM_CONSTANT(BLEND_FACTOR_SRC_ALPHA);
+ BIND_ENUM_CONSTANT(BLEND_FACTOR_ONE_MINUS_SRC_ALPHA);
+ BIND_ENUM_CONSTANT(BLEND_FACTOR_DST_ALPHA);
+ BIND_ENUM_CONSTANT(BLEND_FACTOR_ONE_MINUS_DST_ALPHA);
+ BIND_ENUM_CONSTANT(BLEND_FACTOR_CONSTANT_COLOR);
+ BIND_ENUM_CONSTANT(BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR);
+ BIND_ENUM_CONSTANT(BLEND_FACTOR_CONSTANT_ALPHA);
+ BIND_ENUM_CONSTANT(BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA);
+ BIND_ENUM_CONSTANT(BLEND_FACTOR_SRC_ALPHA_SATURATE);
+ BIND_ENUM_CONSTANT(BLEND_FACTOR_SRC1_COLOR);
+ BIND_ENUM_CONSTANT(BLEND_FACTOR_ONE_MINUS_SRC1_COLOR);
+ BIND_ENUM_CONSTANT(BLEND_FACTOR_SRC1_ALPHA);
+ BIND_ENUM_CONSTANT(BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA);
+ BIND_ENUM_CONSTANT(BLEND_FACTOR_MAX);
+
+ BIND_ENUM_CONSTANT(BLEND_OP_ADD);
+ BIND_ENUM_CONSTANT(BLEND_OP_SUBTRACT);
+ BIND_ENUM_CONSTANT(BLEND_OP_REVERSE_SUBTRACT);
+ BIND_ENUM_CONSTANT(BLEND_OP_MINIMUM);
+ BIND_ENUM_CONSTANT(BLEND_OP_MAXIMUM);
+ BIND_ENUM_CONSTANT(BLEND_OP_MAX);
+
+ BIND_ENUM_CONSTANT(DYNAMIC_STATE_LINE_WIDTH);
+ BIND_ENUM_CONSTANT(DYNAMIC_STATE_DEPTH_BIAS);
+ BIND_ENUM_CONSTANT(DYNAMIC_STATE_BLEND_CONSTANTS);
+ BIND_ENUM_CONSTANT(DYNAMIC_STATE_DEPTH_BOUNDS);
+ BIND_ENUM_CONSTANT(DYNAMIC_STATE_STENCIL_COMPARE_MASK);
+ BIND_ENUM_CONSTANT(DYNAMIC_STATE_STENCIL_WRITE_MASK);
+ BIND_ENUM_CONSTANT(DYNAMIC_STATE_STENCIL_REFERENCE);
+
+ BIND_ENUM_CONSTANT(INITIAL_ACTION_CLEAR); //start rendering and clear the framebuffer (supply params)
+ BIND_ENUM_CONSTANT(INITIAL_ACTION_KEEP); //start rendering); but keep attached color texture contents (depth will be cleared)
+ BIND_ENUM_CONSTANT(INITIAL_ACTION_DROP); //start rendering); ignore what is there); just write above it
+ BIND_ENUM_CONSTANT(INITIAL_ACTION_CONTINUE); //continue rendering (framebuffer must have been left in "continue" state as final action previously)
+ BIND_ENUM_CONSTANT(INITIAL_ACTION_MAX);
+
+ BIND_ENUM_CONSTANT(FINAL_ACTION_READ); //will no longer render to it); allows attached textures to be read again); but depth buffer contents will be dropped (Can't be read from)
+ BIND_ENUM_CONSTANT(FINAL_ACTION_DISCARD); // discard contents after rendering
+ BIND_ENUM_CONSTANT(FINAL_ACTION_CONTINUE); //will continue rendering later); attached textures can't be read until re-bound with "finish"
+ BIND_ENUM_CONSTANT(FINAL_ACTION_MAX);
+
+ BIND_ENUM_CONSTANT(SHADER_STAGE_VERTEX);
+ BIND_ENUM_CONSTANT(SHADER_STAGE_FRAGMENT);
+ BIND_ENUM_CONSTANT(SHADER_STAGE_TESSELATION_CONTROL);
+ BIND_ENUM_CONSTANT(SHADER_STAGE_TESSELATION_EVALUATION);
+ BIND_ENUM_CONSTANT(SHADER_STAGE_COMPUTE);
+ BIND_ENUM_CONSTANT(SHADER_STAGE_MAX);
+ BIND_ENUM_CONSTANT(SHADER_STAGE_VERTEX_BIT);
+ BIND_ENUM_CONSTANT(SHADER_STAGE_FRAGMENT_BIT);
+ BIND_ENUM_CONSTANT(SHADER_STAGE_TESSELATION_CONTROL_BIT);
+ BIND_ENUM_CONSTANT(SHADER_STAGE_TESSELATION_EVALUATION_BIT);
+ BIND_ENUM_CONSTANT(SHADER_STAGE_COMPUTE_BIT);
+
+ BIND_ENUM_CONSTANT(SHADER_LANGUAGE_GLSL);
+ BIND_ENUM_CONSTANT(SHADER_LANGUAGE_HLSL);
+
+ BIND_ENUM_CONSTANT(LIMIT_MAX_BOUND_UNIFORM_SETS);
+ BIND_ENUM_CONSTANT(LIMIT_MAX_FRAMEBUFFER_COLOR_ATTACHMENTS);
+ BIND_ENUM_CONSTANT(LIMIT_MAX_TEXTURES_PER_UNIFORM_SET);
+ BIND_ENUM_CONSTANT(LIMIT_MAX_SAMPLERS_PER_UNIFORM_SET);
+ BIND_ENUM_CONSTANT(LIMIT_MAX_STORAGE_BUFFERS_PER_UNIFORM_SET);
+ BIND_ENUM_CONSTANT(LIMIT_MAX_STORAGE_IMAGES_PER_UNIFORM_SET);
+ BIND_ENUM_CONSTANT(LIMIT_MAX_UNIFORM_BUFFERS_PER_UNIFORM_SET);
+ BIND_ENUM_CONSTANT(LIMIT_MAX_DRAW_INDEXED_INDEX);
+ BIND_ENUM_CONSTANT(LIMIT_MAX_FRAMEBUFFER_HEIGHT);
+ BIND_ENUM_CONSTANT(LIMIT_MAX_FRAMEBUFFER_WIDTH);
+ BIND_ENUM_CONSTANT(LIMIT_MAX_TEXTURE_ARRAY_LAYERS);
+ BIND_ENUM_CONSTANT(LIMIT_MAX_TEXTURE_SIZE_1D);
+ BIND_ENUM_CONSTANT(LIMIT_MAX_TEXTURE_SIZE_2D);
+ BIND_ENUM_CONSTANT(LIMIT_MAX_TEXTURE_SIZE_3D);
+ BIND_ENUM_CONSTANT(LIMIT_MAX_TEXTURE_SIZE_CUBE);
+ BIND_ENUM_CONSTANT(LIMIT_MAX_TEXTURES_PER_SHADER_STAGE);
+ BIND_ENUM_CONSTANT(LIMIT_MAX_SAMPLERS_PER_SHADER_STAGE);
+ BIND_ENUM_CONSTANT(LIMIT_MAX_STORAGE_BUFFERS_PER_SHADER_STAGE);
+ BIND_ENUM_CONSTANT(LIMIT_MAX_STORAGE_IMAGES_PER_SHADER_STAGE);
+ BIND_ENUM_CONSTANT(LIMIT_MAX_UNIFORM_BUFFERS_PER_SHADER_STAGE);
+ BIND_ENUM_CONSTANT(LIMIT_MAX_PUSH_CONSTANT_SIZE);
+ BIND_ENUM_CONSTANT(LIMIT_MAX_UNIFORM_BUFFER_SIZE);
+ BIND_ENUM_CONSTANT(LIMIT_MAX_VERTEX_INPUT_ATTRIBUTE_OFFSET);
+ BIND_ENUM_CONSTANT(LIMIT_MAX_VERTEX_INPUT_ATTRIBUTES);
+ BIND_ENUM_CONSTANT(LIMIT_MAX_VERTEX_INPUT_BINDINGS);
+ BIND_ENUM_CONSTANT(LIMIT_MAX_VERTEX_INPUT_BINDING_STRIDE);
+ BIND_ENUM_CONSTANT(LIMIT_MIN_UNIFORM_BUFFER_OFFSET_ALIGNMENT);
+ BIND_ENUM_CONSTANT(LIMIT_MAX_COMPUTE_SHARED_MEMORY_SIZE);
+ BIND_ENUM_CONSTANT(LIMIT_MAX_COMPUTE_WORKGROUP_COUNT_X);
+ BIND_ENUM_CONSTANT(LIMIT_MAX_COMPUTE_WORKGROUP_COUNT_Y);
+ BIND_ENUM_CONSTANT(LIMIT_MAX_COMPUTE_WORKGROUP_COUNT_Z);
+ BIND_ENUM_CONSTANT(LIMIT_MAX_COMPUTE_WORKGROUP_INVOCATIONS);
+ BIND_ENUM_CONSTANT(LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_X);
+ BIND_ENUM_CONSTANT(LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_Y);
+ BIND_ENUM_CONSTANT(LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_Z);
+
+ BIND_CONSTANT(INVALID_ID);
+ BIND_CONSTANT(INVALID_FORMAT_ID);
+}
+
RenderingDevice::RenderingDevice() {
- singleton = this;
+ if (singleton == nullptr) { // there may be more rendering devices later
+ singleton = this;
+ }
}
diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h
index 4705bcaa75..ee39ee11ed 100644
--- a/servers/rendering/rendering_device.h
+++ b/servers/rendering/rendering_device.h
@@ -32,8 +32,22 @@
#define RENDERING_DEVICE_H
#include "core/object.h"
+#include "core/typed_array.h"
#include "servers/display_server.h"
+class RDTextureFormat;
+class RDTextureView;
+class RDAttachmentFormat;
+class RDSamplerState;
+class RDVertexAttribute;
+class RDShaderSource;
+class RDShaderBytecode;
+class RDUniforms;
+class RDPipelineRasterizationState;
+class RDPipelineMultisampleState;
+class RDPipelineDepthStencilState;
+class RDPipelineColorBlendState;
+
class RenderingDevice : public Object {
GDCLASS(RenderingDevice, Object)
public:
@@ -65,10 +79,14 @@ private:
static RenderingDevice *singleton;
+protected:
+ static void _bind_methods();
+
public:
//base numeric ID for all types
enum {
- INVALID_ID = -1
+ INVALID_ID = -1,
+ INVALID_FORMAT_ID = -1
};
/*****************/
@@ -428,6 +446,7 @@ public:
virtual Error texture_copy(RID p_from_texture, RID p_to_texture, const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_size, uint32_t p_src_mipmap, uint32_t p_dst_mipmap, uint32_t p_src_layer, uint32_t p_dst_layer, bool p_sync_with_draw = false) = 0;
virtual Error texture_clear(RID p_texture, const Color &p_color, uint32_t p_base_mipmap, uint32_t p_mipmaps, uint32_t p_base_layer, uint32_t p_layers, bool p_sync_with_draw = false) = 0;
+ virtual Error texture_resolve_multisample(RID p_from_texture, RID p_to_texture, bool p_sync_with_draw = false) = 0;
/*********************/
/**** FRAMEBUFFER ****/
@@ -529,13 +548,13 @@ public:
VERTEX_FREQUENCY_INSTANCE,
};
- struct VertexDescription {
+ struct VertexAttribute {
uint32_t location; //shader location
uint32_t offset;
DataFormat format;
uint32_t stride;
VertexFrequency frequency;
- VertexDescription() {
+ VertexAttribute() {
location = 0;
offset = 0;
stride = 0;
@@ -548,7 +567,7 @@ public:
typedef int64_t VertexFormatID;
// This ID is warranted to be unique for the same formats, does not need to be freed
- virtual VertexFormatID vertex_format_create(const Vector<VertexDescription> &p_vertex_formats) = 0;
+ virtual VertexFormatID vertex_format_create(const Vector<VertexAttribute> &p_vertex_formats) = 0;
virtual RID vertex_array_create(uint32_t p_vertex_count, VertexFormatID p_vertex_format, const Vector<RID> &p_src_buffers) = 0;
enum IndexBufferFormat {
@@ -563,7 +582,7 @@ public:
/**** SHADER ****/
/****************/
- virtual Vector<uint8_t> shader_compile_from_source(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language = SHADER_LANGUAGE_GLSL, String *r_error = NULL, bool p_allow_cache = true);
+ virtual Vector<uint8_t> shader_compile_from_source(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language = SHADER_LANGUAGE_GLSL, String *r_error = nullptr, bool p_allow_cache = true);
static void shader_set_compile_function(ShaderCompileFunction p_function);
static void shader_set_cache_function(ShaderCacheFunction p_function);
@@ -577,6 +596,7 @@ public:
}
};
+ RID shader_create_from_bytecode(const Ref<RDShaderBytecode> &p_bytecode);
virtual RID shader_create(const Vector<ShaderStageData> &p_stages) = 0;
virtual uint32_t shader_get_vertex_input_attribute_mask(RID p_shader) = 0;
@@ -594,7 +614,7 @@ public:
UNIFORM_TYPE_IMAGE_BUFFER, //texel buffer, (imageBuffer type), for compute mostly
UNIFORM_TYPE_UNIFORM_BUFFER, //regular uniform buffer (or UBO).
UNIFORM_TYPE_STORAGE_BUFFER, //storage buffer ("buffer" qualifier) like UBO, but supports storage, for compute mostly
- UNIFORM_TYPE_INPUT_ATTACHMENT, //used for sub-pass read/write, for compute mostly
+ UNIFORM_TYPE_INPUT_ATTACHMENT, //used for sub-pass read/write, for mobile mostly
UNIFORM_TYPE_MAX
};
@@ -766,7 +786,6 @@ public:
};
struct PipelineDepthStencilState {
-
bool enable_depth_test;
bool enable_depth_write;
CompareOperator depth_compare_operator;
@@ -795,8 +814,8 @@ public:
}
};
- StencilOperationState stencil_operation_front;
- StencilOperationState stencil_operation_back;
+ StencilOperationState front_op;
+ StencilOperationState back_op;
PipelineDepthStencilState() {
enable_depth_test = false;
@@ -810,7 +829,6 @@ public:
};
struct PipelineColorBlendState {
-
bool enable_logic_op;
LogicOperation logic_op;
struct Attachment {
@@ -851,7 +869,6 @@ public:
static PipelineColorBlendState create_blend(int p_attachments = 1) {
PipelineColorBlendState bs;
for (int i = 0; i < p_attachments; i++) {
-
Attachment ba;
ba.enable_blend = true;
ba.src_color_blend_factor = BLEND_FACTOR_SRC_ALPHA;
@@ -883,8 +900,8 @@ public:
DYNAMIC_STATE_STENCIL_REFERENCE = (1 << 6),
};
- virtual RID render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const PipelineRasterizationState &p_rasterization_state, const PipelineMultisampleState &p_multisample_state, const PipelineDepthStencilState &p_depth_stencil_state, const PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags = 0) = 0;
virtual bool render_pipeline_is_valid(RID p_pipeline) = 0;
+ virtual RID render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const PipelineRasterizationState &p_rasterization_state, const PipelineMultisampleState &p_multisample_state, const PipelineDepthStencilState &p_depth_stencil_state, const PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags = 0) = 0;
/**************************/
/**** COMPUTE PIPELINE ****/
@@ -908,6 +925,7 @@ public:
enum InitialAction {
INITIAL_ACTION_CLEAR, //start rendering and clear the framebuffer (supply params)
INITIAL_ACTION_KEEP, //start rendering, but keep attached color texture contents (depth will be cleared)
+ INITIAL_ACTION_DROP, //start rendering, ignore what is there, just write above it
INITIAL_ACTION_CONTINUE, //continue rendering (framebuffer must have been left in "continue" state as final action previously)
INITIAL_ACTION_MAX
};
@@ -930,7 +948,7 @@ public:
virtual void draw_list_bind_vertex_array(DrawListID p_list, RID p_vertex_array) = 0;
virtual void draw_list_bind_index_array(DrawListID p_list, RID p_index_array) = 0;
virtual void draw_list_set_line_width(DrawListID p_list, float p_width) = 0;
- virtual void draw_list_set_push_constant(DrawListID p_list, void *p_data, uint32_t p_data_size) = 0;
+ virtual void draw_list_set_push_constant(DrawListID p_list, const void *p_data, uint32_t p_data_size) = 0;
virtual void draw_list_draw(DrawListID p_list, bool p_use_indices, uint32_t p_instances = 1, uint32_t p_procedural_vertices = 0) = 0;
@@ -948,7 +966,7 @@ public:
virtual ComputeListID compute_list_begin() = 0;
virtual void compute_list_bind_compute_pipeline(ComputeListID p_list, RID p_compute_pipeline) = 0;
virtual void compute_list_bind_uniform_set(ComputeListID p_list, RID p_uniform_set, uint32_t p_index) = 0;
- virtual void compute_list_set_push_constant(ComputeListID p_list, void *p_data, uint32_t p_data_size) = 0;
+ virtual void compute_list_set_push_constant(ComputeListID p_list, const void *p_data, uint32_t p_data_size) = 0;
virtual void compute_list_dispatch(ComputeListID p_list, uint32_t p_x_groups, uint32_t p_y_groups, uint32_t p_z_groups) = 0;
virtual void compute_list_add_barrier(ComputeListID p_list) = 0;
@@ -1022,11 +1040,68 @@ public:
virtual uint32_t get_frame_delay() const = 0;
- static RenderingDevice *get_singleton();
+ virtual void submit() = 0;
+ virtual void sync() = 0;
+
+ virtual uint64_t get_memory_usage() const = 0;
+
+ virtual RenderingDevice *create_local_device() = 0;
+ static RenderingDevice *get_singleton();
RenderingDevice();
+
+protected:
+ //binders to script API
+ RID _texture_create(const Ref<RDTextureFormat> &p_format, const Ref<RDTextureView> &p_view, const TypedArray<PackedByteArray> &p_data = Array());
+ RID _texture_create_shared(const Ref<RDTextureView> &p_view, RID p_with_texture);
+ RID _texture_create_shared_from_slice(const Ref<RDTextureView> &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, TextureSliceType p_slice_type = TEXTURE_SLICE_2D);
+
+ FramebufferFormatID _framebuffer_format_create(const TypedArray<RDAttachmentFormat> &p_attachments);
+ RID _framebuffer_create(const Array &p_textures, FramebufferFormatID p_format_check = INVALID_ID);
+ RID _sampler_create(const Ref<RDSamplerState> &p_state);
+ VertexFormatID _vertex_format_create(const TypedArray<RDVertexAttribute> &p_vertex_formats);
+ RID _vertex_array_create(uint32_t p_vertex_count, VertexFormatID p_vertex_format, const TypedArray<RID> &p_src_buffers);
+
+ Ref<RDShaderBytecode> _shader_compile_from_source(const Ref<RDShaderSource> &p_source, bool p_allow_cache = true);
+
+ RID _uniform_set_create(const Array &p_uniforms, RID p_shader, uint32_t p_shader_set);
+
+ Error _buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const Vector<uint8_t> &p_data, bool p_sync_with_draw = false);
+
+ RID _render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const Ref<RDPipelineRasterizationState> &p_rasterization_state, const Ref<RDPipelineMultisampleState> &p_multisample_state, const Ref<RDPipelineDepthStencilState> &p_depth_stencil_state, const Ref<RDPipelineColorBlendState> &p_blend_state, int p_dynamic_state_flags = 0);
+
+ Vector<int64_t> _draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2());
+ void _draw_list_set_push_constant(DrawListID p_list, const Vector<uint8_t> &p_data, uint32_t p_data_size);
+ void _compute_list_set_push_constant(ComputeListID p_list, const Vector<uint8_t> &p_data, uint32_t p_data_size);
};
+VARIANT_ENUM_CAST(RenderingDevice::ShaderStage)
+VARIANT_ENUM_CAST(RenderingDevice::ShaderLanguage)
+VARIANT_ENUM_CAST(RenderingDevice::CompareOperator)
+VARIANT_ENUM_CAST(RenderingDevice::DataFormat)
+VARIANT_ENUM_CAST(RenderingDevice::TextureType)
+VARIANT_ENUM_CAST(RenderingDevice::TextureSamples)
+VARIANT_ENUM_CAST(RenderingDevice::TextureUsageBits)
+VARIANT_ENUM_CAST(RenderingDevice::TextureSwizzle)
+VARIANT_ENUM_CAST(RenderingDevice::TextureSliceType)
+VARIANT_ENUM_CAST(RenderingDevice::SamplerFilter)
+VARIANT_ENUM_CAST(RenderingDevice::SamplerRepeatMode)
+VARIANT_ENUM_CAST(RenderingDevice::SamplerBorderColor)
+VARIANT_ENUM_CAST(RenderingDevice::VertexFrequency)
+VARIANT_ENUM_CAST(RenderingDevice::IndexBufferFormat)
+VARIANT_ENUM_CAST(RenderingDevice::UniformType)
+VARIANT_ENUM_CAST(RenderingDevice::RenderPrimitive)
+VARIANT_ENUM_CAST(RenderingDevice::PolygonCullMode)
+VARIANT_ENUM_CAST(RenderingDevice::PolygonFrontFace)
+VARIANT_ENUM_CAST(RenderingDevice::StencilOperation)
+VARIANT_ENUM_CAST(RenderingDevice::LogicOperation)
+VARIANT_ENUM_CAST(RenderingDevice::BlendFactor)
+VARIANT_ENUM_CAST(RenderingDevice::BlendOperation)
+VARIANT_ENUM_CAST(RenderingDevice::PipelineDynamicStateFlags)
+VARIANT_ENUM_CAST(RenderingDevice::InitialAction)
+VARIANT_ENUM_CAST(RenderingDevice::FinalAction)
+VARIANT_ENUM_CAST(RenderingDevice::Limit)
+
typedef RenderingDevice RD;
#endif // RENDERING_DEVICE_H
diff --git a/servers/rendering/rendering_device_binds.cpp b/servers/rendering/rendering_device_binds.cpp
new file mode 100644
index 0000000000..0400cebfdc
--- /dev/null
+++ b/servers/rendering/rendering_device_binds.cpp
@@ -0,0 +1,205 @@
+/*************************************************************************/
+/* rendering_device_binds.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 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. */
+/*************************************************************************/
+
+#include "rendering_device_binds.h"
+
+Error RDShaderFile::parse_versions_from_text(const String &p_text, const String p_defines, OpenIncludeFunction p_include_func, void *p_include_func_userdata) {
+ Vector<String> lines = p_text.split("\n");
+
+ bool reading_versions = false;
+ bool stage_found[RD::SHADER_STAGE_MAX] = { false, false, false, false, false };
+ RD::ShaderStage stage = RD::SHADER_STAGE_MAX;
+ static const char *stage_str[RD::SHADER_STAGE_MAX] = {
+ "vertex",
+ "fragment",
+ "tesselation_control",
+ "tesselation_evaluation",
+ "compute",
+ };
+ String stage_code[RD::SHADER_STAGE_MAX];
+ int stages_found = 0;
+ Map<StringName, String> version_texts;
+
+ versions.clear();
+ base_error = "";
+
+ for (int lidx = 0; lidx < lines.size(); lidx++) {
+ String line = lines[lidx];
+
+ {
+ String ls = line.strip_edges();
+ if (ls.begins_with("#[") && ls.ends_with("]")) {
+ String section = ls.substr(2, ls.length() - 3).strip_edges();
+ if (section == "versions") {
+ if (stages_found) {
+ base_error = "Invalid shader file, #[versions] must be the first section found.";
+ break;
+ }
+ reading_versions = true;
+ } else {
+ for (int i = 0; i < RD::SHADER_STAGE_MAX; i++) {
+ if (section == stage_str[i]) {
+ if (stage_found[i]) {
+ base_error = "Invalid shader file, stage appears twice: " + section;
+ break;
+ }
+
+ stage_found[i] = true;
+ stages_found++;
+
+ stage = RD::ShaderStage(i);
+ reading_versions = false;
+ break;
+ }
+ }
+
+ if (base_error != String()) {
+ break;
+ }
+ }
+
+ continue;
+ }
+ }
+
+ if (stage == RD::SHADER_STAGE_MAX && line.strip_edges() != "") {
+ line = line.strip_edges();
+ if (line.begins_with("//") || line.begins_with("/*")) {
+ continue; //assuming comment (single line)
+ }
+ }
+
+ if (reading_versions) {
+ String l = line.strip_edges();
+ if (l != "") {
+ if (l.find("=") == -1) {
+ base_error = "Missing `=` in '" + l + "'. Version syntax is `version = \"<defines with C escaping>\";`.";
+ break;
+ }
+ if (l.find(";") == -1) {
+ // We don't require a semicolon per se, but it's needed for clang-format to handle things properly.
+ base_error = "Missing `;` in '" + l + "'. Version syntax is `version = \"<defines with C escaping>\";`.";
+ break;
+ }
+ Vector<String> slices = l.get_slice(";", 0).split("=");
+ String version = slices[0].strip_edges();
+ if (!version.is_valid_identifier()) {
+ base_error = "Version names must be valid identifiers, found '" + version + "' instead.";
+ break;
+ }
+ String define = slices[1].strip_edges();
+ if (!define.begins_with("\"") || !define.ends_with("\"")) {
+ base_error = "Version text must be quoted using \"\", instead found '" + define + "'.";
+ break;
+ }
+ define = "\n" + define.substr(1, define.length() - 2).c_unescape() + "\n"; // Add newline before and after just in case.
+
+ version_texts[version] = define + "\n" + p_defines;
+ }
+ } else {
+ if (stage == RD::SHADER_STAGE_MAX && line.strip_edges() != "") {
+ base_error = "Text was found that does not belong to a valid section: " + line;
+ break;
+ }
+
+ if (stage != RD::SHADER_STAGE_MAX) {
+ if (line.strip_edges().begins_with("#include")) {
+ if (p_include_func) {
+ //process include
+ String include = line.replace("#include", "").strip_edges();
+ if (!include.begins_with("\"") || !include.ends_with("\"")) {
+ base_error = "Malformed #include syntax, expected #include \"<path>\", found instad: " + include;
+ break;
+ }
+ include = include.substr(1, include.length() - 2).strip_edges();
+ String include_text = p_include_func(include, p_include_func_userdata);
+ if (include_text != String()) {
+ stage_code[stage] += "\n" + include_text + "\n";
+ } else {
+ base_error = "#include failed for file '" + include + "'";
+ }
+ } else {
+ base_error = "#include used, but no include function provided.";
+ }
+ } else {
+ stage_code[stage] += line + "\n";
+ }
+ }
+ }
+ }
+
+ Ref<RDShaderFile> shader_file;
+ shader_file.instance();
+
+ if (base_error == "") {
+ if (stage_found[RD::SHADER_STAGE_COMPUTE] && stages_found > 1) {
+ ERR_FAIL_V_MSG(ERR_PARSE_ERROR, "When writing compute shaders, [compute] mustbe the only stage present.");
+ }
+
+ if (version_texts.empty()) {
+ version_texts[""] = ""; //make sure a default version exists
+ }
+
+ bool errors_found = false;
+
+ /* STEP 2, Compile the versions, add to shader file */
+
+ for (Map<StringName, String>::Element *E = version_texts.front(); E; E = E->next()) {
+ Ref<RDShaderBytecode> bytecode;
+ bytecode.instance();
+
+ for (int i = 0; i < RD::SHADER_STAGE_MAX; i++) {
+ String code = stage_code[i];
+ if (code == String()) {
+ continue;
+ }
+ code = code.replace("VERSION_DEFINES", E->get());
+ String error;
+ Vector<uint8_t> spirv = RenderingDevice::get_singleton()->shader_compile_from_source(RD::ShaderStage(i), code, RD::SHADER_LANGUAGE_GLSL, &error, false);
+ bytecode->set_stage_bytecode(RD::ShaderStage(i), spirv);
+ if (error != "") {
+ error += String() + "\n\nStage '" + stage_str[i] + "' source code: \n\n";
+ Vector<String> sclines = code.split("\n");
+ for (int j = 0; j < sclines.size(); j++) {
+ error += itos(j + 1) + "\t\t" + sclines[j] + "\n";
+ }
+ errors_found = true;
+ }
+ bytecode->set_stage_compile_error(RD::ShaderStage(i), error);
+ }
+
+ set_bytecode(bytecode, E->key());
+ }
+
+ return errors_found ? ERR_PARSE_ERROR : OK;
+ } else {
+ return ERR_PARSE_ERROR;
+ }
+}
diff --git a/servers/rendering/rendering_device_binds.h b/servers/rendering/rendering_device_binds.h
new file mode 100644
index 0000000000..319c6d9fde
--- /dev/null
+++ b/servers/rendering/rendering_device_binds.h
@@ -0,0 +1,629 @@
+/*************************************************************************/
+/* rendering_device_binds.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 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. */
+/*************************************************************************/
+
+#ifndef RENDERING_DEVICE_BINDS_H
+#define RENDERING_DEVICE_BINDS_H
+
+#include "servers/rendering/rendering_device.h"
+
+#define RD_SETGET(m_type, m_member) \
+ void set_##m_member(m_type p_##m_member) { base.m_member = p_##m_member; } \
+ m_type get_##m_member() const { return base.m_member; }
+
+#define RD_BIND(m_variant_type, m_class, m_member) \
+ ClassDB::bind_method(D_METHOD("set_" _MKSTR(m_member), "p_" _MKSTR(member)), &m_class::set_##m_member); \
+ ClassDB::bind_method(D_METHOD("get_" _MKSTR(m_member)), &m_class::get_##m_member); \
+ ADD_PROPERTY(PropertyInfo(m_variant_type, #m_member), "set_" _MKSTR(m_member), "get_" _MKSTR(m_member))
+
+#define RD_SETGET_SUB(m_type, m_sub, m_member) \
+ void set_##m_sub##_##m_member(m_type p_##m_member) { base.m_sub.m_member = p_##m_member; } \
+ m_type get_##m_sub##_##m_member() const { return base.m_sub.m_member; }
+
+#define RD_BIND_SUB(m_variant_type, m_class, m_sub, m_member) \
+ ClassDB::bind_method(D_METHOD("set_" _MKSTR(m_sub) "_" _MKSTR(m_member), "p_" _MKSTR(member)), &m_class::set_##m_sub##_##m_member); \
+ ClassDB::bind_method(D_METHOD("get_" _MKSTR(m_sub) "_" _MKSTR(m_member)), &m_class::get_##m_sub##_##m_member); \
+ ADD_PROPERTY(PropertyInfo(m_variant_type, _MKSTR(m_sub) "_" _MKSTR(m_member)), "set_" _MKSTR(m_sub) "_" _MKSTR(m_member), "get_" _MKSTR(m_sub) "_" _MKSTR(m_member))
+
+class RDTextureFormat : public Reference {
+ GDCLASS(RDTextureFormat, Reference)
+ friend class RenderingDevice;
+
+ RD::TextureFormat base;
+
+public:
+ RD_SETGET(RD::DataFormat, format)
+ RD_SETGET(uint32_t, width)
+ RD_SETGET(uint32_t, height)
+ RD_SETGET(uint32_t, depth)
+ RD_SETGET(uint32_t, array_layers)
+ RD_SETGET(uint32_t, mipmaps)
+ RD_SETGET(RD::TextureType, type)
+ RD_SETGET(RD::TextureSamples, samples)
+ RD_SETGET(uint32_t, usage_bits)
+
+ void add_shareable_format(RD::DataFormat p_format) { base.shareable_formats.push_back(p_format); }
+ void remove_shareable_format(RD::DataFormat p_format) { base.shareable_formats.erase(p_format); }
+
+protected:
+ static void _bind_methods() {
+ RD_BIND(Variant::INT, RDTextureFormat, format);
+ RD_BIND(Variant::INT, RDTextureFormat, width);
+ RD_BIND(Variant::INT, RDTextureFormat, height);
+ RD_BIND(Variant::INT, RDTextureFormat, depth);
+ RD_BIND(Variant::INT, RDTextureFormat, array_layers);
+ RD_BIND(Variant::INT, RDTextureFormat, mipmaps);
+ RD_BIND(Variant::INT, RDTextureFormat, type);
+ RD_BIND(Variant::INT, RDTextureFormat, samples);
+ RD_BIND(Variant::INT, RDTextureFormat, usage_bits);
+ ClassDB::bind_method(D_METHOD("add_shareable_format", "format"), &RDTextureFormat::add_shareable_format);
+ ClassDB::bind_method(D_METHOD("remove_shareable_format", "format"), &RDTextureFormat::remove_shareable_format);
+ }
+};
+
+class RDTextureView : public Reference {
+ GDCLASS(RDTextureView, Reference)
+
+ friend class RenderingDevice;
+
+ RD::TextureView base;
+
+public:
+ RD_SETGET(RD::DataFormat, format_override)
+ RD_SETGET(RD::TextureSwizzle, swizzle_r)
+ RD_SETGET(RD::TextureSwizzle, swizzle_g)
+ RD_SETGET(RD::TextureSwizzle, swizzle_b)
+ RD_SETGET(RD::TextureSwizzle, swizzle_a)
+protected:
+ static void _bind_methods() {
+ RD_BIND(Variant::INT, RDTextureView, format_override);
+ RD_BIND(Variant::INT, RDTextureView, swizzle_r);
+ RD_BIND(Variant::INT, RDTextureView, swizzle_g);
+ RD_BIND(Variant::INT, RDTextureView, swizzle_b);
+ RD_BIND(Variant::INT, RDTextureView, swizzle_a);
+ }
+};
+
+class RDAttachmentFormat : public Reference {
+ GDCLASS(RDAttachmentFormat, Reference)
+ friend class RenderingDevice;
+
+ RD::AttachmentFormat base;
+
+public:
+ RD_SETGET(RD::DataFormat, format)
+ RD_SETGET(RD::TextureSamples, samples)
+ RD_SETGET(uint32_t, usage_flags)
+protected:
+ static void _bind_methods() {
+ RD_BIND(Variant::INT, RDAttachmentFormat, format);
+ RD_BIND(Variant::INT, RDAttachmentFormat, samples);
+ RD_BIND(Variant::INT, RDAttachmentFormat, usage_flags);
+ }
+};
+
+class RDSamplerState : public Reference {
+ GDCLASS(RDSamplerState, Reference)
+ friend class RenderingDevice;
+
+ RD::SamplerState base;
+
+public:
+ RD_SETGET(RD::SamplerFilter, mag_filter)
+ RD_SETGET(RD::SamplerFilter, min_filter)
+ RD_SETGET(RD::SamplerFilter, mip_filter)
+ RD_SETGET(RD::SamplerRepeatMode, repeat_u)
+ RD_SETGET(RD::SamplerRepeatMode, repeat_v)
+ RD_SETGET(RD::SamplerRepeatMode, repeat_w)
+ RD_SETGET(float, lod_bias)
+ RD_SETGET(bool, use_anisotropy)
+ RD_SETGET(float, anisotropy_max)
+ RD_SETGET(bool, enable_compare)
+ RD_SETGET(RD::CompareOperator, compare_op)
+ RD_SETGET(float, min_lod)
+ RD_SETGET(float, max_lod)
+ RD_SETGET(RD::SamplerBorderColor, border_color)
+ RD_SETGET(bool, unnormalized_uvw)
+
+protected:
+ static void _bind_methods() {
+ RD_BIND(Variant::INT, RDSamplerState, mag_filter);
+ RD_BIND(Variant::INT, RDSamplerState, min_filter);
+ RD_BIND(Variant::INT, RDSamplerState, mip_filter);
+ RD_BIND(Variant::INT, RDSamplerState, repeat_u);
+ RD_BIND(Variant::INT, RDSamplerState, repeat_v);
+ RD_BIND(Variant::INT, RDSamplerState, repeat_w);
+ RD_BIND(Variant::FLOAT, RDSamplerState, lod_bias);
+ RD_BIND(Variant::BOOL, RDSamplerState, use_anisotropy);
+ RD_BIND(Variant::FLOAT, RDSamplerState, anisotropy_max);
+ RD_BIND(Variant::BOOL, RDSamplerState, enable_compare);
+ RD_BIND(Variant::INT, RDSamplerState, compare_op);
+ RD_BIND(Variant::FLOAT, RDSamplerState, min_lod);
+ RD_BIND(Variant::FLOAT, RDSamplerState, max_lod);
+ RD_BIND(Variant::INT, RDSamplerState, border_color);
+ RD_BIND(Variant::BOOL, RDSamplerState, unnormalized_uvw);
+ }
+};
+
+class RDVertexAttribute : public Reference {
+ GDCLASS(RDVertexAttribute, Reference)
+ friend class RenderingDevice;
+ RD::VertexAttribute base;
+
+public:
+ RD_SETGET(uint32_t, location)
+ RD_SETGET(uint32_t, offset)
+ RD_SETGET(RD::DataFormat, format)
+ RD_SETGET(uint32_t, stride)
+ RD_SETGET(RD::VertexFrequency, frequency)
+
+protected:
+ static void _bind_methods() {
+ RD_BIND(Variant::INT, RDVertexAttribute, location);
+ RD_BIND(Variant::INT, RDVertexAttribute, offset);
+ RD_BIND(Variant::INT, RDVertexAttribute, format);
+ RD_BIND(Variant::INT, RDVertexAttribute, stride);
+ RD_BIND(Variant::INT, RDVertexAttribute, frequency);
+ }
+};
+class RDShaderSource : public Reference {
+ GDCLASS(RDShaderSource, Reference)
+ String source[RD::SHADER_STAGE_MAX];
+ RD::ShaderLanguage language = RD::SHADER_LANGUAGE_GLSL;
+
+public:
+ void set_stage_source(RD::ShaderStage p_stage, const String &p_source) {
+ ERR_FAIL_INDEX(p_stage, RD::SHADER_STAGE_MAX);
+ source[p_stage] = p_source;
+ }
+
+ String get_stage_source(RD::ShaderStage p_stage) const {
+ ERR_FAIL_INDEX_V(p_stage, RD::SHADER_STAGE_MAX, String());
+ return source[p_stage];
+ }
+
+ void set_language(RD::ShaderLanguage p_language) {
+ language = p_language;
+ }
+
+ RD::ShaderLanguage get_language() const {
+ return language;
+ }
+
+protected:
+ static void _bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_stage_source", "stage", "source"), &RDShaderSource::set_stage_source);
+ ClassDB::bind_method(D_METHOD("get_stage_source", "stage"), &RDShaderSource::get_stage_source);
+
+ ClassDB::bind_method(D_METHOD("set_language", "language"), &RDShaderSource::set_language);
+ ClassDB::bind_method(D_METHOD("get_language"), &RDShaderSource::get_language);
+
+ ADD_GROUP("Source", "source_");
+ ADD_PROPERTYI(PropertyInfo(Variant::STRING, "source_vertex"), "set_stage_source", "get_stage_source", RD::SHADER_STAGE_VERTEX);
+ ADD_PROPERTYI(PropertyInfo(Variant::STRING, "source_fragment"), "set_stage_source", "get_stage_source", RD::SHADER_STAGE_FRAGMENT);
+ ADD_PROPERTYI(PropertyInfo(Variant::STRING, "source_tesselation_control"), "set_stage_source", "get_stage_source", RD::SHADER_STAGE_TESSELATION_CONTROL);
+ ADD_PROPERTYI(PropertyInfo(Variant::STRING, "source_tesselation_evaluation"), "set_stage_source", "get_stage_source", RD::SHADER_STAGE_TESSELATION_EVALUATION);
+ ADD_PROPERTYI(PropertyInfo(Variant::STRING, "source_compute"), "set_stage_source", "get_stage_source", RD::SHADER_STAGE_COMPUTE);
+ ADD_GROUP("Syntax", "source_");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "language", PROPERTY_HINT_RANGE, "GLSL,HLSL"), "set_language", "get_language");
+ }
+};
+
+class RDShaderBytecode : public Resource {
+ GDCLASS(RDShaderBytecode, Resource)
+
+ Vector<uint8_t> bytecode[RD::SHADER_STAGE_MAX];
+ String compile_error[RD::SHADER_STAGE_MAX];
+
+public:
+ void set_stage_bytecode(RD::ShaderStage p_stage, const Vector<uint8_t> &p_bytecode) {
+ ERR_FAIL_INDEX(p_stage, RD::SHADER_STAGE_MAX);
+ bytecode[p_stage] = p_bytecode;
+ }
+
+ Vector<uint8_t> get_stage_bytecode(RD::ShaderStage p_stage) const {
+ ERR_FAIL_INDEX_V(p_stage, RD::SHADER_STAGE_MAX, Vector<uint8_t>());
+ return bytecode[p_stage];
+ }
+
+ void set_stage_compile_error(RD::ShaderStage p_stage, const String &p_compile_error) {
+ ERR_FAIL_INDEX(p_stage, RD::SHADER_STAGE_MAX);
+ compile_error[p_stage] = p_compile_error;
+ }
+
+ String get_stage_compile_error(RD::ShaderStage p_stage) const {
+ ERR_FAIL_INDEX_V(p_stage, RD::SHADER_STAGE_MAX, String());
+ return compile_error[p_stage];
+ }
+
+protected:
+ static void _bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_stage_bytecode", "stage", "bytecode"), &RDShaderBytecode::set_stage_bytecode);
+ ClassDB::bind_method(D_METHOD("get_stage_bytecode", "stage"), &RDShaderBytecode::get_stage_bytecode);
+
+ ClassDB::bind_method(D_METHOD("set_stage_compile_error", "stage", "compile_error"), &RDShaderBytecode::set_stage_compile_error);
+ ClassDB::bind_method(D_METHOD("get_stage_compile_error", "stage"), &RDShaderBytecode::get_stage_compile_error);
+
+ ADD_GROUP("Bytecode", "bytecode_");
+ ADD_PROPERTYI(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "bytecode_vertex"), "set_stage_bytecode", "get_stage_bytecode", RD::SHADER_STAGE_VERTEX);
+ ADD_PROPERTYI(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "bytecode_fragment"), "set_stage_bytecode", "get_stage_bytecode", RD::SHADER_STAGE_FRAGMENT);
+ ADD_PROPERTYI(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "bytecode_tesselation_control"), "set_stage_bytecode", "get_stage_bytecode", RD::SHADER_STAGE_TESSELATION_CONTROL);
+ ADD_PROPERTYI(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "bytecode_tesselation_evaluation"), "set_stage_bytecode", "get_stage_bytecode", RD::SHADER_STAGE_TESSELATION_EVALUATION);
+ ADD_PROPERTYI(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "bytecode_compute"), "set_stage_bytecode", "get_stage_bytecode", RD::SHADER_STAGE_COMPUTE);
+ ADD_GROUP("Compile Error", "compile_error_");
+ ADD_PROPERTYI(PropertyInfo(Variant::STRING, "compile_error_vertex"), "set_stage_compile_error", "get_stage_compile_error", RD::SHADER_STAGE_VERTEX);
+ ADD_PROPERTYI(PropertyInfo(Variant::STRING, "compile_error_fragment"), "set_stage_compile_error", "get_stage_compile_error", RD::SHADER_STAGE_FRAGMENT);
+ ADD_PROPERTYI(PropertyInfo(Variant::STRING, "compile_error_tesselation_control"), "set_stage_compile_error", "get_stage_compile_error", RD::SHADER_STAGE_TESSELATION_CONTROL);
+ ADD_PROPERTYI(PropertyInfo(Variant::STRING, "compile_error_tesselation_evaluation"), "set_stage_compile_error", "get_stage_compile_error", RD::SHADER_STAGE_TESSELATION_EVALUATION);
+ ADD_PROPERTYI(PropertyInfo(Variant::STRING, "compile_error_compute"), "set_stage_compile_error", "get_stage_compile_error", RD::SHADER_STAGE_COMPUTE);
+ }
+};
+
+class RDShaderFile : public Resource {
+ GDCLASS(RDShaderFile, Resource)
+
+ Map<StringName, Ref<RDShaderBytecode>> versions;
+ String base_error;
+
+public:
+ void set_bytecode(const Ref<RDShaderBytecode> &p_bytecode, const StringName &p_version = StringName()) {
+ ERR_FAIL_COND(p_bytecode.is_null());
+ versions[p_version] = p_bytecode;
+ emit_changed();
+ }
+
+ Ref<RDShaderBytecode> get_bytecode(const StringName &p_version = StringName()) const {
+ ERR_FAIL_COND_V(!versions.has(p_version), Ref<RDShaderBytecode>());
+ return versions[p_version];
+ }
+
+ Vector<StringName> get_version_list() const {
+ Vector<StringName> vnames;
+ for (Map<StringName, Ref<RDShaderBytecode>>::Element *E = versions.front(); E; E = E->next()) {
+ vnames.push_back(E->key());
+ }
+ vnames.sort_custom<StringName::AlphCompare>();
+ return vnames;
+ }
+
+ void set_base_error(const String &p_error) {
+ base_error = p_error;
+ emit_changed();
+ }
+
+ String get_base_error() const {
+ return base_error;
+ }
+
+ void print_errors(const String &p_file) {
+ if (base_error != "") {
+ ERR_PRINT("Error parsing shader '" + p_file + "':\n\n" + base_error);
+ } else {
+ for (Map<StringName, Ref<RDShaderBytecode>>::Element *E = versions.front(); E; E = E->next()) {
+ for (int i = 0; i < RD::SHADER_STAGE_MAX; i++) {
+ String error = E->get()->get_stage_compile_error(RD::ShaderStage(i));
+ if (error != String()) {
+ static const char *stage_str[RD::SHADER_STAGE_MAX] = {
+ "vertex",
+ "fragment",
+ "tesselation_control",
+ "tesselation_evaluation",
+ "compute"
+ };
+
+ ERR_PRINT("Error parsing shader '" + p_file + "', version '" + String(E->key()) + "', stage '" + stage_str[i] + "':\n\n" + error);
+ }
+ }
+ }
+ }
+ }
+
+ typedef String (*OpenIncludeFunction)(const String &, void *userdata);
+ Error parse_versions_from_text(const String &p_text, const String p_defines = String(), OpenIncludeFunction p_include_func = nullptr, void *p_include_func_userdata = nullptr);
+
+protected:
+ Dictionary _get_versions() const {
+ Vector<StringName> vnames = get_version_list();
+ Dictionary ret;
+ for (int i = 0; i < vnames.size(); i++) {
+ ret[vnames[i]] = versions[vnames[i]];
+ }
+ return ret;
+ }
+ void _set_versions(const Dictionary &p_versions) {
+ versions.clear();
+ List<Variant> keys;
+ p_versions.get_key_list(&keys);
+ for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
+ StringName name = E->get();
+ Ref<RDShaderBytecode> bc = p_versions[E->get()];
+ ERR_CONTINUE(bc.is_null());
+ versions[name] = bc;
+ }
+
+ emit_changed();
+ }
+
+ static void _bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_bytecode", "bytecode", "version"), &RDShaderFile::set_bytecode, DEFVAL(StringName()));
+ ClassDB::bind_method(D_METHOD("get_bytecode", "version"), &RDShaderFile::get_bytecode, DEFVAL(StringName()));
+ ClassDB::bind_method(D_METHOD("get_version_list"), &RDShaderFile::get_version_list);
+
+ ClassDB::bind_method(D_METHOD("set_base_error", "error"), &RDShaderFile::set_base_error);
+ ClassDB::bind_method(D_METHOD("get_base_error"), &RDShaderFile::get_base_error);
+
+ 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::STRING, "base_error"), "set_base_error", "get_base_error");
+ }
+};
+
+class RDUniform : public Reference {
+ GDCLASS(RDUniform, Reference)
+ friend class RenderingDevice;
+ RD::Uniform base;
+
+public:
+ RD_SETGET(RD::UniformType, type)
+ RD_SETGET(int32_t, binding)
+
+ void add_id(const RID &p_id) { base.ids.push_back(p_id); }
+ void clear_ids() { base.ids.clear(); }
+ Array get_ids() const {
+ Array ids;
+ for (int i = 0; i < base.ids.size(); i++) {
+ ids.push_back(base.ids[i]);
+ }
+ return ids;
+ }
+
+protected:
+ void _set_ids(const Array &p_ids) {
+ base.ids.clear();
+ for (int i = 0; i < p_ids.size(); i++) {
+ RID id = p_ids[i];
+ ERR_FAIL_COND(id.is_null());
+ base.ids.push_back(id);
+ }
+ }
+ static void _bind_methods() {
+ RD_BIND(Variant::INT, RDUniform, type);
+ RD_BIND(Variant::INT, RDUniform, binding);
+ ClassDB::bind_method(D_METHOD("add_id", "id"), &RDUniform::add_id);
+ ClassDB::bind_method(D_METHOD("clear_ids"), &RDUniform::clear_ids);
+ ClassDB::bind_method(D_METHOD("_set_ids", "ids"), &RDUniform::_set_ids);
+ ClassDB::bind_method(D_METHOD("get_ids"), &RDUniform::get_ids);
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "_ids", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_INTERNAL), "_set_ids", "get_ids");
+ }
+};
+class RDPipelineRasterizationState : public Reference {
+ GDCLASS(RDPipelineRasterizationState, Reference)
+ friend class RenderingDevice;
+
+ RD::PipelineRasterizationState base;
+
+public:
+ RD_SETGET(bool, enable_depth_clamp)
+ RD_SETGET(bool, discard_primitives)
+ RD_SETGET(bool, wireframe)
+ RD_SETGET(RD::PolygonCullMode, cull_mode)
+ RD_SETGET(RD::PolygonFrontFace, front_face)
+ RD_SETGET(bool, depth_bias_enable)
+ RD_SETGET(float, depth_bias_constant_factor)
+ RD_SETGET(float, depth_bias_clamp)
+ RD_SETGET(float, depth_bias_slope_factor)
+ RD_SETGET(float, line_width)
+ RD_SETGET(uint32_t, patch_control_points)
+
+protected:
+ static void _bind_methods() {
+ RD_BIND(Variant::BOOL, RDPipelineRasterizationState, enable_depth_clamp);
+ RD_BIND(Variant::BOOL, RDPipelineRasterizationState, discard_primitives);
+ RD_BIND(Variant::BOOL, RDPipelineRasterizationState, wireframe);
+ RD_BIND(Variant::INT, RDPipelineRasterizationState, cull_mode);
+ RD_BIND(Variant::INT, RDPipelineRasterizationState, front_face);
+ RD_BIND(Variant::BOOL, RDPipelineRasterizationState, depth_bias_enable);
+ RD_BIND(Variant::FLOAT, RDPipelineRasterizationState, depth_bias_constant_factor);
+ RD_BIND(Variant::FLOAT, RDPipelineRasterizationState, depth_bias_clamp);
+ RD_BIND(Variant::FLOAT, RDPipelineRasterizationState, depth_bias_slope_factor);
+ RD_BIND(Variant::FLOAT, RDPipelineRasterizationState, line_width);
+ RD_BIND(Variant::INT, RDPipelineRasterizationState, patch_control_points);
+ }
+};
+
+class RDPipelineMultisampleState : public Reference {
+ GDCLASS(RDPipelineMultisampleState, Reference)
+ friend class RenderingDevice;
+
+ RD::PipelineMultisampleState base;
+ TypedArray<int64_t> sample_masks;
+
+public:
+ RD_SETGET(RD::TextureSamples, sample_count)
+ RD_SETGET(bool, enable_sample_shading)
+ RD_SETGET(float, min_sample_shading)
+ RD_SETGET(bool, enable_alpha_to_coverage)
+ RD_SETGET(bool, enable_alpha_to_one)
+
+ void set_sample_masks(const TypedArray<int64_t> &p_masks) { sample_masks = p_masks; }
+ TypedArray<int64_t> get_sample_masks() const { return sample_masks; }
+
+protected:
+ static void _bind_methods() {
+ RD_BIND(Variant::INT, RDPipelineMultisampleState, sample_count);
+ RD_BIND(Variant::BOOL, RDPipelineMultisampleState, enable_sample_shading);
+ RD_BIND(Variant::FLOAT, RDPipelineMultisampleState, min_sample_shading);
+ RD_BIND(Variant::BOOL, RDPipelineMultisampleState, enable_alpha_to_coverage);
+ RD_BIND(Variant::BOOL, RDPipelineMultisampleState, enable_alpha_to_one);
+
+ ClassDB::bind_method(D_METHOD("set_sample_masks", "masks"), &RDPipelineMultisampleState::set_sample_masks);
+ ClassDB::bind_method(D_METHOD("get_sample_masks"), &RDPipelineMultisampleState::get_sample_masks);
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "sample_masks", PROPERTY_HINT_ARRAY_TYPE, "int"), "set_sample_masks", "get_sample_masks");
+ }
+};
+
+class RDPipelineDepthStencilState : public Reference {
+ GDCLASS(RDPipelineDepthStencilState, Reference)
+ friend class RenderingDevice;
+
+ RD::PipelineDepthStencilState base;
+
+public:
+ RD_SETGET(bool, enable_depth_test)
+ RD_SETGET(bool, enable_depth_write)
+ RD_SETGET(RD::CompareOperator, depth_compare_operator)
+ RD_SETGET(bool, enable_depth_range)
+ RD_SETGET(float, depth_range_min)
+ RD_SETGET(float, depth_range_max)
+ RD_SETGET(bool, enable_stencil)
+
+ RD_SETGET_SUB(RD::StencilOperation, front_op, fail)
+ RD_SETGET_SUB(RD::StencilOperation, front_op, pass)
+ RD_SETGET_SUB(RD::StencilOperation, front_op, depth_fail)
+ RD_SETGET_SUB(RD::CompareOperator, front_op, compare)
+ RD_SETGET_SUB(uint32_t, front_op, compare_mask)
+ RD_SETGET_SUB(uint32_t, front_op, write_mask)
+ RD_SETGET_SUB(uint32_t, front_op, reference)
+
+ RD_SETGET_SUB(RD::StencilOperation, back_op, fail)
+ RD_SETGET_SUB(RD::StencilOperation, back_op, pass)
+ RD_SETGET_SUB(RD::StencilOperation, back_op, depth_fail)
+ RD_SETGET_SUB(RD::CompareOperator, back_op, compare)
+ RD_SETGET_SUB(uint32_t, back_op, compare_mask)
+ RD_SETGET_SUB(uint32_t, back_op, write_mask)
+ RD_SETGET_SUB(uint32_t, back_op, reference)
+
+protected:
+ static void _bind_methods() {
+ RD_BIND(Variant::BOOL, RDPipelineDepthStencilState, enable_depth_test);
+ RD_BIND(Variant::BOOL, RDPipelineDepthStencilState, enable_depth_write);
+ RD_BIND(Variant::INT, RDPipelineDepthStencilState, depth_compare_operator);
+ RD_BIND(Variant::BOOL, RDPipelineDepthStencilState, enable_depth_range);
+ RD_BIND(Variant::FLOAT, RDPipelineDepthStencilState, depth_range_min);
+ RD_BIND(Variant::FLOAT, RDPipelineDepthStencilState, depth_range_max);
+ RD_BIND(Variant::BOOL, RDPipelineDepthStencilState, enable_stencil);
+
+ RD_BIND_SUB(Variant::INT, RDPipelineDepthStencilState, front_op, fail);
+ RD_BIND_SUB(Variant::INT, RDPipelineDepthStencilState, front_op, pass);
+ RD_BIND_SUB(Variant::INT, RDPipelineDepthStencilState, front_op, depth_fail);
+ RD_BIND_SUB(Variant::INT, RDPipelineDepthStencilState, front_op, compare);
+ RD_BIND_SUB(Variant::INT, RDPipelineDepthStencilState, front_op, compare_mask);
+ RD_BIND_SUB(Variant::INT, RDPipelineDepthStencilState, front_op, write_mask);
+ RD_BIND_SUB(Variant::INT, RDPipelineDepthStencilState, front_op, reference);
+
+ RD_BIND_SUB(Variant::INT, RDPipelineDepthStencilState, back_op, fail);
+ RD_BIND_SUB(Variant::INT, RDPipelineDepthStencilState, back_op, pass);
+ RD_BIND_SUB(Variant::INT, RDPipelineDepthStencilState, back_op, depth_fail);
+ RD_BIND_SUB(Variant::INT, RDPipelineDepthStencilState, back_op, compare);
+ RD_BIND_SUB(Variant::INT, RDPipelineDepthStencilState, back_op, compare_mask);
+ RD_BIND_SUB(Variant::INT, RDPipelineDepthStencilState, back_op, write_mask);
+ RD_BIND_SUB(Variant::INT, RDPipelineDepthStencilState, back_op, reference);
+ }
+};
+
+class RDPipelineColorBlendStateAttachment : public Reference {
+ GDCLASS(RDPipelineColorBlendStateAttachment, Reference)
+ friend class RenderingDevice;
+ RD::PipelineColorBlendState::Attachment base;
+
+public:
+ RD_SETGET(bool, enable_blend)
+ RD_SETGET(RD::BlendFactor, src_color_blend_factor)
+ RD_SETGET(RD::BlendFactor, dst_color_blend_factor)
+ RD_SETGET(RD::BlendOperation, color_blend_op)
+ RD_SETGET(RD::BlendFactor, src_alpha_blend_factor)
+ RD_SETGET(RD::BlendFactor, dst_alpha_blend_factor)
+ RD_SETGET(RD::BlendOperation, alpha_blend_op)
+ RD_SETGET(bool, write_r)
+ RD_SETGET(bool, write_g)
+ RD_SETGET(bool, write_b)
+ RD_SETGET(bool, write_a)
+
+ void set_as_mix() {
+ base = RD::PipelineColorBlendState::Attachment();
+ base.enable_blend = true;
+ base.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
+ base.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
+ base.src_alpha_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
+ base.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
+ }
+
+protected:
+ static void _bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_as_mix"), &RDPipelineColorBlendStateAttachment::set_as_mix);
+
+ RD_BIND(Variant::BOOL, RDPipelineColorBlendStateAttachment, enable_blend);
+ RD_BIND(Variant::INT, RDPipelineColorBlendStateAttachment, src_color_blend_factor);
+ RD_BIND(Variant::INT, RDPipelineColorBlendStateAttachment, dst_color_blend_factor);
+ RD_BIND(Variant::INT, RDPipelineColorBlendStateAttachment, color_blend_op);
+ RD_BIND(Variant::INT, RDPipelineColorBlendStateAttachment, src_alpha_blend_factor);
+ RD_BIND(Variant::INT, RDPipelineColorBlendStateAttachment, dst_alpha_blend_factor);
+ RD_BIND(Variant::INT, RDPipelineColorBlendStateAttachment, alpha_blend_op);
+ RD_BIND(Variant::BOOL, RDPipelineColorBlendStateAttachment, write_r);
+ RD_BIND(Variant::BOOL, RDPipelineColorBlendStateAttachment, write_g);
+ RD_BIND(Variant::BOOL, RDPipelineColorBlendStateAttachment, write_b);
+ RD_BIND(Variant::BOOL, RDPipelineColorBlendStateAttachment, write_a);
+ }
+};
+
+class RDPipelineColorBlendState : public Reference {
+ GDCLASS(RDPipelineColorBlendState, Reference)
+ friend class RenderingDevice;
+ RD::PipelineColorBlendState base;
+
+ TypedArray<RDPipelineColorBlendStateAttachment> attachments;
+
+public:
+ RD_SETGET(bool, enable_logic_op)
+ RD_SETGET(RD::LogicOperation, logic_op)
+ RD_SETGET(Color, blend_constant)
+
+ void set_attachments(const TypedArray<RDPipelineColorBlendStateAttachment> &p_attachments) {
+ attachments.push_back(p_attachments);
+ }
+
+ TypedArray<RDPipelineColorBlendStateAttachment> get_attachments() const {
+ return attachments;
+ }
+
+protected:
+ static void _bind_methods() {
+ RD_BIND(Variant::BOOL, RDPipelineColorBlendState, enable_logic_op);
+ RD_BIND(Variant::INT, RDPipelineColorBlendState, logic_op);
+ RD_BIND(Variant::COLOR, RDPipelineColorBlendState, blend_constant);
+
+ ClassDB::bind_method(D_METHOD("set_attachments", "atachments"), &RDPipelineColorBlendState::set_attachments);
+ ClassDB::bind_method(D_METHOD("get_attachments"), &RDPipelineColorBlendState::get_attachments);
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "attachments", PROPERTY_HINT_ARRAY_TYPE, "RDPipelineColorBlendStateAttachment"), "set_attachments", "get_attachments");
+ }
+};
+
+#endif // RENDERING_DEVICE_BINDS_H
diff --git a/servers/rendering/rendering_server_canvas.cpp b/servers/rendering/rendering_server_canvas.cpp
index 261bd4c275..5c0741bb3b 100644
--- a/servers/rendering/rendering_server_canvas.cpp
+++ b/servers/rendering/rendering_server_canvas.cpp
@@ -29,6 +29,8 @@
/*************************************************************************/
#include "rendering_server_canvas.h"
+
+#include "core/math/geometry_2d.h"
#include "rendering_server_globals.h"
#include "rendering_server_raster.h"
#include "rendering_server_viewport.h"
@@ -36,25 +38,25 @@
static const int z_range = RS::CANVAS_ITEM_Z_MAX - RS::CANVAS_ITEM_Z_MIN + 1;
void RenderingServerCanvas::_render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RasterizerCanvas::Light *p_lights) {
-
RENDER_TIMESTAMP("Cull CanvasItem Tree");
memset(z_list, 0, z_range * sizeof(RasterizerCanvas::Item *));
memset(z_last_list, 0, z_range * sizeof(RasterizerCanvas::Item *));
for (int i = 0; i < p_child_item_count; i++) {
- _cull_canvas_item(p_child_items[i].item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, NULL, NULL);
+ _cull_canvas_item(p_child_items[i].item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, nullptr, nullptr);
}
if (p_canvas_item) {
- _cull_canvas_item(p_canvas_item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, NULL, NULL);
+ _cull_canvas_item(p_canvas_item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, nullptr, nullptr);
}
- RasterizerCanvas::Item *list = NULL;
- RasterizerCanvas::Item *list_end = NULL;
+ RasterizerCanvas::Item *list = nullptr;
+ RasterizerCanvas::Item *list_end = nullptr;
for (int i = 0; i < z_range; i++) {
- if (!z_list[i])
+ if (!z_list[i]) {
continue;
+ }
if (!list) {
list = z_list[i];
list_end = z_last_list[i];
@@ -78,13 +80,14 @@ void _collect_ysort_children(RenderingServerCanvas::Item *p_canvas_item, Transfo
r_items[r_index] = child_items[i];
child_items[i]->ysort_xform = p_transform;
child_items[i]->ysort_pos = p_transform.xform(child_items[i]->xform.elements[2]);
- child_items[i]->material_owner = child_items[i]->use_parent_material ? p_material_owner : NULL;
+ child_items[i]->material_owner = child_items[i]->use_parent_material ? p_material_owner : nullptr;
}
r_index++;
- if (child_items[i]->sort_y)
+ if (child_items[i]->sort_y) {
_collect_ysort_children(child_items[i], p_transform * child_items[i]->xform, child_items[i]->use_parent_material ? p_material_owner : child_items[i], r_items, r_index);
+ }
}
}
}
@@ -92,19 +95,18 @@ void _collect_ysort_children(RenderingServerCanvas::Item *p_canvas_item, Transfo
void _mark_ysort_dirty(RenderingServerCanvas::Item *ysort_owner, RID_PtrOwner<RenderingServerCanvas::Item> &canvas_item_owner) {
do {
ysort_owner->ysort_children_count = -1;
- ysort_owner = canvas_item_owner.owns(ysort_owner->parent) ? canvas_item_owner.getornull(ysort_owner->parent) : NULL;
+ ysort_owner = canvas_item_owner.owns(ysort_owner->parent) ? canvas_item_owner.getornull(ysort_owner->parent) : nullptr;
} while (ysort_owner && ysort_owner->sort_y);
}
void RenderingServerCanvas::_cull_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RasterizerCanvas::Item **z_list, RasterizerCanvas::Item **z_last_list, Item *p_canvas_clip, Item *p_material_owner) {
-
Item *ci = p_canvas_item;
- if (!ci->visible)
+ if (!ci->visible) {
return;
+ }
if (ci->children_order_dirty) {
-
ci->child_items.sort_custom<ItemIndexSort>();
ci->children_order_dirty = false;
}
@@ -114,23 +116,24 @@ void RenderingServerCanvas::_cull_canvas_item(Item *p_canvas_item, const Transfo
Rect2 global_rect = xform.xform(rect);
global_rect.position += p_clip_rect.position;
- if (ci->use_parent_material && p_material_owner)
+ if (ci->use_parent_material && p_material_owner) {
ci->material_owner = p_material_owner;
- else {
+ } else {
p_material_owner = ci;
- ci->material_owner = NULL;
+ ci->material_owner = nullptr;
}
Color modulate(ci->modulate.r * p_modulate.r, ci->modulate.g * p_modulate.g, ci->modulate.b * p_modulate.b, ci->modulate.a * p_modulate.a);
- if (modulate.a < 0.007)
+ if (modulate.a < 0.007) {
return;
+ }
int child_item_count = ci->child_items.size();
Item **child_items = ci->child_items.ptrw();
if (ci->clip) {
- if (p_canvas_clip != NULL) {
+ if (p_canvas_clip != nullptr) {
ci->final_clip_rect = p_canvas_clip->final_clip_rect.clip(global_rect);
} else {
ci->final_clip_rect = global_rect;
@@ -142,10 +145,9 @@ void RenderingServerCanvas::_cull_canvas_item(Item *p_canvas_item, const Transfo
}
if (ci->sort_y) {
-
if (ci->ysort_children_count == -1) {
ci->ysort_children_count = 0;
- _collect_ysort_children(ci, Transform2D(), p_material_owner, NULL, ci->ysort_children_count);
+ _collect_ysort_children(ci, Transform2D(), p_material_owner, nullptr, ci->ysort_children_count);
}
child_item_count = ci->ysort_children_count;
@@ -158,15 +160,16 @@ void RenderingServerCanvas::_cull_canvas_item(Item *p_canvas_item, const Transfo
sorter.sort(child_items, child_item_count);
}
- if (ci->z_relative)
+ if (ci->z_relative) {
p_z = CLAMP(p_z + ci->z_index, RS::CANVAS_ITEM_Z_MIN, RS::CANVAS_ITEM_Z_MAX);
- else
+ } else {
p_z = ci->z_index;
+ }
for (int i = 0; i < child_item_count; i++) {
-
- if (!child_items[i]->behind || (ci->sort_y && child_items[i]->sort_y))
+ if (!child_items[i]->behind || (ci->sort_y && child_items[i]->sort_y)) {
continue;
+ }
if (ci->sort_y) {
_cull_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner);
} else {
@@ -175,7 +178,6 @@ void RenderingServerCanvas::_cull_canvas_item(Item *p_canvas_item, const Transfo
}
if (ci->copy_back_buffer) {
-
ci->copy_back_buffer->screen_rect = xform.xform(ci->copy_back_buffer->rect).clip(p_clip_rect);
}
@@ -183,7 +185,7 @@ void RenderingServerCanvas::_cull_canvas_item(Item *p_canvas_item, const Transfo
RenderingServerRaster::redraw_request();
}
- if ((ci->commands != NULL && p_clip_rect.intersects(global_rect, true)) || ci->vp_render || ci->copy_back_buffer) {
+ if ((ci->commands != nullptr && p_clip_rect.intersects(global_rect, true)) || ci->vp_render || ci->copy_back_buffer) {
//something to draw?
ci->final_transform = xform;
ci->final_modulate = Color(modulate.r * ci->self_modulate.r, modulate.g * ci->self_modulate.g, modulate.b * ci->self_modulate.b, modulate.a * ci->self_modulate.a);
@@ -204,13 +206,13 @@ void RenderingServerCanvas::_cull_canvas_item(Item *p_canvas_item, const Transfo
ci->z_final = p_z;
- ci->next = NULL;
+ ci->next = nullptr;
}
for (int i = 0; i < child_item_count; i++) {
-
- if (child_items[i]->behind || (ci->sort_y && child_items[i]->sort_y))
+ if (child_items[i]->behind || (ci->sort_y && child_items[i]->sort_y)) {
continue;
+ }
if (ci->sort_y) {
_cull_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner);
} else {
@@ -220,17 +222,15 @@ void RenderingServerCanvas::_cull_canvas_item(Item *p_canvas_item, const Transfo
}
void RenderingServerCanvas::_light_mask_canvas_items(int p_z, RasterizerCanvas::Item *p_canvas_item, RasterizerCanvas::Light *p_masked_lights) {
-
- if (!p_masked_lights)
+ if (!p_masked_lights) {
return;
+ }
RasterizerCanvas::Item *ci = p_canvas_item;
while (ci) {
-
RasterizerCanvas::Light *light = p_masked_lights;
while (light) {
-
if (ci->light_mask & light->item_mask && p_z >= light->z_min && p_z <= light->z_max && ci->global_rect_cache.intersects_transformed(light->xform_cache, light->rect_cache)) {
ci->light_masked = true;
}
@@ -243,11 +243,9 @@ void RenderingServerCanvas::_light_mask_canvas_items(int p_z, RasterizerCanvas::
}
void RenderingServerCanvas::render_canvas(RID p_render_target, Canvas *p_canvas, const Transform2D &p_transform, RasterizerCanvas::Light *p_lights, RasterizerCanvas::Light *p_masked_lights, const Rect2 &p_clip_rect) {
-
RENDER_TIMESTAMP(">Render Canvas");
if (p_canvas->children_order_dirty) {
-
p_canvas->child_items.sort();
p_canvas->children_order_dirty = false;
}
@@ -264,31 +262,26 @@ void RenderingServerCanvas::render_canvas(RID p_render_target, Canvas *p_canvas,
}
if (!has_mirror) {
-
- _render_canvas_item_tree(p_render_target, ci, l, NULL, p_transform, p_clip_rect, p_canvas->modulate, p_lights);
+ _render_canvas_item_tree(p_render_target, ci, l, nullptr, p_transform, p_clip_rect, p_canvas->modulate, p_lights);
} else {
//used for parallaxlayer mirroring
for (int i = 0; i < l; i++) {
-
const Canvas::ChildItem &ci2 = p_canvas->child_items[i];
- _render_canvas_item_tree(p_render_target, NULL, 0, ci2.item, p_transform, p_clip_rect, p_canvas->modulate, p_lights);
+ _render_canvas_item_tree(p_render_target, nullptr, 0, ci2.item, p_transform, p_clip_rect, p_canvas->modulate, p_lights);
//mirroring (useful for scrolling backgrounds)
if (ci2.mirror.x != 0) {
-
Transform2D xform2 = p_transform * Transform2D(0, Vector2(ci2.mirror.x, 0));
- _render_canvas_item_tree(p_render_target, NULL, 0, ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights);
+ _render_canvas_item_tree(p_render_target, nullptr, 0, ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights);
}
if (ci2.mirror.y != 0) {
-
Transform2D xform2 = p_transform * Transform2D(0, Vector2(0, ci2.mirror.y));
- _render_canvas_item_tree(p_render_target, NULL, 0, ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights);
+ _render_canvas_item_tree(p_render_target, nullptr, 0, ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights);
}
if (ci2.mirror.y != 0 && ci2.mirror.x != 0) {
-
Transform2D xform2 = p_transform * Transform2D(0, ci2.mirror);
- _render_canvas_item_tree(p_render_target, NULL, 0, ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights);
+ _render_canvas_item_tree(p_render_target, nullptr, 0, ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights);
}
}
}
@@ -297,7 +290,6 @@ void RenderingServerCanvas::render_canvas(RID p_render_target, Canvas *p_canvas,
}
RID RenderingServerCanvas::canvas_create() {
-
Canvas *canvas = memnew(Canvas);
ERR_FAIL_COND_V(!canvas, RID());
RID rid = canvas_owner.make_rid(canvas);
@@ -306,7 +298,6 @@ RID RenderingServerCanvas::canvas_create() {
}
void RenderingServerCanvas::canvas_set_item_mirroring(RID p_canvas, RID p_item, const Point2 &p_mirroring) {
-
Canvas *canvas = canvas_owner.getornull(p_canvas);
ERR_FAIL_COND(!canvas);
Item *canvas_item = canvas_item_owner.getornull(p_item);
@@ -316,8 +307,8 @@ void RenderingServerCanvas::canvas_set_item_mirroring(RID p_canvas, RID p_item,
ERR_FAIL_COND(idx == -1);
canvas->child_items.write[idx].mirror = p_mirroring;
}
-void RenderingServerCanvas::canvas_set_modulate(RID p_canvas, const Color &p_color) {
+void RenderingServerCanvas::canvas_set_modulate(RID p_canvas, const Color &p_color) {
Canvas *canvas = canvas_owner.getornull(p_canvas);
ERR_FAIL_COND(!canvas);
canvas->modulate = p_color;
@@ -328,7 +319,6 @@ void RenderingServerCanvas::canvas_set_disable_scale(bool p_disable) {
}
void RenderingServerCanvas::canvas_set_parent(RID p_canvas, RID p_parent, float p_scale) {
-
Canvas *canvas = canvas_owner.getornull(p_canvas);
ERR_FAIL_COND(!canvas);
@@ -337,7 +327,6 @@ void RenderingServerCanvas::canvas_set_parent(RID p_canvas, RID p_parent, float
}
RID RenderingServerCanvas::canvas_item_create() {
-
Item *canvas_item = memnew(Item);
ERR_FAIL_COND_V(!canvas_item, RID());
@@ -345,18 +334,14 @@ RID RenderingServerCanvas::canvas_item_create() {
}
void RenderingServerCanvas::canvas_item_set_parent(RID p_item, RID p_parent) {
-
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
if (canvas_item->parent.is_valid()) {
-
if (canvas_owner.owns(canvas_item->parent)) {
-
Canvas *canvas = canvas_owner.getornull(canvas_item->parent);
canvas->erase_item(canvas_item);
} else if (canvas_item_owner.owns(canvas_item->parent)) {
-
Item *item_owner = canvas_item_owner.getornull(canvas_item->parent);
item_owner->child_items.erase(canvas_item);
@@ -370,14 +355,12 @@ void RenderingServerCanvas::canvas_item_set_parent(RID p_item, RID p_parent) {
if (p_parent.is_valid()) {
if (canvas_owner.owns(p_parent)) {
-
Canvas *canvas = canvas_owner.getornull(p_parent);
Canvas::ChildItem ci;
ci.item = canvas_item;
canvas->child_items.push_back(ci);
canvas->children_order_dirty = true;
} else if (canvas_item_owner.owns(p_parent)) {
-
Item *item_owner = canvas_item_owner.getornull(p_parent);
item_owner->child_items.push_back(canvas_item);
item_owner->children_order_dirty = true;
@@ -387,15 +370,14 @@ void RenderingServerCanvas::canvas_item_set_parent(RID p_item, RID p_parent) {
}
} else {
-
ERR_FAIL_MSG("Invalid parent.");
}
}
canvas_item->parent = p_parent;
}
-void RenderingServerCanvas::canvas_item_set_visible(RID p_item, bool p_visible) {
+void RenderingServerCanvas::canvas_item_set_visible(RID p_item, bool p_visible) {
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
@@ -403,8 +385,8 @@ void RenderingServerCanvas::canvas_item_set_visible(RID p_item, bool p_visible)
_mark_ysort_dirty(canvas_item, canvas_item_owner);
}
-void RenderingServerCanvas::canvas_item_set_light_mask(RID p_item, int p_mask) {
+void RenderingServerCanvas::canvas_item_set_light_mask(RID p_item, int p_mask) {
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
@@ -412,43 +394,42 @@ void RenderingServerCanvas::canvas_item_set_light_mask(RID p_item, int p_mask) {
}
void RenderingServerCanvas::canvas_item_set_transform(RID p_item, const Transform2D &p_transform) {
-
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
canvas_item->xform = p_transform;
}
-void RenderingServerCanvas::canvas_item_set_clip(RID p_item, bool p_clip) {
+void RenderingServerCanvas::canvas_item_set_clip(RID p_item, bool p_clip) {
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
canvas_item->clip = p_clip;
}
-void RenderingServerCanvas::canvas_item_set_distance_field_mode(RID p_item, bool p_enable) {
+void RenderingServerCanvas::canvas_item_set_distance_field_mode(RID p_item, bool p_enable) {
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
canvas_item->distance_field = p_enable;
}
-void RenderingServerCanvas::canvas_item_set_custom_rect(RID p_item, bool p_custom_rect, const Rect2 &p_rect) {
+void RenderingServerCanvas::canvas_item_set_custom_rect(RID p_item, bool p_custom_rect, const Rect2 &p_rect) {
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
canvas_item->custom_rect = p_custom_rect;
canvas_item->rect = p_rect;
}
-void RenderingServerCanvas::canvas_item_set_modulate(RID p_item, const Color &p_color) {
+void RenderingServerCanvas::canvas_item_set_modulate(RID p_item, const Color &p_color) {
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
canvas_item->modulate = p_color;
}
-void RenderingServerCanvas::canvas_item_set_self_modulate(RID p_item, const Color &p_color) {
+void RenderingServerCanvas::canvas_item_set_self_modulate(RID p_item, const Color &p_color) {
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
@@ -456,7 +437,6 @@ void RenderingServerCanvas::canvas_item_set_self_modulate(RID p_item, const Colo
}
void RenderingServerCanvas::canvas_item_set_draw_behind_parent(RID p_item, bool p_enable) {
-
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
@@ -464,7 +444,6 @@ void RenderingServerCanvas::canvas_item_set_draw_behind_parent(RID p_item, bool
}
void RenderingServerCanvas::canvas_item_set_update_when_visible(RID p_item, bool p_update) {
-
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
@@ -472,28 +451,24 @@ void RenderingServerCanvas::canvas_item_set_update_when_visible(RID p_item, bool
}
void RenderingServerCanvas::canvas_item_set_default_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) {
-
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
canvas_item->texture_filter = p_filter;
}
void RenderingServerCanvas::canvas_item_set_default_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) {
-
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
canvas_item->texture_repeat = p_repeat;
}
void RenderingServerCanvas::canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width) {
-
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
Item::CommandPrimitive *line = canvas_item->alloc_command<Item::CommandPrimitive>();
ERR_FAIL_COND(!line);
if (p_width > 1.001) {
-
Vector2 t = (p_from - p_to).tangent().normalized();
line->points[0] = p_from + t * p_width;
line->points[1] = p_from - t * p_width;
@@ -512,7 +487,6 @@ void RenderingServerCanvas::canvas_item_add_line(RID p_item, const Point2 &p_fro
}
void RenderingServerCanvas::canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width) {
-
ERR_FAIL_COND(p_points.size() < 2);
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
@@ -604,7 +578,6 @@ void RenderingServerCanvas::canvas_item_add_polyline(RID p_item, const Vector<Po
}
void RenderingServerCanvas::canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width) {
-
ERR_FAIL_COND(p_points.size() < 2);
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
@@ -625,7 +598,6 @@ void RenderingServerCanvas::canvas_item_add_multiline(RID p_item, const Vector<P
}
void RenderingServerCanvas::canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color) {
-
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
@@ -636,7 +608,6 @@ void RenderingServerCanvas::canvas_item_add_rect(RID p_item, const Rect2 &p_rect
}
void RenderingServerCanvas::canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color) {
-
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
@@ -674,7 +645,6 @@ void RenderingServerCanvas::canvas_item_add_circle(RID p_item, const Point2 &p_p
}
void RenderingServerCanvas::canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile, const Color &p_modulate, bool p_transpose, RID p_normal_map, RID p_specular_map, const Color &p_specular_color_shininess, RenderingServer::CanvasItemTextureFilter p_filter, RenderingServer::CanvasItemTextureRepeat p_repeat) {
-
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
@@ -690,12 +660,10 @@ void RenderingServerCanvas::canvas_item_add_texture_rect(RID p_item, const Rect2
}
if (p_rect.size.x < 0) {
-
rect->flags |= RasterizerCanvas::CANVAS_RECT_FLIP_H;
rect->rect.size.x = -rect->rect.size.x;
}
if (p_rect.size.y < 0) {
-
rect->flags |= RasterizerCanvas::CANVAS_RECT_FLIP_V;
rect->rect.size.y = -rect->rect.size.y;
}
@@ -708,7 +676,6 @@ void RenderingServerCanvas::canvas_item_add_texture_rect(RID p_item, const Rect2
}
void RenderingServerCanvas::canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, RID p_normal_map, RID p_specular_map, const Color &p_specular_color_shininess, bool p_clip_uv, RenderingServer::CanvasItemTextureFilter p_filter, RenderingServer::CanvasItemTextureRepeat p_repeat) {
-
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
@@ -722,22 +689,18 @@ void RenderingServerCanvas::canvas_item_add_texture_rect_region(RID p_item, cons
rect->flags = RasterizerCanvas::CANVAS_RECT_REGION;
if (p_rect.size.x < 0) {
-
rect->flags |= RasterizerCanvas::CANVAS_RECT_FLIP_H;
rect->rect.size.x = -rect->rect.size.x;
}
if (p_src_rect.size.x < 0) {
-
rect->flags ^= RasterizerCanvas::CANVAS_RECT_FLIP_H;
rect->source.size.x = -rect->source.size.x;
}
if (p_rect.size.y < 0) {
-
rect->flags |= RasterizerCanvas::CANVAS_RECT_FLIP_V;
rect->rect.size.y = -rect->rect.size.y;
}
if (p_src_rect.size.y < 0) {
-
rect->flags ^= RasterizerCanvas::CANVAS_RECT_FLIP_V;
rect->source.size.y = -rect->source.size.y;
}
@@ -753,7 +716,6 @@ void RenderingServerCanvas::canvas_item_add_texture_rect_region(RID p_item, cons
}
void RenderingServerCanvas::canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, RS::NinePatchAxisMode p_x_axis_mode, RS::NinePatchAxisMode p_y_axis_mode, bool p_draw_center, const Color &p_modulate, RID p_normal_map, RID p_specular_map, const Color &p_specular_color_shininess, RenderingServer::CanvasItemTextureFilter p_filter, RenderingServer::CanvasItemTextureRepeat p_repeat) {
-
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
@@ -772,8 +734,8 @@ void RenderingServerCanvas::canvas_item_add_nine_patch(RID p_item, const Rect2 &
style->axis_x = p_x_axis_mode;
style->axis_y = p_y_axis_mode;
}
-void RenderingServerCanvas::canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width, RID p_normal_map, RID p_specular_map, const Color &p_specular_color_shininess, RenderingServer::CanvasItemTextureFilter p_filter, RenderingServer::CanvasItemTextureRepeat p_repeat) {
+void RenderingServerCanvas::canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width, RID p_normal_map, RID p_specular_map, const Color &p_specular_color_shininess, RenderingServer::CanvasItemTextureFilter p_filter, RenderingServer::CanvasItemTextureRepeat p_repeat) {
uint32_t pc = p_points.size();
ERR_FAIL_COND(pc == 0 || pc > 4);
@@ -804,7 +766,6 @@ void RenderingServerCanvas::canvas_item_add_primitive(RID p_item, const Vector<P
}
void RenderingServerCanvas::canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, RID p_normal_map, RID p_specular_map, const Color &p_specular_color_shininess, RenderingServer::CanvasItemTextureFilter p_filter, RenderingServer::CanvasItemTextureRepeat p_repeat) {
-
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
#ifdef DEBUG_ENABLED
@@ -815,7 +776,7 @@ void RenderingServerCanvas::canvas_item_add_polygon(RID p_item, const Vector<Poi
ERR_FAIL_COND(color_size != 0 && color_size != 1 && color_size != pointcount);
ERR_FAIL_COND(uv_size != 0 && (uv_size != pointcount));
#endif
- Vector<int> indices = Geometry::triangulate_polygon(p_points);
+ Vector<int> indices = Geometry2D::triangulate_polygon(p_points);
ERR_FAIL_COND_MSG(indices.empty(), "Invalid polygon data, triangulation failed.");
Item::CommandPolygon *polygon = canvas_item->alloc_command<Item::CommandPolygon>();
@@ -827,7 +788,6 @@ void RenderingServerCanvas::canvas_item_add_polygon(RID p_item, const Vector<Poi
}
void RenderingServerCanvas::canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, const Vector<int> &p_bones, const Vector<float> &p_weights, RID p_texture, int p_count, RID p_normal_map, RID p_specular_map, const Color &p_specular_color_shininess, RenderingServer::CanvasItemTextureFilter p_filter, RenderingServer::CanvasItemTextureRepeat p_repeat) {
-
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
@@ -850,7 +810,6 @@ void RenderingServerCanvas::canvas_item_add_triangle_array(RID p_item, const Vec
}
void RenderingServerCanvas::canvas_item_add_set_transform(RID p_item, const Transform2D &p_transform) {
-
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
@@ -860,7 +819,6 @@ void RenderingServerCanvas::canvas_item_add_set_transform(RID p_item, const Tran
}
void RenderingServerCanvas::canvas_item_add_mesh(RID p_item, const RID &p_mesh, const Transform2D &p_transform, const Color &p_modulate, RID p_texture, RID p_normal_map, RID p_specular_map, const Color &p_specular_color_shininess, RenderingServer::CanvasItemTextureFilter p_filter, RenderingServer::CanvasItemTextureRepeat p_repeat) {
-
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
@@ -872,8 +830,8 @@ void RenderingServerCanvas::canvas_item_add_mesh(RID p_item, const RID &p_mesh,
m->transform = p_transform;
m->modulate = p_modulate;
}
-void RenderingServerCanvas::canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture, RID p_normal_map, RID p_specular_map, const Color &p_specular_color_shininess, RenderingServer::CanvasItemTextureFilter p_filter, RenderingServer::CanvasItemTextureRepeat p_repeat) {
+void RenderingServerCanvas::canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture, RID p_normal_map, RID p_specular_map, const Color &p_specular_color_shininess, RenderingServer::CanvasItemTextureFilter p_filter, RenderingServer::CanvasItemTextureRepeat p_repeat) {
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
@@ -888,7 +846,6 @@ void RenderingServerCanvas::canvas_item_add_particles(RID p_item, RID p_particle
}
void RenderingServerCanvas::canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture, RID p_normal_map, RID p_specular_map, const Color &p_specular_color_shininess, RenderingServer::CanvasItemTextureFilter p_filter, RenderingServer::CanvasItemTextureRepeat p_repeat) {
-
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
@@ -900,7 +857,6 @@ void RenderingServerCanvas::canvas_item_add_multimesh(RID p_item, RID p_mesh, RI
}
void RenderingServerCanvas::canvas_item_add_clip_ignore(RID p_item, bool p_ignore) {
-
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
@@ -908,8 +864,8 @@ void RenderingServerCanvas::canvas_item_add_clip_ignore(RID p_item, bool p_ignor
ERR_FAIL_COND(!ci);
ci->ignore = p_ignore;
}
-void RenderingServerCanvas::canvas_item_set_sort_children_by_y(RID p_item, bool p_enable) {
+void RenderingServerCanvas::canvas_item_set_sort_children_by_y(RID p_item, bool p_enable) {
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
@@ -917,8 +873,8 @@ void RenderingServerCanvas::canvas_item_set_sort_children_by_y(RID p_item, bool
_mark_ysort_dirty(canvas_item, canvas_item_owner);
}
-void RenderingServerCanvas::canvas_item_set_z_index(RID p_item, int p_z) {
+void RenderingServerCanvas::canvas_item_set_z_index(RID p_item, int p_z) {
ERR_FAIL_COND(p_z < RS::CANVAS_ITEM_Z_MIN || p_z > RS::CANVAS_ITEM_Z_MAX);
Item *canvas_item = canvas_item_owner.getornull(p_item);
@@ -926,8 +882,8 @@ void RenderingServerCanvas::canvas_item_set_z_index(RID p_item, int p_z) {
canvas_item->z_index = p_z;
}
-void RenderingServerCanvas::canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable) {
+void RenderingServerCanvas::canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable) {
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
@@ -935,7 +891,6 @@ void RenderingServerCanvas::canvas_item_set_z_as_relative_to_parent(RID p_item,
}
void RenderingServerCanvas::canvas_item_attach_skeleton(RID p_item, RID p_skeleton) {
-
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
@@ -943,15 +898,14 @@ void RenderingServerCanvas::canvas_item_attach_skeleton(RID p_item, RID p_skelet
}
void RenderingServerCanvas::canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable, const Rect2 &p_rect) {
-
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
- if (bool(canvas_item->copy_back_buffer != NULL) != p_enable) {
+ if (bool(canvas_item->copy_back_buffer != nullptr) != p_enable) {
if (p_enable) {
canvas_item->copy_back_buffer = memnew(RasterizerCanvas::Item::CopyBackBuffer);
} else {
memdelete(canvas_item->copy_back_buffer);
- canvas_item->copy_back_buffer = NULL;
+ canvas_item->copy_back_buffer = nullptr;
}
}
@@ -962,14 +916,13 @@ void RenderingServerCanvas::canvas_item_set_copy_to_backbuffer(RID p_item, bool
}
void RenderingServerCanvas::canvas_item_clear(RID p_item) {
-
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
canvas_item->clear();
}
-void RenderingServerCanvas::canvas_item_set_draw_index(RID p_item, int p_index) {
+void RenderingServerCanvas::canvas_item_set_draw_index(RID p_item, int p_index) {
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
@@ -989,7 +942,6 @@ void RenderingServerCanvas::canvas_item_set_draw_index(RID p_item, int p_index)
}
void RenderingServerCanvas::canvas_item_set_material(RID p_item, RID p_material) {
-
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
@@ -997,7 +949,6 @@ void RenderingServerCanvas::canvas_item_set_material(RID p_item, RID p_material)
}
void RenderingServerCanvas::canvas_item_set_use_parent_material(RID p_item, bool p_enable) {
-
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
@@ -1005,57 +956,54 @@ void RenderingServerCanvas::canvas_item_set_use_parent_material(RID p_item, bool
}
RID RenderingServerCanvas::canvas_light_create() {
-
RasterizerCanvas::Light *clight = memnew(RasterizerCanvas::Light);
clight->light_internal = RSG::canvas_render->light_create();
return canvas_light_owner.make_rid(clight);
}
-void RenderingServerCanvas::canvas_light_attach_to_canvas(RID p_light, RID p_canvas) {
+void RenderingServerCanvas::canvas_light_attach_to_canvas(RID p_light, RID p_canvas) {
RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light);
ERR_FAIL_COND(!clight);
if (clight->canvas.is_valid()) {
-
Canvas *canvas = canvas_owner.getornull(clight->canvas);
canvas->lights.erase(clight);
}
- if (!canvas_owner.owns(p_canvas))
+ if (!canvas_owner.owns(p_canvas)) {
p_canvas = RID();
+ }
clight->canvas = p_canvas;
if (clight->canvas.is_valid()) {
-
Canvas *canvas = canvas_owner.getornull(clight->canvas);
canvas->lights.insert(clight);
}
}
void RenderingServerCanvas::canvas_light_set_enabled(RID p_light, bool p_enabled) {
-
RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light);
ERR_FAIL_COND(!clight);
clight->enabled = p_enabled;
}
-void RenderingServerCanvas::canvas_light_set_scale(RID p_light, float p_scale) {
+void RenderingServerCanvas::canvas_light_set_scale(RID p_light, float p_scale) {
RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light);
ERR_FAIL_COND(!clight);
clight->scale = p_scale;
}
-void RenderingServerCanvas::canvas_light_set_transform(RID p_light, const Transform2D &p_transform) {
+void RenderingServerCanvas::canvas_light_set_transform(RID p_light, const Transform2D &p_transform) {
RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light);
ERR_FAIL_COND(!clight);
clight->xform = p_transform;
}
-void RenderingServerCanvas::canvas_light_set_texture(RID p_light, RID p_texture) {
+void RenderingServerCanvas::canvas_light_set_texture(RID p_light, RID p_texture) {
RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light);
ERR_FAIL_COND(!clight);
@@ -1063,66 +1011,66 @@ void RenderingServerCanvas::canvas_light_set_texture(RID p_light, RID p_texture)
clight->version++;
RSG::canvas_render->light_set_texture(clight->light_internal, p_texture);
}
-void RenderingServerCanvas::canvas_light_set_texture_offset(RID p_light, const Vector2 &p_offset) {
+void RenderingServerCanvas::canvas_light_set_texture_offset(RID p_light, const Vector2 &p_offset) {
RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light);
ERR_FAIL_COND(!clight);
clight->texture_offset = p_offset;
}
-void RenderingServerCanvas::canvas_light_set_color(RID p_light, const Color &p_color) {
+void RenderingServerCanvas::canvas_light_set_color(RID p_light, const Color &p_color) {
RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light);
ERR_FAIL_COND(!clight);
clight->color = p_color;
}
-void RenderingServerCanvas::canvas_light_set_height(RID p_light, float p_height) {
+void RenderingServerCanvas::canvas_light_set_height(RID p_light, float p_height) {
RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light);
ERR_FAIL_COND(!clight);
clight->height = p_height;
}
-void RenderingServerCanvas::canvas_light_set_energy(RID p_light, float p_energy) {
+void RenderingServerCanvas::canvas_light_set_energy(RID p_light, float p_energy) {
RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light);
ERR_FAIL_COND(!clight);
clight->energy = p_energy;
}
-void RenderingServerCanvas::canvas_light_set_z_range(RID p_light, int p_min_z, int p_max_z) {
+void RenderingServerCanvas::canvas_light_set_z_range(RID p_light, int p_min_z, int p_max_z) {
RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light);
ERR_FAIL_COND(!clight);
clight->z_min = p_min_z;
clight->z_max = p_max_z;
}
-void RenderingServerCanvas::canvas_light_set_layer_range(RID p_light, int p_min_layer, int p_max_layer) {
+void RenderingServerCanvas::canvas_light_set_layer_range(RID p_light, int p_min_layer, int p_max_layer) {
RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light);
ERR_FAIL_COND(!clight);
clight->layer_max = p_max_layer;
clight->layer_min = p_min_layer;
}
-void RenderingServerCanvas::canvas_light_set_item_cull_mask(RID p_light, int p_mask) {
+void RenderingServerCanvas::canvas_light_set_item_cull_mask(RID p_light, int p_mask) {
RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light);
ERR_FAIL_COND(!clight);
clight->item_mask = p_mask;
}
-void RenderingServerCanvas::canvas_light_set_item_shadow_cull_mask(RID p_light, int p_mask) {
+void RenderingServerCanvas::canvas_light_set_item_shadow_cull_mask(RID p_light, int p_mask) {
RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light);
ERR_FAIL_COND(!clight);
clight->item_shadow_mask = p_mask;
}
-void RenderingServerCanvas::canvas_light_set_mode(RID p_light, RS::CanvasLightMode p_mode) {
+void RenderingServerCanvas::canvas_light_set_mode(RID p_light, RS::CanvasLightMode p_mode) {
RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light);
ERR_FAIL_COND(!clight);
@@ -1130,7 +1078,6 @@ void RenderingServerCanvas::canvas_light_set_mode(RID p_light, RS::CanvasLightMo
}
void RenderingServerCanvas::canvas_light_set_shadow_enabled(RID p_light, bool p_enabled) {
-
RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light);
ERR_FAIL_COND(!clight);
@@ -1143,15 +1090,15 @@ void RenderingServerCanvas::canvas_light_set_shadow_enabled(RID p_light, bool p_
}
void RenderingServerCanvas::canvas_light_set_shadow_buffer_size(RID p_light, int p_size) {
-
ERR_FAIL_COND(p_size < 32 || p_size > 16384);
RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light);
ERR_FAIL_COND(!clight);
int new_size = next_power_of_2(p_size);
- if (new_size == clight->shadow_buffer_size)
+ if (new_size == clight->shadow_buffer_size) {
return;
+ }
clight->shadow_buffer_size = next_power_of_2(p_size);
clight->version++;
@@ -1160,14 +1107,13 @@ void RenderingServerCanvas::canvas_light_set_shadow_buffer_size(RID p_light, int
}
void RenderingServerCanvas::canvas_light_set_shadow_filter(RID p_light, RS::CanvasLightShadowFilter p_filter) {
-
RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light);
ERR_FAIL_COND(!clight);
clight->shadow_filter = p_filter;
}
-void RenderingServerCanvas::canvas_light_set_shadow_color(RID p_light, const Color &p_color) {
+void RenderingServerCanvas::canvas_light_set_shadow_color(RID p_light, const Color &p_color) {
RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light);
ERR_FAIL_COND(!clight);
@@ -1175,49 +1121,46 @@ void RenderingServerCanvas::canvas_light_set_shadow_color(RID p_light, const Col
}
void RenderingServerCanvas::canvas_light_set_shadow_smooth(RID p_light, float p_smooth) {
-
RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light);
ERR_FAIL_COND(!clight);
clight->shadow_smooth = p_smooth;
}
RID RenderingServerCanvas::canvas_light_occluder_create() {
-
RasterizerCanvas::LightOccluderInstance *occluder = memnew(RasterizerCanvas::LightOccluderInstance);
return canvas_light_occluder_owner.make_rid(occluder);
}
-void RenderingServerCanvas::canvas_light_occluder_attach_to_canvas(RID p_occluder, RID p_canvas) {
+void RenderingServerCanvas::canvas_light_occluder_attach_to_canvas(RID p_occluder, RID p_canvas) {
RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_occluder);
ERR_FAIL_COND(!occluder);
if (occluder->canvas.is_valid()) {
-
Canvas *canvas = canvas_owner.getornull(occluder->canvas);
canvas->occluders.erase(occluder);
}
- if (!canvas_owner.owns(p_canvas))
+ if (!canvas_owner.owns(p_canvas)) {
p_canvas = RID();
+ }
occluder->canvas = p_canvas;
if (occluder->canvas.is_valid()) {
-
Canvas *canvas = canvas_owner.getornull(occluder->canvas);
canvas->occluders.insert(occluder);
}
}
-void RenderingServerCanvas::canvas_light_occluder_set_enabled(RID p_occluder, bool p_enabled) {
+void RenderingServerCanvas::canvas_light_occluder_set_enabled(RID p_occluder, bool p_enabled) {
RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_occluder);
ERR_FAIL_COND(!occluder);
occluder->enabled = p_enabled;
}
-void RenderingServerCanvas::canvas_light_occluder_set_polygon(RID p_occluder, RID p_polygon) {
+void RenderingServerCanvas::canvas_light_occluder_set_polygon(RID p_occluder, RID p_polygon) {
RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_occluder);
ERR_FAIL_COND(!occluder);
@@ -1244,15 +1187,15 @@ void RenderingServerCanvas::canvas_light_occluder_set_polygon(RID p_occluder, RI
}
}
}
-void RenderingServerCanvas::canvas_light_occluder_set_transform(RID p_occluder, const Transform2D &p_xform) {
+void RenderingServerCanvas::canvas_light_occluder_set_transform(RID p_occluder, const Transform2D &p_xform) {
RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_occluder);
ERR_FAIL_COND(!occluder);
occluder->xform = p_xform;
}
-void RenderingServerCanvas::canvas_light_occluder_set_light_mask(RID p_occluder, int p_mask) {
+void RenderingServerCanvas::canvas_light_occluder_set_light_mask(RID p_occluder, int p_mask) {
RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_occluder);
ERR_FAIL_COND(!occluder);
@@ -1260,13 +1203,12 @@ void RenderingServerCanvas::canvas_light_occluder_set_light_mask(RID p_occluder,
}
RID RenderingServerCanvas::canvas_occluder_polygon_create() {
-
LightOccluderPolygon *occluder_poly = memnew(LightOccluderPolygon);
occluder_poly->occluder = RSG::canvas_render->occluder_polygon_create();
return canvas_light_occluder_polygon_owner.make_rid(occluder_poly);
}
-void RenderingServerCanvas::canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const Vector<Vector2> &p_shape, bool p_closed) {
+void RenderingServerCanvas::canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const Vector<Vector2> &p_shape, bool p_closed) {
if (p_shape.size() < 3) {
canvas_occluder_polygon_set_shape_as_lines(p_occluder_polygon, p_shape);
return;
@@ -1285,7 +1227,6 @@ void RenderingServerCanvas::canvas_occluder_polygon_set_shape(RID p_occluder_pol
max--;
}
for (int i = 0; i < max; i++) {
-
Vector2 a = r[i];
Vector2 b = r[(i + 1) % (lc / 2)];
w[i * 2 + 0] = a;
@@ -1295,8 +1236,8 @@ void RenderingServerCanvas::canvas_occluder_polygon_set_shape(RID p_occluder_pol
canvas_occluder_polygon_set_shape_as_lines(p_occluder_polygon, lines);
}
-void RenderingServerCanvas::canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon, const Vector<Vector2> &p_shape) {
+void RenderingServerCanvas::canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon, const Vector<Vector2> &p_shape) {
LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.getornull(p_occluder_polygon);
ERR_FAIL_COND(!occluder_poly);
ERR_FAIL_COND(p_shape.size() & 1);
@@ -1306,10 +1247,11 @@ void RenderingServerCanvas::canvas_occluder_polygon_set_shape_as_lines(RID p_occ
{
const Vector2 *r = p_shape.ptr();
for (int i = 0; i < lc; i++) {
- if (i == 0)
+ if (i == 0) {
occluder_poly->aabb.position = r[i];
- else
+ } else {
occluder_poly->aabb.expand_to(r[i]);
+ }
}
}
@@ -1320,7 +1262,6 @@ void RenderingServerCanvas::canvas_occluder_polygon_set_shape_as_lines(RID p_occ
}
void RenderingServerCanvas::canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon, RS::CanvasOccluderPolygonCullMode p_mode) {
-
LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.getornull(p_occluder_polygon);
ERR_FAIL_COND(!occluder_poly);
occluder_poly->cull_mode = p_mode;
@@ -1331,14 +1272,11 @@ void RenderingServerCanvas::canvas_occluder_polygon_set_cull_mode(RID p_occluder
}
bool RenderingServerCanvas::free(RID p_rid) {
-
if (canvas_owner.owns(p_rid)) {
-
Canvas *canvas = canvas_owner.getornull(p_rid);
ERR_FAIL_COND_V(!canvas, false);
while (canvas->viewports.size()) {
-
RenderingServerViewport::Viewport *vp = RSG::viewport->viewport_owner.getornull(canvas->viewports.front()->get());
ERR_FAIL_COND_V(!vp, true);
@@ -1350,17 +1288,14 @@ bool RenderingServerCanvas::free(RID p_rid) {
}
for (int i = 0; i < canvas->child_items.size(); i++) {
-
canvas->child_items[i].item->parent = RID();
}
for (Set<RasterizerCanvas::Light *>::Element *E = canvas->lights.front(); E; E = E->next()) {
-
E->get()->canvas = RID();
}
for (Set<RasterizerCanvas::LightOccluderInstance *>::Element *E = canvas->occluders.front(); E; E = E->next()) {
-
E->get()->canvas = RID();
}
@@ -1369,18 +1304,14 @@ bool RenderingServerCanvas::free(RID p_rid) {
memdelete(canvas);
} else if (canvas_item_owner.owns(p_rid)) {
-
Item *canvas_item = canvas_item_owner.getornull(p_rid);
ERR_FAIL_COND_V(!canvas_item, true);
if (canvas_item->parent.is_valid()) {
-
if (canvas_owner.owns(canvas_item->parent)) {
-
Canvas *canvas = canvas_owner.getornull(canvas_item->parent);
canvas->erase_item(canvas_item);
} else if (canvas_item_owner.owns(canvas_item->parent)) {
-
Item *item_owner = canvas_item_owner.getornull(canvas_item->parent);
item_owner->child_items.erase(canvas_item);
@@ -1391,7 +1322,6 @@ bool RenderingServerCanvas::free(RID p_rid) {
}
for (int i = 0; i < canvas_item->child_items.size(); i++) {
-
canvas_item->child_items[i]->parent = RID();
}
@@ -1406,14 +1336,14 @@ bool RenderingServerCanvas::free(RID p_rid) {
memdelete(canvas_item);
} else if (canvas_light_owner.owns(p_rid)) {
-
RasterizerCanvas::Light *canvas_light = canvas_light_owner.getornull(p_rid);
ERR_FAIL_COND_V(!canvas_light, true);
if (canvas_light->canvas.is_valid()) {
Canvas *canvas = canvas_owner.getornull(canvas_light->canvas);
- if (canvas)
+ if (canvas) {
canvas->lights.erase(canvas_light);
+ }
}
RSG::canvas_render->free(canvas_light->light_internal);
@@ -1422,12 +1352,10 @@ bool RenderingServerCanvas::free(RID p_rid) {
memdelete(canvas_light);
} else if (canvas_light_occluder_owner.owns(p_rid)) {
-
RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_rid);
ERR_FAIL_COND_V(!occluder, true);
if (occluder->polygon.is_valid()) {
-
LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.getornull(occluder->polygon);
if (occluder_poly) {
occluder_poly->owners.erase(occluder);
@@ -1435,7 +1363,6 @@ bool RenderingServerCanvas::free(RID p_rid) {
}
if (occluder->canvas.is_valid() && canvas_owner.owns(occluder->canvas)) {
-
Canvas *canvas = canvas_owner.getornull(occluder->canvas);
canvas->occluders.erase(occluder);
}
@@ -1444,13 +1371,11 @@ bool RenderingServerCanvas::free(RID p_rid) {
memdelete(occluder);
} else if (canvas_light_occluder_polygon_owner.owns(p_rid)) {
-
LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.getornull(p_rid);
ERR_FAIL_COND_V(!occluder_poly, true);
RSG::canvas_render->free(occluder_poly->occluder);
while (occluder_poly->owners.size()) {
-
occluder_poly->owners.front()->get()->polygon = RID();
occluder_poly->owners.erase(occluder_poly->owners.front());
}
@@ -1465,7 +1390,6 @@ bool RenderingServerCanvas::free(RID p_rid) {
}
RenderingServerCanvas::RenderingServerCanvas() {
-
z_list = (RasterizerCanvas::Item **)memalloc(z_range * sizeof(RasterizerCanvas::Item *));
z_last_list = (RasterizerCanvas::Item **)memalloc(z_range * sizeof(RasterizerCanvas::Item *));
@@ -1473,7 +1397,6 @@ RenderingServerCanvas::RenderingServerCanvas() {
}
RenderingServerCanvas::~RenderingServerCanvas() {
-
memfree(z_list);
memfree(z_last_list);
}
diff --git a/servers/rendering/rendering_server_canvas.h b/servers/rendering/rendering_server_canvas.h
index c79b74f287..59c0d1fa52 100644
--- a/servers/rendering/rendering_server_canvas.h
+++ b/servers/rendering/rendering_server_canvas.h
@@ -37,7 +37,6 @@
class RenderingServerCanvas {
public:
struct Item : public RasterizerCanvas::Item {
-
RID parent; // canvas it belongs to
List<Item *>::Element *E;
int z_index;
@@ -59,7 +58,7 @@ public:
Item() {
children_order_dirty = true;
- E = NULL;
+ E = nullptr;
z_index = 0;
modulate = Color(1, 1, 1, 1);
self_modulate = Color(1, 1, 1, 1);
@@ -76,26 +75,22 @@ public:
};
struct ItemIndexSort {
-
_FORCE_INLINE_ bool operator()(const Item *p_left, const Item *p_right) const {
-
return p_left->index < p_right->index;
}
};
struct ItemPtrSort {
-
_FORCE_INLINE_ bool operator()(const Item *p_left, const Item *p_right) const {
-
- if (Math::is_equal_approx(p_left->ysort_pos.y, p_right->ysort_pos.y))
+ if (Math::is_equal_approx(p_left->ysort_pos.y, p_right->ysort_pos.y)) {
return p_left->ysort_pos.x < p_right->ysort_pos.x;
+ }
return p_left->ysort_pos.y < p_right->ysort_pos.y;
}
};
struct LightOccluderPolygon {
-
bool active;
Rect2 aabb;
RS::CanvasOccluderPolygonCullMode cull_mode;
@@ -113,10 +108,8 @@ public:
RID_PtrOwner<RasterizerCanvas::LightOccluderInstance> canvas_light_occluder_owner;
struct Canvas : public RenderingServerViewport::CanvasBase {
-
Set<RID> viewports;
struct ChildItem {
-
Point2 mirror;
Item *item;
bool operator<(const ChildItem &p_item) const {
@@ -136,15 +129,17 @@ public:
int find_item(Item *p_item) {
for (int i = 0; i < child_items.size(); i++) {
- if (child_items[i].item == p_item)
+ if (child_items[i].item == p_item) {
return i;
+ }
}
return -1;
}
void erase_item(Item *p_item) {
int idx = find_item(p_item);
- if (idx >= 0)
+ if (idx >= 0) {
child_items.remove(idx);
+ }
}
Canvas() {
diff --git a/servers/rendering/rendering_server_globals.cpp b/servers/rendering/rendering_server_globals.cpp
index 251cf64184..5a270520a9 100644
--- a/servers/rendering/rendering_server_globals.cpp
+++ b/servers/rendering/rendering_server_globals.cpp
@@ -30,11 +30,11 @@
#include "rendering_server_globals.h"
-RasterizerStorage *RenderingServerGlobals::storage = NULL;
-RasterizerCanvas *RenderingServerGlobals::canvas_render = NULL;
-RasterizerScene *RenderingServerGlobals::scene_render = NULL;
-Rasterizer *RenderingServerGlobals::rasterizer = NULL;
+RasterizerStorage *RenderingServerGlobals::storage = nullptr;
+RasterizerCanvas *RenderingServerGlobals::canvas_render = nullptr;
+RasterizerScene *RenderingServerGlobals::scene_render = nullptr;
+Rasterizer *RenderingServerGlobals::rasterizer = nullptr;
-RenderingServerCanvas *RenderingServerGlobals::canvas = NULL;
-RenderingServerViewport *RenderingServerGlobals::viewport = NULL;
-RenderingServerScene *RenderingServerGlobals::scene = NULL;
+RenderingServerCanvas *RenderingServerGlobals::canvas = nullptr;
+RenderingServerViewport *RenderingServerGlobals::viewport = nullptr;
+RenderingServerScene *RenderingServerGlobals::scene = nullptr;
diff --git a/servers/rendering/rendering_server_raster.cpp b/servers/rendering/rendering_server_raster.cpp
index 7cc06527e4..d30160702b 100644
--- a/servers/rendering/rendering_server_raster.cpp
+++ b/servers/rendering/rendering_server_raster.cpp
@@ -45,7 +45,6 @@ int RenderingServerRaster::changes = 0;
/* BLACK BARS */
void RenderingServerRaster::black_bars_set_margins(int p_left, int p_top, int p_right, int p_bottom) {
-
black_margin[MARGIN_LEFT] = p_left;
black_margin[MARGIN_TOP] = p_top;
black_margin[MARGIN_RIGHT] = p_right;
@@ -53,7 +52,6 @@ void RenderingServerRaster::black_bars_set_margins(int p_left, int p_top, int p_
}
void RenderingServerRaster::black_bars_set_images(RID p_left, RID p_top, RID p_right, RID p_bottom) {
-
black_image[MARGIN_LEFT] = p_left;
black_image[MARGIN_TOP] = p_top;
black_image[MARGIN_RIGHT] = p_right;
@@ -61,30 +59,32 @@ void RenderingServerRaster::black_bars_set_images(RID p_left, RID p_top, RID p_r
}
void RenderingServerRaster::_draw_margins() {
-
RSG::canvas_render->draw_window_margins(black_margin, black_image);
};
/* FREE */
void RenderingServerRaster::free(RID p_rid) {
-
- if (RSG::storage->free(p_rid))
+ if (RSG::storage->free(p_rid)) {
return;
- if (RSG::canvas->free(p_rid))
+ }
+ if (RSG::canvas->free(p_rid)) {
return;
- if (RSG::viewport->free(p_rid))
+ }
+ if (RSG::viewport->free(p_rid)) {
return;
- if (RSG::scene->free(p_rid))
+ }
+ if (RSG::scene->free(p_rid)) {
return;
- if (RSG::scene_render->free(p_rid))
+ }
+ if (RSG::scene_render->free(p_rid)) {
return;
+ }
}
/* EVENT QUEUING */
void RenderingServerRaster::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();
@@ -95,7 +95,6 @@ void RenderingServerRaster::request_frame_drawn_callback(Object *p_where, const
}
void RenderingServerRaster::draw(bool p_swap_buffers, double frame_step) {
-
//needs to be done before changes is reset to 0, to not force the editor to redraw
RS::get_singleton()->emit_signal("frame_pre_draw");
@@ -117,7 +116,6 @@ void RenderingServerRaster::draw(bool p_swap_buffers, double frame_step) {
RSG::rasterizer->end_frame(p_swap_buffers);
while (frame_drawn_callbacks.front()) {
-
Object *obj = ObjectDB::get_instance(frame_drawn_callbacks.front()->get().object);
if (obj) {
Callable::CallError ce;
@@ -135,16 +133,27 @@ void RenderingServerRaster::draw(bool p_swap_buffers, double frame_step) {
if (RSG::storage->get_captured_timestamps_count()) {
Vector<FrameProfileArea> new_profile;
- new_profile.resize(RSG::storage->get_captured_timestamps_count());
+ if (RSG::storage->capturing_timestamps) {
+ new_profile.resize(RSG::storage->get_captured_timestamps_count());
+ }
uint64_t base_cpu = RSG::storage->get_captured_timestamp_cpu_time(0);
uint64_t base_gpu = RSG::storage->get_captured_timestamp_gpu_time(0);
for (uint32_t i = 0; i < RSG::storage->get_captured_timestamps_count(); i++) {
- uint64_t time_cpu = RSG::storage->get_captured_timestamp_cpu_time(i) - base_cpu;
- uint64_t time_gpu = RSG::storage->get_captured_timestamp_gpu_time(i) - base_gpu;
- new_profile.write[i].gpu_msec = float(time_gpu / 1000) / 1000.0;
- new_profile.write[i].cpu_msec = float(time_cpu) / 1000.0;
- new_profile.write[i].name = RSG::storage->get_captured_timestamp_name(i);
+ uint64_t time_cpu = RSG::storage->get_captured_timestamp_cpu_time(i);
+ uint64_t time_gpu = RSG::storage->get_captured_timestamp_gpu_time(i);
+
+ String name = RSG::storage->get_captured_timestamp_name(i);
+
+ if (name.begins_with("vp_")) {
+ RSG::viewport->handle_timestamp(name, time_cpu, time_gpu);
+ }
+
+ if (RSG::storage->capturing_timestamps) {
+ new_profile.write[i].gpu_msec = float((time_gpu - base_gpu) / 1000) / 1000.0;
+ new_profile.write[i].cpu_msec = float(time_cpu - base_cpu) / 1000.0;
+ new_profile.write[i].name = RSG::storage->get_captured_timestamp_name(i);
+ }
}
frame_profile = new_profile;
@@ -152,18 +161,19 @@ void RenderingServerRaster::draw(bool p_swap_buffers, double frame_step) {
frame_profile_frame = RSG::storage->get_captured_timestamps_frame();
}
+
void RenderingServerRaster::sync() {
}
-bool RenderingServerRaster::has_changed() const {
+bool RenderingServerRaster::has_changed() const {
return changes > 0;
}
-void RenderingServerRaster::init() {
+void RenderingServerRaster::init() {
RSG::rasterizer->initialize();
}
-void RenderingServerRaster::finish() {
+void RenderingServerRaster::finish() {
if (test_cube.is_valid()) {
free(test_cube);
}
@@ -174,17 +184,14 @@ void RenderingServerRaster::finish() {
/* STATUS INFORMATION */
int RenderingServerRaster::get_render_info(RenderInfo p_info) {
-
return RSG::storage->get_render_info(p_info);
}
String RenderingServerRaster::get_video_adapter_name() const {
-
return RSG::storage->get_video_adapter_name();
}
String RenderingServerRaster::get_video_adapter_vendor() const {
-
return RSG::storage->get_video_adapter_vendor();
}
@@ -203,16 +210,15 @@ Vector<RenderingServer::FrameProfileArea> RenderingServerRaster::get_frame_profi
/* TESTING */
void RenderingServerRaster::set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter) {
-
redraw_request();
RSG::rasterizer->set_boot_image(p_image, p_color, p_scale, p_use_filter);
}
+
void RenderingServerRaster::set_default_clear_color(const Color &p_color) {
RSG::viewport->set_default_clear_color(p_color);
}
bool RenderingServerRaster::has_feature(Features p_feature) const {
-
return false;
}
@@ -224,12 +230,10 @@ RID RenderingServerRaster::get_test_cube() {
}
bool RenderingServerRaster::has_os_feature(const String &p_feature) const {
-
return RSG::storage->has_os_feature(p_feature);
}
void RenderingServerRaster::set_debug_generate_wireframes(bool p_generate) {
-
RSG::storage->set_debug_generate_wireframes(p_generate);
}
@@ -244,8 +248,8 @@ bool RenderingServerRaster::is_low_end() const {
//return RSG::rasterizer->is_low_end();
return false;
}
-RenderingServerRaster::RenderingServerRaster() {
+RenderingServerRaster::RenderingServerRaster() {
RSG::canvas = memnew(RenderingServerCanvas);
RSG::viewport = memnew(RenderingServerViewport);
RSG::scene = memnew(RenderingServerScene);
@@ -263,7 +267,6 @@ RenderingServerRaster::RenderingServerRaster() {
}
RenderingServerRaster::~RenderingServerRaster() {
-
memdelete(RSG::canvas);
memdelete(RSG::viewport);
memdelete(RSG::rasterizer);
diff --git a/servers/rendering/rendering_server_raster.h b/servers/rendering/rendering_server_raster.h
index 7c18bf91ce..8a3c55118d 100644
--- a/servers/rendering/rendering_server_raster.h
+++ b/servers/rendering/rendering_server_raster.h
@@ -40,7 +40,6 @@
#include "servers/rendering_server.h"
class RenderingServerRaster : public RenderingServer {
-
enum {
MAX_INSTANCE_CULL = 8192,
@@ -61,7 +60,6 @@ class RenderingServerRaster : public RenderingServer {
RID black_image[4];
struct FrameDrawnCallbacks {
-
ObjectID object;
StringName method;
Variant param;
@@ -98,6 +96,8 @@ public:
#define BIND0R(m_r, m_name) \
m_r m_name() { return BINDBASE->m_name(); }
+#define BIND0RC(m_r, m_name) \
+ m_r m_name() const { return BINDBASE->m_name(); }
#define BIND1R(m_r, m_name, m_type1) \
m_r m_name(m_type1 arg1) { return BINDBASE->m_name(arg1); }
#define BIND1RC(m_r, m_name, m_type1) \
@@ -106,13 +106,21 @@ public:
m_r m_name(m_type1 arg1, m_type2 arg2) { return BINDBASE->m_name(arg1, arg2); }
#define BIND2RC(m_r, m_name, m_type1, m_type2) \
m_r m_name(m_type1 arg1, m_type2 arg2) const { return BINDBASE->m_name(arg1, arg2); }
+#define BIND3R(m_r, m_name, m_type1, m_type2, m_type3) \
+ m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3) { return BINDBASE->m_name(arg1, arg2, arg3); }
#define BIND3RC(m_r, m_name, m_type1, m_type2, m_type3) \
m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3) const { return BINDBASE->m_name(arg1, arg2, arg3); }
+#define BIND4R(m_r, m_name, m_type1, m_type2, m_type3, m_type4) \
+ m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4) { return BINDBASE->m_name(arg1, arg2, arg3, arg4); }
#define BIND4RC(m_r, m_name, m_type1, m_type2, m_type3, m_type4) \
m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4) const { return BINDBASE->m_name(arg1, arg2, arg3, arg4); }
+#define BIND0(m_name) \
+ void m_name() { DISPLAY_CHANGED BINDBASE->m_name(); }
#define BIND1(m_name, m_type1) \
void m_name(m_type1 arg1) { DISPLAY_CHANGED BINDBASE->m_name(arg1); }
+#define BIND1C(m_name, m_type1) \
+ void m_name(m_type1 arg1) const { DISPLAY_CHANGED BINDBASE->m_name(arg1); }
#define BIND2(m_name, m_type1, m_type2) \
void m_name(m_type1 arg1, m_type2 arg2) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2); }
#define BIND2C(m_name, m_type1, m_type2) \
@@ -164,7 +172,7 @@ public:
//these also go pass-through
BIND0R(RID, texture_2d_placeholder_create)
- BIND0R(RID, texture_2d_layered_placeholder_create)
+ BIND1R(RID, texture_2d_layered_placeholder_create, TextureLayeredType)
BIND0R(RID, texture_3d_placeholder_create)
BIND1RC(Ref<Image>, texture_2d_get, RID)
@@ -340,6 +348,20 @@ public:
BIND2(reflection_probe_set_cull_mask, RID, uint32_t)
BIND2(reflection_probe_set_resolution, RID, int)
+ /* DECAL API */
+
+ BIND0R(RID, decal_create)
+
+ BIND2(decal_set_extents, RID, const Vector3 &)
+ BIND3(decal_set_texture, RID, DecalTexture, RID)
+ BIND2(decal_set_emission_energy, RID, float)
+ BIND2(decal_set_albedo_mix, RID, float)
+ BIND2(decal_set_modulate, RID, const Color &)
+ BIND2(decal_set_cull_mask, RID, uint32_t)
+ BIND4(decal_set_distance_fade, RID, bool, float, float)
+ BIND3(decal_set_fade, RID, float, float)
+ BIND2(decal_set_normal_fade, RID, float)
+
/* BAKED LIGHT API */
BIND0R(RID, gi_probe_create)
@@ -384,23 +406,19 @@ public:
BIND2(gi_probe_set_anisotropy_strength, RID, float)
BIND1RC(float, gi_probe_get_anisotropy_strength, RID)
- /* LIGHTMAP CAPTURE */
-
- BIND0R(RID, lightmap_capture_create)
+ /* LIGHTMAP */
- BIND2(lightmap_capture_set_bounds, RID, const AABB &)
- BIND1RC(AABB, lightmap_capture_get_bounds, RID)
+ BIND0R(RID, lightmap_create)
- BIND2(lightmap_capture_set_octree, RID, const Vector<uint8_t> &)
- BIND1RC(Vector<uint8_t>, lightmap_capture_get_octree, RID)
-
- BIND2(lightmap_capture_set_octree_cell_transform, RID, const Transform &)
- BIND1RC(Transform, lightmap_capture_get_octree_cell_transform, RID)
- BIND2(lightmap_capture_set_octree_cell_subdiv, RID, int)
- BIND1RC(int, lightmap_capture_get_octree_cell_subdiv, RID)
-
- BIND2(lightmap_capture_set_energy, RID, float)
- BIND1RC(float, lightmap_capture_get_energy, RID)
+ BIND3(lightmap_set_textures, RID, RID, bool)
+ BIND2(lightmap_set_probe_bounds, RID, const AABB &)
+ BIND2(lightmap_set_probe_interior, RID, bool)
+ BIND5(lightmap_set_probe_capture_data, RID, const PackedVector3Array &, const PackedColorArray &, const PackedInt32Array &, const PackedInt32Array &)
+ BIND1RC(PackedVector3Array, lightmap_get_probe_capture_points, RID)
+ BIND1RC(PackedColorArray, lightmap_get_probe_capture_sh, RID)
+ BIND1RC(PackedInt32Array, lightmap_get_probe_capture_tetrahedra, RID)
+ BIND1RC(PackedInt32Array, lightmap_get_probe_capture_bsp_tree, RID)
+ BIND1(lightmap_set_probe_capture_update_speed, float)
/* PARTICLES */
@@ -456,7 +474,7 @@ public:
BIND0R(RID, viewport_create)
- BIND2(viewport_set_use_arvr, RID, bool)
+ BIND2(viewport_set_use_xr, RID, bool)
BIND3(viewport_set_size, RID, int, int)
BIND2(viewport_set_active, RID, bool)
@@ -489,10 +507,15 @@ public:
BIND2(viewport_set_shadow_atlas_size, RID, int)
BIND3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int)
BIND2(viewport_set_msaa, RID, ViewportMSAA)
+ BIND2(viewport_set_screen_space_aa, RID, ViewportScreenSpaceAA)
BIND2R(int, viewport_get_render_info, RID, ViewportRenderInfo)
BIND2(viewport_set_debug_draw, RID, ViewportDebugDraw)
+ BIND2(viewport_set_measure_render_time, RID, bool)
+ BIND1RC(float, viewport_get_measured_render_time_cpu, RID)
+ BIND1RC(float, viewport_get_measured_render_time_gpu, RID)
+
/* ENVIRONMENT API */
#undef BINDBASE
@@ -507,6 +530,7 @@ public:
BIND2(sky_set_radiance_size, RID, int)
BIND2(sky_set_mode, RID, SkyMode)
BIND2(sky_set_material, RID, RID)
+ BIND4R(Ref<Image>, sky_bake_panorama, RID, float, bool, const Size2i &)
BIND0R(RID, environment_create)
@@ -523,7 +547,9 @@ public:
#if 0
BIND2(environment_set_camera_feed_id, RID, int)
#endif
- BIND7(environment_set_ssr, RID, bool, int, float, float, float, bool)
+ BIND6(environment_set_ssr, RID, bool, int, float, float, float)
+ BIND1(environment_set_ssr_roughness_quality, EnvironmentSSRRoughnessQuality)
+
BIND9(environment_set_ssao, RID, bool, float, float, float, float, float, EnvironmentSSAOBlur, float)
BIND2(environment_set_ssao_quality, EnvironmentSSAOQuality, bool)
@@ -538,7 +564,11 @@ public:
BIND7(environment_set_fog_depth, RID, bool, float, float, float, bool, float)
BIND5(environment_set_fog_height, RID, bool, float, float, float)
+ BIND3R(Ref<Image>, environment_bake_panorama, RID, bool, const Size2i &)
+
BIND2(screen_space_roughness_limiter_set_active, bool, float)
+ BIND1(sub_surface_scattering_set_quality, SubSurfaceScatteringQuality)
+ BIND2(sub_surface_scattering_set_scale, float, float)
/* CAMERA EFFECTS */
@@ -550,6 +580,9 @@ public:
BIND8(camera_effects_set_dof_blur, RID, bool, float, float, bool, float, float, float)
BIND3(camera_effects_set_custom_exposure, RID, bool, float)
+ BIND1(shadows_quality_set, ShadowQuality);
+ BIND1(directional_shadow_quality_set, ShadowQuality);
+
/* SCENARIO API */
#undef BINDBASE
@@ -573,7 +606,6 @@ public:
BIND3(instance_set_blend_shape_weight, RID, int, float)
BIND3(instance_set_surface_material, RID, int, RID)
BIND2(instance_set_visible, RID, bool)
- BIND3(instance_set_use_lightmap, RID, RID, RID)
BIND2(instance_set_custom_aabb, RID, AABB)
@@ -593,6 +625,14 @@ public:
BIND5(instance_geometry_set_draw_range, RID, float, float, float, float)
BIND2(instance_geometry_set_as_instance_lod, RID, RID)
+ BIND4(instance_geometry_set_lightmap, RID, RID, const Rect2 &, int)
+
+ BIND3(instance_geometry_set_shader_parameter, RID, const StringName &, const Variant &)
+ BIND2RC(Variant, instance_geometry_get_shader_parameter, RID, const StringName &)
+ BIND2RC(Variant, instance_geometry_get_shader_parameter_default_value, RID, const StringName &)
+ BIND2C(instance_geometry_get_shader_parameter_list, RID, List<PropertyInfo> *)
+
+ BIND3R(TypedArray<Image>, bake_render_uv2, RID, const Vector<RID> &, const Size2i &)
#undef BINDBASE
//from now on, calls forwarded to this singleton
@@ -691,6 +731,23 @@ public:
BIND2(canvas_occluder_polygon_set_cull_mode, RID, CanvasOccluderPolygonCullMode)
+ /* GLOBAL VARIABLES */
+
+#undef BINDBASE
+//from now on, calls forwarded to this singleton
+#define BINDBASE RSG::storage
+
+ BIND3(global_variable_add, const StringName &, GlobalVariableType, const Variant &)
+ BIND1(global_variable_remove, const StringName &)
+ BIND0RC(Vector<StringName>, global_variable_get_list)
+ BIND2(global_variable_set, const StringName &, const Variant &)
+ BIND2(global_variable_set_override, const StringName &, const Variant &)
+ BIND1RC(GlobalVariableType, global_variable_get_type, const StringName &)
+ BIND1RC(Variant, global_variable_get, const StringName &)
+
+ BIND1(global_variables_load_settings, bool)
+ BIND0(global_variables_clear)
+
/* BLACK BARS */
virtual void black_bars_set_margins(int p_left, int p_top, int p_right, int p_bottom);
diff --git a/servers/rendering/rendering_server_scene.cpp b/servers/rendering/rendering_server_scene.cpp
index 04e4b8dace..7b8504036e 100644
--- a/servers/rendering/rendering_server_scene.cpp
+++ b/servers/rendering/rendering_server_scene.cpp
@@ -39,13 +39,11 @@
/* CAMERA API */
RID RenderingServerScene::camera_create() {
-
Camera *camera = memnew(Camera);
return camera_owner.make_rid(camera);
}
void RenderingServerScene::camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far) {
-
Camera *camera = camera_owner.getornull(p_camera);
ERR_FAIL_COND(!camera);
camera->type = Camera::PERSPECTIVE;
@@ -55,7 +53,6 @@ void RenderingServerScene::camera_set_perspective(RID p_camera, float p_fovy_deg
}
void RenderingServerScene::camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far) {
-
Camera *camera = camera_owner.getornull(p_camera);
ERR_FAIL_COND(!camera);
camera->type = Camera::ORTHOGONAL;
@@ -75,14 +72,12 @@ void RenderingServerScene::camera_set_frustum(RID p_camera, float p_size, Vector
}
void RenderingServerScene::camera_set_transform(RID p_camera, const Transform &p_transform) {
-
Camera *camera = camera_owner.getornull(p_camera);
ERR_FAIL_COND(!camera);
camera->transform = p_transform.orthonormalized();
}
void RenderingServerScene::camera_set_cull_mask(RID p_camera, uint32_t p_layers) {
-
Camera *camera = camera_owner.getornull(p_camera);
ERR_FAIL_COND(!camera);
@@ -90,21 +85,18 @@ void RenderingServerScene::camera_set_cull_mask(RID p_camera, uint32_t p_layers)
}
void RenderingServerScene::camera_set_environment(RID p_camera, RID p_env) {
-
Camera *camera = camera_owner.getornull(p_camera);
ERR_FAIL_COND(!camera);
camera->env = p_env;
}
void RenderingServerScene::camera_set_camera_effects(RID p_camera, RID p_fx) {
-
Camera *camera = camera_owner.getornull(p_camera);
ERR_FAIL_COND(!camera);
camera->effects = p_fx;
}
void RenderingServerScene::camera_set_use_vertical_aspect(RID p_camera, bool p_enable) {
-
Camera *camera = camera_owner.getornull(p_camera);
ERR_FAIL_COND(!camera);
camera->vaspect = p_enable;
@@ -113,7 +105,6 @@ void RenderingServerScene::camera_set_use_vertical_aspect(RID p_camera, bool p_e
/* SCENARIO API */
void *RenderingServerScene::_instance_pair(void *p_self, OctreeElementID, Instance *p_A, int, OctreeElementID, Instance *p_B, int) {
-
//RenderingServerScene *self = (RenderingServerScene*)p_self;
Instance *A = p_A;
Instance *B = p_B;
@@ -124,7 +115,6 @@ void *RenderingServerScene::_instance_pair(void *p_self, OctreeElementID, Instan
}
if (B->base_type == RS::INSTANCE_LIGHT && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
-
InstanceLightData *light = static_cast<InstanceLightData *>(B->base_data);
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
@@ -135,14 +125,12 @@ void *RenderingServerScene::_instance_pair(void *p_self, OctreeElementID, Instan
List<InstanceLightData::PairInfo>::Element *E = light->geometries.push_back(pinfo);
if (geom->can_cast_shadows) {
-
light->shadow_dirty = true;
}
geom->lighting_dirty = true;
return E; //this element should make freeing faster
} else if (B->base_type == RS::INSTANCE_REFLECTION_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
-
InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(B->base_data);
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
@@ -155,21 +143,35 @@ void *RenderingServerScene::_instance_pair(void *p_self, OctreeElementID, Instan
geom->reflection_dirty = true;
return E; //this element should make freeing faster
- } else if (B->base_type == RS::INSTANCE_LIGHTMAP_CAPTURE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
-
- InstanceLightmapCaptureData *lightmap_capture = static_cast<InstanceLightmapCaptureData *>(B->base_data);
+ } else if (B->base_type == RS::INSTANCE_DECAL && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
+ InstanceDecalData *decal = static_cast<InstanceDecalData *>(B->base_data);
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
- InstanceLightmapCaptureData::PairInfo pinfo;
+ InstanceDecalData::PairInfo pinfo;
pinfo.geometry = A;
- pinfo.L = geom->lightmap_captures.push_back(B);
+ pinfo.L = geom->decals.push_back(B);
+
+ List<InstanceDecalData::PairInfo>::Element *E = decal->geometries.push_back(pinfo);
- List<InstanceLightmapCaptureData::PairInfo>::Element *E = lightmap_capture->geometries.push_back(pinfo);
- ((RenderingServerScene *)p_self)->_instance_queue_update(A, false, false); //need to update capture
+ geom->decal_dirty = true;
return E; //this element should make freeing faster
- } else if (B->base_type == RS::INSTANCE_GI_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
+ } else if (B->base_type == RS::INSTANCE_LIGHTMAP && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
+ InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(B->base_data);
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
+ if (A->dynamic_gi) {
+ InstanceLightmapData::PairInfo pinfo;
+ pinfo.geometry = A;
+ pinfo.L = geom->lightmap_captures.push_back(B);
+ List<InstanceLightmapData::PairInfo>::Element *E = lightmap_data->geometries.push_back(pinfo);
+ ((RenderingServerScene *)p_self)->_instance_queue_update(A, false, false); //need to update capture
+ return E; //this element should make freeing faster
+ } else {
+ return nullptr;
+ }
+
+ } else if (B->base_type == RS::INSTANCE_GI_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data);
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
@@ -189,15 +191,14 @@ void *RenderingServerScene::_instance_pair(void *p_self, OctreeElementID, Instan
return E; //this element should make freeing faster
} else if (B->base_type == RS::INSTANCE_GI_PROBE && A->base_type == RS::INSTANCE_LIGHT) {
-
InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data);
return gi_probe->lights.insert(A);
}
- return NULL;
+ return nullptr;
}
-void RenderingServerScene::_instance_unpair(void *p_self, OctreeElementID, Instance *p_A, int, OctreeElementID, Instance *p_B, int, void *udata) {
+void RenderingServerScene::_instance_unpair(void *p_self, OctreeElementID, Instance *p_A, int, OctreeElementID, Instance *p_B, int, void *udata) {
//RenderingServerScene *self = (RenderingServerScene*)p_self;
Instance *A = p_A;
Instance *B = p_B;
@@ -208,7 +209,6 @@ void RenderingServerScene::_instance_unpair(void *p_self, OctreeElementID, Insta
}
if (B->base_type == RS::INSTANCE_LIGHT && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
-
InstanceLightData *light = static_cast<InstanceLightData *>(B->base_data);
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
@@ -223,7 +223,6 @@ void RenderingServerScene::_instance_unpair(void *p_self, OctreeElementID, Insta
geom->lighting_dirty = true;
} else if (B->base_type == RS::INSTANCE_REFLECTION_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
-
InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(B->base_data);
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
@@ -233,19 +232,29 @@ void RenderingServerScene::_instance_unpair(void *p_self, OctreeElementID, Insta
reflection_probe->geometries.erase(E);
geom->reflection_dirty = true;
- } else if (B->base_type == RS::INSTANCE_LIGHTMAP_CAPTURE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
-
- InstanceLightmapCaptureData *lightmap_capture = static_cast<InstanceLightmapCaptureData *>(B->base_data);
+ } else if (B->base_type == RS::INSTANCE_DECAL && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
+ InstanceDecalData *decal = static_cast<InstanceDecalData *>(B->base_data);
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
- List<InstanceLightmapCaptureData::PairInfo>::Element *E = reinterpret_cast<List<InstanceLightmapCaptureData::PairInfo>::Element *>(udata);
+ List<InstanceDecalData::PairInfo>::Element *E = reinterpret_cast<List<InstanceDecalData::PairInfo>::Element *>(udata);
- geom->lightmap_captures.erase(E->get().L);
- lightmap_capture->geometries.erase(E);
- ((RenderingServerScene *)p_self)->_instance_queue_update(A, false, false); //need to update capture
+ geom->decals.erase(E->get().L);
+ decal->geometries.erase(E);
- } else if (B->base_type == RS::INSTANCE_GI_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
+ geom->decal_dirty = true;
+ } else if (B->base_type == RS::INSTANCE_LIGHTMAP && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
+ if (udata) { //only for dynamic geometries
+ InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(B->base_data);
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
+ List<InstanceLightmapData::PairInfo>::Element *E = reinterpret_cast<List<InstanceLightmapData::PairInfo>::Element *>(udata);
+
+ geom->lightmap_captures.erase(E->get().L);
+ lightmap_data->geometries.erase(E);
+ ((RenderingServerScene *)p_self)->_instance_queue_update(A, false, false); //need to update capture
+ }
+
+ } else if (B->base_type == RS::INSTANCE_GI_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data);
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
@@ -261,7 +270,6 @@ void RenderingServerScene::_instance_unpair(void *p_self, OctreeElementID, Insta
geom->gi_probes_dirty = true;
} else if (B->base_type == RS::INSTANCE_GI_PROBE && A->base_type == RS::INSTANCE_LIGHT) {
-
InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data);
Set<Instance *>::Element *E = reinterpret_cast<Set<Instance *>::Element *>(udata);
@@ -270,7 +278,6 @@ void RenderingServerScene::_instance_unpair(void *p_self, OctreeElementID, Insta
}
RID RenderingServerScene::scenario_create() {
-
Scenario *scenario = memnew(Scenario);
ERR_FAIL_COND_V(!scenario, RID());
RID scenario_rid = scenario_owner.make_rid(scenario);
@@ -289,35 +296,30 @@ RID RenderingServerScene::scenario_create() {
}
void RenderingServerScene::scenario_set_debug(RID p_scenario, RS::ScenarioDebugMode p_debug_mode) {
-
Scenario *scenario = scenario_owner.getornull(p_scenario);
ERR_FAIL_COND(!scenario);
scenario->debug = p_debug_mode;
}
void RenderingServerScene::scenario_set_environment(RID p_scenario, RID p_environment) {
-
Scenario *scenario = scenario_owner.getornull(p_scenario);
ERR_FAIL_COND(!scenario);
scenario->environment = p_environment;
}
void RenderingServerScene::scenario_set_camera_effects(RID p_scenario, RID p_camera_effects) {
-
Scenario *scenario = scenario_owner.getornull(p_scenario);
ERR_FAIL_COND(!scenario);
scenario->camera_effects = p_camera_effects;
}
void RenderingServerScene::scenario_set_fallback_environment(RID p_scenario, RID p_environment) {
-
Scenario *scenario = scenario_owner.getornull(p_scenario);
ERR_FAIL_COND(!scenario);
scenario->fallback_environment = p_environment;
}
void RenderingServerScene::scenario_set_reflection_atlas_size(RID p_scenario, int p_reflection_size, int p_reflection_count) {
-
Scenario *scenario = scenario_owner.getornull(p_scenario);
ERR_FAIL_COND(!scenario);
RSG::scene_render->reflection_atlas_set_size(scenario->reflection_atlas, p_reflection_size, p_reflection_count);
@@ -326,20 +328,21 @@ void RenderingServerScene::scenario_set_reflection_atlas_size(RID p_scenario, in
/* INSTANCING API */
void RenderingServerScene::_instance_queue_update(Instance *p_instance, bool p_update_aabb, bool p_update_dependencies) {
-
- if (p_update_aabb)
+ if (p_update_aabb) {
p_instance->update_aabb = true;
- if (p_update_dependencies)
+ }
+ if (p_update_dependencies) {
p_instance->update_dependencies = true;
+ }
- if (p_instance->update_item.in_list())
+ if (p_instance->update_item.in_list()) {
return;
+ }
_instance_update_list.add(&p_instance->update_item);
}
RID RenderingServerScene::instance_create() {
-
Instance *instance = memnew(Instance);
ERR_FAIL_COND_V(!instance, RID());
@@ -350,7 +353,6 @@ RID RenderingServerScene::instance_create() {
}
void RenderingServerScene::instance_set_base(RID p_instance, RID p_base) {
-
Instance *instance = instance_owner.getornull(p_instance);
ERR_FAIL_COND(!instance);
@@ -366,7 +368,6 @@ void RenderingServerScene::instance_set_base(RID p_instance, RID p_base) {
switch (instance->base_type) {
case RS::INSTANCE_LIGHT: {
-
InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data);
#ifdef DEBUG_ENABLED
if (light->geometries.size()) {
@@ -375,28 +376,30 @@ void RenderingServerScene::instance_set_base(RID p_instance, RID p_base) {
#endif
if (instance->scenario && light->D) {
instance->scenario->directional_lights.erase(light->D);
- light->D = NULL;
+ light->D = nullptr;
}
RSG::scene_render->free(light->instance);
} break;
case RS::INSTANCE_REFLECTION_PROBE: {
-
InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(instance->base_data);
RSG::scene_render->free(reflection_probe->instance);
if (reflection_probe->update_list.in_list()) {
reflection_probe_render_list.remove(&reflection_probe->update_list);
}
} break;
- case RS::INSTANCE_LIGHTMAP_CAPTURE: {
+ case RS::INSTANCE_DECAL: {
+ InstanceDecalData *decal = static_cast<InstanceDecalData *>(instance->base_data);
+ RSG::scene_render->free(decal->instance);
- InstanceLightmapCaptureData *lightmap_capture = static_cast<InstanceLightmapCaptureData *>(instance->base_data);
+ } break;
+ case RS::INSTANCE_LIGHTMAP: {
+ InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(instance->base_data);
//erase dependencies, since no longer a lightmap
- while (lightmap_capture->users.front()) {
- instance_set_use_lightmap(lightmap_capture->users.front()->get()->self, RID(), RID());
+ while (lightmap_data->users.front()) {
+ instance_geometry_set_lightmap(lightmap_data->users.front()->get()->self, RID(), Rect2(), 0);
}
} break;
case RS::INSTANCE_GI_PROBE: {
-
InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(instance->base_data);
#ifdef DEBUG_ENABLED
if (gi_probe->geometries.size()) {
@@ -412,14 +415,6 @@ void RenderingServerScene::instance_set_base(RID p_instance, RID p_base) {
gi_probe_update_list.remove(&gi_probe->update_element);
}
- if (instance->lightmap_capture) {
- Instance *capture = (Instance *)instance->lightmap_capture;
- InstanceLightmapCaptureData *lightmap_capture = static_cast<InstanceLightmapCaptureData *>(capture->base_data);
- lightmap_capture->users.erase(instance);
- instance->lightmap_capture = NULL;
- instance->lightmap = RID();
- }
-
RSG::scene_render->free(gi_probe->probe_instance);
} break;
@@ -429,7 +424,7 @@ void RenderingServerScene::instance_set_base(RID p_instance, RID p_base) {
if (instance->base_data) {
memdelete(instance->base_data);
- instance->base_data = NULL;
+ instance->base_data = nullptr;
}
instance->blend_values.clear();
@@ -440,13 +435,11 @@ void RenderingServerScene::instance_set_base(RID p_instance, RID p_base) {
instance->base = RID();
if (p_base.is_valid()) {
-
instance->base_type = RSG::storage->get_base_type(p_base);
ERR_FAIL_COND(instance->base_type == RS::INSTANCE_NONE);
switch (instance->base_type) {
case RS::INSTANCE_LIGHT: {
-
InstanceLightData *light = memnew(InstanceLightData);
if (scenario && RSG::storage->light_get_type(p_base) == RS::LIGHT_DIRECTIONAL) {
@@ -461,7 +454,6 @@ void RenderingServerScene::instance_set_base(RID p_instance, RID p_base) {
case RS::INSTANCE_MULTIMESH:
case RS::INSTANCE_IMMEDIATE:
case RS::INSTANCE_PARTICLES: {
-
InstanceGeometryData *geom = memnew(InstanceGeometryData);
instance->base_data = geom;
if (instance->base_type == RS::INSTANCE_MESH) {
@@ -469,21 +461,25 @@ void RenderingServerScene::instance_set_base(RID p_instance, RID p_base) {
}
} break;
case RS::INSTANCE_REFLECTION_PROBE: {
-
InstanceReflectionProbeData *reflection_probe = memnew(InstanceReflectionProbeData);
reflection_probe->owner = instance;
instance->base_data = reflection_probe;
reflection_probe->instance = RSG::scene_render->reflection_probe_instance_create(p_base);
} break;
- case RS::INSTANCE_LIGHTMAP_CAPTURE: {
+ case RS::INSTANCE_DECAL: {
+ InstanceDecalData *decal = memnew(InstanceDecalData);
+ decal->owner = instance;
+ instance->base_data = decal;
- InstanceLightmapCaptureData *lightmap_capture = memnew(InstanceLightmapCaptureData);
- instance->base_data = lightmap_capture;
- //lightmap_capture->instance = RSG::scene_render->lightmap_capture_instance_create(p_base);
+ decal->instance = RSG::scene_render->decal_instance_create(p_base);
+ } break;
+ case RS::INSTANCE_LIGHTMAP: {
+ InstanceLightmapData *lightmap_data = memnew(InstanceLightmapData);
+ instance->base_data = lightmap_data;
+ //lightmap_data->instance = RSG::scene_render->lightmap_data_instance_create(p_base);
} break;
case RS::INSTANCE_GI_PROBE: {
-
InstanceGIProbeData *gi_probe = memnew(InstanceGIProbeData);
instance->base_data = gi_probe;
gi_probe->owner = instance;
@@ -507,13 +503,12 @@ void RenderingServerScene::instance_set_base(RID p_instance, RID p_base) {
_instance_queue_update(instance, true, true);
}
-void RenderingServerScene::instance_set_scenario(RID p_instance, RID p_scenario) {
+void RenderingServerScene::instance_set_scenario(RID p_instance, RID p_scenario) {
Instance *instance = instance_owner.getornull(p_instance);
ERR_FAIL_COND(!instance);
if (instance->scenario) {
-
instance->scenario->instances.remove(&instance->scenario_item);
if (instance->octree_id) {
@@ -522,9 +517,7 @@ void RenderingServerScene::instance_set_scenario(RID p_instance, RID p_scenario)
}
switch (instance->base_type) {
-
case RS::INSTANCE_LIGHT: {
-
InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data);
#ifdef DEBUG_ENABLED
if (light->geometries.size()) {
@@ -533,7 +526,7 @@ void RenderingServerScene::instance_set_scenario(RID p_instance, RID p_scenario)
#endif
if (light->D) {
instance->scenario->directional_lights.erase(light->D);
- light->D = NULL;
+ light->D = nullptr;
}
} break;
case RS::INSTANCE_REFLECTION_PROBE: {
@@ -542,7 +535,6 @@ void RenderingServerScene::instance_set_scenario(RID p_instance, RID p_scenario)
} break;
case RS::INSTANCE_GI_PROBE: {
-
InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(instance->base_data);
#ifdef DEBUG_ENABLED
@@ -564,11 +556,10 @@ void RenderingServerScene::instance_set_scenario(RID p_instance, RID p_scenario)
}
}
- instance->scenario = NULL;
+ instance->scenario = nullptr;
}
if (p_scenario.is_valid()) {
-
Scenario *scenario = scenario_owner.getornull(p_scenario);
ERR_FAIL_COND(!scenario);
@@ -577,9 +568,7 @@ void RenderingServerScene::instance_set_scenario(RID p_instance, RID p_scenario)
scenario->instances.add(&instance->scenario_item);
switch (instance->base_type) {
-
case RS::INSTANCE_LIGHT: {
-
InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data);
if (RSG::storage->light_get_type(instance->base) == RS::LIGHT_DIRECTIONAL) {
@@ -587,7 +576,6 @@ void RenderingServerScene::instance_set_scenario(RID p_instance, RID p_scenario)
}
} break;
case RS::INSTANCE_GI_PROBE: {
-
InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(instance->base_data);
if (!gi_probe->update_element.in_list()) {
gi_probe_update_list.add(&gi_probe->update_element);
@@ -600,20 +588,21 @@ void RenderingServerScene::instance_set_scenario(RID p_instance, RID p_scenario)
_instance_queue_update(instance, true, true);
}
}
-void RenderingServerScene::instance_set_layer_mask(RID p_instance, uint32_t p_mask) {
+void RenderingServerScene::instance_set_layer_mask(RID p_instance, uint32_t p_mask) {
Instance *instance = instance_owner.getornull(p_instance);
ERR_FAIL_COND(!instance);
instance->layer_mask = p_mask;
}
-void RenderingServerScene::instance_set_transform(RID p_instance, const Transform &p_transform) {
+void RenderingServerScene::instance_set_transform(RID p_instance, const Transform &p_transform) {
Instance *instance = instance_owner.getornull(p_instance);
ERR_FAIL_COND(!instance);
- if (instance->transform == p_transform)
+ if (instance->transform == p_transform) {
return; //must be checked to avoid worst evil
+ }
#ifdef DEBUG_ENABLED
@@ -631,15 +620,15 @@ void RenderingServerScene::instance_set_transform(RID p_instance, const Transfor
instance->transform = p_transform;
_instance_queue_update(instance, true);
}
-void RenderingServerScene::instance_attach_object_instance_id(RID p_instance, ObjectID p_id) {
+void RenderingServerScene::instance_attach_object_instance_id(RID p_instance, ObjectID p_id) {
Instance *instance = instance_owner.getornull(p_instance);
ERR_FAIL_COND(!instance);
instance->object_id = p_id;
}
-void RenderingServerScene::instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight) {
+void RenderingServerScene::instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight) {
Instance *instance = instance_owner.getornull(p_instance);
ERR_FAIL_COND(!instance);
@@ -652,7 +641,6 @@ void RenderingServerScene::instance_set_blend_shape_weight(RID p_instance, int p
}
void RenderingServerScene::instance_set_surface_material(RID p_instance, int p_surface, RID p_material) {
-
Instance *instance = instance_owner.getornull(p_instance);
ERR_FAIL_COND(!instance);
@@ -669,12 +657,12 @@ void RenderingServerScene::instance_set_surface_material(RID p_instance, int p_s
}
void RenderingServerScene::instance_set_visible(RID p_instance, bool p_visible) {
-
Instance *instance = instance_owner.getornull(p_instance);
ERR_FAIL_COND(!instance);
- if (instance->visible == p_visible)
+ if (instance->visible == p_visible) {
return;
+ }
instance->visible = p_visible;
@@ -691,9 +679,15 @@ void RenderingServerScene::instance_set_visible(RID p_instance, bool p_visible)
}
} break;
- case RS::INSTANCE_LIGHTMAP_CAPTURE: {
+ case RS::INSTANCE_DECAL: {
+ if (instance->octree_id && instance->scenario) {
+ instance->scenario->octree.set_pairable(instance->octree_id, p_visible, 1 << RS::INSTANCE_DECAL, p_visible ? RS::INSTANCE_GEOMETRY_MASK : 0);
+ }
+
+ } break;
+ case RS::INSTANCE_LIGHTMAP: {
if (instance->octree_id && instance->scenario) {
- instance->scenario->octree.set_pairable(instance->octree_id, p_visible, 1 << RS::INSTANCE_LIGHTMAP_CAPTURE, p_visible ? RS::INSTANCE_GEOMETRY_MASK : 0);
+ instance->scenario->octree.set_pairable(instance->octree_id, p_visible, 1 << RS::INSTANCE_LIGHTMAP, p_visible ? RS::INSTANCE_GEOMETRY_MASK : 0);
}
} break;
@@ -707,67 +701,43 @@ void RenderingServerScene::instance_set_visible(RID p_instance, bool p_visible)
}
}
}
+
inline bool is_geometry_instance(RenderingServer::InstanceType p_type) {
return p_type == RS::INSTANCE_MESH || p_type == RS::INSTANCE_MULTIMESH || p_type == RS::INSTANCE_PARTICLES || p_type == RS::INSTANCE_IMMEDIATE;
}
-void RenderingServerScene::instance_set_use_lightmap(RID p_instance, RID p_lightmap_instance, RID p_lightmap) {
-
- Instance *instance = instance_owner.getornull(p_instance);
- ERR_FAIL_COND(!instance);
-
- if (instance->lightmap_capture) {
- InstanceLightmapCaptureData *lightmap_capture = static_cast<InstanceLightmapCaptureData *>(((Instance *)instance->lightmap_capture)->base_data);
- lightmap_capture->users.erase(instance);
- instance->lightmap = RID();
- instance->lightmap_capture = NULL;
- }
-
- if (p_lightmap_instance.is_valid()) {
- Instance *lightmap_instance = instance_owner.getornull(p_lightmap_instance);
- ERR_FAIL_COND(!lightmap_instance);
- ERR_FAIL_COND(lightmap_instance->base_type != RS::INSTANCE_LIGHTMAP_CAPTURE);
- instance->lightmap_capture = lightmap_instance;
-
- InstanceLightmapCaptureData *lightmap_capture = static_cast<InstanceLightmapCaptureData *>(((Instance *)instance->lightmap_capture)->base_data);
- lightmap_capture->users.insert(instance);
- instance->lightmap = p_lightmap;
- }
-}
-
void RenderingServerScene::instance_set_custom_aabb(RID p_instance, AABB p_aabb) {
-
Instance *instance = instance_owner.getornull(p_instance);
ERR_FAIL_COND(!instance);
ERR_FAIL_COND(!is_geometry_instance(instance->base_type));
if (p_aabb != AABB()) {
-
// Set custom AABB
- if (instance->custom_aabb == NULL)
+ if (instance->custom_aabb == nullptr) {
instance->custom_aabb = memnew(AABB);
+ }
*instance->custom_aabb = p_aabb;
} else {
-
// Clear custom AABB
- if (instance->custom_aabb != NULL) {
+ if (instance->custom_aabb != nullptr) {
memdelete(instance->custom_aabb);
- instance->custom_aabb = NULL;
+ instance->custom_aabb = nullptr;
}
}
- if (instance->scenario)
+ if (instance->scenario) {
_instance_queue_update(instance, true, false);
+ }
}
void RenderingServerScene::instance_attach_skeleton(RID p_instance, RID p_skeleton) {
-
Instance *instance = instance_owner.getornull(p_instance);
ERR_FAIL_COND(!instance);
- if (instance->skeleton == p_skeleton)
+ if (instance->skeleton == p_skeleton) {
return;
+ }
instance->skeleton = p_skeleton;
@@ -790,7 +760,6 @@ void RenderingServerScene::instance_set_extra_visibility_margin(RID p_instance,
}
Vector<ObjectID> RenderingServerScene::instances_cull_aabb(const AABB &p_aabb, RID p_scenario) const {
-
Vector<ObjectID> instances;
Scenario *scenario = scenario_owner.getornull(p_scenario);
ERR_FAIL_COND_V(!scenario, instances);
@@ -802,19 +771,19 @@ Vector<ObjectID> RenderingServerScene::instances_cull_aabb(const AABB &p_aabb, R
culled = scenario->octree.cull_aabb(p_aabb, cull, 1024);
for (int i = 0; i < culled; i++) {
-
Instance *instance = cull[i];
ERR_CONTINUE(!instance);
- if (instance->object_id.is_null())
+ if (instance->object_id.is_null()) {
continue;
+ }
instances.push_back(instance->object_id);
}
return instances;
}
-Vector<ObjectID> RenderingServerScene::instances_cull_ray(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario) const {
+Vector<ObjectID> RenderingServerScene::instances_cull_ray(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario) const {
Vector<ObjectID> instances;
Scenario *scenario = scenario_owner.getornull(p_scenario);
ERR_FAIL_COND_V(!scenario, instances);
@@ -827,16 +796,17 @@ Vector<ObjectID> RenderingServerScene::instances_cull_ray(const Vector3 &p_from,
for (int i = 0; i < culled; i++) {
Instance *instance = cull[i];
ERR_CONTINUE(!instance);
- if (instance->object_id.is_null())
+ if (instance->object_id.is_null()) {
continue;
+ }
instances.push_back(instance->object_id);
}
return instances;
}
-Vector<ObjectID> RenderingServerScene::instances_cull_convex(const Vector<Plane> &p_convex, RID p_scenario) const {
+Vector<ObjectID> RenderingServerScene::instances_cull_convex(const Vector<Plane> &p_convex, RID p_scenario) const {
Vector<ObjectID> instances;
Scenario *scenario = scenario_owner.getornull(p_scenario);
ERR_FAIL_COND_V(!scenario, instances);
@@ -848,11 +818,11 @@ Vector<ObjectID> RenderingServerScene::instances_cull_convex(const Vector<Plane>
culled = scenario->octree.cull_convex(p_convex, cull, 1024);
for (int i = 0; i < culled; i++) {
-
Instance *instance = cull[i];
ERR_CONTINUE(!instance);
- if (instance->object_id.is_null())
+ if (instance->object_id.is_null()) {
continue;
+ }
instances.push_back(instance->object_id);
}
@@ -861,21 +831,17 @@ Vector<ObjectID> RenderingServerScene::instances_cull_convex(const Vector<Plane>
}
void RenderingServerScene::instance_geometry_set_flag(RID p_instance, RS::InstanceFlags p_flags, bool p_enabled) {
-
Instance *instance = instance_owner.getornull(p_instance);
ERR_FAIL_COND(!instance);
//ERR_FAIL_COND(((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK));
switch (p_flags) {
-
case RS::INSTANCE_FLAG_USE_BAKED_LIGHT: {
-
instance->baked_light = p_enabled;
} break;
case RS::INSTANCE_FLAG_USE_DYNAMIC_GI: {
-
if (p_enabled == instance->dynamic_gi) {
//bye, redundant
return;
@@ -893,7 +859,6 @@ void RenderingServerScene::instance_geometry_set_flag(RID p_instance, RS::Instan
} break;
case RS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE: {
-
instance->redraw_if_visible = p_enabled;
} break;
@@ -901,16 +866,16 @@ void RenderingServerScene::instance_geometry_set_flag(RID p_instance, RS::Instan
}
}
}
-void RenderingServerScene::instance_geometry_set_cast_shadows_setting(RID p_instance, RS::ShadowCastingSetting p_shadow_casting_setting) {
+void RenderingServerScene::instance_geometry_set_cast_shadows_setting(RID p_instance, RS::ShadowCastingSetting p_shadow_casting_setting) {
Instance *instance = instance_owner.getornull(p_instance);
ERR_FAIL_COND(!instance);
instance->cast_shadows = p_shadow_casting_setting;
_instance_queue_update(instance, false, true);
}
-void RenderingServerScene::instance_geometry_set_material_override(RID p_instance, RID p_material) {
+void RenderingServerScene::instance_geometry_set_material_override(RID p_instance, RID p_material) {
Instance *instance = instance_owner.getornull(p_instance);
ERR_FAIL_COND(!instance);
@@ -920,15 +885,94 @@ void RenderingServerScene::instance_geometry_set_material_override(RID p_instanc
void RenderingServerScene::instance_geometry_set_draw_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin) {
}
+
void RenderingServerScene::instance_geometry_set_as_instance_lod(RID p_instance, RID p_as_lod_of_instance) {
}
-void RenderingServerScene::_update_instance(Instance *p_instance) {
+void RenderingServerScene::instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_slice_index) {
+ Instance *instance = instance_owner.getornull(p_instance);
+ ERR_FAIL_COND(!instance);
+
+ if (instance->lightmap) {
+ InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(((Instance *)instance->lightmap)->base_data);
+ lightmap_data->users.erase(instance);
+ instance->lightmap = nullptr;
+ }
+
+ Instance *lightmap_instance = instance_owner.getornull(p_lightmap);
+
+ instance->lightmap = lightmap_instance;
+ instance->lightmap_uv_scale = p_lightmap_uv_scale;
+ instance->lightmap_slice_index = p_slice_index;
+
+ if (lightmap_instance) {
+ InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(lightmap_instance->base_data);
+ lightmap_data->users.insert(instance);
+ }
+}
+
+void RenderingServerScene::instance_geometry_set_shader_parameter(RID p_instance, const StringName &p_parameter, const Variant &p_value) {
+ Instance *instance = instance_owner.getornull(p_instance);
+ ERR_FAIL_COND(!instance);
+ Map<StringName, RasterizerScene::InstanceBase::InstanceShaderParameter>::Element *E = instance->instance_shader_parameters.find(p_parameter);
+
+ if (!E) {
+ RasterizerScene::InstanceBase::InstanceShaderParameter isp;
+ isp.index = -1;
+ isp.info = PropertyInfo();
+ isp.value = p_value;
+ instance->instance_shader_parameters[p_parameter] = isp;
+ } else {
+ E->get().value = p_value;
+ if (E->get().index >= 0 && instance->instance_allocated_shader_parameters) {
+ //update directly
+ RSG::storage->global_variables_instance_update(p_instance, E->get().index, p_value);
+ }
+ }
+}
+
+Variant RenderingServerScene::instance_geometry_get_shader_parameter(RID p_instance, const StringName &p_parameter) const {
+ const Instance *instance = const_cast<RenderingServerScene *>(this)->instance_owner.getornull(p_instance);
+ ERR_FAIL_COND_V(!instance, Variant());
+
+ if (instance->instance_shader_parameters.has(p_parameter)) {
+ return instance->instance_shader_parameters[p_parameter].value;
+ }
+ return Variant();
+}
+
+Variant RenderingServerScene::instance_geometry_get_shader_parameter_default_value(RID p_instance, const StringName &p_parameter) const {
+ const Instance *instance = const_cast<RenderingServerScene *>(this)->instance_owner.getornull(p_instance);
+ ERR_FAIL_COND_V(!instance, Variant());
+
+ if (instance->instance_shader_parameters.has(p_parameter)) {
+ return instance->instance_shader_parameters[p_parameter].default_value;
+ }
+ return Variant();
+}
+
+void RenderingServerScene::instance_geometry_get_shader_parameter_list(RID p_instance, List<PropertyInfo> *p_parameters) const {
+ const Instance *instance = const_cast<RenderingServerScene *>(this)->instance_owner.getornull(p_instance);
+ ERR_FAIL_COND(!instance);
+
+ const_cast<RenderingServerScene *>(this)->update_dirty_instances();
+
+ Vector<StringName> names;
+ for (Map<StringName, RasterizerScene::InstanceBase::InstanceShaderParameter>::Element *E = instance->instance_shader_parameters.front(); E; E = E->next()) {
+ names.push_back(E->key());
+ }
+ names.sort_custom<StringName::AlphCompare>();
+ for (int i = 0; i < names.size(); i++) {
+ PropertyInfo pinfo = instance->instance_shader_parameters[names[i]].info;
+ p_parameters->push_back(pinfo);
+ }
+}
+
+void RenderingServerScene::_update_instance(Instance *p_instance) {
p_instance->version++;
if (p_instance->base_type == RS::INSTANCE_LIGHT) {
-
InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data);
RSG::scene_render->light_instance_set_transform(light->instance, p_instance->transform);
@@ -936,22 +980,25 @@ void RenderingServerScene::_update_instance(Instance *p_instance) {
}
if (p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE) {
-
InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(p_instance->base_data);
RSG::scene_render->reflection_probe_instance_set_transform(reflection_probe->instance, p_instance->transform);
reflection_probe->reflection_dirty = true;
}
- if (p_instance->base_type == RS::INSTANCE_GI_PROBE) {
+ if (p_instance->base_type == RS::INSTANCE_DECAL) {
+ InstanceDecalData *decal = static_cast<InstanceDecalData *>(p_instance->base_data);
+
+ RSG::scene_render->decal_instance_set_transform(decal->instance, p_instance->transform);
+ }
+ if (p_instance->base_type == RS::INSTANCE_GI_PROBE) {
InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(p_instance->base_data);
RSG::scene_render->gi_probe_instance_set_transform_to_data(gi_probe->probe_instance, p_instance->transform);
}
if (p_instance->base_type == RS::INSTANCE_PARTICLES) {
-
RSG::storage->particles_set_emission_transform(p_instance->base, p_instance->transform);
}
@@ -960,7 +1007,6 @@ void RenderingServerScene::_update_instance(Instance *p_instance) {
}
if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
-
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);
//make sure lights are updated if it casts shadow
@@ -971,16 +1017,28 @@ void RenderingServerScene::_update_instance(Instance *p_instance) {
}
}
- if (!p_instance->lightmap_capture && geom->lightmap_captures.size()) {
+ if (!p_instance->lightmap && geom->lightmap_captures.size()) {
//affected by lightmap captures, must update capture info!
_update_instance_lightmap_captures(p_instance);
} else {
- if (!p_instance->lightmap_capture_data.empty()) {
- p_instance->lightmap_capture_data.resize(0); //not in use, clear capture data
+ if (!p_instance->lightmap_sh.empty()) {
+ p_instance->lightmap_sh.clear(); //don't need SH
+ p_instance->lightmap_target_sh.clear(); //don't need SH
}
}
}
+ if (p_instance->base_type == RS::INSTANCE_LIGHTMAP) {
+ //if this moved, update the captured objects
+ InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(p_instance->base_data);
+ //erase dependencies, since no longer a lightmap
+
+ for (List<InstanceLightmapData::PairInfo>::Element *E = lightmap_data->geometries.front(); E; E = E->next()) {
+ Instance *geom = E->get().geometry;
+ _instance_queue_update(geom, true, false);
+ }
+ }
+
p_instance->mirror = p_instance->transform.basis.determinant() < 0.0;
AABB new_aabb;
@@ -990,18 +1048,15 @@ void RenderingServerScene::_update_instance(Instance *p_instance) {
p_instance->transformed_aabb = new_aabb;
if (!p_instance->scenario) {
-
return;
}
if (p_instance->octree_id == 0) {
-
uint32_t base_type = 1 << p_instance->base_type;
uint32_t pairable_mask = 0;
bool pairable = false;
- if (p_instance->base_type == RS::INSTANCE_LIGHT || p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE || p_instance->base_type == RS::INSTANCE_LIGHTMAP_CAPTURE) {
-
+ if (p_instance->base_type == RS::INSTANCE_LIGHT || p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE || p_instance->base_type == RS::INSTANCE_DECAL || p_instance->base_type == RS::INSTANCE_LIGHTMAP) {
pairable_mask = p_instance->visible ? RS::INSTANCE_GEOMETRY_MASK : 0;
pairable = true;
}
@@ -1016,7 +1071,6 @@ void RenderingServerScene::_update_instance(Instance *p_instance) {
p_instance->octree_id = p_instance->scenario->octree.create(p_instance, new_aabb, 0, pairable, base_type, pairable_mask);
} else {
-
/*
if (new_aabb==p_instance->data.transformed_aabb)
return;
@@ -1027,67 +1081,65 @@ void RenderingServerScene::_update_instance(Instance *p_instance) {
}
void RenderingServerScene::_update_instance_aabb(Instance *p_instance) {
-
AABB new_aabb;
ERR_FAIL_COND(p_instance->base_type != RS::INSTANCE_NONE && !p_instance->base.is_valid());
switch (p_instance->base_type) {
case RenderingServer::INSTANCE_NONE: {
-
// do nothing
} break;
case RenderingServer::INSTANCE_MESH: {
-
- if (p_instance->custom_aabb)
+ if (p_instance->custom_aabb) {
new_aabb = *p_instance->custom_aabb;
- else
+ } else {
new_aabb = RSG::storage->mesh_get_aabb(p_instance->base, p_instance->skeleton);
+ }
} break;
case RenderingServer::INSTANCE_MULTIMESH: {
-
- if (p_instance->custom_aabb)
+ if (p_instance->custom_aabb) {
new_aabb = *p_instance->custom_aabb;
- else
+ } else {
new_aabb = RSG::storage->multimesh_get_aabb(p_instance->base);
+ }
} break;
case RenderingServer::INSTANCE_IMMEDIATE: {
-
- if (p_instance->custom_aabb)
+ if (p_instance->custom_aabb) {
new_aabb = *p_instance->custom_aabb;
- else
+ } else {
new_aabb = RSG::storage->immediate_get_aabb(p_instance->base);
+ }
} break;
case RenderingServer::INSTANCE_PARTICLES: {
-
- if (p_instance->custom_aabb)
+ if (p_instance->custom_aabb) {
new_aabb = *p_instance->custom_aabb;
- else
+ } else {
new_aabb = RSG::storage->particles_get_aabb(p_instance->base);
+ }
} break;
case RenderingServer::INSTANCE_LIGHT: {
-
new_aabb = RSG::storage->light_get_aabb(p_instance->base);
} break;
case RenderingServer::INSTANCE_REFLECTION_PROBE: {
-
new_aabb = RSG::storage->reflection_probe_get_aabb(p_instance->base);
} break;
- case RenderingServer::INSTANCE_GI_PROBE: {
+ case RenderingServer::INSTANCE_DECAL: {
+ new_aabb = RSG::storage->decal_get_aabb(p_instance->base);
+ } break;
+ case RenderingServer::INSTANCE_GI_PROBE: {
new_aabb = RSG::storage->gi_probe_get_bounds(p_instance->base);
} break;
- case RenderingServer::INSTANCE_LIGHTMAP_CAPTURE: {
-
- new_aabb = RSG::storage->lightmap_capture_get_bounds(p_instance->base);
+ case RenderingServer::INSTANCE_LIGHTMAP: {
+ new_aabb = RSG::storage->lightmap_get_aabb(p_instance->base);
} break;
default: {
@@ -1095,247 +1147,92 @@ void RenderingServerScene::_update_instance_aabb(Instance *p_instance) {
}
// <Zylann> This is why I didn't re-use Instance::aabb to implement custom AABBs
- if (p_instance->extra_margin)
+ if (p_instance->extra_margin) {
new_aabb.grow_by(p_instance->extra_margin);
+ }
p_instance->aabb = new_aabb;
}
-_FORCE_INLINE_ static void _light_capture_sample_octree(const RasterizerStorage::LightmapCaptureOctree *p_octree, int p_cell_subdiv, const Vector3 &p_pos, const Vector3 &p_dir, float p_level, Vector3 &r_color, float &r_alpha) {
-
- static const Vector3 aniso_normal[6] = {
- Vector3(-1, 0, 0),
- Vector3(1, 0, 0),
- Vector3(0, -1, 0),
- Vector3(0, 1, 0),
- Vector3(0, 0, -1),
- Vector3(0, 0, 1)
- };
-
- int size = 1 << (p_cell_subdiv - 1);
-
- int clamp_v = size - 1;
- //first of all, clamp
- Vector3 pos;
- pos.x = CLAMP(p_pos.x, 0, clamp_v);
- pos.y = CLAMP(p_pos.y, 0, clamp_v);
- pos.z = CLAMP(p_pos.z, 0, clamp_v);
-
- float level = (p_cell_subdiv - 1) - p_level;
-
- int target_level;
- float level_filter;
- if (level <= 0.0) {
- level_filter = 0;
- target_level = 0;
- } else {
- target_level = Math::ceil(level);
- level_filter = target_level - level;
- }
-
- Vector3 color[2][8];
- float alpha[2][8];
- zeromem(alpha, sizeof(float) * 2 * 8);
-
- //find cell at given level first
-
- for (int c = 0; c < 2; c++) {
-
- int current_level = MAX(0, target_level - c);
- int level_cell_size = (1 << (p_cell_subdiv - 1)) >> current_level;
-
- for (int n = 0; n < 8; n++) {
-
- int x = int(pos.x);
- int y = int(pos.y);
- int z = int(pos.z);
+void RenderingServerScene::_update_instance_lightmap_captures(Instance *p_instance) {
+ bool first_set = p_instance->lightmap_sh.size() == 0;
+ p_instance->lightmap_sh.resize(9); //using SH
+ p_instance->lightmap_target_sh.resize(9); //using SH
+ Color *instance_sh = p_instance->lightmap_target_sh.ptrw();
+ bool inside = false;
+ Color accum_sh[9];
+ float accum_blend = 0.0;
- if (n & 1)
- x += level_cell_size;
- if (n & 2)
- y += level_cell_size;
- if (n & 4)
- z += level_cell_size;
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);
+ for (List<Instance *>::Element *E = geom->lightmap_captures.front(); E; E = E->next()) {
+ Instance *lightmap = E->get();
- int ofs_x = 0;
- int ofs_y = 0;
- int ofs_z = 0;
+ bool interior = RSG::storage->lightmap_is_interior(lightmap->base);
- x = CLAMP(x, 0, clamp_v);
- y = CLAMP(y, 0, clamp_v);
- z = CLAMP(z, 0, clamp_v);
+ if (inside && !interior) {
+ continue; //we are inside, ignore exteriors
+ }
- int half = size / 2;
- uint32_t cell = 0;
- for (int i = 0; i < current_level; i++) {
+ Transform to_bounds = lightmap->transform.affine_inverse();
+ Vector3 center = p_instance->transform.xform(p_instance->aabb.position + p_instance->aabb.size * 0.5); //use aabb center
- const RasterizerStorage::LightmapCaptureOctree *bc = &p_octree[cell];
+ Vector3 lm_pos = to_bounds.xform(center);
- int child = 0;
- if (x >= ofs_x + half) {
- child |= 1;
- ofs_x += half;
- }
- if (y >= ofs_y + half) {
- child |= 2;
- ofs_y += half;
- }
- if (z >= ofs_z + half) {
- child |= 4;
- ofs_z += half;
- }
+ AABB bounds = RSG::storage->lightmap_get_aabb(lightmap->base);
+ if (!bounds.has_point(lm_pos)) {
+ continue; //not in this lightmap
+ }
- cell = bc->children[child];
- if (cell == RasterizerStorage::LightmapCaptureOctree::CHILD_EMPTY)
- break;
+ Color sh[9];
+ RSG::storage->lightmap_tap_sh_light(lightmap->base, lm_pos, sh);
- half >>= 1;
+ //rotate it
+ Basis rot = lightmap->transform.basis.orthonormalized();
+ for (int i = 0; i < 3; i++) {
+ float csh[9];
+ for (int j = 0; j < 9; j++) {
+ csh[j] = sh[j][i];
}
-
- if (cell == RasterizerStorage::LightmapCaptureOctree::CHILD_EMPTY) {
- alpha[c][n] = 0;
- } else {
- alpha[c][n] = p_octree[cell].alpha;
-
- for (int i = 0; i < 6; i++) {
- //anisotropic read light
- float amount = p_dir.dot(aniso_normal[i]);
- if (amount < 0)
- amount = 0;
- color[c][n].x += p_octree[cell].light[i][0] / 1024.0 * amount;
- color[c][n].y += p_octree[cell].light[i][1] / 1024.0 * amount;
- color[c][n].z += p_octree[cell].light[i][2] / 1024.0 * amount;
- }
+ rot.rotate_sh(csh);
+ for (int j = 0; j < 9; j++) {
+ sh[j][i] = csh[j];
}
-
- //print_line("\tlev " + itos(c) + " - " + itos(n) + " alpha: " + rtos(cells[test_cell].alpha) + " col: " + color[c][n]);
}
- }
-
- float target_level_size = size >> target_level;
- Vector3 pos_fract[2];
-
- pos_fract[0].x = Math::fmod(pos.x, target_level_size) / target_level_size;
- pos_fract[0].y = Math::fmod(pos.y, target_level_size) / target_level_size;
- pos_fract[0].z = Math::fmod(pos.z, target_level_size) / target_level_size;
- target_level_size = size >> MAX(0, target_level - 1);
+ Vector3 inner_pos = ((lm_pos - bounds.position) / bounds.size) * 2.0 - Vector3(1.0, 1.0, 1.0);
- pos_fract[1].x = Math::fmod(pos.x, target_level_size) / target_level_size;
- pos_fract[1].y = Math::fmod(pos.y, target_level_size) / target_level_size;
- pos_fract[1].z = Math::fmod(pos.z, target_level_size) / target_level_size;
+ float blend = MAX(inner_pos.x, MAX(inner_pos.y, inner_pos.z));
+ //make blend more rounded
+ blend = Math::lerp(inner_pos.length(), blend, blend);
+ blend *= blend;
+ blend = MAX(0.0, 1.0 - blend);
- float alpha_interp[2];
- Vector3 color_interp[2];
-
- for (int i = 0; i < 2; i++) {
-
- Vector3 color_x00 = color[i][0].linear_interpolate(color[i][1], pos_fract[i].x);
- Vector3 color_xy0 = color[i][2].linear_interpolate(color[i][3], pos_fract[i].x);
- Vector3 blend_z0 = color_x00.linear_interpolate(color_xy0, pos_fract[i].y);
-
- Vector3 color_x0z = color[i][4].linear_interpolate(color[i][5], pos_fract[i].x);
- Vector3 color_xyz = color[i][6].linear_interpolate(color[i][7], pos_fract[i].x);
- Vector3 blend_z1 = color_x0z.linear_interpolate(color_xyz, pos_fract[i].y);
-
- color_interp[i] = blend_z0.linear_interpolate(blend_z1, pos_fract[i].z);
-
- float alpha_x00 = Math::lerp(alpha[i][0], alpha[i][1], pos_fract[i].x);
- float alpha_xy0 = Math::lerp(alpha[i][2], alpha[i][3], pos_fract[i].x);
- float alpha_z0 = Math::lerp(alpha_x00, alpha_xy0, pos_fract[i].y);
-
- float alpha_x0z = Math::lerp(alpha[i][4], alpha[i][5], pos_fract[i].x);
- float alpha_xyz = Math::lerp(alpha[i][6], alpha[i][7], pos_fract[i].x);
- float alpha_z1 = Math::lerp(alpha_x0z, alpha_xyz, pos_fract[i].y);
-
- alpha_interp[i] = Math::lerp(alpha_z0, alpha_z1, pos_fract[i].z);
- }
-
- r_color = color_interp[0].linear_interpolate(color_interp[1], level_filter);
- r_alpha = Math::lerp(alpha_interp[0], alpha_interp[1], level_filter);
-
- //print_line("pos: " + p_posf + " level " + rtos(p_level) + " down to " + itos(target_level) + "." + rtos(level_filter) + " color " + r_color + " alpha " + rtos(r_alpha));
-}
-
-_FORCE_INLINE_ static Color _light_capture_voxel_cone_trace(const RasterizerStorage::LightmapCaptureOctree *p_octree, const Vector3 &p_pos, const Vector3 &p_dir, float p_aperture, int p_cell_subdiv) {
-
- float bias = 0.0; //no need for bias here
- float max_distance = (Vector3(1, 1, 1) * (1 << (p_cell_subdiv - 1))).length();
-
- float dist = bias;
- float alpha = 0.0;
- Vector3 color;
-
- Vector3 scolor;
- float salpha;
-
- while (dist < max_distance && alpha < 0.95) {
- float diameter = MAX(1.0, 2.0 * p_aperture * dist);
- _light_capture_sample_octree(p_octree, p_cell_subdiv, p_pos + dist * p_dir, p_dir, log2(diameter), scolor, salpha);
- float a = (1.0 - alpha);
- color += scolor * a;
- alpha += a * salpha;
- dist += diameter * 0.5;
- }
-
- return Color(color.x, color.y, color.z, alpha);
-}
-
-void RenderingServerScene::_update_instance_lightmap_captures(Instance *p_instance) {
-
- InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);
-
- static const Vector3 cone_traces[12] = {
- Vector3(0, 0, 1),
- Vector3(0.866025, 0, 0.5),
- Vector3(0.267617, 0.823639, 0.5),
- Vector3(-0.700629, 0.509037, 0.5),
- Vector3(-0.700629, -0.509037, 0.5),
- Vector3(0.267617, -0.823639, 0.5),
- Vector3(0, 0, -1),
- Vector3(0.866025, 0, -0.5),
- Vector3(0.267617, 0.823639, -0.5),
- Vector3(-0.700629, 0.509037, -0.5),
- Vector3(-0.700629, -0.509037, -0.5),
- Vector3(0.267617, -0.823639, -0.5)
- };
-
- float cone_aperture = 0.577; // tan(angle) 60 degrees
-
- if (p_instance->lightmap_capture_data.empty()) {
- p_instance->lightmap_capture_data.resize(12);
+ if (interior && !inside) {
+ //do not blend, just replace
+ for (int j = 0; j < 9; j++) {
+ accum_sh[j] = sh[j] * blend;
+ }
+ accum_blend = blend;
+ inside = true;
+ } else {
+ for (int j = 0; j < 9; j++) {
+ accum_sh[j] += sh[j] * blend;
+ }
+ accum_blend += blend;
+ }
}
- //print_line("update captures for pos: " + p_instance->transform.origin);
-
- for (int i = 0; i < 12; i++)
- new (&p_instance->lightmap_capture_data.ptrw()[i]) Color;
-
- //this could use some sort of blending..
- for (List<Instance *>::Element *E = geom->lightmap_captures.front(); E; E = E->next()) {
- const Vector<RasterizerStorage::LightmapCaptureOctree> *octree = RSG::storage->lightmap_capture_get_octree_ptr(E->get()->base);
- //print_line("octree size: " + itos(octree->size()));
- if (octree->size() == 0)
- continue;
- Transform to_cell_xform = RSG::storage->lightmap_capture_get_octree_cell_transform(E->get()->base);
- int cell_subdiv = RSG::storage->lightmap_capture_get_octree_cell_subdiv(E->get()->base);
- to_cell_xform = to_cell_xform * E->get()->transform.affine_inverse();
-
- const RasterizerStorage::LightmapCaptureOctree *octree_r = octree->ptr();
-
- Vector3 pos = to_cell_xform.xform(p_instance->transform.origin);
-
- for (int i = 0; i < 12; i++) {
-
- Vector3 dir = to_cell_xform.basis.xform(cone_traces[i]).normalized();
- Color capture = _light_capture_voxel_cone_trace(octree_r, pos, dir, cone_aperture, cell_subdiv);
- p_instance->lightmap_capture_data.write[i] += capture;
+ if (accum_blend > 0.0) {
+ for (int j = 0; j < 9; j++) {
+ instance_sh[j] = accum_sh[j] / accum_blend;
+ if (first_set) {
+ p_instance->lightmap_sh.write[j] = instance_sh[j];
+ }
}
}
}
-bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_shadow_atlas, Scenario *p_scenario) {
-
+bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario) {
InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data);
Transform light_transform = p_instance->transform;
@@ -1344,19 +1241,19 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
bool animated_material_found = false;
switch (RSG::storage->light_get_type(p_instance->base)) {
-
case RS::LIGHT_DIRECTIONAL: {
-
- float max_distance = p_cam_projection.get_z_far();
- float shadow_max = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE);
+ real_t max_distance = p_cam_projection.get_z_far();
+ real_t shadow_max = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE);
if (shadow_max > 0 && !p_cam_orthogonal) { //its impractical (and leads to unwanted behaviors) to set max distance in orthogonal camera
max_distance = MIN(shadow_max, max_distance);
}
max_distance = MAX(max_distance, p_cam_projection.get_z_near() + 0.001);
- float min_distance = MIN(p_cam_projection.get_z_near(), max_distance);
+ real_t min_distance = MIN(p_cam_projection.get_z_near(), max_distance);
RS::LightDirectionalShadowDepthRangeMode depth_range_mode = RSG::storage->light_directional_get_shadow_depth_range_mode(p_instance->base);
+ real_t pancake_size = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE);
+
if (depth_range_mode == RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_OPTIMIZED) {
//optimize min/max
Vector<Plane> planes = p_cam_projection.get_projection_planes(p_cam_transform);
@@ -1365,11 +1262,10 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
//check distance max and min
bool found_items = false;
- float z_max = -1e20;
- float z_min = 1e20;
+ real_t z_max = -1e20;
+ real_t z_min = 1e20;
for (int i = 0; i < cull_count; i++) {
-
Instance *instance = instance_shadow_cull_result[i];
if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) {
continue;
@@ -1379,7 +1275,7 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
animated_material_found = true;
}
- float max, min;
+ real_t max, min;
instance->transformed_aabb.project_range_in_plane(base, min, max);
if (max > z_max) {
@@ -1399,16 +1295,22 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
}
}
- float range = max_distance - min_distance;
+ real_t range = max_distance - min_distance;
int splits = 0;
switch (RSG::storage->light_directional_get_shadow_mode(p_instance->base)) {
- case RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: splits = 1; break;
- case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: splits = 2; break;
- case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: splits = 4; break;
+ case RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL:
+ splits = 1;
+ break;
+ case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS:
+ splits = 2;
+ break;
+ case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS:
+ splits = 4;
+ break;
}
- float distances[5];
+ real_t distances[5];
distances[0] = min_distance;
for (int i = 0; i < splits; i++) {
@@ -1417,30 +1319,29 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
distances[splits] = max_distance;
- float texture_size = RSG::scene_render->get_directional_light_shadow_size(light->instance);
+ real_t texture_size = RSG::scene_render->get_directional_light_shadow_size(light->instance);
bool overlap = RSG::storage->light_directional_get_blend_splits(p_instance->base);
- float first_radius = 0.0;
+ real_t first_radius = 0.0;
- for (int i = 0; i < splits; i++) {
+ real_t min_distance_bias_scale = pancake_size > 0 ? distances[1] / 10.0 : 0;
+ for (int i = 0; i < splits; i++) {
RENDER_TIMESTAMP("Culling Directional Light split" + itos(i));
// setup a camera matrix for that range!
CameraMatrix camera_matrix;
- float aspect = p_cam_projection.get_aspect();
+ real_t aspect = p_cam_projection.get_aspect();
if (p_cam_orthogonal) {
-
Vector2 vp_he = p_cam_projection.get_viewport_half_extents();
camera_matrix.set_orthogonal(vp_he.y * 2.0, aspect, distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], false);
} else {
-
- float fov = p_cam_projection.get_fov();
- camera_matrix.set_perspective(fov, aspect, distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], false);
+ real_t fov = p_cam_projection.get_fov(); //this is actually yfov, because set aspect tries to keep it
+ camera_matrix.set_perspective(fov, aspect, distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], true);
}
//obtain the frustum endpoints
@@ -1458,63 +1359,68 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
Vector3 z_vec = transform.basis.get_axis(Vector3::AXIS_Z).normalized();
//z_vec points agsint the camera, like in default opengl
- float x_min = 0.f, x_max = 0.f;
- float y_min = 0.f, y_max = 0.f;
- float z_min = 0.f, z_max = 0.f;
+ real_t x_min = 0.f, x_max = 0.f;
+ real_t y_min = 0.f, y_max = 0.f;
+ real_t z_min = 0.f, z_max = 0.f;
// FIXME: z_max_cam is defined, computed, but not used below when setting up
// ortho_camera. Commented out for now to fix warnings but should be investigated.
- float x_min_cam = 0.f, x_max_cam = 0.f;
- float y_min_cam = 0.f, y_max_cam = 0.f;
- float z_min_cam = 0.f;
- //float z_max_cam = 0.f;
+ real_t x_min_cam = 0.f, x_max_cam = 0.f;
+ real_t y_min_cam = 0.f, y_max_cam = 0.f;
+ real_t z_min_cam = 0.f;
+ //real_t z_max_cam = 0.f;
- float bias_scale = 1.0;
+ real_t bias_scale = 1.0;
+ real_t aspect_bias_scale = 1.0;
//used for culling
for (int j = 0; j < 8; j++) {
+ real_t d_x = x_vec.dot(endpoints[j]);
+ real_t d_y = y_vec.dot(endpoints[j]);
+ real_t d_z = z_vec.dot(endpoints[j]);
- float d_x = x_vec.dot(endpoints[j]);
- float d_y = y_vec.dot(endpoints[j]);
- float d_z = z_vec.dot(endpoints[j]);
-
- if (j == 0 || d_x < x_min)
+ if (j == 0 || d_x < x_min) {
x_min = d_x;
- if (j == 0 || d_x > x_max)
+ }
+ if (j == 0 || d_x > x_max) {
x_max = d_x;
+ }
- if (j == 0 || d_y < y_min)
+ if (j == 0 || d_y < y_min) {
y_min = d_y;
- if (j == 0 || d_y > y_max)
+ }
+ if (j == 0 || d_y > y_max) {
y_max = d_y;
+ }
- if (j == 0 || d_z < z_min)
+ if (j == 0 || d_z < z_min) {
z_min = d_z;
- if (j == 0 || d_z > z_max)
+ }
+ if (j == 0 || d_z > z_max) {
z_max = d_z;
+ }
}
+ real_t radius = 0;
+ real_t soft_shadow_expand = 0;
+ Vector3 center;
+
{
//camera viewport stuff
- Vector3 center;
-
for (int j = 0; j < 8; j++) {
-
center += endpoints[j];
}
center /= 8.0;
//center=x_vec*(x_max-x_min)*0.5 + y_vec*(y_max-y_min)*0.5 + z_vec*(z_max-z_min)*0.5;
- float radius = 0;
-
for (int j = 0; j < 8; j++) {
-
- float d = center.distance_to(endpoints[j]);
- if (d > radius)
+ real_t d = center.distance_to(endpoints[j]);
+ if (d > radius) {
radius = d;
+ }
}
radius *= texture_size / (texture_size - 2.0); //add a texel by each side
@@ -1525,18 +1431,33 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
bias_scale = radius / first_radius;
}
- x_max_cam = x_vec.dot(center) + radius;
- x_min_cam = x_vec.dot(center) - radius;
- y_max_cam = y_vec.dot(center) + radius;
- y_min_cam = y_vec.dot(center) - radius;
- //z_max_cam = z_vec.dot(center) + radius;
z_min_cam = z_vec.dot(center) - radius;
+ {
+ float soft_shadow_angle = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SIZE);
+
+ if (soft_shadow_angle > 0.0 && pancake_size > 0.0) {
+ float z_range = (z_vec.dot(center) + radius + pancake_size) - z_min_cam;
+ soft_shadow_expand = Math::tan(Math::deg2rad(soft_shadow_angle)) * z_range;
+
+ x_max += soft_shadow_expand;
+ y_max += soft_shadow_expand;
+
+ x_min -= soft_shadow_expand;
+ y_min -= soft_shadow_expand;
+ }
+ }
+
+ x_max_cam = x_vec.dot(center) + radius + soft_shadow_expand;
+ x_min_cam = x_vec.dot(center) - radius - soft_shadow_expand;
+ y_max_cam = y_vec.dot(center) + radius + soft_shadow_expand;
+ y_min_cam = y_vec.dot(center) - radius - soft_shadow_expand;
+
if (depth_range_mode == RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE) {
//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
- float unit = radius * 2.0 / texture_size;
+ real_t unit = radius * 2.0 / texture_size;
x_max_cam = Math::stepify(x_max_cam, unit);
x_min_cam = Math::stepify(x_min_cam, unit);
@@ -1566,9 +1487,9 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
Plane near_plane(light_transform.origin, -light_transform.basis.get_axis(2));
+ real_t cull_max = 0;
for (int j = 0; j < cull_count; j++) {
-
- float min, max;
+ real_t min, max;
Instance *instance = instance_shadow_cull_result[j];
if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) {
cull_count--;
@@ -1580,23 +1501,107 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
instance->transformed_aabb.project_range_in_plane(Plane(z_vec, 0), min, max);
instance->depth = near_plane.distance_to(instance->transform.origin);
instance->depth_layer = 0;
- if (max > z_max)
- z_max = max;
+ if (j == 0 || max > cull_max) {
+ cull_max = max;
+ }
}
- {
+ if (cull_max > z_max) {
+ z_max = cull_max;
+ }
+ if (pancake_size > 0) {
+ z_max = z_vec.dot(center) + radius + pancake_size;
+ }
+
+ if (aspect != 1.0) {
+ // if the aspect is different, then the radius will become larger.
+ // if this happens, then bias needs to be adjusted too, as depth will increase
+ // to do this, compare the depth of one that would have resulted from a square frustum
+
+ CameraMatrix camera_matrix_square;
+ if (p_cam_orthogonal) {
+ Vector2 vp_he = camera_matrix.get_viewport_half_extents();
+ if (p_cam_vaspect) {
+ camera_matrix_square.set_orthogonal(vp_he.x * 2.0, 1.0, distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], true);
+ } else {
+ camera_matrix_square.set_orthogonal(vp_he.y * 2.0, 1.0, distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], false);
+ }
+ } else {
+ Vector2 vp_he = camera_matrix.get_viewport_half_extents();
+ if (p_cam_vaspect) {
+ camera_matrix_square.set_frustum(vp_he.x * 2.0, 1.0, Vector2(), distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], true);
+ } else {
+ camera_matrix_square.set_frustum(vp_he.y * 2.0, 1.0, Vector2(), distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], false);
+ }
+ }
+
+ Vector3 endpoints_square[8]; // frustum plane endpoints
+ res = camera_matrix_square.get_endpoints(p_cam_transform, endpoints_square);
+ ERR_CONTINUE(!res);
+ Vector3 center_square;
+ real_t z_max_square = 0;
+
+ for (int j = 0; j < 8; j++) {
+ center_square += endpoints_square[j];
+
+ real_t d_z = z_vec.dot(endpoints_square[j]);
+
+ if (j == 0 || d_z > z_max_square) {
+ z_max_square = d_z;
+ }
+ }
+
+ if (cull_max > z_max_square) {
+ z_max_square = cull_max;
+ }
+
+ center_square /= 8.0;
+
+ real_t radius_square = 0;
+
+ for (int j = 0; j < 8; j++) {
+ real_t d = center_square.distance_to(endpoints_square[j]);
+ if (d > radius_square) {
+ radius_square = d;
+ }
+ }
+
+ radius_square *= texture_size / (texture_size - 2.0); //add a texel by each side
+
+ if (pancake_size > 0) {
+ z_max_square = z_vec.dot(center_square) + radius_square + pancake_size;
+ }
+
+ real_t z_min_cam_square = z_vec.dot(center_square) - radius_square;
+
+ aspect_bias_scale = (z_max - z_min_cam) / (z_max_square - z_min_cam_square);
+
+ // this is not entirely perfect, because the cull-adjusted z-max may be different
+ // but at least it's warranted that it results in a greater bias, so no acne should be present either way.
+ // pancaking also helps with this.
+ }
+
+ {
CameraMatrix ortho_camera;
real_t half_x = (x_max_cam - x_min_cam) * 0.5;
real_t half_y = (y_max_cam - y_min_cam) * 0.5;
ortho_camera.set_orthogonal(-half_x, half_x, -half_y, half_y, 0, (z_max - z_min_cam));
+ Vector2 uv_scale(1.0 / (x_max_cam - x_min_cam), 1.0 / (y_max_cam - y_min_cam));
+
Transform ortho_transform;
ortho_transform.basis = transform.basis;
ortho_transform.origin = x_vec * (x_min_cam + half_x) + y_vec * (y_min_cam + half_y) + z_vec * z_max;
- RSG::scene_render->light_instance_set_shadow_transform(light->instance, ortho_camera, ortho_transform, 0, distances[i + 1], i, bias_scale);
+ {
+ Vector3 max_in_view = p_cam_transform.affine_inverse().xform(z_vec * cull_max);
+ Vector3 dir_in_view = p_cam_transform.xform_inv(z_vec).normalized();
+ cull_max = dir_in_view.dot(max_in_view);
+ }
+
+ RSG::scene_render->light_instance_set_shadow_transform(light->instance, ortho_camera, ortho_transform, z_max - z_min_cam, distances[i + 1], i, radius * 2.0 / texture_size, bias_scale * aspect_bias_scale * min_distance_bias_scale, z_max, uv_scale);
}
RSG::scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count);
@@ -1604,32 +1609,29 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
} break;
case RS::LIGHT_OMNI: {
-
RS::LightOmniShadowMode shadow_mode = RSG::storage->light_omni_get_shadow_mode(p_instance->base);
if (shadow_mode == RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID || !RSG::scene_render->light_instances_can_render_shadow_cube()) {
-
for (int i = 0; i < 2; i++) {
-
//using this one ensures that raster deferred will have it
RENDER_TIMESTAMP("Culling Shadow Paraboloid" + itos(i));
- float radius = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
+ real_t radius = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
- float z = i == 0 ? -1 : 1;
+ real_t z = i == 0 ? -1 : 1;
Vector<Plane> planes;
- planes.resize(5);
+ planes.resize(6);
planes.write[0] = light_transform.xform(Plane(Vector3(0, 0, z), radius));
planes.write[1] = light_transform.xform(Plane(Vector3(1, 0, z).normalized(), radius));
planes.write[2] = light_transform.xform(Plane(Vector3(-1, 0, z).normalized(), radius));
planes.write[3] = light_transform.xform(Plane(Vector3(0, 1, z).normalized(), radius));
planes.write[4] = light_transform.xform(Plane(Vector3(0, -1, z).normalized(), radius));
+ planes.write[5] = light_transform.xform(Plane(Vector3(0, 0, -z), 0));
int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, RS::INSTANCE_GEOMETRY_MASK);
Plane near_plane(light_transform.origin, light_transform.basis.get_axis(2) * z);
for (int j = 0; j < cull_count; j++) {
-
Instance *instance = instance_shadow_cull_result[j];
if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) {
cull_count--;
@@ -1645,17 +1647,16 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
}
}
- RSG::scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, i);
+ RSG::scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, i, 0);
RSG::scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count);
}
} else { //shadow cube
- float radius = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
+ real_t radius = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
CameraMatrix cm;
cm.set_perspective(90, 1, 0.01, radius);
for (int i = 0; i < 6; i++) {
-
RENDER_TIMESTAMP("Culling Shadow Cube side" + itos(i));
//using this one ensures that raster deferred will have it
@@ -1684,7 +1685,6 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
Plane near_plane(xform.origin, -xform.basis.get_axis(2));
for (int j = 0; j < cull_count; j++) {
-
Instance *instance = instance_shadow_cull_result[j];
if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) {
cull_count--;
@@ -1699,21 +1699,20 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
}
}
- RSG::scene_render->light_instance_set_shadow_transform(light->instance, cm, xform, radius, 0, i);
+ RSG::scene_render->light_instance_set_shadow_transform(light->instance, cm, xform, radius, 0, i, 0);
RSG::scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count);
}
//restore the regular DP matrix
- RSG::scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, 0);
+ RSG::scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, 0, 0);
}
} break;
case RS::LIGHT_SPOT: {
-
RENDER_TIMESTAMP("Culling Spot Light");
- float radius = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
- float angle = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SPOT_ANGLE);
+ real_t radius = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
+ real_t angle = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SPOT_ANGLE);
CameraMatrix cm;
cm.set_perspective(angle * 2.0, 1.0, 0.01, radius);
@@ -1723,7 +1722,6 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
Plane near_plane(light_transform.origin, -light_transform.basis.get_axis(2));
for (int j = 0; j < cull_count; j++) {
-
Instance *instance = instance_shadow_cull_result[j];
if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) {
cull_count--;
@@ -1738,7 +1736,7 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
}
}
- RSG::scene_render->light_instance_set_shadow_transform(light->instance, cm, light_transform, radius, 0, 0);
+ RSG::scene_render->light_instance_set_shadow_transform(light->instance, cm, light_transform, radius, 0, 0, 0);
RSG::scene_render->render_shadow(light->instance, p_shadow_atlas, 0, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count);
} break;
@@ -1760,7 +1758,6 @@ void RenderingServerScene::render_camera(RID p_render_buffers, RID p_camera, RID
switch (camera->type) {
case Camera::ORTHOGONAL: {
-
camera_matrix.set_orthogonal(
camera->size,
p_viewport_size.width / (float)p_viewport_size.height,
@@ -1770,7 +1767,6 @@ void RenderingServerScene::render_camera(RID p_render_buffers, RID p_camera, RID
ortho = true;
} break;
case Camera::PERSPECTIVE: {
-
camera_matrix.set_perspective(
camera->fov,
p_viewport_size.width / (float)p_viewport_size.height,
@@ -1781,7 +1777,6 @@ void RenderingServerScene::render_camera(RID p_render_buffers, RID p_camera, RID
} break;
case Camera::FRUSTUM: {
-
camera_matrix.set_frustum(
camera->size,
p_viewport_size.width / (float)p_viewport_size.height,
@@ -1793,12 +1788,12 @@ void RenderingServerScene::render_camera(RID p_render_buffers, RID p_camera, RID
} break;
}
- _prepare_scene(camera->transform, camera_matrix, ortho, camera->env, camera->effects, camera->visible_layers, p_scenario, p_shadow_atlas, RID());
+ _prepare_scene(camera->transform, camera_matrix, ortho, camera->vaspect, camera->env, camera->effects, camera->visible_layers, p_scenario, p_shadow_atlas, RID());
_render_scene(p_render_buffers, camera->transform, camera_matrix, ortho, camera->env, camera->effects, p_scenario, p_shadow_atlas, RID(), -1);
#endif
}
-void RenderingServerScene::render_camera(RID p_render_buffers, Ref<ARVRInterface> &p_interface, ARVRInterface::Eyes p_eye, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas) {
+void RenderingServerScene::render_camera(RID p_render_buffers, Ref<XRInterface> &p_interface, XRInterface::Eyes p_eye, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas) {
// render for AR/VR interface
Camera *camera = camera_owner.getornull(p_camera);
@@ -1810,16 +1805,14 @@ void RenderingServerScene::render_camera(RID p_render_buffers, Ref<ARVRInterface
// We also ignore our camera position, it will have been positioned with a slightly old tracking position.
// Instead we take our origin point and have our ar/vr interface add fresh tracking data! Whoohoo!
- Transform world_origin = ARVRServer::get_singleton()->get_world_origin();
+ Transform world_origin = XRServer::get_singleton()->get_world_origin();
Transform cam_transform = p_interface->get_transform_for_eye(p_eye, world_origin);
// For stereo render we only prepare for our left eye and then reuse the outcome for our right eye
- if (p_eye == ARVRInterface::EYE_LEFT) {
- ///@TODO possibly move responsibility for this into our ARVRServer or ARVRInterface?
-
+ if (p_eye == XRInterface::EYE_LEFT) {
// Center our transform, we assume basis is equal.
Transform mono_transform = cam_transform;
- Transform right_transform = p_interface->get_transform_for_eye(ARVRInterface::EYE_RIGHT, world_origin);
+ Transform right_transform = p_interface->get_transform_for_eye(XRInterface::EYE_RIGHT, world_origin);
mono_transform.origin += right_transform.origin;
mono_transform.origin *= 0.5;
@@ -1872,17 +1865,17 @@ void RenderingServerScene::render_camera(RID p_render_buffers, Ref<ARVRInterface
mono_transform *= apply_z_shift;
// now prepare our scene with our adjusted transform projection matrix
- _prepare_scene(mono_transform, combined_matrix, false, camera->env, camera->effects, camera->visible_layers, p_scenario, p_shadow_atlas, RID());
- } else if (p_eye == ARVRInterface::EYE_MONO) {
+ _prepare_scene(mono_transform, combined_matrix, false, false, camera->env, camera->effects, camera->visible_layers, p_scenario, p_shadow_atlas, RID());
+ } else if (p_eye == XRInterface::EYE_MONO) {
// For mono render, prepare as per usual
- _prepare_scene(cam_transform, camera_matrix, false, camera->env, camera->effects, camera->visible_layers, p_scenario, p_shadow_atlas, RID());
+ _prepare_scene(cam_transform, camera_matrix, false, false, camera->env, camera->effects, camera->visible_layers, p_scenario, p_shadow_atlas, RID());
}
// And render our scene...
_render_scene(p_render_buffers, cam_transform, camera_matrix, false, camera->env, camera->effects, p_scenario, p_shadow_atlas, RID(), -1);
};
-void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, RID p_force_camera_effects, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, bool p_using_shadows) {
+void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_force_environment, RID p_force_camera_effects, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, bool p_using_shadows) {
// Note, in stereo rendering:
// - p_cam_transform will be a transform in the middle of our two eyes
// - p_cam_projection is a wider frustrum that encompasses both eyes
@@ -1908,7 +1901,9 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const
light_cull_count = 0;
reflection_probe_cull_count = 0;
+ decal_cull_count = 0;
gi_probe_cull_count = 0;
+ lightmap_cull_count = 0;
//light_samplers_culled=0;
@@ -1923,9 +1918,10 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const
//removed, will replace with culling
/* STEP 4 - REMOVE FURTHER CULLED OBJECTS, ADD LIGHTS */
+ uint64_t frame_number = RSG::rasterizer->get_frame_number();
+ float lightmap_probe_update_speed = RSG::storage->lightmap_get_probe_capture_update_speed() * RSG::rasterizer->get_frame_delta_time();
for (int i = 0; i < instance_cull_count; i++) {
-
Instance *ins = instance_cull_result[i];
bool keep = false;
@@ -1933,9 +1929,7 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const
if ((camera_layer_mask & ins->layer_mask) == 0) {
//failure
} else if (ins->base_type == RS::INSTANCE_LIGHT && ins->visible) {
-
if (light_cull_count < MAX_LIGHTS_CULLED) {
-
InstanceLightData *light = static_cast<InstanceLightData *>(ins->base_data);
if (!light->geometries.empty()) {
@@ -1950,9 +1944,7 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const
}
}
} else if (ins->base_type == RS::INSTANCE_REFLECTION_PROBE && ins->visible) {
-
if (reflection_probe_cull_count < MAX_REFLECTION_PROBES_CULLED) {
-
InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(ins->base_data);
if (p_reflection_probe != reflection_probe->instance) {
@@ -1977,9 +1969,18 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const
}
}
}
+ } else if (ins->base_type == RS::INSTANCE_DECAL && ins->visible) {
+ if (decal_cull_count < MAX_DECALS_CULLED) {
+ InstanceDecalData *decal = static_cast<InstanceDecalData *>(ins->base_data);
+
+ if (!decal->geometries.empty()) {
+ //do not add this decal if no geometry is affected by it..
+ decal_instance_cull_result[decal_cull_count] = decal->instance;
+ decal_cull_count++;
+ }
+ }
} else if (ins->base_type == RS::INSTANCE_GI_PROBE && ins->visible) {
-
InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(ins->base_data);
if (!gi_probe->update_element.in_list()) {
gi_probe_update_list.add(&gi_probe->update_element);
@@ -1989,9 +1990,13 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const
gi_probe_instance_cull_result[gi_probe_cull_count] = gi_probe->probe_instance;
gi_probe_cull_count++;
}
+ } else if (ins->base_type == RS::INSTANCE_LIGHTMAP && ins->visible) {
+ if (lightmap_cull_count < MAX_LIGHTMAPS_CULLED) {
+ lightmap_cull_result[lightmap_cull_count] = ins;
+ lightmap_cull_count++;
+ }
} else if (((1 << ins->base_type) & RS::INSTANCE_GEOMETRY_MASK) && ins->visible && ins->cast_shadows != RS::SHADOW_CASTING_SETTING_SHADOWS_ONLY) {
-
keep = true;
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(ins->base_data);
@@ -2018,7 +2023,6 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const
ins->light_instances.resize(geom->lighting.size());
for (List<Instance *>::Element *E = geom->lighting.front(); E; E = E->next()) {
-
InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data);
ins->light_instances.write[l++] = light->instance;
@@ -2033,7 +2037,6 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const
ins->reflection_probe_instances.resize(geom->reflection_probes.size());
for (List<Instance *>::Element *E = geom->reflection_probes.front(); E; E = E->next()) {
-
InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(E->get()->base_data);
ins->reflection_probe_instances.write[l++] = reflection_probe->instance;
@@ -2048,7 +2051,6 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const
ins->gi_probe_instances.resize(geom->gi_probes.size());
for (List<Instance *>::Element *E = geom->gi_probes.front(); E; E = E->next()) {
-
InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(E->get()->base_data);
ins->gi_probe_instances.write[l++] = gi_probe->probe_instance;
@@ -2057,6 +2059,14 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const
geom->gi_probes_dirty = false;
}
+ if (ins->last_frame_pass != frame_number && !ins->lightmap_target_sh.empty() && !ins->lightmap_sh.empty()) {
+ Color *sh = ins->lightmap_sh.ptrw();
+ const Color *target_sh = ins->lightmap_target_sh.ptr();
+ for (uint32_t j = 0; j < 9; j++) {
+ sh[j] = sh[j].lerp(target_sh[j], MIN(1.0, lightmap_probe_update_speed));
+ }
+ }
+
ins->depth = near_plane.distance_to(ins->transform.origin);
ins->depth_layer = CLAMP(int(ins->depth * 16 / z_far), 0, 15);
}
@@ -2068,9 +2078,9 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const
i--;
ins->last_render_pass = 0; // make invalid
} else {
-
ins->last_render_pass = render_pass;
}
+ ins->last_frame_pass = frame_number;
}
/* STEP 5 - PROCESS LIGHTS */
@@ -2080,18 +2090,17 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const
// directional lights
{
-
Instance **lights_with_shadow = (Instance **)alloca(sizeof(Instance *) * scenario->directional_lights.size());
int directional_shadow_count = 0;
for (List<Instance *>::Element *E = scenario->directional_lights.front(); E; E = E->next()) {
-
if (light_cull_count + directional_light_count >= MAX_LIGHTS_CULLED) {
break;
}
- if (!E->get()->visible)
+ if (!E->get()->visible) {
continue;
+ }
InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data);
@@ -2109,10 +2118,9 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const
RSG::scene_render->set_directional_shadow_count(directional_shadow_count);
for (int i = 0; i < directional_shadow_count; i++) {
-
RENDER_TIMESTAMP(">Rendering Directional Light " + itos(i));
- _light_instance_update_shadow(lights_with_shadow[i], p_cam_transform, p_cam_projection, p_cam_orthogonal, p_shadow_atlas, scenario);
+ _light_instance_update_shadow(lights_with_shadow[i], p_cam_transform, p_cam_projection, p_cam_orthogonal, p_cam_vaspect, p_shadow_atlas, scenario);
RENDER_TIMESTAMP("<Rendering Directional Light " + itos(i));
}
@@ -2123,11 +2131,11 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const
//SortArray<Instance*,_InstanceLightsort> sorter;
//sorter.sort(light_cull_result,light_cull_count);
for (int i = 0; i < light_cull_count; i++) {
-
Instance *ins = light_cull_result[i];
- if (!p_shadow_atlas.is_valid() || !RSG::storage->light_has_shadow(ins->base))
+ if (!p_shadow_atlas.is_valid() || !RSG::storage->light_has_shadow(ins->base)) {
continue;
+ }
InstanceLightData *light = static_cast<InstanceLightData *>(ins->base_data);
@@ -2143,9 +2151,7 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const
Vector2 vp_half_extents = p_cam_projection.get_viewport_half_extents();
switch (RSG::storage->light_get_type(ins->base)) {
-
case RS::LIGHT_OMNI: {
-
float radius = RSG::storage->light_get_param(ins->base, RS::LIGHT_PARAM_RANGE);
//get two points parallel to near plane
@@ -2169,7 +2175,6 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const
coverage = screen_diameter / (vp_half_extents.x + vp_half_extents.y);
} break;
case RS::LIGHT_SPOT: {
-
float radius = RSG::storage->light_get_param(ins->base, RS::LIGHT_PARAM_RANGE);
float angle = RSG::storage->light_get_param(ins->base, RS::LIGHT_PARAM_SPOT_ANGLE);
@@ -2214,7 +2219,7 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const
if (redraw) {
//must redraw!
RENDER_TIMESTAMP(">Rendering Light " + itos(i));
- light->shadow_dirty = _light_instance_update_shadow(ins, p_cam_transform, p_cam_projection, p_cam_orthogonal, p_shadow_atlas, scenario);
+ light->shadow_dirty = _light_instance_update_shadow(ins, p_cam_transform, p_cam_projection, p_cam_orthogonal, p_cam_vaspect, p_shadow_atlas, scenario);
RENDER_TIMESTAMP("<Rendering Light " + itos(i));
}
}
@@ -2222,18 +2227,18 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const
}
void RenderingServerScene::_render_scene(RID p_render_buffers, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, RID p_force_camera_effects, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {
-
Scenario *scenario = scenario_owner.getornull(p_scenario);
/* ENVIRONMENT */
RID environment;
- if (p_force_environment.is_valid()) //camera has more environment priority
+ if (p_force_environment.is_valid()) { //camera has more environment priority
environment = p_force_environment;
- else if (scenario->environment.is_valid())
+ } else if (scenario->environment.is_valid()) {
environment = scenario->environment;
- else
+ } else {
environment = scenario->fallback_environment;
+ }
RID camera_effects;
if (p_force_camera_effects.is_valid()) {
@@ -2244,27 +2249,26 @@ void RenderingServerScene::_render_scene(RID p_render_buffers, const Transform p
/* PROCESS GEOMETRY AND DRAW SCENE */
RENDER_TIMESTAMP("Render Scene ");
- RSG::scene_render->render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_orthogonal, (RasterizerScene::InstanceBase **)instance_cull_result, instance_cull_count, light_instance_cull_result, light_cull_count + directional_light_count, reflection_probe_instance_cull_result, reflection_probe_cull_count, gi_probe_instance_cull_result, gi_probe_cull_count, environment, camera_effects, p_shadow_atlas, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass);
+ RSG::scene_render->render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_orthogonal, (RasterizerScene::InstanceBase **)instance_cull_result, instance_cull_count, light_instance_cull_result, light_cull_count + directional_light_count, reflection_probe_instance_cull_result, reflection_probe_cull_count, gi_probe_instance_cull_result, gi_probe_cull_count, decal_instance_cull_result, decal_cull_count, (RasterizerScene::InstanceBase **)lightmap_cull_result, lightmap_cull_count, environment, camera_effects, p_shadow_atlas, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass);
}
void RenderingServerScene::render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas) {
-
#ifndef _3D_DISABLED
Scenario *scenario = scenario_owner.getornull(p_scenario);
RID environment;
- if (scenario->environment.is_valid())
+ if (scenario->environment.is_valid()) {
environment = scenario->environment;
- else
+ } else {
environment = scenario->fallback_environment;
+ }
RENDER_TIMESTAMP("Render Empty Scene ");
- RSG::scene_render->render_scene(p_render_buffers, Transform(), CameraMatrix(), true, NULL, 0, NULL, 0, NULL, 0, NULL, 0, environment, RID(), p_shadow_atlas, scenario->reflection_atlas, RID(), 0);
+ RSG::scene_render->render_scene(p_render_buffers, Transform(), CameraMatrix(), true, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, environment, RID(), p_shadow_atlas, scenario->reflection_atlas, RID(), 0);
#endif
}
bool RenderingServerScene::_render_reflection_probe_step(Instance *p_instance, int p_step) {
-
InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(p_instance->base_data);
Scenario *scenario = p_instance->scenario;
ERR_FAIL_COND_V(!scenario, true);
@@ -2272,14 +2276,12 @@ bool RenderingServerScene::_render_reflection_probe_step(Instance *p_instance, i
RenderingServerRaster::redraw_request(); //update, so it updates in editor
if (p_step == 0) {
-
if (!RSG::scene_render->reflection_probe_instance_begin_render(reflection_probe->instance, scenario->reflection_atlas)) {
return true; //all full
}
}
if (p_step >= 0 && p_step < 6) {
-
static const Vector3 view_normals[6] = {
Vector3(+1, 0, 0),
Vector3(-1, 0, 0),
@@ -2319,12 +2321,11 @@ bool RenderingServerScene::_render_reflection_probe_step(Instance *p_instance, i
bool use_shadows = RSG::storage->reflection_probe_renders_shadows(p_instance->base);
if (use_shadows) {
-
shadow_atlas = scenario->reflection_probe_shadow_atlas;
}
RENDER_TIMESTAMP("Render Reflection Probe, Step " + itos(p_step));
- _prepare_scene(xform, cm, false, RID(), RID(), RSG::storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, shadow_atlas, reflection_probe->instance, use_shadows);
+ _prepare_scene(xform, cm, false, false, RID(), RID(), RSG::storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, shadow_atlas, reflection_probe->instance, use_shadows);
_render_scene(RID(), xform, cm, false, RID(), RID(), p_instance->scenario->self, shadow_atlas, reflection_probe->instance, p_step);
} else {
@@ -2337,7 +2338,6 @@ bool RenderingServerScene::_render_reflection_probe_step(Instance *p_instance, i
}
void RenderingServerScene::render_probes() {
-
/* REFLECTION PROBES */
SelfList<InstanceReflectionProbeData> *ref_probe = reflection_probe_render_list.first();
@@ -2345,15 +2345,14 @@ void RenderingServerScene::render_probes() {
bool busy = false;
while (ref_probe) {
-
SelfList<InstanceReflectionProbeData> *next = ref_probe->next();
RID base = ref_probe->self()->owner->base;
switch (RSG::storage->reflection_probe_get_update_mode(base)) {
-
case RS::REFLECTION_PROBE_UPDATE_ONCE: {
- if (busy) //already rendering something
+ if (busy) { //already rendering something
break;
+ }
bool done = _render_reflection_probe_step(ref_probe->self()->owner, ref_probe->self()->render_step);
if (done) {
@@ -2365,7 +2364,6 @@ void RenderingServerScene::render_probes() {
busy = true; //do not render another one of this kind
} break;
case RS::REFLECTION_PROBE_UPDATE_ALWAYS: {
-
int step = 0;
bool done = false;
while (!done) {
@@ -2389,7 +2387,6 @@ void RenderingServerScene::render_probes() {
}
while (gi_probe) {
-
SelfList<InstanceGIProbeData> *next = gi_probe->next();
InstanceGIProbeData *probe = gi_probe->self();
@@ -2400,7 +2397,6 @@ void RenderingServerScene::render_probes() {
bool cache_dirty = false;
int cache_count = 0;
{
-
int light_cache_size = probe->light_cache.size();
const InstanceGIProbeData::LightCache *caches = probe->light_cache.ptr();
const RID *instance_caches = probe->light_instances.ptr();
@@ -2417,7 +2413,6 @@ void RenderingServerScene::render_probes() {
} else if (idx >= light_cache_size) {
cache_dirty = true;
} else {
-
const InstanceGIProbeData::LightCache *cache = &caches[idx];
if (
@@ -2440,7 +2435,6 @@ void RenderingServerScene::render_probes() {
}
for (List<Instance *>::Element *E = probe->owner->scenario->directional_lights.front(); E; E = E->next()) {
-
Instance *instance = E->get();
InstanceLightData *instance_light = (InstanceLightData *)instance->base_data;
if (!instance->visible) {
@@ -2451,7 +2445,6 @@ void RenderingServerScene::render_probes() {
} else if (idx >= light_cache_size) {
cache_dirty = true;
} else {
-
const InstanceGIProbeData::LightCache *cache = &caches[idx];
if (
@@ -2558,7 +2551,6 @@ void RenderingServerScene::render_probes() {
ins->gi_probe_instances.resize(geom->gi_probes.size());
for (List<Instance *>::Element *F = geom->gi_probes.front(); F; F = F->next()) {
-
InstanceGIProbeData *gi_probe2 = static_cast<InstanceGIProbeData *>(F->get()->base_data);
ins->gi_probe_instances.write[l++] = gi_probe2->probe_instance;
@@ -2579,14 +2571,40 @@ void RenderingServerScene::render_probes() {
}
}
-void RenderingServerScene::_update_dirty_instance(Instance *p_instance) {
+void RenderingServerScene::_update_instance_shader_parameters_from_material(Map<StringName, RasterizerScene::InstanceBase::InstanceShaderParameter> &isparams, const Map<StringName, RasterizerScene::InstanceBase::InstanceShaderParameter> &existing_isparams, RID p_material) {
+ List<RasterizerStorage::InstanceShaderParam> plist;
+ RSG::storage->material_get_instance_shader_parameters(p_material, &plist);
+ for (List<RasterizerStorage::InstanceShaderParam>::Element *E = plist.front(); E; E = E->next()) {
+ StringName name = E->get().info.name;
+ if (isparams.has(name)) {
+ if (isparams[name].info.type != E->get().info.type) {
+ WARN_PRINT("More than one material in instance export the same instance shader uniform '" + E->get().info.name + "', but they do it with different data types. Only the first one (in order) will display correctly.");
+ }
+ if (isparams[name].index != E->get().index) {
+ WARN_PRINT("More than one material in instance export the same instance shader uniform '" + E->get().info.name + "', but they do it with different indices. Only the first one (in order) will display correctly.");
+ }
+ continue; //first one found always has priority
+ }
+
+ RasterizerScene::InstanceBase::InstanceShaderParameter isp;
+ isp.index = E->get().index;
+ isp.info = E->get().info;
+ isp.default_value = E->get().default_value;
+ if (existing_isparams.has(name)) {
+ isp.value = existing_isparams[name].value;
+ } else {
+ isp.value = E->get().default_value;
+ }
+ isparams[name] = isp;
+ }
+}
+void RenderingServerScene::_update_dirty_instance(Instance *p_instance) {
if (p_instance->update_aabb) {
_update_instance_aabb(p_instance);
}
if (p_instance->update_dependencies) {
-
p_instance->instance_increase_version();
if (p_instance->base.is_valid()) {
@@ -2613,19 +2631,23 @@ void RenderingServerScene::_update_dirty_instance(Instance *p_instance) {
}
if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
-
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);
bool can_cast_shadows = true;
bool is_animated = false;
+ Map<StringName, RasterizerScene::InstanceBase::InstanceShaderParameter> isparams;
if (p_instance->cast_shadows == RS::SHADOW_CASTING_SETTING_OFF) {
can_cast_shadows = false;
- } else if (p_instance->material_override.is_valid()) {
- can_cast_shadows = RSG::storage->material_casts_shadows(p_instance->material_override);
+ }
+
+ if (p_instance->material_override.is_valid()) {
+ if (!RSG::storage->material_casts_shadows(p_instance->material_override)) {
+ can_cast_shadows = false;
+ }
is_animated = RSG::storage->material_is_animated(p_instance->material_override);
+ _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, p_instance->material_override);
} else {
-
if (p_instance->base_type == RS::INSTANCE_MESH) {
RID mesh = p_instance->base;
@@ -2633,13 +2655,11 @@ void RenderingServerScene::_update_dirty_instance(Instance *p_instance) {
bool cast_shadows = false;
for (int i = 0; i < p_instance->materials.size(); i++) {
-
RID mat = p_instance->materials[i].is_valid() ? p_instance->materials[i] : RSG::storage->mesh_surface_get_material(mesh, i);
if (!mat.is_valid()) {
cast_shadows = true;
} else {
-
if (RSG::storage->material_casts_shadows(mat)) {
cast_shadows = true;
}
@@ -2648,6 +2668,8 @@ void RenderingServerScene::_update_dirty_instance(Instance *p_instance) {
is_animated = true;
}
+ _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat);
+
RSG::storage->material_update_dependency(mat, p_instance);
}
}
@@ -2660,19 +2682,16 @@ void RenderingServerScene::_update_dirty_instance(Instance *p_instance) {
} else if (p_instance->base_type == RS::INSTANCE_MULTIMESH) {
RID mesh = RSG::storage->multimesh_get_mesh(p_instance->base);
if (mesh.is_valid()) {
-
bool cast_shadows = false;
int sc = RSG::storage->mesh_get_surface_count(mesh);
for (int i = 0; i < sc; i++) {
-
RID mat = RSG::storage->mesh_surface_get_material(mesh, i);
if (!mat.is_valid()) {
cast_shadows = true;
} else {
-
if (RSG::storage->material_casts_shadows(mat)) {
cast_shadows = true;
}
@@ -2680,6 +2699,8 @@ void RenderingServerScene::_update_dirty_instance(Instance *p_instance) {
is_animated = true;
}
+ _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat);
+
RSG::storage->material_update_dependency(mat, p_instance);
}
}
@@ -2691,40 +2712,42 @@ void RenderingServerScene::_update_dirty_instance(Instance *p_instance) {
RSG::storage->base_update_dependency(mesh, p_instance);
}
} else if (p_instance->base_type == RS::INSTANCE_IMMEDIATE) {
-
RID mat = RSG::storage->immediate_get_material(p_instance->base);
- can_cast_shadows = !mat.is_valid() || RSG::storage->material_casts_shadows(mat);
+ if (!(!mat.is_valid() || RSG::storage->material_casts_shadows(mat))) {
+ can_cast_shadows = false;
+ }
if (mat.is_valid() && RSG::storage->material_is_animated(mat)) {
is_animated = true;
}
if (mat.is_valid()) {
+ _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat);
+ }
+
+ if (mat.is_valid()) {
RSG::storage->material_update_dependency(mat, p_instance);
}
} else if (p_instance->base_type == RS::INSTANCE_PARTICLES) {
-
bool cast_shadows = false;
int dp = RSG::storage->particles_get_draw_passes(p_instance->base);
for (int i = 0; i < dp; i++) {
-
RID mesh = RSG::storage->particles_get_draw_pass_mesh(p_instance->base, i);
- if (!mesh.is_valid())
+ if (!mesh.is_valid()) {
continue;
+ }
int sc = RSG::storage->mesh_get_surface_count(mesh);
for (int j = 0; j < sc; j++) {
-
RID mat = RSG::storage->mesh_surface_get_material(mesh, j);
if (!mat.is_valid()) {
cast_shadows = true;
} else {
-
if (RSG::storage->material_casts_shadows(mat)) {
cast_shadows = true;
}
@@ -2733,6 +2756,8 @@ void RenderingServerScene::_update_dirty_instance(Instance *p_instance) {
is_animated = true;
}
+ _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat);
+
RSG::storage->material_update_dependency(mat, p_instance);
}
}
@@ -2755,6 +2780,22 @@ void RenderingServerScene::_update_dirty_instance(Instance *p_instance) {
}
geom->material_is_animated = is_animated;
+ p_instance->instance_shader_parameters = isparams;
+
+ if (p_instance->instance_allocated_shader_parameters != (p_instance->instance_shader_parameters.size() > 0)) {
+ p_instance->instance_allocated_shader_parameters = (p_instance->instance_shader_parameters.size() > 0);
+ if (p_instance->instance_allocated_shader_parameters) {
+ p_instance->instance_allocated_shader_parameters_offset = RSG::storage->global_variables_instance_allocate(p_instance->self);
+ for (Map<StringName, RasterizerScene::InstanceBase::InstanceShaderParameter>::Element *E = p_instance->instance_shader_parameters.front(); E; E = E->next()) {
+ if (E->get().value.get_type() != Variant::NIL) {
+ RSG::storage->global_variables_instance_update(p_instance->self, E->get().index, E->get().value);
+ }
+ }
+ } else {
+ RSG::storage->global_variables_instance_free(p_instance->self);
+ p_instance->instance_allocated_shader_parameters_offset = -1;
+ }
+ }
}
if (p_instance->skeleton.is_valid()) {
@@ -2773,26 +2814,21 @@ void RenderingServerScene::_update_dirty_instance(Instance *p_instance) {
}
void RenderingServerScene::update_dirty_instances() {
-
RSG::storage->update_dirty_resources();
while (_instance_update_list.first()) {
-
_update_dirty_instance(_instance_update_list.first()->self());
}
}
bool RenderingServerScene::free(RID p_rid) {
-
if (camera_owner.owns(p_rid)) {
-
Camera *camera = camera_owner.getornull(p_rid);
camera_owner.free(p_rid);
memdelete(camera);
} else if (scenario_owner.owns(p_rid)) {
-
Scenario *scenario = scenario_owner.getornull(p_rid);
while (scenario->instances.first()) {
@@ -2810,12 +2846,16 @@ bool RenderingServerScene::free(RID p_rid) {
Instance *instance = instance_owner.getornull(p_rid);
- instance_set_use_lightmap(p_rid, RID(), RID());
+ instance_geometry_set_lightmap(p_rid, RID(), Rect2(), 0);
instance_set_scenario(p_rid, RID());
instance_set_base(p_rid, RID());
instance_geometry_set_material_override(p_rid, RID());
instance_attach_skeleton(p_rid, RID());
+ if (instance->instance_allocated_shader_parameters) {
+ //free the used shader parameters
+ RSG::storage->global_variables_instance_free(instance->self);
+ }
update_dirty_instances(); //in case something changed this
instance_owner.free(p_rid);
@@ -2827,10 +2867,13 @@ bool RenderingServerScene::free(RID p_rid) {
return true;
}
-RenderingServerScene *RenderingServerScene::singleton = NULL;
+TypedArray<Image> RenderingServerScene::bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) {
+ return RSG::scene_render->bake_render_uv2(p_base, p_material_overrides, p_image_size);
+}
-RenderingServerScene::RenderingServerScene() {
+RenderingServerScene *RenderingServerScene::singleton = nullptr;
+RenderingServerScene::RenderingServerScene() {
render_pass = 1;
singleton = this;
}
diff --git a/servers/rendering/rendering_server_scene.h b/servers/rendering/rendering_server_scene.h
index 9e09136216..f2e2918f21 100644
--- a/servers/rendering/rendering_server_scene.h
+++ b/servers/rendering/rendering_server_scene.h
@@ -33,13 +33,12 @@
#include "servers/rendering/rasterizer.h"
-#include "core/math/geometry.h"
#include "core/math/octree.h"
#include "core/os/semaphore.h"
#include "core/os/thread.h"
#include "core/rid_owner.h"
#include "core/self_list.h"
-#include "servers/arvr/arvr_interface.h"
+#include "servers/xr/xr_interface.h"
class RenderingServerScene {
public:
@@ -48,8 +47,10 @@ public:
MAX_INSTANCE_CULL = 65536,
MAX_LIGHTS_CULLED = 4096,
MAX_REFLECTION_PROBES_CULLED = 4096,
+ MAX_DECALS_CULLED = 4096,
MAX_GI_PROBES_CULLED = 4096,
MAX_ROOM_CULL = 32,
+ MAX_LIGHTMAPS_CULLED = 4096,
MAX_EXTERIOR_PORTALS = 128,
};
@@ -60,7 +61,6 @@ public:
/* CAMERA API */
struct Camera {
-
enum Type {
PERSPECTIVE,
ORTHOGONAL,
@@ -79,9 +79,8 @@ public:
Transform transform;
Camera() {
-
visible_layers = 0xFFFFFFFF;
- fov = 70;
+ fov = 75;
type = PERSPECTIVE;
znear = 0.05;
zfar = 100;
@@ -108,7 +107,6 @@ public:
struct Instance;
struct Scenario {
-
RS::ScenarioDebugMode debug;
RID self;
@@ -142,12 +140,10 @@ public:
/* INSTANCING API */
struct InstanceBaseData {
-
virtual ~InstanceBaseData() {}
};
struct Instance : RasterizerScene::InstanceBase {
-
RID self;
//scenario stuff
OctreeElementID octree_id;
@@ -170,6 +166,8 @@ public:
float lod_end_hysteresis;
RID lod_instance;
+ Vector<Color> lightmap_target_sh; //target is used for incrementally changing the SH over time, this avoids pops in some corner cases and when going interior <-> exterior
+
uint64_t last_render_pass;
uint64_t last_frame_pass;
@@ -194,9 +192,8 @@ public:
Instance() :
scenario_item(this),
update_item(this) {
-
octree_id = 0;
- scenario = NULL;
+ scenario = nullptr;
update_aabb = false;
update_dependencies = false;
@@ -213,17 +210,18 @@ public:
last_render_pass = 0;
last_frame_pass = 0;
version = 1;
- base_data = NULL;
+ base_data = nullptr;
- custom_aabb = NULL;
+ custom_aabb = nullptr;
}
~Instance() {
-
- if (base_data)
+ if (base_data) {
memdelete(base_data);
- if (custom_aabb)
+ }
+ if (custom_aabb) {
memdelete(custom_aabb);
+ }
}
};
@@ -231,12 +229,14 @@ public:
void _instance_queue_update(Instance *p_instance, bool p_update_aabb, bool p_update_dependencies = false);
struct InstanceGeometryData : public InstanceBaseData {
-
List<Instance *> lighting;
bool lighting_dirty;
bool can_cast_shadows;
bool material_is_animated;
+ List<Instance *> decals;
+ bool decal_dirty;
+
List<Instance *> reflection_probes;
bool reflection_dirty;
@@ -246,17 +246,16 @@ public:
List<Instance *> lightmap_captures;
InstanceGeometryData() {
-
lighting_dirty = false;
reflection_dirty = true;
can_cast_shadows = true;
material_is_animated = true;
gi_probes_dirty = true;
+ decal_dirty = true;
}
};
struct InstanceReflectionProbeData : public InstanceBaseData {
-
Instance *owner;
struct PairInfo {
@@ -273,16 +272,28 @@ public:
InstanceReflectionProbeData() :
update_list(this) {
-
reflection_dirty = true;
render_step = -1;
}
};
+ struct InstanceDecalData : public InstanceBaseData {
+ Instance *owner;
+ RID instance;
+
+ struct PairInfo {
+ List<Instance *>::Element *L; //reflection iterator in geometry
+ Instance *geometry;
+ };
+ List<PairInfo> geometries;
+
+ InstanceDecalData() {
+ }
+ };
+
SelfList<InstanceReflectionProbeData>::List reflection_probe_render_list;
struct InstanceLightData : public InstanceBaseData {
-
struct PairInfo {
List<Instance *>::Element *L; //light iterator in geometry
Instance *geometry;
@@ -299,16 +310,14 @@ public:
Instance *baked_light;
InstanceLightData() {
-
shadow_dirty = true;
- D = NULL;
+ D = nullptr;
last_version = 0;
- baked_light = NULL;
+ baked_light = nullptr;
}
};
struct InstanceGIProbeData : public InstanceBaseData {
-
Instance *owner;
struct PairInfo {
@@ -322,7 +331,6 @@ public:
Set<Instance *> lights;
struct LightCache {
-
RS::LightType type;
Transform transform;
Color color;
@@ -354,8 +362,7 @@ public:
SelfList<InstanceGIProbeData>::List gi_probe_update_list;
- struct InstanceLightmapCaptureData : public InstanceBaseData {
-
+ struct InstanceLightmapData : public InstanceBaseData {
struct PairInfo {
List<Instance *>::Element *L; //iterator in geometry
Instance *geometry;
@@ -364,7 +371,7 @@ public:
Set<Instance *> users;
- InstanceLightmapCaptureData() {
+ InstanceLightmapData() {
}
};
@@ -376,9 +383,13 @@ public:
int light_cull_count;
int directional_light_count;
RID reflection_probe_instance_cull_result[MAX_REFLECTION_PROBES_CULLED];
+ RID decal_instance_cull_result[MAX_DECALS_CULLED];
int reflection_probe_cull_count;
+ int decal_cull_count;
RID gi_probe_instance_cull_result[MAX_GI_PROBES_CULLED];
int gi_probe_cull_count;
+ Instance *lightmap_cull_result[MAX_LIGHTS_CULLED];
+ int lightmap_cull_count;
RID_PtrOwner<Instance> instance_owner;
@@ -392,7 +403,6 @@ public:
virtual void instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight);
virtual void instance_set_surface_material(RID p_instance, int p_surface, RID p_material);
virtual void instance_set_visible(RID p_instance, bool p_visible);
- virtual void instance_set_use_lightmap(RID p_instance, RID p_lightmap_instance, RID p_lightmap);
virtual void instance_set_custom_aabb(RID p_instance, AABB p_aabb);
@@ -412,25 +422,35 @@ public:
virtual void instance_geometry_set_draw_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin);
virtual void instance_geometry_set_as_instance_lod(RID p_instance, RID p_as_lod_of_instance);
+ virtual void instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_slice_index);
+
+ void _update_instance_shader_parameters_from_material(Map<StringName, RasterizerScene::InstanceBase::InstanceShaderParameter> &isparams, const Map<StringName, RasterizerScene::InstanceBase::InstanceShaderParameter> &existing_isparams, RID p_material);
+
+ virtual void instance_geometry_set_shader_parameter(RID p_instance, const StringName &p_parameter, const Variant &p_value);
+ virtual void instance_geometry_get_shader_parameter_list(RID p_instance, List<PropertyInfo> *p_parameters) const;
+ virtual Variant instance_geometry_get_shader_parameter(RID p_instance, const StringName &p_parameter) const;
+ virtual Variant instance_geometry_get_shader_parameter_default_value(RID p_instance, const StringName &p_parameter) const;
_FORCE_INLINE_ void _update_instance(Instance *p_instance);
_FORCE_INLINE_ void _update_instance_aabb(Instance *p_instance);
_FORCE_INLINE_ void _update_dirty_instance(Instance *p_instance);
_FORCE_INLINE_ void _update_instance_lightmap_captures(Instance *p_instance);
- _FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_shadow_atlas, Scenario *p_scenario);
+ _FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario);
bool _render_reflection_probe_step(Instance *p_instance, int p_step);
- void _prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, RID p_force_camera_effects, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, bool p_using_shadows = true);
+ void _prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_force_environment, RID p_force_camera_effects, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, bool p_using_shadows = true);
void _render_scene(RID p_render_buffers, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, RID p_force_camera_effects, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
void render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas);
void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas);
- void render_camera(RID p_render_buffers, Ref<ARVRInterface> &p_interface, ARVRInterface::Eyes p_eye, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas);
+ void render_camera(RID p_render_buffers, Ref<XRInterface> &p_interface, XRInterface::Eyes p_eye, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas);
void update_dirty_instances();
void render_probes();
+ TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size);
+
bool free(RID p_rid);
RenderingServerScene();
diff --git a/servers/rendering/rendering_server_viewport.cpp b/servers/rendering/rendering_server_viewport.cpp
index f80b914760..48be6ca13b 100644
--- a/servers/rendering/rendering_server_viewport.cpp
+++ b/servers/rendering/rendering_server_viewport.cpp
@@ -36,7 +36,6 @@
#include "rendering_server_scene.h"
static Transform2D _canvas_get_transform(RenderingServerViewport::Viewport *p_viewport, RenderingServerCanvas::Canvas *p_canvas, RenderingServerViewport::Viewport::CanvasData *p_canvas_data, const Vector2 &p_vp_size) {
-
Transform2D xf = p_viewport->global_transform;
float scale = 1.0;
@@ -62,24 +61,28 @@ static Transform2D _canvas_get_transform(RenderingServerViewport::Viewport *p_vi
return xf;
}
-void RenderingServerViewport::_draw_3d(Viewport *p_viewport, ARVRInterface::Eyes p_eye) {
-
+void RenderingServerViewport::_draw_3d(Viewport *p_viewport, XRInterface::Eyes p_eye) {
RENDER_TIMESTAMP(">Begin Rendering 3D Scene");
- Ref<ARVRInterface> arvr_interface;
- if (ARVRServer::get_singleton() != NULL) {
- arvr_interface = ARVRServer::get_singleton()->get_primary_interface();
+ Ref<XRInterface> xr_interface;
+ if (XRServer::get_singleton() != nullptr) {
+ xr_interface = XRServer::get_singleton()->get_primary_interface();
}
- if (p_viewport->use_arvr && arvr_interface.is_valid()) {
- RSG::scene->render_camera(p_viewport->render_buffers, arvr_interface, p_eye, p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
+ if (p_viewport->use_xr && xr_interface.is_valid()) {
+ RSG::scene->render_camera(p_viewport->render_buffers, xr_interface, p_eye, p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
} else {
RSG::scene->render_camera(p_viewport->render_buffers, p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
}
RENDER_TIMESTAMP("<End Rendering 3D Scene");
}
-void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::Eyes p_eye) {
+void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface::Eyes p_eye) {
+ if (p_viewport->measure_render_time) {
+ String rt_id = "vp_begin_" + itos(p_viewport->self.get_id());
+ RSG::storage->capture_timestamp(rt_id);
+ timestamp_vp_map[rt_id] = p_viewport->self;
+ }
/* Camera should always be BEFORE any other 3D */
@@ -89,7 +92,6 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface
Color bgcolor = RSG::storage->get_default_clear_color();
if (!p_viewport->hide_canvas && !p_viewport->disable_environment && RSG::scene->scenario_owner.owns(p_viewport->scenario)) {
-
RenderingServerScene::Scenario *scenario = RSG::scene->scenario_owner.getornull(p_viewport->scenario);
ERR_FAIL_COND(!scenario);
if (RSG::scene_render->is_environment(scenario->environment)) {
@@ -113,7 +115,7 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface
if ((scenario_draw_canvas_bg || can_draw_3d) && !p_viewport->render_buffers.is_valid()) {
//wants to draw 3D but there is no render buffer, create
p_viewport->render_buffers = RSG::scene_render->render_buffers_create();
- RSG::scene_render->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, p_viewport->size.width, p_viewport->size.height, p_viewport->msaa);
+ RSG::scene_render->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, p_viewport->size.width, p_viewport->size.height, p_viewport->msaa, p_viewport->screen_space_aa);
}
RSG::storage->render_target_request_clear(p_viewport->render_target, bgcolor);
@@ -128,16 +130,15 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface
Map<Viewport::CanvasKey, Viewport::CanvasData *> canvas_map;
Rect2 clip_rect(0, 0, p_viewport->size.x, p_viewport->size.y);
- RasterizerCanvas::Light *lights = NULL;
- RasterizerCanvas::Light *lights_with_shadow = NULL;
- RasterizerCanvas::Light *lights_with_mask = NULL;
+ RasterizerCanvas::Light *lights = nullptr;
+ RasterizerCanvas::Light *lights_with_shadow = nullptr;
+ RasterizerCanvas::Light *lights_with_mask = nullptr;
Rect2 shadow_rect;
int light_count = 0;
RENDER_TIMESTAMP("Cull Canvas Lights");
for (Map<RID, Viewport::CanvasData>::Element *E = p_viewport->canvas_map.front(); E; E = E->next()) {
-
RenderingServerCanvas::Canvas *canvas = static_cast<RenderingServerCanvas::Canvas *>(E->get().canvas);
Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E->get(), clip_rect.size);
@@ -145,7 +146,6 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface
//find lights in canvas
for (Set<RasterizerCanvas::Light *>::Element *F = canvas->lights.front(); F; F = F->next()) {
-
RasterizerCanvas::Light *cl = F->get();
if (cl->enabled && cl->texture.is_valid()) {
//not super efficient..
@@ -157,19 +157,17 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface
cl->xform_cache = xf * cl->xform;
if (clip_rect.intersects_transformed(cl->xform_cache, cl->rect_cache)) {
-
cl->filter_next_ptr = lights;
lights = cl;
- // cl->texture_cache = NULL;
+ // cl->texture_cache = nullptr;
Transform2D scale;
scale.scale(cl->rect_cache.size);
scale.elements[2] = cl->rect_cache.position;
cl->light_shader_xform = cl->xform * scale;
//cl->light_shader_pos = cl->xform_cache[2];
if (cl->use_shadow) {
-
cl->shadows_next_ptr = lights_with_shadow;
- if (lights_with_shadow == NULL) {
+ if (lights_with_shadow == nullptr) {
shadow_rect = cl->xform_cache.xform(cl->rect_cache);
} else {
shadow_rect = shadow_rect.merge(cl->xform_cache.xform(cl->rect_cache));
@@ -196,24 +194,22 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface
if (lights_with_shadow) {
//update shadows if any
- RasterizerCanvas::LightOccluderInstance *occluders = NULL;
+ RasterizerCanvas::LightOccluderInstance *occluders = nullptr;
RENDER_TIMESTAMP(">Render 2D Shadows");
RENDER_TIMESTAMP("Cull Occluders");
//make list of occluders
for (Map<RID, Viewport::CanvasData>::Element *E = p_viewport->canvas_map.front(); E; E = E->next()) {
-
RenderingServerCanvas::Canvas *canvas = static_cast<RenderingServerCanvas::Canvas *>(E->get().canvas);
Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E->get(), clip_rect.size);
for (Set<RasterizerCanvas::LightOccluderInstance *>::Element *F = canvas->occluders.front(); F; F = F->next()) {
-
- if (!F->get()->enabled)
+ if (!F->get()->enabled) {
continue;
+ }
F->get()->xform_cache = xf * F->get()->xform;
if (shadow_rect.intersects_transformed(F->get()->xform_cache, F->get()->aabb_cache)) {
-
F->get()->next = occluders;
occluders = F->get();
}
@@ -223,7 +219,6 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface
RasterizerCanvas::Light *light = lights_with_shadow;
while (light) {
-
RENDER_TIMESTAMP("Render Shadow");
RSG::canvas_render->light_update_shadow(light->light_internal, light->xform_cache.affine_inverse(), light->item_shadow_mask, light->radius_cache / 1000.0, light->radius_cache * 1.1, occluders);
@@ -244,12 +239,11 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface
}
for (Map<Viewport::CanvasKey, Viewport::CanvasData *>::Element *E = canvas_map.front(); E; E = E->next()) {
-
RenderingServerCanvas::Canvas *canvas = static_cast<RenderingServerCanvas::Canvas *>(E->get()->canvas);
Transform2D xform = _canvas_get_transform(p_viewport, canvas, E->get(), clip_rect.size);
- RasterizerCanvas::Light *canvas_lights = NULL;
+ RasterizerCanvas::Light *canvas_lights = nullptr;
RasterizerCanvas::Light *ptr = lights;
while (ptr) {
@@ -289,21 +283,26 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface
//was never cleared in the end, force clear it
RSG::storage->render_target_do_clear_request(p_viewport->render_target);
}
+
+ if (p_viewport->measure_render_time) {
+ String rt_id = "vp_end_" + itos(p_viewport->self.get_id());
+ RSG::storage->capture_timestamp(rt_id);
+ timestamp_vp_map[rt_id] = p_viewport->self;
+ }
}
void RenderingServerViewport::draw_viewports() {
+ timestamp_vp_map.clear();
-#if 0
- // get our arvr interface in case we need it
- Ref<ARVRInterface> arvr_interface;
+ // get our xr interface in case we need it
+ Ref<XRInterface> xr_interface;
- if (ARVRServer::get_singleton() != NULL) {
- arvr_interface = ARVRServer::get_singleton()->get_primary_interface();
+ if (XRServer::get_singleton() != nullptr) {
+ xr_interface = XRServer::get_singleton()->get_primary_interface();
// process all our active interfaces
- ARVRServer::get_singleton()->_process();
+ XRServer::get_singleton()->_process();
}
-#endif
if (Engine::get_singleton()->is_editor_hint()) {
set_default_clear_color(GLOBAL_GET("rendering/environment/default_clear_color"));
@@ -323,8 +322,9 @@ void RenderingServerViewport::draw_viewports() {
Viewport *vp = active_viewports[i];
- if (vp->update_mode == RS::VIEWPORT_UPDATE_DISABLED)
+ if (vp->update_mode == RS::VIEWPORT_UPDATE_DISABLED) {
continue;
+ }
if (!vp->render_target.is_valid()) {
continue;
@@ -356,7 +356,6 @@ void RenderingServerViewport::draw_viewports() {
}
for (int i = 0; i < active_viewports.size(); i++) {
-
Viewport *vp = active_viewports[i];
if (vp->last_pass != draw_viewports_pass) {
@@ -367,38 +366,41 @@ void RenderingServerViewport::draw_viewports() {
RSG::storage->render_target_set_as_unused(vp->render_target);
#if 0
- if (vp->use_arvr && arvr_interface.is_valid()) {
+ // TODO fix up this code after we change our commit_for_eye to accept our new render targets
+
+ if (vp->use_xr && xr_interface.is_valid()) {
// override our size, make sure it matches our required size
- vp->size = arvr_interface->get_render_targetsize();
+ vp->size = xr_interface->get_render_targetsize();
RSG::storage->render_target_set_size(vp->render_target, vp->size.x, vp->size.y);
// render mono or left eye first
- ARVRInterface::Eyes leftOrMono = arvr_interface->is_stereo() ? ARVRInterface::EYE_LEFT : ARVRInterface::EYE_MONO;
+ XRInterface::Eyes leftOrMono = xr_interface->is_stereo() ? XRInterface::EYE_LEFT : XRInterface::EYE_MONO;
// check for an external texture destination for our left eye/mono
- RSG::storage->render_target_set_external_texture(vp->render_target, arvr_interface->get_external_texture_for_eye(leftOrMono));
+ // TODO investigate how we're going to make external textures work
+ RSG::storage->render_target_set_external_texture(vp->render_target, xr_interface->get_external_texture_for_eye(leftOrMono));
// set our render target as current
RSG::rasterizer->set_current_render_target(vp->render_target);
// and draw left eye/mono
_draw_viewport(vp, leftOrMono);
- arvr_interface->commit_for_eye(leftOrMono, vp->render_target, vp->viewport_to_screen_rect);
+ xr_interface->commit_for_eye(leftOrMono, vp->render_target, vp->viewport_to_screen_rect);
// render right eye
- if (leftOrMono == ARVRInterface::EYE_LEFT) {
+ if (leftOrMono == XRInterface::EYE_LEFT) {
// check for an external texture destination for our right eye
- RSG::storage->render_target_set_external_texture(vp->render_target, arvr_interface->get_external_texture_for_eye(ARVRInterface::EYE_RIGHT));
+ RSG::storage->render_target_set_external_texture(vp->render_target, xr_interface->get_external_texture_for_eye(XRInterface::EYE_RIGHT));
// commit for eye may have changed the render target
RSG::rasterizer->set_current_render_target(vp->render_target);
- _draw_viewport(vp, ARVRInterface::EYE_RIGHT);
- arvr_interface->commit_for_eye(ARVRInterface::EYE_RIGHT, vp->render_target, vp->viewport_to_screen_rect);
+ _draw_viewport(vp, XRInterface::EYE_RIGHT);
+ xr_interface->commit_for_eye(XRInterface::EYE_RIGHT, vp->render_target, vp->viewport_to_screen_rect);
}
// and for our frame timing, mark when we've finished committing our eyes
- ARVRServer::get_singleton()->_mark_commit();
+ XRServer::get_singleton()->_mark_commit();
} else {
#endif
{
@@ -455,7 +457,6 @@ void RenderingServerViewport::draw_viewports() {
}
RID RenderingServerViewport::viewport_create() {
-
Viewport *viewport = memnew(Viewport);
RID rid = viewport_owner.make_rid(viewport);
@@ -470,15 +471,14 @@ RID RenderingServerViewport::viewport_create() {
return rid;
}
-void RenderingServerViewport::viewport_set_use_arvr(RID p_viewport, bool p_use_arvr) {
+void RenderingServerViewport::viewport_set_use_xr(RID p_viewport, bool p_use_xr) {
Viewport *viewport = viewport_owner.getornull(p_viewport);
ERR_FAIL_COND(!viewport);
- viewport->use_arvr = p_use_arvr;
+ viewport->use_xr = p_use_xr;
}
void RenderingServerViewport::viewport_set_size(RID p_viewport, int p_width, int p_height) {
-
ERR_FAIL_COND(p_width < 0 && p_height < 0);
Viewport *viewport = viewport_owner.getornull(p_viewport);
@@ -491,13 +491,12 @@ void RenderingServerViewport::viewport_set_size(RID p_viewport, int p_width, int
RSG::scene_render->free(viewport->render_buffers);
viewport->render_buffers = RID();
} else {
- RSG::scene_render->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa);
+ RSG::scene_render->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, viewport->screen_space_aa);
}
}
}
void RenderingServerViewport::viewport_set_active(RID p_viewport, bool p_active) {
-
Viewport *viewport = viewport_owner.getornull(p_viewport);
ERR_FAIL_COND(!viewport);
@@ -510,7 +509,6 @@ void RenderingServerViewport::viewport_set_active(RID p_viewport, bool p_active)
}
void RenderingServerViewport::viewport_set_parent_viewport(RID p_viewport, RID p_parent_viewport) {
-
Viewport *viewport = viewport_owner.getornull(p_viewport);
ERR_FAIL_COND(!viewport);
@@ -518,7 +516,6 @@ void RenderingServerViewport::viewport_set_parent_viewport(RID p_viewport, RID p
}
void RenderingServerViewport::viewport_set_clear_mode(RID p_viewport, RS::ViewportClearMode p_clear_mode) {
-
Viewport *viewport = viewport_owner.getornull(p_viewport);
ERR_FAIL_COND(!viewport);
@@ -526,7 +523,6 @@ void RenderingServerViewport::viewport_set_clear_mode(RID p_viewport, RS::Viewpo
}
void RenderingServerViewport::viewport_attach_to_screen(RID p_viewport, const Rect2 &p_rect, DisplayServer::WindowID p_screen) {
-
Viewport *viewport = viewport_owner.getornull(p_viewport);
ERR_FAIL_COND(!viewport);
@@ -534,7 +530,6 @@ void RenderingServerViewport::viewport_attach_to_screen(RID p_viewport, const Re
// If using GLES2 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);
RSG::storage->render_target_set_position(viewport->render_target, p_rect.position.x, p_rect.position.y);
}
@@ -542,10 +537,8 @@ void RenderingServerViewport::viewport_attach_to_screen(RID p_viewport, const Re
viewport->viewport_to_screen_rect = p_rect;
viewport->viewport_to_screen = p_screen;
} else {
-
// 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);
}
@@ -559,12 +552,12 @@ void RenderingServerViewport::viewport_set_render_direct_to_screen(RID p_viewpor
Viewport *viewport = viewport_owner.getornull(p_viewport);
ERR_FAIL_COND(!viewport);
- if (p_enable == viewport->viewport_render_direct_to_screen)
+ if (p_enable == viewport->viewport_render_direct_to_screen) {
return;
+ }
// if disabled, reset render_target size and position
if (!p_enable) {
-
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);
}
@@ -574,14 +567,12 @@ void RenderingServerViewport::viewport_set_render_direct_to_screen(RID p_viewpor
// if attached to screen already, setup screen size and position, this needs to happen after setting flag to avoid an unnecessary buffer allocation
if (RSG::rasterizer->is_low_end() && viewport->viewport_to_screen_rect != Rect2() && p_enable) {
-
RSG::storage->render_target_set_size(viewport->render_target, viewport->viewport_to_screen_rect.size.x, viewport->viewport_to_screen_rect.size.y);
RSG::storage->render_target_set_position(viewport->render_target, viewport->viewport_to_screen_rect.position.x, viewport->viewport_to_screen_rect.position.y);
}
}
void RenderingServerViewport::viewport_set_update_mode(RID p_viewport, RS::ViewportUpdateMode p_mode) {
-
Viewport *viewport = viewport_owner.getornull(p_viewport);
ERR_FAIL_COND(!viewport);
@@ -589,7 +580,6 @@ void RenderingServerViewport::viewport_set_update_mode(RID p_viewport, RS::Viewp
}
RID RenderingServerViewport::viewport_get_texture(RID p_viewport) const {
-
const Viewport *viewport = viewport_owner.getornull(p_viewport);
ERR_FAIL_COND_V(!viewport, RID());
@@ -597,21 +587,20 @@ RID RenderingServerViewport::viewport_get_texture(RID p_viewport) const {
}
void RenderingServerViewport::viewport_set_hide_scenario(RID p_viewport, bool p_hide) {
-
Viewport *viewport = viewport_owner.getornull(p_viewport);
ERR_FAIL_COND(!viewport);
viewport->hide_scenario = p_hide;
}
-void RenderingServerViewport::viewport_set_hide_canvas(RID p_viewport, bool p_hide) {
+void RenderingServerViewport::viewport_set_hide_canvas(RID p_viewport, bool p_hide) {
Viewport *viewport = viewport_owner.getornull(p_viewport);
ERR_FAIL_COND(!viewport);
viewport->hide_canvas = p_hide;
}
-void RenderingServerViewport::viewport_set_disable_environment(RID p_viewport, bool p_disable) {
+void RenderingServerViewport::viewport_set_disable_environment(RID p_viewport, bool p_disable) {
Viewport *viewport = viewport_owner.getornull(p_viewport);
ERR_FAIL_COND(!viewport);
@@ -619,21 +608,20 @@ void RenderingServerViewport::viewport_set_disable_environment(RID p_viewport, b
}
void RenderingServerViewport::viewport_attach_camera(RID p_viewport, RID p_camera) {
-
Viewport *viewport = viewport_owner.getornull(p_viewport);
ERR_FAIL_COND(!viewport);
viewport->camera = p_camera;
}
-void RenderingServerViewport::viewport_set_scenario(RID p_viewport, RID p_scenario) {
+void RenderingServerViewport::viewport_set_scenario(RID p_viewport, RID p_scenario) {
Viewport *viewport = viewport_owner.getornull(p_viewport);
ERR_FAIL_COND(!viewport);
viewport->scenario = p_scenario;
}
-void RenderingServerViewport::viewport_attach_canvas(RID p_viewport, RID p_canvas) {
+void RenderingServerViewport::viewport_attach_canvas(RID p_viewport, RID p_canvas) {
Viewport *viewport = viewport_owner.getornull(p_viewport);
ERR_FAIL_COND(!viewport);
@@ -649,7 +637,6 @@ void RenderingServerViewport::viewport_attach_canvas(RID p_viewport, RID p_canva
}
void RenderingServerViewport::viewport_remove_canvas(RID p_viewport, RID p_canvas) {
-
Viewport *viewport = viewport_owner.getornull(p_viewport);
ERR_FAIL_COND(!viewport);
@@ -659,16 +646,16 @@ void RenderingServerViewport::viewport_remove_canvas(RID p_viewport, RID p_canva
viewport->canvas_map.erase(p_canvas);
canvas->viewports.erase(p_viewport);
}
-void RenderingServerViewport::viewport_set_canvas_transform(RID p_viewport, RID p_canvas, const Transform2D &p_offset) {
+void RenderingServerViewport::viewport_set_canvas_transform(RID p_viewport, RID p_canvas, const Transform2D &p_offset) {
Viewport *viewport = viewport_owner.getornull(p_viewport);
ERR_FAIL_COND(!viewport);
ERR_FAIL_COND(!viewport->canvas_map.has(p_canvas));
viewport->canvas_map[p_canvas].transform = p_offset;
}
-void RenderingServerViewport::viewport_set_transparent_background(RID p_viewport, bool p_enabled) {
+void RenderingServerViewport::viewport_set_transparent_background(RID p_viewport, bool p_enabled) {
Viewport *viewport = viewport_owner.getornull(p_viewport);
ERR_FAIL_COND(!viewport);
@@ -677,14 +664,13 @@ void RenderingServerViewport::viewport_set_transparent_background(RID p_viewport
}
void RenderingServerViewport::viewport_set_global_canvas_transform(RID p_viewport, const Transform2D &p_transform) {
-
Viewport *viewport = viewport_owner.getornull(p_viewport);
ERR_FAIL_COND(!viewport);
viewport->global_transform = p_transform;
}
-void RenderingServerViewport::viewport_set_canvas_stacking(RID p_viewport, RID p_canvas, int p_layer, int p_sublayer) {
+void RenderingServerViewport::viewport_set_canvas_stacking(RID p_viewport, RID p_canvas, int p_layer, int p_sublayer) {
Viewport *viewport = viewport_owner.getornull(p_viewport);
ERR_FAIL_COND(!viewport);
@@ -694,7 +680,6 @@ void RenderingServerViewport::viewport_set_canvas_stacking(RID p_viewport, RID p
}
void RenderingServerViewport::viewport_set_shadow_atlas_size(RID p_viewport, int p_size) {
-
Viewport *viewport = viewport_owner.getornull(p_viewport);
ERR_FAIL_COND(!viewport);
@@ -704,7 +689,6 @@ void RenderingServerViewport::viewport_set_shadow_atlas_size(RID p_viewport, int
}
void RenderingServerViewport::viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv) {
-
Viewport *viewport = viewport_owner.getornull(p_viewport);
ERR_FAIL_COND(!viewport);
@@ -712,7 +696,6 @@ void RenderingServerViewport::viewport_set_shadow_atlas_quadrant_subdivision(RID
}
void RenderingServerViewport::viewport_set_msaa(RID p_viewport, RS::ViewportMSAA p_msaa) {
-
Viewport *viewport = viewport_owner.getornull(p_viewport);
ERR_FAIL_COND(!viewport);
@@ -721,33 +704,64 @@ void RenderingServerViewport::viewport_set_msaa(RID p_viewport, RS::ViewportMSAA
}
viewport->msaa = p_msaa;
if (viewport->render_buffers.is_valid()) {
- RSG::scene_render->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, p_msaa);
+ RSG::scene_render->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, p_msaa, viewport->screen_space_aa);
}
}
-int RenderingServerViewport::viewport_get_render_info(RID p_viewport, RS::ViewportRenderInfo p_info) {
+void RenderingServerViewport::viewport_set_screen_space_aa(RID p_viewport, RS::ViewportScreenSpaceAA p_mode) {
+ Viewport *viewport = viewport_owner.getornull(p_viewport);
+ ERR_FAIL_COND(!viewport);
+ if (viewport->screen_space_aa == p_mode) {
+ return;
+ }
+ viewport->screen_space_aa = p_mode;
+ if (viewport->render_buffers.is_valid()) {
+ RSG::scene_render->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, p_mode);
+ }
+}
+
+int RenderingServerViewport::viewport_get_render_info(RID p_viewport, RS::ViewportRenderInfo p_info) {
ERR_FAIL_INDEX_V(p_info, RS::VIEWPORT_RENDER_INFO_MAX, -1);
Viewport *viewport = viewport_owner.getornull(p_viewport);
- if (!viewport)
+ if (!viewport) {
return 0; //there should be a lock here..
+ }
return viewport->render_info[p_info];
}
void RenderingServerViewport::viewport_set_debug_draw(RID p_viewport, RS::ViewportDebugDraw p_draw) {
-
Viewport *viewport = viewport_owner.getornull(p_viewport);
ERR_FAIL_COND(!viewport);
viewport->debug_draw = p_draw;
}
-bool RenderingServerViewport::free(RID p_rid) {
+void RenderingServerViewport::viewport_set_measure_render_time(RID p_viewport, bool p_enable) {
+ Viewport *viewport = viewport_owner.getornull(p_viewport);
+ ERR_FAIL_COND(!viewport);
- if (viewport_owner.owns(p_rid)) {
+ viewport->measure_render_time = p_enable;
+}
+
+float RenderingServerViewport::viewport_get_measured_render_time_cpu(RID p_viewport) const {
+ Viewport *viewport = viewport_owner.getornull(p_viewport);
+ ERR_FAIL_COND_V(!viewport, 0);
+
+ return double(viewport->time_cpu_end - viewport->time_cpu_begin) / 1000.0;
+}
+float RenderingServerViewport::viewport_get_measured_render_time_gpu(RID p_viewport) const {
+ Viewport *viewport = viewport_owner.getornull(p_viewport);
+ ERR_FAIL_COND_V(!viewport, 0);
+
+ return double((viewport->time_gpu_end - viewport->time_gpu_begin) / 1000) / 1000.0;
+}
+
+bool RenderingServerViewport::free(RID p_rid) {
+ if (viewport_owner.owns(p_rid)) {
Viewport *viewport = viewport_owner.getornull(p_rid);
RSG::storage->free(viewport->render_target);
@@ -772,6 +786,28 @@ bool RenderingServerViewport::free(RID p_rid) {
return false;
}
+void RenderingServerViewport::handle_timestamp(String p_timestamp, uint64_t p_cpu_time, uint64_t p_gpu_time) {
+ RID *vp = timestamp_vp_map.getptr(p_timestamp);
+ if (!vp) {
+ return;
+ }
+
+ Viewport *viewport = viewport_owner.getornull(*vp);
+ if (!viewport) {
+ return;
+ }
+
+ if (p_timestamp.begins_with("vp_begin")) {
+ viewport->time_cpu_begin = p_cpu_time;
+ viewport->time_gpu_begin = p_gpu_time;
+ }
+
+ if (p_timestamp.begins_with("vp_end")) {
+ viewport->time_cpu_end = p_cpu_time;
+ viewport->time_gpu_end = p_gpu_time;
+ }
+}
+
void RenderingServerViewport::set_default_clear_color(const Color &p_color) {
RSG::storage->set_default_clear_color(p_color);
}
diff --git a/servers/rendering/rendering_server_viewport.h b/servers/rendering/rendering_server_viewport.h
index f574c58d96..0b90646e4f 100644
--- a/servers/rendering/rendering_server_viewport.h
+++ b/servers/rendering/rendering_server_viewport.h
@@ -34,8 +34,8 @@
#include "core/rid_owner.h"
#include "core/self_list.h"
#include "rasterizer.h"
-#include "servers/arvr/arvr_interface.h"
#include "servers/rendering_server.h"
+#include "servers/xr/xr_interface.h"
class RenderingServerViewport {
public:
@@ -43,11 +43,10 @@ public:
};
struct Viewport {
-
RID self;
RID parent;
- bool use_arvr; /* use arvr interface to override camera positioning and projection matrices and control output */
+ bool use_xr; /* use xr interface to override camera positioning and projection matrices and control output */
Size2i size;
RID camera;
@@ -59,6 +58,7 @@ public:
RID render_buffers;
RS::ViewportMSAA msaa;
+ RS::ViewportScreenSpaceAA screen_space_aa;
DisplayServer::WindowID viewport_to_screen;
Rect2 viewport_to_screen_rect;
@@ -67,8 +67,13 @@ public:
bool hide_scenario;
bool hide_canvas;
bool disable_environment;
- bool disable_3d_by_usage;
- bool keep_3d_linear;
+ bool measure_render_time;
+
+ uint64_t time_cpu_begin;
+ uint64_t time_cpu_end;
+
+ uint64_t time_gpu_begin;
+ uint64_t time_gpu_end;
RID shadow_atlas;
int shadow_atlas_size;
@@ -83,12 +88,12 @@ public:
bool transparent_bg;
struct CanvasKey {
-
int64_t stacking;
RID canvas;
bool operator<(const CanvasKey &p_canvas) const {
- if (stacking == p_canvas.stacking)
+ if (stacking == p_canvas.stacking) {
return canvas < p_canvas.canvas;
+ }
return stacking < p_canvas.stacking;
}
CanvasKey() {
@@ -103,7 +108,6 @@ public:
};
struct CanvasData {
-
CanvasBase *canvas;
Transform2D transform;
int layer;
@@ -121,28 +125,37 @@ public:
disable_environment = false;
viewport_to_screen = DisplayServer::INVALID_WINDOW_ID;
shadow_atlas_size = 0;
- keep_3d_linear = false;
+ measure_render_time = false;
+
debug_draw = RS::VIEWPORT_DEBUG_DRAW_DISABLED;
msaa = RS::VIEWPORT_MSAA_DISABLED;
+ screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED;
+
for (int i = 0; i < RS::VIEWPORT_RENDER_INFO_MAX; i++) {
render_info[i] = 0;
}
- use_arvr = false;
+ use_xr = false;
+
+ time_cpu_begin = 0;
+ time_cpu_end = 0;
+
+ time_gpu_begin = 0;
+ time_gpu_end = 0;
}
};
+ HashMap<String, RID> timestamp_vp_map;
+
uint64_t draw_viewports_pass = 0;
mutable RID_PtrOwner<Viewport> viewport_owner;
struct ViewportSort {
_FORCE_INLINE_ bool operator()(const Viewport *p_left, const Viewport *p_right) const {
-
bool left_to_screen = p_left->viewport_to_screen_rect.size != Size2();
bool right_to_screen = p_right->viewport_to_screen_rect.size != Size2();
if (left_to_screen == right_to_screen) {
-
return p_right->parent == p_left->self;
}
return (right_to_screen ? 0 : 1) < (left_to_screen ? 0 : 1);
@@ -152,13 +165,13 @@ public:
Vector<Viewport *> active_viewports;
private:
- void _draw_3d(Viewport *p_viewport, ARVRInterface::Eyes p_eye);
- void _draw_viewport(Viewport *p_viewport, ARVRInterface::Eyes p_eye = ARVRInterface::EYE_MONO);
+ void _draw_3d(Viewport *p_viewport, XRInterface::Eyes p_eye);
+ void _draw_viewport(Viewport *p_viewport, XRInterface::Eyes p_eye = XRInterface::EYE_MONO);
public:
RID viewport_create();
- void viewport_set_use_arvr(RID p_viewport, bool p_use_arvr);
+ void viewport_set_use_xr(RID p_viewport, bool p_use_xr);
void viewport_set_size(RID p_viewport, int p_width, int p_height);
@@ -192,10 +205,17 @@ public:
void viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv);
void viewport_set_msaa(RID p_viewport, RS::ViewportMSAA p_msaa);
+ void viewport_set_screen_space_aa(RID p_viewport, RS::ViewportScreenSpaceAA p_mode);
virtual int viewport_get_render_info(RID p_viewport, RS::ViewportRenderInfo p_info);
virtual void viewport_set_debug_draw(RID p_viewport, RS::ViewportDebugDraw p_draw);
+ void viewport_set_measure_render_time(RID p_viewport, bool p_enable);
+ float viewport_get_measured_render_time_cpu(RID p_viewport) const;
+ float viewport_get_measured_render_time_gpu(RID p_viewport) const;
+
+ void handle_timestamp(String p_timestamp, uint64_t p_cpu_time, uint64_t p_gpu_time);
+
void set_default_clear_color(const Color &p_color);
void draw_viewports();
diff --git a/servers/rendering/rendering_server_wrap_mt.cpp b/servers/rendering/rendering_server_wrap_mt.cpp
index 5d6d523901..9aa6593cbe 100644
--- a/servers/rendering/rendering_server_wrap_mt.cpp
+++ b/servers/rendering/rendering_server_wrap_mt.cpp
@@ -34,32 +34,26 @@
#include "servers/display_server.h"
void RenderingServerWrapMT::thread_exit() {
-
exit = true;
}
void RenderingServerWrapMT::thread_draw(bool p_swap_buffers, double frame_step) {
-
if (!atomic_decrement(&draw_pending)) {
-
rendering_server->draw(p_swap_buffers, frame_step);
}
}
void RenderingServerWrapMT::thread_flush() {
-
atomic_decrement(&draw_pending);
}
void RenderingServerWrapMT::_thread_callback(void *_instance) {
-
RenderingServerWrapMT *vsmt = reinterpret_cast<RenderingServerWrapMT *>(_instance);
vsmt->thread_loop();
}
void RenderingServerWrapMT::thread_loop() {
-
server_thread = Thread::get_caller_id();
DisplayServer::get_singleton()->make_rendering_thread();
@@ -81,33 +75,25 @@ void RenderingServerWrapMT::thread_loop() {
/* EVENT QUEUING */
void RenderingServerWrapMT::sync() {
-
if (create_thread) {
-
atomic_increment(&draw_pending);
command_queue.push_and_sync(this, &RenderingServerWrapMT::thread_flush);
} else {
-
command_queue.flush_all(); //flush all pending from other threads
}
}
void RenderingServerWrapMT::draw(bool p_swap_buffers, double frame_step) {
-
if (create_thread) {
-
atomic_increment(&draw_pending);
command_queue.push(this, &RenderingServerWrapMT::thread_draw, p_swap_buffers, frame_step);
} else {
-
rendering_server->draw(p_swap_buffers, frame_step);
}
}
void RenderingServerWrapMT::init() {
-
if (create_thread) {
-
print_verbose("RenderingServerWrapMT: Creating render thread");
DisplayServer::get_singleton()->release_rendering_thread();
if (create_thread) {
@@ -119,24 +105,11 @@ void RenderingServerWrapMT::init() {
}
print_verbose("RenderingServerWrapMT: Finished render thread");
} else {
-
rendering_server->init();
}
}
void RenderingServerWrapMT::finish() {
-
- if (thread) {
-
- command_queue.push(this, &RenderingServerWrapMT::thread_exit);
- Thread::wait_to_finish(thread);
- memdelete(thread);
-
- thread = NULL;
- } else {
- rendering_server->finish();
- }
-
sky_free_cached_ids();
shader_free_cached_ids();
material_free_cached_ids();
@@ -149,7 +122,7 @@ void RenderingServerWrapMT::finish() {
spot_light_free_cached_ids();
reflection_probe_free_cached_ids();
gi_probe_free_cached_ids();
- lightmap_capture_free_cached_ids();
+ lightmap_free_cached_ids();
particles_free_cached_ids();
camera_free_cached_ids();
viewport_free_cached_ids();
@@ -161,24 +134,32 @@ void RenderingServerWrapMT::finish() {
canvas_item_free_cached_ids();
canvas_light_occluder_free_cached_ids();
canvas_occluder_polygon_free_cached_ids();
+
+ if (thread) {
+ command_queue.push(this, &RenderingServerWrapMT::thread_exit);
+ Thread::wait_to_finish(thread);
+ memdelete(thread);
+
+ thread = nullptr;
+ } else {
+ rendering_server->finish();
+ }
}
void RenderingServerWrapMT::set_use_vsync_callback(bool p_enable) {
-
singleton_mt->call_set_use_vsync(p_enable);
}
-RenderingServerWrapMT *RenderingServerWrapMT::singleton_mt = NULL;
+RenderingServerWrapMT *RenderingServerWrapMT::singleton_mt = nullptr;
RenderingServerWrapMT::RenderingServerWrapMT(RenderingServer *p_contained, bool p_create_thread) :
command_queue(p_create_thread) {
-
singleton_mt = this;
DisplayServer::switch_vsync_function = set_use_vsync_callback; //as this goes to another thread, make sure it goes properly
rendering_server = p_contained;
create_thread = p_create_thread;
- thread = NULL;
+ thread = nullptr;
draw_pending = 0;
draw_thread_up = false;
pool_max_size = GLOBAL_GET("memory/limits/multithreaded_server/rid_pool_prealloc");
@@ -191,7 +172,6 @@ RenderingServerWrapMT::RenderingServerWrapMT(RenderingServer *p_contained, bool
}
RenderingServerWrapMT::~RenderingServerWrapMT() {
-
memdelete(rendering_server);
//finish();
}
diff --git a/servers/rendering/rendering_server_wrap_mt.h b/servers/rendering/rendering_server_wrap_mt.h
index bcd1344f44..a746aa52b2 100644
--- a/servers/rendering/rendering_server_wrap_mt.h
+++ b/servers/rendering/rendering_server_wrap_mt.h
@@ -36,7 +36,6 @@
#include "servers/rendering_server.h"
class RenderingServerWrapMT : public RenderingServer {
-
// the real visual server
mutable RenderingServer *rendering_server;
@@ -92,7 +91,7 @@ public:
//these also go pass-through
virtual RID texture_2d_placeholder_create() { return rendering_server->texture_2d_placeholder_create(); }
- virtual RID texture_2d_layered_placeholder_create() { return rendering_server->texture_2d_layered_placeholder_create(); }
+ virtual RID texture_2d_layered_placeholder_create(TextureLayeredType p_type) { return rendering_server->texture_2d_layered_placeholder_create(p_type); }
virtual RID texture_3d_placeholder_create() { return rendering_server->texture_3d_placeholder_create(); }
FUNC1RC(Ref<Image>, texture_2d_get, RID)
@@ -264,6 +263,20 @@ public:
FUNC2(reflection_probe_set_cull_mask, RID, uint32_t)
FUNC2(reflection_probe_set_resolution, RID, int)
+ /* DECAL API */
+
+ FUNCRID(decal)
+
+ FUNC2(decal_set_extents, RID, const Vector3 &)
+ FUNC3(decal_set_texture, RID, DecalTexture, RID)
+ FUNC2(decal_set_emission_energy, RID, float)
+ FUNC2(decal_set_albedo_mix, RID, float)
+ FUNC2(decal_set_modulate, RID, const Color &)
+ FUNC2(decal_set_cull_mask, RID, uint32_t)
+ FUNC4(decal_set_distance_fade, RID, bool, float, float)
+ FUNC3(decal_set_fade, RID, float, float)
+ FUNC2(decal_set_normal_fade, RID, float)
+
/* BAKED LIGHT API */
FUNCRID(gi_probe)
@@ -310,19 +323,17 @@ public:
/* LIGHTMAP CAPTURE */
- FUNCRID(lightmap_capture)
+ FUNCRID(lightmap)
+ FUNC3(lightmap_set_textures, RID, RID, bool)
+ FUNC2(lightmap_set_probe_bounds, RID, const AABB &)
+ FUNC2(lightmap_set_probe_interior, RID, bool)
+ FUNC5(lightmap_set_probe_capture_data, RID, const PackedVector3Array &, const PackedColorArray &, const PackedInt32Array &, const PackedInt32Array &)
+ FUNC1RC(PackedVector3Array, lightmap_get_probe_capture_points, RID)
+ FUNC1RC(PackedColorArray, lightmap_get_probe_capture_sh, RID)
+ FUNC1RC(PackedInt32Array, lightmap_get_probe_capture_tetrahedra, RID)
+ FUNC1RC(PackedInt32Array, lightmap_get_probe_capture_bsp_tree, RID)
- FUNC2(lightmap_capture_set_bounds, RID, const AABB &)
- FUNC1RC(AABB, lightmap_capture_get_bounds, RID)
-
- FUNC2(lightmap_capture_set_octree, RID, const Vector<uint8_t> &)
- FUNC1RC(Vector<uint8_t>, lightmap_capture_get_octree, RID)
- FUNC2(lightmap_capture_set_octree_cell_transform, RID, const Transform &)
- FUNC1RC(Transform, lightmap_capture_get_octree_cell_transform, RID)
- FUNC2(lightmap_capture_set_octree_cell_subdiv, RID, int)
- FUNC1RC(int, lightmap_capture_get_octree_cell_subdiv, RID)
- FUNC2(lightmap_capture_set_energy, RID, float)
- FUNC1RC(float, lightmap_capture_get_energy, RID)
+ FUNC1(lightmap_set_probe_capture_update_speed, float)
/* PARTICLES */
@@ -370,7 +381,7 @@ public:
FUNCRID(viewport)
- FUNC2(viewport_set_use_arvr, RID, bool)
+ FUNC2(viewport_set_use_xr, RID, bool)
FUNC3(viewport_set_size, RID, int, int)
@@ -403,6 +414,7 @@ public:
FUNC2(viewport_set_shadow_atlas_size, RID, int)
FUNC3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int)
FUNC2(viewport_set_msaa, RID, ViewportMSAA)
+ FUNC2(viewport_set_screen_space_aa, RID, ViewportScreenSpaceAA)
//this passes directly to avoid stalling, but it's pretty dangerous, so don't call after freeing a viewport
virtual int viewport_get_render_info(RID p_viewport, ViewportRenderInfo p_info) {
@@ -411,6 +423,14 @@ public:
FUNC2(viewport_set_debug_draw, RID, ViewportDebugDraw)
+ FUNC2(viewport_set_measure_render_time, RID, bool)
+ virtual float viewport_get_measured_render_time_cpu(RID p_viewport) const {
+ return rendering_server->viewport_get_measured_render_time_cpu(p_viewport);
+ }
+ virtual float viewport_get_measured_render_time_gpu(RID p_viewport) const {
+ return rendering_server->viewport_get_measured_render_time_gpu(p_viewport);
+ }
+
FUNC1(directional_shadow_atlas_set_size, int)
/* SKY API */
@@ -419,6 +439,7 @@ public:
FUNC2(sky_set_radiance_size, RID, int)
FUNC2(sky_set_mode, RID, SkyMode)
FUNC2(sky_set_material, RID, RID)
+ FUNC4R(Ref<Image>, sky_bake_panorama, RID, float, bool, const Size2i &)
/* ENVIRONMENT API */
@@ -437,7 +458,9 @@ public:
#if 0
FUNC2(environment_set_camera_feed_id, RID, int)
#endif
- FUNC7(environment_set_ssr, RID, bool, int, float, float, float, bool)
+ FUNC6(environment_set_ssr, RID, bool, int, float, float, float)
+ FUNC1(environment_set_ssr_roughness_quality, EnvironmentSSRRoughnessQuality)
+
FUNC9(environment_set_ssao, RID, bool, float, float, float, float, float, EnvironmentSSAOBlur, float)
FUNC2(environment_set_ssao_quality, EnvironmentSSAOQuality, bool)
@@ -453,7 +476,11 @@ public:
FUNC7(environment_set_fog_depth, RID, bool, float, float, float, bool, float)
FUNC5(environment_set_fog_height, RID, bool, float, float, float)
+ FUNC3R(Ref<Image>, environment_bake_panorama, RID, bool, const Size2i &)
+
FUNC2(screen_space_roughness_limiter_set_active, bool, float)
+ FUNC1(sub_surface_scattering_set_quality, SubSurfaceScatteringQuality)
+ FUNC2(sub_surface_scattering_set_scale, float, float)
FUNCRID(camera_effects)
@@ -463,6 +490,9 @@ public:
FUNC8(camera_effects_set_dof_blur, RID, bool, float, float, bool, float, float, float)
FUNC3(camera_effects_set_custom_exposure, RID, bool, float)
+ FUNC1(shadows_quality_set, ShadowQuality);
+ FUNC1(directional_shadow_quality_set, ShadowQuality);
+
FUNCRID(scenario)
FUNC2(scenario_set_debug, RID, ScenarioDebugMode)
@@ -481,7 +511,6 @@ public:
FUNC3(instance_set_blend_shape_weight, RID, int, float)
FUNC3(instance_set_surface_material, RID, int, RID)
FUNC2(instance_set_visible, RID, bool)
- FUNC3(instance_set_use_lightmap, RID, RID, RID)
FUNC2(instance_set_custom_aabb, RID, AABB)
@@ -501,6 +530,16 @@ public:
FUNC5(instance_geometry_set_draw_range, RID, float, float, float, float)
FUNC2(instance_geometry_set_as_instance_lod, RID, RID)
+ FUNC4(instance_geometry_set_lightmap, RID, RID, const Rect2 &, int)
+
+ 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 &)
+ FUNC2SC(instance_geometry_get_shader_parameter_list, RID, List<PropertyInfo> *)
+
+ /* BAKE */
+
+ FUNC3R(TypedArray<Image>, bake_render_uv2, RID, const Vector<RID> &, const Size2i &)
/* CANVAS (2D) */
@@ -595,6 +634,18 @@ public:
FUNC2(canvas_occluder_polygon_set_cull_mode, RID, CanvasOccluderPolygonCullMode)
+ /* GLOBAL VARIABLES */
+
+ FUNC3(global_variable_add, const StringName &, GlobalVariableType, const Variant &)
+ FUNC1(global_variable_remove, const StringName &)
+ FUNC0RC(Vector<StringName>, global_variable_get_list)
+ FUNC2(global_variable_set, const StringName &, const Variant &)
+ FUNC2(global_variable_set_override, const StringName &, const Variant &)
+ FUNC1RC(GlobalVariableType, global_variable_get_type, const StringName &)
+ FUNC1RC(Variant, global_variable_get, const StringName &)
+ FUNC1(global_variables_load_settings, bool)
+ FUNC0(global_variables_clear)
+
/* BLACK BARS */
FUNC4(black_bars_set_margins, int, int, int, int)
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index 300c38db22..2ec65b7ea8 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -34,22 +34,18 @@
#include "servers/rendering_server.h"
static bool _is_text_char(CharType c) {
-
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_';
}
static bool _is_number(CharType c) {
-
return (c >= '0' && c <= '9');
}
static bool _is_hex(CharType c) {
-
return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
}
String ShaderLanguage::get_operator_text(Operator p_op) {
-
static const char *op_names[OP_MAX] = { "==",
"!=",
"<",
@@ -132,6 +128,7 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
"TYPE_ISAMPLER3D",
"TYPE_USAMPLER3D",
"TYPE_SAMPLERCUBE",
+ "TYPE_SAMPLERCUBEARRAY",
"INTERPOLATION_FLAT",
"INTERPOLATION_SMOOTH",
"CONST",
@@ -194,6 +191,8 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
"SEMICOLON",
"PERIOD",
"UNIFORM",
+ "INSTANCE",
+ "GLOBAL",
"VARYING",
"IN",
"OUT",
@@ -207,6 +206,7 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
"HINT_BLACK_ALBEDO_TEXTURE",
"HINT_COLOR",
"HINT_RANGE",
+ "HINT_INSTANCE_INDEX",
"FILTER_NEAREST",
"FILTER_LINEAR",
"FILTER_NEAREST_MIPMAP",
@@ -222,7 +222,6 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
};
String ShaderLanguage::get_token_text(Token p_token) {
-
String name = token_names[p_token.type];
if (p_token.type == TK_INT_CONSTANT || p_token.type == TK_REAL_CONSTANT) {
name += "(" + rtos(p_token.constant) + ")";
@@ -236,7 +235,6 @@ String ShaderLanguage::get_token_text(Token p_token) {
}
ShaderLanguage::Token ShaderLanguage::_make_token(TokenType p_type, const StringName &p_text) {
-
Token tk;
tk.type = p_type;
tk.text = p_text;
@@ -280,6 +278,7 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
{ TK_TYPE_ISAMPLER3D, "isampler3D" },
{ TK_TYPE_USAMPLER3D, "usampler3D" },
{ TK_TYPE_SAMPLERCUBE, "samplerCube" },
+ { TK_TYPE_SAMPLERCUBEARRAY, "samplerCubeArray" },
{ TK_INTERPOLATION_FLAT, "flat" },
{ TK_INTERPOLATION_SMOOTH, "smooth" },
{ TK_CONST, "const" },
@@ -300,6 +299,8 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
{ TK_CF_RETURN, "return" },
{ TK_CF_DISCARD, "discard" },
{ TK_UNIFORM, "uniform" },
+ { TK_INSTANCE, "instance" },
+ { TK_GLOBAL, "global" },
{ TK_VARYING, "varying" },
{ TK_ARG_IN, "in" },
{ TK_ARG_OUT, "out" },
@@ -319,6 +320,7 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
{ TK_HINT_BLACK_ALBEDO_TEXTURE, "hint_black_albedo" },
{ TK_HINT_COLOR, "hint_color" },
{ TK_HINT_RANGE, "hint_range" },
+ { TK_HINT_INSTANCE_INDEX, "instance_index" },
{ TK_FILTER_NEAREST, "filter_nearest" },
{ TK_FILTER_LINEAR, "filter_linear" },
{ TK_FILTER_NEAREST_MIPMAP, "filter_nearest_mipmap" },
@@ -328,17 +330,15 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
{ TK_REPEAT_ENABLE, "repeat_enable" },
{ TK_REPEAT_DISABLE, "repeat_disable" },
{ TK_SHADER_TYPE, "shader_type" },
- { TK_ERROR, NULL }
+ { TK_ERROR, nullptr }
};
ShaderLanguage::Token ShaderLanguage::_get_token() {
-
#define GETCHAR(m_idx) (((char_idx + m_idx) < code.length()) ? code[char_idx + m_idx] : CharType(0))
while (true) {
char_idx++;
switch (GETCHAR(-1)) {
-
case 0:
return _make_token(TK_EOF);
case 0xFFFF:
@@ -351,7 +351,6 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
tk_line++;
continue;
case '/': {
-
switch (GETCHAR(0)) {
case '*': { // block comment
@@ -399,7 +398,6 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
continue; //a comment, continue to next token
} break;
case '=': {
-
if (GETCHAR(0) == '=') {
char_idx++;
return _make_token(TK_OP_EQUAL);
@@ -488,7 +486,6 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
return _make_token(TK_OP_BIT_AND);
} break;
case '|': {
-
if (GETCHAR(0) == '=') {
char_idx++;
return _make_token(TK_OP_ASSIGN_BIT_OR);
@@ -500,7 +497,6 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
} break;
case '*': {
-
if (GETCHAR(0) == '=') {
char_idx++;
return _make_token(TK_OP_ASSIGN_MUL);
@@ -508,12 +504,10 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
return _make_token(TK_OP_MUL);
} break;
case '+': {
-
if (GETCHAR(0) == '=') {
char_idx++;
return _make_token(TK_OP_ASSIGN_ADD);
} else if (GETCHAR(0) == '+') {
-
char_idx++;
return _make_token(TK_OP_INCREMENT);
}
@@ -521,12 +515,10 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
return _make_token(TK_OP_ADD);
} break;
case '-': {
-
if (GETCHAR(0) == '=') {
char_idx++;
return _make_token(TK_OP_ASSIGN_SUB);
} else if (GETCHAR(0) == '-') {
-
char_idx++;
return _make_token(TK_OP_DECREMENT);
}
@@ -534,7 +526,6 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
return _make_token(TK_OP_SUB);
} break;
case '%': {
-
if (GETCHAR(0) == '=') {
char_idx++;
return _make_token(TK_OP_ASSIGN_MOD);
@@ -543,7 +534,6 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
return _make_token(TK_OP_MOD);
} break;
default: {
-
char_idx--; //go back one, since we have no idea what this is
if (_is_number(GETCHAR(0)) || (GETCHAR(0) == '.' && _is_number(GETCHAR(1)))) {
@@ -559,32 +549,38 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
while (true) {
if (GETCHAR(i) == '.') {
- if (period_found || exponent_found || hexa_found || float_suffix_found)
+ if (period_found || exponent_found || hexa_found || float_suffix_found) {
return _make_token(TK_ERROR, "Invalid numeric constant");
+ }
period_found = true;
} else if (GETCHAR(i) == 'x') {
- if (hexa_found || str.length() != 1 || str[0] != '0')
+ if (hexa_found || str.length() != 1 || str[0] != '0') {
return _make_token(TK_ERROR, "Invalid numeric constant");
+ }
hexa_found = true;
} else if (GETCHAR(i) == 'e') {
- if (hexa_found || exponent_found || float_suffix_found)
+ if (hexa_found || exponent_found || float_suffix_found) {
return _make_token(TK_ERROR, "Invalid numeric constant");
+ }
exponent_found = true;
} else if (GETCHAR(i) == 'f') {
- if (hexa_found || exponent_found)
+ if (hexa_found || exponent_found) {
return _make_token(TK_ERROR, "Invalid numeric constant");
+ }
float_suffix_found = true;
} else if (_is_number(GETCHAR(i))) {
- if (float_suffix_found)
+ if (float_suffix_found) {
return _make_token(TK_ERROR, "Invalid numeric constant");
+ }
} else if (hexa_found && _is_hex(GETCHAR(i))) {
-
} else if ((GETCHAR(i) == '-' || GETCHAR(i) == '+') && exponent_found) {
- if (sign_found)
+ if (sign_found) {
return _make_token(TK_ERROR, "Invalid numeric constant");
+ }
sign_found = true;
- } else
+ } else {
break;
+ }
str += CharType(GETCHAR(i));
i++;
@@ -640,10 +636,11 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
char_idx += str.length();
Token tk;
- if (period_found || exponent_found || float_suffix_found)
+ if (period_found || exponent_found || float_suffix_found) {
tk.type = TK_REAL_CONSTANT;
- else
+ } else {
tk.type = TK_INT_CONSTANT;
+ }
if (hexa_found) {
tk.constant = (double)str.hex_to_int64(true);
@@ -666,7 +663,6 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
String str;
while (_is_text_char(GETCHAR(0))) {
-
str += CharType(GETCHAR(0));
char_idx++;
}
@@ -676,9 +672,7 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
int idx = 0;
while (keyword_list[idx].text) {
-
if (str == keyword_list[idx].text) {
-
return _make_token(keyword_list[idx].token);
}
idx++;
@@ -689,10 +683,11 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
return _make_token(TK_IDENTIFIER, str);
}
- if (GETCHAR(0) > 32)
+ if (GETCHAR(0) > 32) {
return _make_token(TK_ERROR, "Tokenizer: Unknown character #" + itos(GETCHAR(0)) + ": '" + String::chr(GETCHAR(0)) + "'");
- else
+ } else {
return _make_token(TK_ERROR, "Tokenizer: Unknown character #" + itos(GETCHAR(0)));
+ }
} break;
}
@@ -704,7 +699,6 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
}
String ShaderLanguage::token_debug(const String &p_code) {
-
clear();
code = p_code;
@@ -713,7 +707,6 @@ String ShaderLanguage::token_debug(const String &p_code) {
Token tk = _get_token();
while (tk.type != TK_EOF && tk.type != TK_ERROR) {
-
output += itos(tk_line) + ": " + get_token_text(tk) + "\n";
tk = _get_token();
}
@@ -746,7 +739,6 @@ bool ShaderLanguage::is_token_variable_datatype(TokenType p_type) {
}
bool ShaderLanguage::is_token_datatype(TokenType p_type) {
-
return (
p_type == TK_TYPE_VOID ||
p_type == TK_TYPE_BOOL ||
@@ -777,31 +769,29 @@ bool ShaderLanguage::is_token_datatype(TokenType p_type) {
p_type == TK_TYPE_SAMPLER3D ||
p_type == TK_TYPE_ISAMPLER3D ||
p_type == TK_TYPE_USAMPLER3D ||
- p_type == TK_TYPE_SAMPLERCUBE);
+ p_type == TK_TYPE_SAMPLERCUBE ||
+ p_type == TK_TYPE_SAMPLERCUBEARRAY);
}
ShaderLanguage::DataType ShaderLanguage::get_token_datatype(TokenType p_type) {
-
return DataType(p_type - TK_TYPE_VOID);
}
bool ShaderLanguage::is_token_interpolation(TokenType p_type) {
-
return (
p_type == TK_INTERPOLATION_FLAT ||
p_type == TK_INTERPOLATION_SMOOTH);
}
ShaderLanguage::DataInterpolation ShaderLanguage::get_token_interpolation(TokenType p_type) {
-
- if (p_type == TK_INTERPOLATION_FLAT)
+ if (p_type == TK_INTERPOLATION_FLAT) {
return INTERPOLATION_FLAT;
- else
+ } else {
return INTERPOLATION_SMOOTH;
+ }
}
bool ShaderLanguage::is_token_precision(TokenType p_type) {
-
return (
p_type == TK_PRECISION_LOW ||
p_type == TK_PRECISION_MID ||
@@ -809,20 +799,23 @@ bool ShaderLanguage::is_token_precision(TokenType p_type) {
}
ShaderLanguage::DataPrecision ShaderLanguage::get_token_precision(TokenType p_type) {
-
- if (p_type == TK_PRECISION_LOW)
+ if (p_type == TK_PRECISION_LOW) {
return PRECISION_LOWP;
- else if (p_type == TK_PRECISION_HIGH)
+ } else if (p_type == TK_PRECISION_HIGH) {
return PRECISION_HIGHP;
- else
+ } else {
return PRECISION_MEDIUMP;
+ }
}
String ShaderLanguage::get_precision_name(DataPrecision p_type) {
switch (p_type) {
- case PRECISION_LOWP: return "lowp";
- case PRECISION_MEDIUMP: return "mediump";
- case PRECISION_HIGHP: return "highp";
+ case PRECISION_LOWP:
+ return "lowp";
+ case PRECISION_MEDIUMP:
+ return "mediump";
+ case PRECISION_HIGHP:
+ return "highp";
default:
break;
}
@@ -830,56 +823,87 @@ String ShaderLanguage::get_precision_name(DataPrecision p_type) {
}
String ShaderLanguage::get_datatype_name(DataType p_type) {
-
switch (p_type) {
-
- case TYPE_VOID: return "void";
- case TYPE_BOOL: return "bool";
- case TYPE_BVEC2: return "bvec2";
- case TYPE_BVEC3: return "bvec3";
- case TYPE_BVEC4: return "bvec4";
- case TYPE_INT: return "int";
- case TYPE_IVEC2: return "ivec2";
- case TYPE_IVEC3: return "ivec3";
- case TYPE_IVEC4: return "ivec4";
- case TYPE_UINT: return "uint";
- case TYPE_UVEC2: return "uvec2";
- case TYPE_UVEC3: return "uvec3";
- case TYPE_UVEC4: return "uvec4";
- case TYPE_FLOAT: return "float";
- case TYPE_VEC2: return "vec2";
- case TYPE_VEC3: return "vec3";
- case TYPE_VEC4: return "vec4";
- case TYPE_MAT2: return "mat2";
- case TYPE_MAT3: return "mat3";
- case TYPE_MAT4: return "mat4";
- case TYPE_SAMPLER2D: return "sampler2D";
- case TYPE_ISAMPLER2D: return "isampler2D";
- case TYPE_USAMPLER2D: return "usampler2D";
- case TYPE_SAMPLER2DARRAY: return "sampler2DArray";
- case TYPE_ISAMPLER2DARRAY: return "isampler2DArray";
- case TYPE_USAMPLER2DARRAY: return "usampler2DArray";
- case TYPE_SAMPLER3D: return "sampler3D";
- case TYPE_ISAMPLER3D: return "isampler3D";
- case TYPE_USAMPLER3D: return "usampler3D";
- case TYPE_SAMPLERCUBE: return "samplerCube";
- case TYPE_STRUCT: return "struct";
+ case TYPE_VOID:
+ return "void";
+ case TYPE_BOOL:
+ return "bool";
+ case TYPE_BVEC2:
+ return "bvec2";
+ case TYPE_BVEC3:
+ return "bvec3";
+ case TYPE_BVEC4:
+ return "bvec4";
+ case TYPE_INT:
+ return "int";
+ case TYPE_IVEC2:
+ return "ivec2";
+ case TYPE_IVEC3:
+ return "ivec3";
+ case TYPE_IVEC4:
+ return "ivec4";
+ case TYPE_UINT:
+ return "uint";
+ case TYPE_UVEC2:
+ return "uvec2";
+ case TYPE_UVEC3:
+ return "uvec3";
+ case TYPE_UVEC4:
+ return "uvec4";
+ case TYPE_FLOAT:
+ return "float";
+ case TYPE_VEC2:
+ return "vec2";
+ case TYPE_VEC3:
+ return "vec3";
+ case TYPE_VEC4:
+ return "vec4";
+ case TYPE_MAT2:
+ return "mat2";
+ case TYPE_MAT3:
+ return "mat3";
+ case TYPE_MAT4:
+ return "mat4";
+ case TYPE_SAMPLER2D:
+ return "sampler2D";
+ case TYPE_ISAMPLER2D:
+ return "isampler2D";
+ case TYPE_USAMPLER2D:
+ return "usampler2D";
+ case TYPE_SAMPLER2DARRAY:
+ return "sampler2DArray";
+ case TYPE_ISAMPLER2DARRAY:
+ return "isampler2DArray";
+ case TYPE_USAMPLER2DARRAY:
+ return "usampler2DArray";
+ case TYPE_SAMPLER3D:
+ return "sampler3D";
+ case TYPE_ISAMPLER3D:
+ return "isampler3D";
+ case TYPE_USAMPLER3D:
+ return "usampler3D";
+ case TYPE_SAMPLERCUBE:
+ return "samplerCube";
+ case TYPE_SAMPLERCUBEARRAY:
+ return "samplerCubeArray";
+ case TYPE_STRUCT:
+ return "struct";
+ case TYPE_MAX:
+ return "invalid";
}
return "";
}
bool ShaderLanguage::is_token_nonvoid_datatype(TokenType p_type) {
-
return is_token_datatype(p_type) && p_type != TK_TYPE_VOID;
}
void ShaderLanguage::clear() {
-
current_function = StringName();
completion_type = COMPLETION_NONE;
- completion_block = NULL;
+ completion_block = nullptr;
completion_function = StringName();
completion_class = SubClassTag::TAG_GLOBAL;
completion_struct = StringName();
@@ -897,9 +921,7 @@ void ShaderLanguage::clear() {
}
bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_reassign, const Map<StringName, BuiltInInfo> &p_builtin_types, const StringName &p_identifier, DataType *r_data_type, IdentifierType *r_type, bool *r_is_const, int *r_array_size, StringName *r_struct_name) {
-
if (p_builtin_types.has(p_identifier)) {
-
if (r_data_type) {
*r_data_type = p_builtin_types[p_identifier].type;
}
@@ -913,10 +935,9 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea
return true;
}
- FunctionNode *function = NULL;
+ FunctionNode *function = nullptr;
while (p_block) {
-
if (p_block->variables.has(p_identifier)) {
if (r_data_type) {
*r_data_type = p_block->variables[p_identifier].type;
@@ -1003,9 +1024,9 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea
}
for (int i = 0; i < shader->functions.size(); i++) {
-
- if (!shader->functions[i].callable)
+ if (!shader->functions[i].callable) {
continue;
+ }
if (shader->functions[i].name == p_identifier) {
if (r_data_type) {
@@ -1022,7 +1043,6 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea
}
bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type) {
-
bool valid = false;
DataType ret_type = TYPE_VOID;
@@ -1055,7 +1075,6 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
} break;
case OP_NOT: {
-
DataType na = p_op->arguments[0]->get_datatype();
valid = na == TYPE_BOOL;
ret_type = TYPE_BOOL;
@@ -1194,7 +1213,6 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
case OP_ASSIGN_SHIFT_RIGHT:
case OP_SHIFT_LEFT:
case OP_SHIFT_RIGHT: {
-
DataType na = p_op->arguments[0]->get_datatype();
DataType nb = p_op->arguments[1]->get_datatype();
@@ -1256,7 +1274,6 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
case OP_ASSIGN_SUB:
case OP_ASSIGN_MUL:
case OP_ASSIGN_DIV: {
-
DataType na = p_op->arguments[0]->get_datatype();
DataType nb = p_op->arguments[1]->get_datatype();
@@ -1316,7 +1333,6 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
case OP_BIT_AND:
case OP_BIT_OR:
case OP_BIT_XOR: {
-
/*
* The bitwise operators and (&), exclusive-or (^), and inclusive-or (|). The operands must be of type
* signed or unsigned integers or integer vectors. The operands cannot be vectors of differing size. If
@@ -1396,8 +1412,9 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
}
}
- if (r_ret_type)
+ if (r_ret_type) {
*r_ret_type = ret_type;
+ }
return valid;
}
@@ -2004,6 +2021,7 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "textureSize", TYPE_IVEC3, { TYPE_ISAMPLER3D, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
{ "textureSize", TYPE_IVEC3, { TYPE_USAMPLER3D, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
{ "textureSize", TYPE_IVEC2, { TYPE_SAMPLERCUBE, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
+ { "textureSize", TYPE_IVEC2, { TYPE_SAMPLERCUBEARRAY, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
{ "texture", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
{ "texture", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
@@ -2025,6 +2043,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
{ "texture", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
{ "texture", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
+ { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false },
+ { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
{ "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
{ "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true },
@@ -2055,6 +2075,7 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
{ "textureLod", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
{ "textureLod", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
+ { "textureLod", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
{ "texelFetch", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
{ "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true },
@@ -2086,6 +2107,7 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
{ "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
{ "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
+ { "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
{ "dFdx", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
{ "dFdx", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true },
@@ -2107,18 +2129,17 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
//array
{ "length", TYPE_INT, { TYPE_VOID }, TAG_ARRAY, true },
- { NULL, TYPE_VOID, { TYPE_VOID }, TAG_GLOBAL, false }
+ { nullptr, TYPE_VOID, { TYPE_VOID }, TAG_GLOBAL, false }
};
const ShaderLanguage::BuiltinFuncOutArgs ShaderLanguage::builtin_func_out_args[] = {
//constructors
{ "modf", 1 },
- { NULL, 0 }
+ { nullptr, 0 }
};
bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, OperatorNode *p_func, DataType *r_ret_type, StringName *r_ret_type_str) {
-
ERR_FAIL_COND_V(p_func->op != OP_CALL && p_func->op != OP_CONSTRUCT, false);
Vector<DataType> args;
@@ -2144,18 +2165,15 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const Map<Strin
int idx = 0;
while (builtin_func_defs[idx].name) {
-
if (completion_class != builtin_func_defs[idx].tag) {
idx++;
continue;
}
if (name == builtin_func_defs[idx].name) {
-
failed_builtin = true;
bool fail = false;
for (int i = 0; i < argcount; i++) {
-
if (get_scalar_type(args[i]) == args[i] && p_func->arguments[i + 1]->type == Node::TYPE_CONSTANT && convert_constant(static_cast<ConstantNode *>(p_func->arguments[i + 1]), builtin_func_defs[idx].args[i])) {
//all good, but needs implicit conversion later
} else if (args[i] != builtin_func_defs[idx].args[i]) {
@@ -2174,20 +2192,18 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const Map<Strin
}
}
- if (!fail && argcount < 4 && builtin_func_defs[idx].args[argcount] != TYPE_VOID)
+ if (!fail && argcount < 4 && builtin_func_defs[idx].args[argcount] != TYPE_VOID) {
fail = true; //make sure the number of arguments matches
+ }
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;
@@ -2275,7 +2291,6 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const Map<Strin
}
//implicitly convert values if possible
for (int i = 0; i < argcount; i++) {
-
if (get_scalar_type(args[i]) != args[i] || args[i] == builtin_func_defs[idx].args[i] || p_func->arguments[i + 1]->type != Node::TYPE_CONSTANT) {
//can't do implicit conversion here
continue;
@@ -2292,8 +2307,9 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const Map<Strin
p_func->arguments.write[i + 1] = conversion;
}
- if (r_ret_type)
+ if (r_ret_type) {
*r_ret_type = builtin_func_defs[idx].rettype;
+ }
return true;
}
@@ -2304,7 +2320,6 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const Map<Strin
}
if (unsupported_builtin) {
-
String arglist = "";
for (int i = 0; i < argcount; i++) {
if (i > 0) {
@@ -2321,8 +2336,9 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const Map<Strin
if (failed_builtin) {
String err = "Invalid arguments for built-in function: " + String(name) + "(";
for (int i = 0; i < argcount; i++) {
- if (i > 0)
+ if (i > 0) {
err += ",";
+ }
if (p_func->arguments[i + 1]->type == Node::TYPE_CONSTANT && p_func->arguments[i + 1]->get_datatype() == TYPE_INT && static_cast<ConstantNode *>(p_func->arguments[i + 1])->values[0].sint < 0) {
err += "-";
@@ -2340,7 +2356,6 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const Map<Strin
BlockNode *block = p_block;
while (block) {
-
if (block->parent_function) {
exclude_function = block->parent_function->name;
}
@@ -2353,9 +2368,9 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const Map<Strin
}
for (int i = 0; i < shader->functions.size(); i++) {
-
- if (name != shader->functions[i].name)
+ if (name != shader->functions[i].name) {
continue;
+ }
if (!shader->functions[i].callable) {
_set_error("Function '" + String(name) + " can't be called from source code.");
@@ -2364,8 +2379,9 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const Map<Strin
FunctionNode *pfunc = shader->functions[i].function;
- if (pfunc->arguments.size() != args.size())
+ if (pfunc->arguments.size() != args.size()) {
continue;
+ }
bool fail = false;
@@ -2383,10 +2399,8 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const Map<Strin
}
if (!fail) {
-
//implicitly convert values if possible
for (int k = 0; k < args.size(); k++) {
-
if (get_scalar_type(args[k]) != args[k] || args[k] == pfunc->arguments[k].type || p_func->arguments[k + 1]->type != Node::TYPE_CONSTANT) {
//can't do implicit conversion here
continue;
@@ -2430,7 +2444,6 @@ bool ShaderLanguage::_compare_datatypes_in_nodes(Node *a, Node *b) const {
}
bool ShaderLanguage::_parse_function_arguments(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, OperatorNode *p_func, int *r_complete_arg) {
-
TkPos pos = _get_tkpos();
Token tk = _get_token();
@@ -2441,16 +2454,13 @@ bool ShaderLanguage::_parse_function_arguments(BlockNode *p_block, const Map<Str
_set_tkpos(pos);
while (true) {
-
if (r_complete_arg) {
pos = _get_tkpos();
tk = _get_token();
if (tk.type == TK_CURSOR) {
-
*r_complete_arg = p_func->arguments.size() - 1;
} else {
-
_set_tkpos(pos);
}
}
@@ -2458,7 +2468,6 @@ bool ShaderLanguage::_parse_function_arguments(BlockNode *p_block, const Map<Str
Node *arg = _parse_and_reduce_expression(p_block, p_builtin_types);
if (!arg) {
-
return false;
}
@@ -2467,7 +2476,6 @@ bool ShaderLanguage::_parse_function_arguments(BlockNode *p_block, const Map<Str
tk = _get_token();
if (tk.type == TK_PARENTHESIS_CLOSE) {
-
return true;
} else if (tk.type != TK_COMMA) {
// something is broken
@@ -2480,7 +2488,6 @@ bool ShaderLanguage::_parse_function_arguments(BlockNode *p_block, const Map<Str
}
bool ShaderLanguage::is_token_operator(TokenType p_type) {
-
return (p_type == TK_OP_EQUAL ||
p_type == TK_OP_NOT_EQUAL ||
p_type == TK_OP_LESS ||
@@ -2519,7 +2526,6 @@ bool ShaderLanguage::is_token_operator(TokenType p_type) {
}
bool ShaderLanguage::convert_constant(ConstantNode *p_constant, DataType p_to_type, ConstantNode::Value *p_value) {
-
if (p_constant->datatype == p_to_type) {
if (p_value) {
for (int i = 0; i < p_constant->values.size(); i++) {
@@ -2528,13 +2534,11 @@ bool ShaderLanguage::convert_constant(ConstantNode *p_constant, DataType p_to_ty
}
return true;
} else if (p_constant->datatype == TYPE_INT && p_to_type == TYPE_FLOAT) {
-
if (p_value) {
p_value->real = p_constant->values[0].sint;
}
return true;
} else if (p_constant->datatype == TYPE_UINT && p_to_type == TYPE_FLOAT) {
-
if (p_value) {
p_value->real = p_constant->values[0].uint;
}
@@ -2548,7 +2552,6 @@ bool ShaderLanguage::convert_constant(ConstantNode *p_constant, DataType p_to_ty
}
return true;
} else if (p_constant->datatype == TYPE_UINT && p_to_type == TYPE_INT) {
-
if (p_constant->values[0].uint > 0x7FFFFFFF) {
return false;
}
@@ -2556,17 +2559,16 @@ bool ShaderLanguage::convert_constant(ConstantNode *p_constant, DataType p_to_ty
p_value->sint = p_constant->values[0].uint;
}
return true;
- } else
+ } else {
return false;
+ }
}
bool ShaderLanguage::is_scalar_type(DataType p_type) {
-
return p_type == TYPE_BOOL || p_type == TYPE_INT || p_type == TYPE_UINT || p_type == TYPE_FLOAT;
}
bool ShaderLanguage::is_sampler_type(DataType p_type) {
-
return p_type == TYPE_SAMPLER2D ||
p_type == TYPE_ISAMPLER2D ||
p_type == TYPE_USAMPLER2D ||
@@ -2576,7 +2578,8 @@ bool ShaderLanguage::is_sampler_type(DataType p_type) {
p_type == TYPE_SAMPLER3D ||
p_type == TYPE_ISAMPLER3D ||
p_type == TYPE_USAMPLER3D ||
- p_type == TYPE_SAMPLERCUBE;
+ p_type == TYPE_SAMPLERCUBE ||
+ p_type == TYPE_SAMPLERCUBEARRAY;
}
Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::ConstantNode::Value> &p_value, DataType p_type, ShaderLanguage::ShaderNode::Uniform::Hint p_hint) {
@@ -2670,7 +2673,8 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
case ShaderLanguage::TYPE_USAMPLER2DARRAY:
case ShaderLanguage::TYPE_USAMPLER2D:
case ShaderLanguage::TYPE_USAMPLER3D:
- case ShaderLanguage::TYPE_SAMPLERCUBE: {
+ case ShaderLanguage::TYPE_SAMPLERCUBE:
+ case ShaderLanguage::TYPE_SAMPLERCUBEARRAY: {
// Texture types, likely not relevant here.
break;
}
@@ -2678,6 +2682,8 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
break;
case ShaderLanguage::TYPE_VOID:
break;
+ case ShaderLanguage::TYPE_MAX:
+ break;
}
return value;
}
@@ -2687,8 +2693,12 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform &p_uniform) {
PropertyInfo pi;
switch (p_uniform.type) {
- case ShaderLanguage::TYPE_VOID: pi.type = Variant::NIL; break;
- case ShaderLanguage::TYPE_BOOL: pi.type = Variant::BOOL; break;
+ case ShaderLanguage::TYPE_VOID:
+ pi.type = Variant::NIL;
+ break;
+ case ShaderLanguage::TYPE_BOOL:
+ pi.type = Variant::BOOL;
+ break;
case ShaderLanguage::TYPE_BVEC2:
pi.type = Variant::INT;
pi.hint = PROPERTY_HINT_FLAGS;
@@ -2719,7 +2729,6 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform
case ShaderLanguage::TYPE_UVEC2:
case ShaderLanguage::TYPE_UVEC3:
case ShaderLanguage::TYPE_UVEC4: {
-
pi.type = Variant::PACKED_INT32_ARRAY;
} break;
case ShaderLanguage::TYPE_FLOAT: {
@@ -2730,8 +2739,12 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform
}
} break;
- case ShaderLanguage::TYPE_VEC2: pi.type = Variant::VECTOR2; break;
- case ShaderLanguage::TYPE_VEC3: pi.type = Variant::VECTOR3; break;
+ case ShaderLanguage::TYPE_VEC2:
+ pi.type = Variant::VECTOR2;
+ break;
+ case ShaderLanguage::TYPE_VEC3:
+ pi.type = Variant::VECTOR3;
+ break;
case ShaderLanguage::TYPE_VEC4: {
if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
pi.type = Variant::COLOR;
@@ -2739,13 +2752,18 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform
pi.type = Variant::PLANE;
}
} break;
- case ShaderLanguage::TYPE_MAT2: pi.type = Variant::TRANSFORM2D; break;
- case ShaderLanguage::TYPE_MAT3: pi.type = Variant::BASIS; break;
- case ShaderLanguage::TYPE_MAT4: pi.type = Variant::TRANSFORM; break;
+ case ShaderLanguage::TYPE_MAT2:
+ pi.type = Variant::TRANSFORM2D;
+ break;
+ case ShaderLanguage::TYPE_MAT3:
+ pi.type = Variant::BASIS;
+ break;
+ case ShaderLanguage::TYPE_MAT4:
+ pi.type = Variant::TRANSFORM;
+ break;
case ShaderLanguage::TYPE_SAMPLER2D:
case ShaderLanguage::TYPE_ISAMPLER2D:
case ShaderLanguage::TYPE_USAMPLER2D: {
-
pi.type = Variant::OBJECT;
pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
pi.hint_string = "Texture2D";
@@ -2753,10 +2771,9 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform
case ShaderLanguage::TYPE_SAMPLER2DARRAY:
case ShaderLanguage::TYPE_ISAMPLER2DARRAY:
case ShaderLanguage::TYPE_USAMPLER2DARRAY: {
-
pi.type = Variant::OBJECT;
pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
- pi.hint_string = "TextureArray";
+ pi.hint_string = "TextureLayered";
} break;
case ShaderLanguage::TYPE_SAMPLER3D:
case ShaderLanguage::TYPE_ISAMPLER3D:
@@ -2765,15 +2782,17 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform
pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
pi.hint_string = "Texture3D";
} break;
- case ShaderLanguage::TYPE_SAMPLERCUBE: {
-
+ case ShaderLanguage::TYPE_SAMPLERCUBE:
+ case ShaderLanguage::TYPE_SAMPLERCUBEARRAY: {
pi.type = Variant::OBJECT;
pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
- pi.hint_string = "CubeMap";
+ pi.hint_string = "TextureLayered";
} break;
case ShaderLanguage::TYPE_STRUCT: {
// FIXME: Implement this.
} break;
+ case ShaderLanguage::TYPE_MAX:
+ break;
}
return pi;
}
@@ -2818,22 +2837,23 @@ uint32_t ShaderLanguage::get_type_size(DataType p_type) {
case TYPE_ISAMPLER3D:
case TYPE_USAMPLER3D:
case TYPE_SAMPLERCUBE:
+ case TYPE_SAMPLERCUBEARRAY:
return 4; //not really, but useful for indices
case TYPE_STRUCT:
// FIXME: Implement.
return 0;
+ case ShaderLanguage::TYPE_MAX:
+ return 0;
}
return 0;
}
void ShaderLanguage::get_keyword_list(List<String> *r_keywords) {
-
Set<String> kws;
int idx = 0;
while (keyword_list[idx].text) {
-
kws.insert(keyword_list[idx].text);
idx++;
}
@@ -2841,7 +2861,6 @@ void ShaderLanguage::get_keyword_list(List<String> *r_keywords) {
idx = 0;
while (builtin_func_defs[idx].name) {
-
kws.insert(builtin_func_defs[idx].name);
idx++;
@@ -2853,13 +2872,11 @@ void ShaderLanguage::get_keyword_list(List<String> *r_keywords) {
}
void ShaderLanguage::get_builtin_funcs(List<String> *r_keywords) {
-
Set<String> kws;
int idx = 0;
while (builtin_func_defs[idx].name) {
-
kws.insert(builtin_func_defs[idx].name);
idx++;
@@ -2871,7 +2888,6 @@ void ShaderLanguage::get_builtin_funcs(List<String> *r_keywords) {
}
ShaderLanguage::DataType ShaderLanguage::get_scalar_type(DataType p_type) {
-
static const DataType scalar_types[] = {
TYPE_VOID,
TYPE_BOOL,
@@ -2934,7 +2950,6 @@ int ShaderLanguage::get_cardinality(DataType p_type) {
}
bool ShaderLanguage::_get_completable_identifier(BlockNode *p_block, CompletionType p_type, StringName &identifier) {
-
identifier = StringName();
TkPos pos = { 0, 0 };
@@ -2948,7 +2963,6 @@ bool ShaderLanguage::_get_completable_identifier(BlockNode *p_block, CompletionT
}
if (tk.type == TK_CURSOR) {
-
completion_type = p_type;
completion_line = tk_line;
completion_block = p_block;
@@ -2991,9 +3005,7 @@ bool ShaderLanguage::_is_operator_assign(Operator p_op) const {
}
bool ShaderLanguage::_validate_assign(Node *p_node, const Map<StringName, BuiltInInfo> &p_builtin_types, String *r_message) {
-
if (p_node->type == Node::TYPE_OPERATOR) {
-
OperatorNode *op = static_cast<OperatorNode *>(p_node);
if (op->op == OP_INDEX) {
@@ -3004,42 +3016,45 @@ bool ShaderLanguage::_validate_assign(Node *p_node, const Map<StringName, BuiltI
return _validate_assign(op->arguments[1], p_builtin_types, r_message);
} else if (op->op == OP_CALL) {
- if (r_message)
+ if (r_message) {
*r_message = RTR("Assignment to function.");
+ }
return false;
}
} else if (p_node->type == Node::TYPE_MEMBER) {
-
MemberNode *member = static_cast<MemberNode *>(p_node);
if (member->has_swizzling_duplicates) {
- if (r_message)
+ if (r_message) {
*r_message = RTR("Swizzling assignment contains duplicates.");
+ }
return false;
}
return _validate_assign(member->owner, p_builtin_types, r_message);
} else if (p_node->type == Node::TYPE_VARIABLE) {
-
VariableNode *var = static_cast<VariableNode *>(p_node);
if (shader->uniforms.has(var->name)) {
- if (r_message)
+ if (r_message) {
*r_message = RTR("Assignment to uniform.");
+ }
return false;
}
if (shader->varyings.has(var->name) && current_function != String("vertex")) {
- if (r_message)
+ if (r_message) {
*r_message = RTR("Varyings can only be assigned in vertex function.");
+ }
return false;
}
if (shader->constants.has(var->name) || var->is_const) {
- if (r_message)
+ if (r_message) {
*r_message = RTR("Constants cannot be modified.");
+ }
return false;
}
@@ -3047,33 +3062,34 @@ bool ShaderLanguage::_validate_assign(Node *p_node, const Map<StringName, BuiltI
return true;
}
} else if (p_node->type == Node::TYPE_ARRAY) {
-
ArrayNode *arr = static_cast<ArrayNode *>(p_node);
if (arr->is_const) {
- if (r_message)
+ if (r_message) {
*r_message = RTR("Constants cannot be modified.");
+ }
return false;
}
if (shader->varyings.has(arr->name) && current_function != String("vertex")) {
- if (r_message)
+ if (r_message) {
*r_message = RTR("Varyings can only be assigned in vertex function.");
+ }
return false;
}
return true;
}
- if (r_message)
+ if (r_message) {
*r_message = "Assignment to constant expression.";
+ }
return false;
}
bool ShaderLanguage::_propagate_function_call_sampler_uniform_settings(StringName p_name, int p_argument, TextureFilter p_filter, TextureRepeat p_repeat) {
for (int i = 0; shader->functions.size(); i++) {
if (shader->functions[i].name == p_name) {
-
ERR_FAIL_INDEX_V(p_argument, shader->functions[i].function->arguments.size(), false);
FunctionNode::Argument *arg = &shader->functions[i].function->arguments.write[p_argument];
if (arg->tex_builtin_check) {
@@ -3084,12 +3100,10 @@ bool ShaderLanguage::_propagate_function_call_sampler_uniform_settings(StringNam
if (arg->tex_argument_filter == p_filter && arg->tex_argument_repeat == p_repeat) {
return true;
} else {
-
_set_error("Sampler argument #" + itos(p_argument) + " of function '" + String(p_name) + "' called more than once using textures that differ in either filter or repeat setting.");
return false;
}
} else {
-
arg->tex_argument_check = true;
arg->tex_argument_filter = p_filter;
arg->tex_argument_repeat = p_repeat;
@@ -3106,10 +3120,10 @@ bool ShaderLanguage::_propagate_function_call_sampler_uniform_settings(StringNam
}
ERR_FAIL_V(false); //bug? function not found
}
+
bool ShaderLanguage::_propagate_function_call_sampler_builtin_reference(StringName p_name, int p_argument, const StringName &p_builtin) {
for (int i = 0; shader->functions.size(); i++) {
if (shader->functions[i].name == p_name) {
-
ERR_FAIL_INDEX_V(p_argument, shader->functions[i].function->arguments.size(), false);
FunctionNode::Argument *arg = &shader->functions[i].function->arguments.write[p_argument];
if (arg->tex_argument_check) {
@@ -3124,7 +3138,6 @@ bool ShaderLanguage::_propagate_function_call_sampler_builtin_reference(StringNa
return false;
}
} else {
-
arg->tex_builtin_check = true;
arg->tex_builtin = p_builtin;
@@ -3143,14 +3156,12 @@ bool ShaderLanguage::_propagate_function_call_sampler_builtin_reference(StringNa
}
ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types) {
-
Vector<Expression> expression;
//Vector<TokenType> operators;
while (true) {
-
- Node *expr = NULL;
+ Node *expr = nullptr;
TkPos prepos = _get_tkpos();
Token tk = _get_token();
TkPos pos = _get_tkpos();
@@ -3161,19 +3172,18 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
//handle subexpression
expr = _parse_and_reduce_expression(p_block, p_builtin_types);
- if (!expr)
- return NULL;
+ if (!expr) {
+ return nullptr;
+ }
tk = _get_token();
if (tk.type != TK_PARENTHESIS_CLOSE) {
-
_set_error("Expected ')' in expression");
- return NULL;
+ return nullptr;
}
} else if (tk.type == TK_REAL_CONSTANT) {
-
ConstantNode *constant = alloc_node<ConstantNode>();
ConstantNode::Value v;
v.real = tk.constant;
@@ -3182,7 +3192,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
expr = constant;
} else if (tk.type == TK_INT_CONSTANT) {
-
ConstantNode *constant = alloc_node<ConstantNode>();
ConstantNode::Value v;
v.sint = tk.constant;
@@ -3191,7 +3200,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
expr = constant;
} else if (tk.type == TK_TRUE) {
-
//handle true constant
ConstantNode *constant = alloc_node<ConstantNode>();
ConstantNode::Value v;
@@ -3201,7 +3209,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
expr = constant;
} else if (tk.type == TK_FALSE) {
-
//handle false constant
ConstantNode *constant = alloc_node<ConstantNode>();
ConstantNode::Value v;
@@ -3211,10 +3218,9 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
expr = constant;
} else if (tk.type == TK_TYPE_VOID) {
-
//make sure void is not used in expression
_set_error("Void value not allowed in Expression");
- return NULL;
+ return nullptr;
} else if (is_token_nonvoid_datatype(tk.type)) {
//basic type constructor
@@ -3222,7 +3228,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
func->op = OP_CONSTRUCT;
if (is_token_precision(tk.type)) {
-
func->return_precision_cache = get_token_precision(tk.type);
tk = _get_token();
}
@@ -3234,7 +3239,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
tk = _get_token();
if (tk.type != TK_PARENTHESIS_OPEN) {
_set_error("Expected '(' after type name");
- return NULL;
+ return nullptr;
}
int carg = -1;
@@ -3249,23 +3254,23 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
completion_argument = carg;
}
- if (!ok)
- return NULL;
+ if (!ok) {
+ return nullptr;
+ }
if (!_validate_function_call(p_block, p_builtin_types, func, &func->return_cache, &func->struct_name)) {
_set_error("No matching constructor found for: '" + String(funcname->name) + "'");
- return NULL;
+ return nullptr;
}
expr = _reduce_expression(p_block, func);
} else if (tk.type == TK_IDENTIFIER) {
-
_set_tkpos(prepos);
StringName identifier;
- StructNode *pstruct = NULL;
+ StructNode *pstruct = nullptr;
bool struct_init = false;
_get_completable_identifier(p_block, COMPLETION_IDENTIFIER, identifier);
@@ -3277,7 +3282,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
tk = _get_token();
if (tk.type == TK_PARENTHESIS_OPEN) {
-
if (struct_init) { //a struct constructor
const StringName &name = identifier;
@@ -3294,7 +3298,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
Node *nexpr;
if (pstruct->members[i]->array_size != 0) {
-
DataType type = pstruct->members[i]->get_datatype();
String struct_name = pstruct->members[i]->struct_name;
int array_size = pstruct->members[i]->array_size;
@@ -3310,14 +3313,13 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
if (tk.type == TK_CURLY_BRACKET_OPEN) {
auto_size = true;
} else {
-
if (shader->structs.has(tk.text)) {
type2 = TYPE_STRUCT;
struct_name2 = tk.text;
} else {
if (!is_token_variable_datatype(tk.type)) {
_set_error("Invalid data type for array");
- return NULL;
+ return nullptr;
}
type2 = get_token_datatype(tk.type);
}
@@ -3335,7 +3337,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
Node *n = _parse_and_reduce_expression(p_block, p_builtin_types);
if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) {
_set_error("Expected single integer constant > 0");
- return NULL;
+ return nullptr;
}
ConstantNode *cnode = (ConstantNode *)n;
@@ -3343,24 +3345,24 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
array_size2 = cnode->values[0].sint;
if (array_size2 <= 0) {
_set_error("Expected single integer constant > 0");
- return NULL;
+ return nullptr;
}
} else {
_set_error("Expected single integer constant > 0");
- return NULL;
+ return nullptr;
}
tk = _get_token();
if (tk.type != TK_BRACKET_CLOSE) {
_set_error("Expected ']'");
- return NULL;
+ return nullptr;
} else {
tk = _get_token();
}
}
} else {
_set_error("Expected '['");
- return NULL;
+ return nullptr;
}
if (type != type2 || struct_name != struct_name2 || array_size != array_size2) {
@@ -3383,7 +3385,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
error_str += itos(array_size);
error_str += "]'";
_set_error(error_str);
- return NULL;
+ return nullptr;
}
}
@@ -3393,15 +3395,14 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
if (tk.type == TK_PARENTHESIS_OPEN || auto_size) { // initialization
while (true) {
-
Node *n = _parse_and_reduce_expression(p_block, p_builtin_types);
if (!n) {
- return NULL;
+ return nullptr;
}
if (type != n->get_datatype() || struct_name != n->get_datatype_name()) {
_set_error("Invalid assignment of '" + (n->get_datatype() == TYPE_STRUCT ? n->get_datatype_name() : get_datatype_name(n->get_datatype())) + "' to '" + (type == TYPE_STRUCT ? struct_name : get_datatype_name(type)) + "'");
- return NULL;
+ return nullptr;
}
tk = _get_token();
@@ -3415,34 +3416,35 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
an->initializer.push_back(n);
break;
} else {
- if (auto_size)
+ if (auto_size) {
_set_error("Expected '}' or ','");
- else
+ } else {
_set_error("Expected ')' or ','");
- return NULL;
+ }
+ return nullptr;
}
}
if (an->initializer.size() != array_size) {
_set_error("Array size mismatch");
- return NULL;
+ return nullptr;
}
} else {
_set_error("Expected array initialization!");
- return NULL;
+ return nullptr;
}
nexpr = an;
} else {
nexpr = _parse_and_reduce_expression(p_block, p_builtin_types);
if (!nexpr) {
- return NULL;
+ return nullptr;
}
Node *node = pstruct->members[i];
if (!_compare_datatypes_in_nodes(pstruct->members[i], nexpr)) {
String type_name = nexpr->get_datatype() == TYPE_STRUCT ? nexpr->get_datatype_name() : get_datatype_name(nexpr->get_datatype());
String type_name2 = node->get_datatype() == TYPE_STRUCT ? node->get_datatype_name() : get_datatype_name(node->get_datatype());
_set_error("Invalid assignment of '" + type_name + "' to '" + type_name2 + "'");
- return NULL;
+ return nullptr;
}
}
@@ -3450,7 +3452,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
tk = _get_token();
if (tk.type != TK_COMMA) {
_set_error("Expected ','");
- return NULL;
+ return nullptr;
}
}
func->arguments.push_back(nexpr);
@@ -3458,7 +3460,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
tk = _get_token();
if (tk.type != TK_PARENTHESIS_CLOSE) {
_set_error("Expected ')'");
- return NULL;
+ return nullptr;
}
expr = func;
@@ -3482,7 +3484,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
while (bnode) {
if (bnode->variables.has(name)) {
_set_error("Expected function name");
- return NULL;
+ return nullptr;
}
bnode = bnode->parent_block;
}
@@ -3513,12 +3515,13 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
completion_argument = carg;
}
- if (!ok)
- return NULL;
+ if (!ok) {
+ return nullptr;
+ }
if (!_validate_function_call(p_block, p_builtin_types, func, &func->return_cache, &func->struct_name)) {
_set_error("No matching function found for: '" + String(funcname->name) + "'");
- return NULL;
+ return nullptr;
}
completion_class = TAG_GLOBAL; // reset sub-class
if (function_index >= 0) {
@@ -3527,14 +3530,12 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
FunctionNode *call_function = shader->functions[function_index].function;
if (call_function) {
-
//get current base function
- FunctionNode *base_function = NULL;
+ FunctionNode *base_function = nullptr;
{
BlockNode *b = p_block;
while (b) {
-
if (b->parent_function) {
base_function = b->parent_function;
break;
@@ -3544,7 +3545,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
}
- ERR_FAIL_COND_V(!base_function, NULL); //bug, wtf
+ ERR_FAIL_COND_V(!base_function, nullptr); //bug, wtf
for (int i = 0; i < call_function->arguments.size(); i++) {
int argidx = i + 1;
@@ -3556,7 +3557,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
error = true;
} else if (n->type == Node::TYPE_ARRAY) {
ArrayNode *an = static_cast<ArrayNode *>(n);
- if (an->call_expression != NULL) {
+ if (an->call_expression != nullptr) {
error = true;
}
} else if (n->type == Node::TYPE_VARIABLE) {
@@ -3584,7 +3585,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
if (error) {
_set_error(vformat("Constant value cannot be passed for '%s' parameter!", _get_qualifier_str(call_function->arguments[i].qualifier)));
- return NULL;
+ return nullptr;
}
}
if (is_sampler_type(call_function->arguments[i].type)) {
@@ -3599,12 +3600,12 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
ERR_CONTINUE(u->type != call_function->arguments[i].type); //this should have been validated previously
//propagate
if (!_propagate_function_call_sampler_uniform_settings(name, i, u->filter, u->repeat)) {
- return NULL;
+ return nullptr;
}
} else if (p_builtin_types.has(varname)) {
//a built-in
if (!_propagate_function_call_sampler_builtin_reference(name, i, varname)) {
- return NULL;
+ return nullptr;
}
} else {
//or this comes from an argument, but nothing else can be a sampler
@@ -3653,30 +3654,29 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
if (!found) {
_set_error("Unknown identifier in expression: " + String(identifier));
- return NULL;
+ return nullptr;
}
} else {
-
if (!_find_identifier(p_block, false, p_builtin_types, identifier, &data_type, &ident_type, &is_const, &array_size, &struct_name)) {
_set_error("Unknown identifier in expression: " + String(identifier));
- return NULL;
+ return nullptr;
}
if (ident_type == IDENTIFIER_FUNCTION) {
_set_error("Can't use function as identifier: " + String(identifier));
- return NULL;
+ return nullptr;
}
}
- Node *index_expression = NULL;
- Node *call_expression = NULL;
+ Node *index_expression = nullptr;
+ Node *call_expression = nullptr;
if (array_size > 0) {
tk = _get_token();
if (tk.type != TK_BRACKET_OPEN && tk.type != TK_PERIOD) {
_set_error("Expected '[' or '.'");
- return NULL;
+ return nullptr;
}
if (tk.type == TK_PERIOD) {
@@ -3684,18 +3684,20 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
p_block->block_tag = SubClassTag::TAG_ARRAY;
call_expression = _parse_and_reduce_expression(p_block, p_builtin_types);
p_block->block_tag = SubClassTag::TAG_GLOBAL;
- if (!call_expression)
- return NULL;
+ if (!call_expression) {
+ return nullptr;
+ }
data_type = call_expression->get_datatype();
} else { // indexing
index_expression = _parse_and_reduce_expression(p_block, p_builtin_types);
- if (!index_expression)
- return NULL;
+ if (!index_expression) {
+ return nullptr;
+ }
if (index_expression->get_datatype() != TYPE_INT && index_expression->get_datatype() != TYPE_UINT) {
_set_error("Only integer expressions are allowed for indexing");
- return NULL;
+ return nullptr;
}
if (index_expression->type == Node::TYPE_CONSTANT) {
@@ -3705,7 +3707,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
int value = cnode->values[0].sint;
if (value < 0 || value >= array_size) {
_set_error(vformat("Index [%s] out of range [%s..%s]", value, 0, array_size - 1));
- return NULL;
+ return nullptr;
}
}
}
@@ -3714,7 +3716,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
tk = _get_token();
if (tk.type != TK_BRACKET_CLOSE) {
_set_error("Expected ']'");
- return NULL;
+ return nullptr;
}
}
@@ -3728,7 +3730,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
expr = arrname;
} else {
-
VariableNode *varname = alloc_node<VariableNode>();
varname->name = identifier;
varname->datatype_cache = data_type;
@@ -3740,28 +3741,38 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
} else if (tk.type == TK_OP_ADD) {
continue; //this one does nothing
} else if (tk.type == TK_OP_SUB || tk.type == TK_OP_NOT || tk.type == TK_OP_BIT_INVERT || tk.type == TK_OP_INCREMENT || tk.type == TK_OP_DECREMENT) {
-
Expression e;
e.is_op = true;
switch (tk.type) {
- case TK_OP_SUB: e.op = OP_NEGATE; break;
- case TK_OP_NOT: e.op = OP_NOT; break;
- case TK_OP_BIT_INVERT: e.op = OP_BIT_INVERT; break;
- case TK_OP_INCREMENT: e.op = OP_INCREMENT; break;
- case TK_OP_DECREMENT: e.op = OP_DECREMENT; break;
- default: ERR_FAIL_V(NULL);
+ case TK_OP_SUB:
+ e.op = OP_NEGATE;
+ break;
+ case TK_OP_NOT:
+ e.op = OP_NOT;
+ break;
+ case TK_OP_BIT_INVERT:
+ e.op = OP_BIT_INVERT;
+ break;
+ case TK_OP_INCREMENT:
+ e.op = OP_INCREMENT;
+ break;
+ case TK_OP_DECREMENT:
+ e.op = OP_DECREMENT;
+ break;
+ default:
+ ERR_FAIL_V(nullptr);
}
expression.push_back(e);
continue;
} else {
_set_error("Expected expression, found: " + get_token_text(tk));
- return NULL;
+ return nullptr;
//nothing
}
- ERR_FAIL_COND_V(!expr, NULL);
+ ERR_FAIL_COND_V(!expr, nullptr);
/* OK now see what's NEXT to the operator.. */
/* OK now see what's NEXT to the operator.. */
@@ -3774,9 +3785,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
if (tk.type == TK_CURSOR) {
//do nothing
} else if (tk.type == TK_IDENTIFIER) {
-
} else if (tk.type == TK_PERIOD) {
-
DataType dt = expr->get_datatype();
String st = expr->get_datatype_name();
@@ -3791,7 +3800,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
if (identifier == StringName()) {
_set_error("Expected identifier as member");
- return NULL;
+ return nullptr;
}
String ident = identifier;
@@ -3831,7 +3840,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
case TYPE_IVEC2:
case TYPE_UVEC2:
case TYPE_VEC2: {
-
int l = ident.length();
if (l == 1) {
member_type = DataType(dt - 1);
@@ -3848,7 +3856,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
const CharType *c = ident.ptr();
for (int i = 0; i < l; i++) {
-
switch (c[i]) {
case 'r':
case 'g':
@@ -3897,7 +3904,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
case TYPE_IVEC3:
case TYPE_UVEC3:
case TYPE_VEC3: {
-
int l = ident.length();
if (l == 1) {
member_type = DataType(dt - 2);
@@ -3914,7 +3920,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
const CharType *c = ident.ptr();
for (int i = 0; i < l; i++) {
-
switch (c[i]) {
case 'r':
case 'g':
@@ -3966,7 +3971,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
case TYPE_IVEC4:
case TYPE_UVEC4:
case TYPE_VEC4: {
-
int l = ident.length();
if (l == 1) {
member_type = DataType(dt - 3);
@@ -3983,7 +3987,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
const CharType *c = ident.ptr();
for (int i = 0; i < l; i++) {
-
switch (c[i]) {
case 'r':
case 'g':
@@ -4042,12 +4045,12 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
if (mix_error) {
_set_error("Cannot combine symbols from different sets in expression ." + ident);
- return NULL;
+ return nullptr;
}
if (!ok) {
_set_error("Invalid member for " + (dt == TYPE_STRUCT ? st : get_datatype_name(dt)) + " expression: ." + ident);
- return NULL;
+ return nullptr;
}
MemberNode *mn = alloc_node<MemberNode>();
@@ -4062,20 +4065,19 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
mn->has_swizzling_duplicates = repeated;
if (array_size > 0) {
-
tk = _get_token();
if (tk.type == TK_PERIOD) {
_set_error("Nested array length() is not yet implemented");
- return NULL;
+ return nullptr;
} else if (tk.type == TK_BRACKET_OPEN) {
-
Node *index_expression = _parse_and_reduce_expression(p_block, p_builtin_types);
- if (!index_expression)
- return NULL;
+ if (!index_expression) {
+ return nullptr;
+ }
if (index_expression->get_datatype() != TYPE_INT && index_expression->get_datatype() != TYPE_UINT) {
_set_error("Only integer expressions are allowed for indexing");
- return NULL;
+ return nullptr;
}
if (index_expression->type == Node::TYPE_CONSTANT) {
@@ -4085,7 +4087,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
int value = cnode->values[0].sint;
if (value < 0 || value >= array_size) {
_set_error(vformat("Index [%s] out of range [%s..%s]", value, 0, array_size - 1));
- return NULL;
+ return nullptr;
}
}
}
@@ -4094,13 +4096,13 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
tk = _get_token();
if (tk.type != TK_BRACKET_CLOSE) {
_set_error("Expected ']'");
- return NULL;
+ return nullptr;
}
mn->index_expression = index_expression;
} else {
_set_error("Expected '[' or '.'");
- return NULL;
+ return nullptr;
}
}
@@ -4117,14 +4119,14 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
*/
} else if (tk.type == TK_BRACKET_OPEN) {
-
Node *index = _parse_and_reduce_expression(p_block, p_builtin_types);
- if (!index)
- return NULL;
+ if (!index) {
+ return nullptr;
+ }
if (index->get_datatype() != TYPE_INT && index->get_datatype() != TYPE_UINT) {
_set_error("Only integer datatypes are allowed for indexing");
- return NULL;
+ return nullptr;
}
DataType member_type = TYPE_VOID;
@@ -4139,17 +4141,28 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
uint32_t index_constant = static_cast<ConstantNode *>(index)->values[0].uint;
if (index_constant >= 2) {
_set_error("Index out of range (0-1)");
- return NULL;
+ return nullptr;
}
}
switch (expr->get_datatype()) {
- case TYPE_BVEC2: member_type = TYPE_BOOL; break;
- case TYPE_VEC2: member_type = TYPE_FLOAT; break;
- case TYPE_IVEC2: member_type = TYPE_INT; break;
- case TYPE_UVEC2: member_type = TYPE_UINT; break;
- case TYPE_MAT2: member_type = TYPE_VEC2; break;
- default: break;
+ case TYPE_BVEC2:
+ member_type = TYPE_BOOL;
+ break;
+ case TYPE_VEC2:
+ member_type = TYPE_FLOAT;
+ break;
+ case TYPE_IVEC2:
+ member_type = TYPE_INT;
+ break;
+ case TYPE_UVEC2:
+ member_type = TYPE_UINT;
+ break;
+ case TYPE_MAT2:
+ member_type = TYPE_VEC2;
+ break;
+ default:
+ break;
}
break;
@@ -4162,17 +4175,28 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
uint32_t index_constant = static_cast<ConstantNode *>(index)->values[0].uint;
if (index_constant >= 3) {
_set_error("Index out of range (0-2)");
- return NULL;
+ return nullptr;
}
}
switch (expr->get_datatype()) {
- case TYPE_BVEC3: member_type = TYPE_BOOL; break;
- case TYPE_VEC3: member_type = TYPE_FLOAT; break;
- case TYPE_IVEC3: member_type = TYPE_INT; break;
- case TYPE_UVEC3: member_type = TYPE_UINT; break;
- case TYPE_MAT3: member_type = TYPE_VEC3; break;
- default: break;
+ case TYPE_BVEC3:
+ member_type = TYPE_BOOL;
+ break;
+ case TYPE_VEC3:
+ member_type = TYPE_FLOAT;
+ break;
+ case TYPE_IVEC3:
+ member_type = TYPE_INT;
+ break;
+ case TYPE_UVEC3:
+ member_type = TYPE_UINT;
+ break;
+ case TYPE_MAT3:
+ member_type = TYPE_VEC3;
+ break;
+ default:
+ break;
}
break;
case TYPE_BVEC4:
@@ -4184,22 +4208,33 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
uint32_t index_constant = static_cast<ConstantNode *>(index)->values[0].uint;
if (index_constant >= 4) {
_set_error("Index out of range (0-3)");
- return NULL;
+ return nullptr;
}
}
switch (expr->get_datatype()) {
- case TYPE_BVEC4: member_type = TYPE_BOOL; break;
- case TYPE_VEC4: member_type = TYPE_FLOAT; break;
- case TYPE_IVEC4: member_type = TYPE_INT; break;
- case TYPE_UVEC4: member_type = TYPE_UINT; break;
- case TYPE_MAT4: member_type = TYPE_VEC4; break;
- default: break;
+ case TYPE_BVEC4:
+ member_type = TYPE_BOOL;
+ break;
+ case TYPE_VEC4:
+ member_type = TYPE_FLOAT;
+ break;
+ case TYPE_IVEC4:
+ member_type = TYPE_INT;
+ break;
+ case TYPE_UVEC4:
+ member_type = TYPE_UINT;
+ break;
+ case TYPE_MAT4:
+ member_type = TYPE_VEC4;
+ break;
+ default:
+ break;
}
break;
default: {
_set_error("Object of type '" + (expr->get_datatype() == TYPE_STRUCT ? expr->get_datatype_name() : get_datatype_name(expr->get_datatype())) + "' can't be indexed");
- return NULL;
+ return nullptr;
}
}
@@ -4213,27 +4248,25 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
tk = _get_token();
if (tk.type != TK_BRACKET_CLOSE) {
_set_error("Expected ']' after indexing expression");
- return NULL;
+ return nullptr;
}
} else if (tk.type == TK_OP_INCREMENT || tk.type == TK_OP_DECREMENT) {
-
OperatorNode *op = alloc_node<OperatorNode>();
op->op = tk.type == TK_OP_DECREMENT ? OP_POST_DECREMENT : OP_POST_INCREMENT;
op->arguments.push_back(expr);
if (!_validate_operator(op, &op->return_cache)) {
_set_error("Invalid base type for increment/decrement operator");
- return NULL;
+ return nullptr;
}
if (!_validate_assign(expr, p_builtin_types)) {
_set_error("Invalid use of increment/decrement operator in constant expression.");
- return NULL;
+ return nullptr;
}
expr = op;
} else {
-
_set_tkpos(pos2);
break;
}
@@ -4248,46 +4281,106 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
tk = _get_token();
if (is_token_operator(tk.type)) {
-
Expression o;
o.is_op = true;
switch (tk.type) {
-
- case TK_OP_EQUAL: o.op = OP_EQUAL; break;
- case TK_OP_NOT_EQUAL: o.op = OP_NOT_EQUAL; break;
- case TK_OP_LESS: o.op = OP_LESS; break;
- case TK_OP_LESS_EQUAL: o.op = OP_LESS_EQUAL; break;
- case TK_OP_GREATER: o.op = OP_GREATER; break;
- case TK_OP_GREATER_EQUAL: o.op = OP_GREATER_EQUAL; break;
- case TK_OP_AND: o.op = OP_AND; break;
- case TK_OP_OR: o.op = OP_OR; break;
- case TK_OP_ADD: o.op = OP_ADD; break;
- case TK_OP_SUB: o.op = OP_SUB; break;
- case TK_OP_MUL: o.op = OP_MUL; break;
- case TK_OP_DIV: o.op = OP_DIV; break;
- case TK_OP_MOD: o.op = OP_MOD; break;
- case TK_OP_SHIFT_LEFT: o.op = OP_SHIFT_LEFT; break;
- case TK_OP_SHIFT_RIGHT: o.op = OP_SHIFT_RIGHT; break;
- case TK_OP_ASSIGN: o.op = OP_ASSIGN; break;
- case TK_OP_ASSIGN_ADD: o.op = OP_ASSIGN_ADD; break;
- case TK_OP_ASSIGN_SUB: o.op = OP_ASSIGN_SUB; break;
- case TK_OP_ASSIGN_MUL: o.op = OP_ASSIGN_MUL; break;
- case TK_OP_ASSIGN_DIV: o.op = OP_ASSIGN_DIV; break;
- case TK_OP_ASSIGN_MOD: o.op = OP_ASSIGN_MOD; break;
- case TK_OP_ASSIGN_SHIFT_LEFT: o.op = OP_ASSIGN_SHIFT_LEFT; break;
- case TK_OP_ASSIGN_SHIFT_RIGHT: o.op = OP_ASSIGN_SHIFT_RIGHT; break;
- case TK_OP_ASSIGN_BIT_AND: o.op = OP_ASSIGN_BIT_AND; break;
- case TK_OP_ASSIGN_BIT_OR: o.op = OP_ASSIGN_BIT_OR; break;
- case TK_OP_ASSIGN_BIT_XOR: o.op = OP_ASSIGN_BIT_XOR; break;
- case TK_OP_BIT_AND: o.op = OP_BIT_AND; break;
- case TK_OP_BIT_OR: o.op = OP_BIT_OR; break;
- case TK_OP_BIT_XOR: o.op = OP_BIT_XOR; break;
- case TK_QUESTION: o.op = OP_SELECT_IF; break;
- case TK_COLON: o.op = OP_SELECT_ELSE; break;
+ case TK_OP_EQUAL:
+ o.op = OP_EQUAL;
+ break;
+ case TK_OP_NOT_EQUAL:
+ o.op = OP_NOT_EQUAL;
+ break;
+ case TK_OP_LESS:
+ o.op = OP_LESS;
+ break;
+ case TK_OP_LESS_EQUAL:
+ o.op = OP_LESS_EQUAL;
+ break;
+ case TK_OP_GREATER:
+ o.op = OP_GREATER;
+ break;
+ case TK_OP_GREATER_EQUAL:
+ o.op = OP_GREATER_EQUAL;
+ break;
+ case TK_OP_AND:
+ o.op = OP_AND;
+ break;
+ case TK_OP_OR:
+ o.op = OP_OR;
+ break;
+ case TK_OP_ADD:
+ o.op = OP_ADD;
+ break;
+ case TK_OP_SUB:
+ o.op = OP_SUB;
+ break;
+ case TK_OP_MUL:
+ o.op = OP_MUL;
+ break;
+ case TK_OP_DIV:
+ o.op = OP_DIV;
+ break;
+ case TK_OP_MOD:
+ o.op = OP_MOD;
+ break;
+ case TK_OP_SHIFT_LEFT:
+ o.op = OP_SHIFT_LEFT;
+ break;
+ case TK_OP_SHIFT_RIGHT:
+ o.op = OP_SHIFT_RIGHT;
+ break;
+ case TK_OP_ASSIGN:
+ o.op = OP_ASSIGN;
+ break;
+ case TK_OP_ASSIGN_ADD:
+ o.op = OP_ASSIGN_ADD;
+ break;
+ case TK_OP_ASSIGN_SUB:
+ o.op = OP_ASSIGN_SUB;
+ break;
+ case TK_OP_ASSIGN_MUL:
+ o.op = OP_ASSIGN_MUL;
+ break;
+ case TK_OP_ASSIGN_DIV:
+ o.op = OP_ASSIGN_DIV;
+ break;
+ case TK_OP_ASSIGN_MOD:
+ o.op = OP_ASSIGN_MOD;
+ break;
+ case TK_OP_ASSIGN_SHIFT_LEFT:
+ o.op = OP_ASSIGN_SHIFT_LEFT;
+ break;
+ case TK_OP_ASSIGN_SHIFT_RIGHT:
+ o.op = OP_ASSIGN_SHIFT_RIGHT;
+ break;
+ case TK_OP_ASSIGN_BIT_AND:
+ o.op = OP_ASSIGN_BIT_AND;
+ break;
+ case TK_OP_ASSIGN_BIT_OR:
+ o.op = OP_ASSIGN_BIT_OR;
+ break;
+ case TK_OP_ASSIGN_BIT_XOR:
+ o.op = OP_ASSIGN_BIT_XOR;
+ break;
+ case TK_OP_BIT_AND:
+ o.op = OP_BIT_AND;
+ break;
+ case TK_OP_BIT_OR:
+ o.op = OP_BIT_OR;
+ break;
+ case TK_OP_BIT_XOR:
+ o.op = OP_BIT_XOR;
+ break;
+ case TK_QUESTION:
+ o.op = OP_SELECT_IF;
+ break;
+ case TK_COLON:
+ o.op = OP_SELECT_ELSE;
+ break;
default: {
_set_error("Invalid token for operator: " + get_token_text(tk));
- return NULL;
+ return nullptr;
}
}
@@ -4302,16 +4395,13 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
/* Reduce the set set of expressions and place them in an operator tree, respecting precedence */
while (expression.size() > 1) {
-
int next_op = -1;
int min_priority = 0xFFFFF;
bool is_unary = false;
bool is_ternary = false;
for (int i = 0; i < expression.size(); i++) {
-
if (!expression[i].is_op) {
-
continue;
}
@@ -4320,14 +4410,30 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
int priority;
switch (expression[i].op) {
- case OP_EQUAL: priority = 8; break;
- case OP_NOT_EQUAL: priority = 8; break;
- case OP_LESS: priority = 7; break;
- case OP_LESS_EQUAL: priority = 7; break;
- case OP_GREATER: priority = 7; break;
- case OP_GREATER_EQUAL: priority = 7; break;
- case OP_AND: priority = 12; break;
- case OP_OR: priority = 14; break;
+ case OP_EQUAL:
+ priority = 8;
+ break;
+ case OP_NOT_EQUAL:
+ priority = 8;
+ break;
+ case OP_LESS:
+ priority = 7;
+ break;
+ case OP_LESS_EQUAL:
+ priority = 7;
+ break;
+ case OP_GREATER:
+ priority = 7;
+ break;
+ case OP_GREATER_EQUAL:
+ priority = 7;
+ break;
+ case OP_AND:
+ priority = 12;
+ break;
+ case OP_OR:
+ priority = 14;
+ break;
case OP_NOT:
priority = 3;
unary = true;
@@ -4336,27 +4442,69 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
priority = 3;
unary = true;
break;
- case OP_ADD: priority = 5; break;
- case OP_SUB: priority = 5; break;
- case OP_MUL: priority = 4; break;
- case OP_DIV: priority = 4; break;
- case OP_MOD: priority = 4; break;
- case OP_SHIFT_LEFT: priority = 6; break;
- case OP_SHIFT_RIGHT: priority = 6; break;
- case OP_ASSIGN: priority = 16; break;
- case OP_ASSIGN_ADD: priority = 16; break;
- case OP_ASSIGN_SUB: priority = 16; break;
- case OP_ASSIGN_MUL: priority = 16; break;
- case OP_ASSIGN_DIV: priority = 16; break;
- case OP_ASSIGN_MOD: priority = 16; break;
- case OP_ASSIGN_SHIFT_LEFT: priority = 16; break;
- case OP_ASSIGN_SHIFT_RIGHT: priority = 16; break;
- case OP_ASSIGN_BIT_AND: priority = 16; break;
- case OP_ASSIGN_BIT_OR: priority = 16; break;
- case OP_ASSIGN_BIT_XOR: priority = 16; break;
- case OP_BIT_AND: priority = 9; break;
- case OP_BIT_OR: priority = 11; break;
- case OP_BIT_XOR: priority = 10; break;
+ case OP_ADD:
+ priority = 5;
+ break;
+ case OP_SUB:
+ priority = 5;
+ break;
+ case OP_MUL:
+ priority = 4;
+ break;
+ case OP_DIV:
+ priority = 4;
+ break;
+ case OP_MOD:
+ priority = 4;
+ break;
+ case OP_SHIFT_LEFT:
+ priority = 6;
+ break;
+ case OP_SHIFT_RIGHT:
+ priority = 6;
+ break;
+ case OP_ASSIGN:
+ priority = 16;
+ break;
+ case OP_ASSIGN_ADD:
+ priority = 16;
+ break;
+ case OP_ASSIGN_SUB:
+ priority = 16;
+ break;
+ case OP_ASSIGN_MUL:
+ priority = 16;
+ break;
+ case OP_ASSIGN_DIV:
+ priority = 16;
+ break;
+ case OP_ASSIGN_MOD:
+ priority = 16;
+ break;
+ case OP_ASSIGN_SHIFT_LEFT:
+ priority = 16;
+ break;
+ case OP_ASSIGN_SHIFT_RIGHT:
+ priority = 16;
+ break;
+ case OP_ASSIGN_BIT_AND:
+ priority = 16;
+ break;
+ case OP_ASSIGN_BIT_OR:
+ priority = 16;
+ break;
+ case OP_ASSIGN_BIT_XOR:
+ priority = 16;
+ break;
+ case OP_BIT_AND:
+ priority = 9;
+ break;
+ case OP_BIT_OR:
+ priority = 11;
+ break;
+ case OP_BIT_XOR:
+ priority = 10;
+ break;
case OP_BIT_INVERT:
priority = 3;
unary = true;
@@ -4379,7 +4527,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
break;
default:
- ERR_FAIL_V(NULL); //unexpected operator
+ ERR_FAIL_V(nullptr); //unexpected operator
}
if (priority < min_priority) {
@@ -4392,32 +4540,28 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
}
- ERR_FAIL_COND_V(next_op == -1, NULL);
+ ERR_FAIL_COND_V(next_op == -1, nullptr);
// OK! create operator..
// OK! create operator..
if (is_unary) {
-
int expr_pos = next_op;
while (expression[expr_pos].is_op) {
-
expr_pos++;
if (expr_pos == expression.size()) {
//can happen..
_set_error("Unexpected end of expression...");
- return NULL;
+ return nullptr;
}
}
//consecutively do unary operators
for (int i = expr_pos - 1; i >= next_op; i--) {
-
OperatorNode *op = alloc_node<OperatorNode>();
op->op = expression[i].op;
if ((op->op == OP_INCREMENT || op->op == OP_DECREMENT) && !_validate_assign(expression[i + 1].node, p_builtin_types)) {
-
_set_error("Can't use increment/decrement operator in constant expression.");
- return NULL;
+ return nullptr;
}
op->arguments.push_back(expression[i + 1].node);
@@ -4425,29 +4569,28 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
expression.write[i].node = op;
if (!_validate_operator(op, &op->return_cache)) {
-
String at;
for (int j = 0; j < op->arguments.size(); j++) {
- if (j > 0)
+ if (j > 0) {
at += " and ";
+ }
at += get_datatype_name(op->arguments[j]->get_datatype());
}
_set_error("Invalid arguments to unary operator '" + get_operator_text(op->op) + "' :" + at);
- return NULL;
+ return nullptr;
}
expression.remove(i + 1);
}
} else if (is_ternary) {
-
if (next_op < 1 || next_op >= (expression.size() - 1)) {
_set_error("Parser bug...");
- ERR_FAIL_V(NULL);
+ ERR_FAIL_V(nullptr);
}
if (next_op + 2 >= expression.size() || !expression[next_op + 2].is_op || expression[next_op + 2].op != OP_SELECT_ELSE) {
_set_error("Missing matching ':' for select operator");
- return NULL;
+ return nullptr;
}
OperatorNode *op = alloc_node<OperatorNode>();
@@ -4459,15 +4602,15 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
expression.write[next_op - 1].is_op = false;
expression.write[next_op - 1].node = op;
if (!_validate_operator(op, &op->return_cache)) {
-
String at;
for (int i = 0; i < op->arguments.size(); i++) {
- if (i > 0)
+ if (i > 0) {
at += " and ";
+ }
at += get_datatype_name(op->arguments[i]->get_datatype());
}
_set_error("Invalid argument to ternary ?: operator: " + at);
- return NULL;
+ return nullptr;
}
for (int i = 0; i < 4; i++) {
@@ -4475,28 +4618,24 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
} else {
-
if (next_op < 1 || next_op >= (expression.size() - 1)) {
_set_error("Parser bug...");
- ERR_FAIL_V(NULL);
+ ERR_FAIL_V(nullptr);
}
OperatorNode *op = alloc_node<OperatorNode>();
op->op = expression[next_op].op;
if (expression[next_op - 1].is_op) {
-
_set_error("Parser bug...");
- ERR_FAIL_V(NULL);
+ ERR_FAIL_V(nullptr);
}
if (_is_operator_assign(op->op)) {
-
String assign_message;
if (!_validate_assign(expression[next_op - 1].node, p_builtin_types, &assign_message)) {
-
_set_error(assign_message);
- return NULL;
+ return nullptr;
}
}
@@ -4516,11 +4655,11 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
//replace all 3 nodes by this operator and make it an expression
if (!_validate_operator(op, &op->return_cache)) {
-
String at;
for (int i = 0; i < op->arguments.size(); i++) {
- if (i > 0)
+ if (i > 0) {
at += " and ";
+ }
if (op->arguments[i]->get_datatype() == TYPE_STRUCT) {
at += op->arguments[i]->get_datatype_name();
} else {
@@ -4528,7 +4667,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
}
_set_error("Invalid arguments to operator '" + get_operator_text(op->op) + "' :" + at);
- return NULL;
+ return nullptr;
}
expression.remove(next_op);
@@ -4540,15 +4679,14 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
ShaderLanguage::Node *ShaderLanguage::_reduce_expression(BlockNode *p_block, ShaderLanguage::Node *p_node) {
-
- if (p_node->type != Node::TYPE_OPERATOR)
+ if (p_node->type != Node::TYPE_OPERATOR) {
return p_node;
+ }
//for now only reduce simple constructors
OperatorNode *op = static_cast<OperatorNode *>(p_node);
if (op->op == OP_CONSTRUCT) {
-
ERR_FAIL_COND_V(op->arguments[0]->type != Node::TYPE_VARIABLE, p_node);
DataType type = op->get_datatype();
@@ -4558,7 +4696,6 @@ ShaderLanguage::Node *ShaderLanguage::_reduce_expression(BlockNode *p_block, Sha
Vector<ConstantNode::Value> values;
for (int i = 1; i < op->arguments.size(); i++) {
-
op->arguments.write[i] = _reduce_expression(p_block, op->arguments[i]);
if (op->arguments[i]->type == Node::TYPE_CONSTANT) {
ConstantNode *cn = static_cast<ConstantNode *>(op->arguments[i]);
@@ -4568,7 +4705,6 @@ ShaderLanguage::Node *ShaderLanguage::_reduce_expression(BlockNode *p_block, Sha
values.push_back(cn->values[j]);
}
} else if (get_scalar_type(cn->datatype) == cn->datatype) {
-
ConstantNode::Value v;
if (!convert_constant(cn, base, &v)) {
return p_node;
@@ -4612,10 +4748,8 @@ ShaderLanguage::Node *ShaderLanguage::_reduce_expression(BlockNode *p_block, Sha
cn->values = values;
return cn;
} else if (op->op == OP_NEGATE) {
-
op->arguments.write[0] = _reduce_expression(p_block, op->arguments[0]);
if (op->arguments[0]->type == Node::TYPE_CONSTANT) {
-
ConstantNode *cn = static_cast<ConstantNode *>(op->arguments[0]);
DataType base = get_scalar_type(cn->datatype);
@@ -4623,7 +4757,6 @@ ShaderLanguage::Node *ShaderLanguage::_reduce_expression(BlockNode *p_block, Sha
Vector<ConstantNode::Value> values;
for (int i = 0; i < cn->values.size(); i++) {
-
ConstantNode::Value nv;
switch (base) {
case TYPE_BOOL: {
@@ -4655,10 +4788,10 @@ ShaderLanguage::Node *ShaderLanguage::_reduce_expression(BlockNode *p_block, Sha
}
ShaderLanguage::Node *ShaderLanguage::_parse_and_reduce_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types) {
-
ShaderLanguage::Node *expr = _parse_expression(p_block, p_builtin_types);
- if (!expr) //errored
- return NULL;
+ if (!expr) { //errored
+ return nullptr;
+ }
expr = _reduce_expression(p_block, expr);
@@ -4666,9 +4799,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_and_reduce_expression(BlockNode *p_
}
Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, bool p_just_one, bool p_can_break, bool p_can_continue) {
-
while (true) {
-
TkPos pos = _get_tkpos();
Token tk = _get_token();
@@ -4741,10 +4872,9 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
tk = _get_token();
- Node *vardecl = NULL;
+ Node *vardecl = nullptr;
while (true) {
-
if (tk.type != TK_IDENTIFIER) {
_set_error("Expected identifier after type");
return ERR_PARSE_ERROR;
@@ -4752,7 +4882,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
StringName name = tk.text;
ShaderLanguage::IdentifierType itype;
- if (_find_identifier(p_block, true, p_builtin_types, name, (ShaderLanguage::DataType *)0, &itype)) {
+ if (_find_identifier(p_block, true, p_builtin_types, name, (ShaderLanguage::DataType *)nullptr, &itype)) {
if (itype != IDENTIFIER_FUNCTION) {
_set_error("Redefinition of '" + String(name) + "'");
return ERR_PARSE_ERROR;
@@ -4797,7 +4927,6 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
if (tk.type == TK_BRACKET_CLOSE) {
unknown_size = true;
} else {
-
if (tk.type != TK_INT_CONSTANT || ((int)tk.constant) <= 0) {
_set_error("Expected integer constant > 0 or ']'");
return ERR_PARSE_ERROR;
@@ -4817,7 +4946,6 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
tk = _get_token();
if (tk.type == TK_OP_ASSIGN) {
-
if (RenderingServer::get_singleton()->is_low_end()) {
_set_error("Array initialization is supported only on high-end platform!");
return ERR_PARSE_ERROR;
@@ -4826,7 +4954,6 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
tk = _get_token();
if (tk.type != TK_CURLY_BRACKET_OPEN) {
-
if (unknown_size) {
_set_error("Expected '{'");
return ERR_PARSE_ERROR;
@@ -4955,7 +5082,6 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
if (tk.type == TK_PARENTHESIS_OPEN || curly) { // initialization
while (true) {
-
Node *n = _parse_and_reduce_expression(p_block, p_builtin_types);
if (!n) {
return ERR_PARSE_ERROR;
@@ -4982,10 +5108,11 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
decl.initializer.push_back(n);
break;
} else {
- if (curly)
+ if (curly) {
_set_error("Expected '}' or ','");
- else
+ } else {
_set_error("Expected ')' or ','");
+ }
return ERR_PARSE_ERROR;
}
}
@@ -5011,7 +5138,6 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
node->declarations.push_back(decl);
} else if (tk.type == TK_OP_ASSIGN) {
-
VariableDeclarationNode *node = alloc_node<VariableDeclarationNode>();
if (is_struct) {
node->struct_name = struct_name;
@@ -5025,12 +5151,13 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
VariableDeclarationNode::Declaration decl;
decl.name = name;
- decl.initializer = NULL;
+ decl.initializer = nullptr;
//variable created with assignment! must parse an expression
Node *n = _parse_and_reduce_expression(p_block, p_builtin_types);
- if (!n)
+ if (!n) {
return ERR_PARSE_ERROR;
+ }
if (node->is_const && n->type == Node::TYPE_OPERATOR && ((OperatorNode *)n)->op == OP_CALL) {
_set_error("Expected constant expression after '='");
return ERR_PARSE_ERROR;
@@ -5061,7 +5188,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
VariableDeclarationNode::Declaration decl;
decl.name = name;
- decl.initializer = NULL;
+ decl.initializer = nullptr;
node->declarations.push_back(decl);
}
@@ -5102,8 +5229,9 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
ControlFlowNode *cf = alloc_node<ControlFlowNode>();
cf->flow_op = FLOW_OP_IF;
Node *n = _parse_and_reduce_expression(p_block, p_builtin_types);
- if (!n)
+ if (!n) {
return ERR_PARSE_ERROR;
+ }
if (n->get_datatype() != TYPE_BOOL) {
_set_error("Expected boolean expression");
@@ -5123,13 +5251,13 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
p_block->statements.push_back(cf);
Error err = _parse_block(block, p_builtin_types, true, p_can_break, p_can_continue);
- if (err)
+ if (err) {
return err;
+ }
pos = _get_tkpos();
tk = _get_token();
if (tk.type == TK_CF_ELSE) {
-
block = alloc_node<BlockNode>();
block->parent_block = p_block;
cf->blocks.push_back(block);
@@ -5139,7 +5267,6 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
_set_tkpos(pos); //rollback
}
} else if (tk.type == TK_CF_SWITCH) {
-
if (RenderingServer::get_singleton()->is_low_end()) {
_set_error("\"switch\" operator is supported only on high-end platform!");
return ERR_PARSE_ERROR;
@@ -5154,8 +5281,9 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
ControlFlowNode *cf = alloc_node<ControlFlowNode>();
cf->flow_op = FLOW_OP_SWITCH;
Node *n = _parse_and_reduce_expression(p_block, p_builtin_types);
- if (!n)
+ if (!n) {
return ERR_PARSE_ERROR;
+ }
if (n->get_datatype() != TYPE_INT) {
_set_error("Expected integer expression");
return ERR_PARSE_ERROR;
@@ -5282,13 +5410,13 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
p_block->statements.push_back(cf);
Error err = _parse_block(case_block, p_builtin_types, false, true, false);
- if (err)
+ if (err) {
return err;
+ }
return OK;
} else if (tk.type == TK_CF_DEFAULT) {
-
if (p_block && p_block->block_type == BlockNode::BLOCK_TYPE_CASE) {
_set_tkpos(pos);
return OK;
@@ -5316,8 +5444,9 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
p_block->statements.push_back(cf);
Error err = _parse_block(default_block, p_builtin_types, false, true, false);
- if (err)
+ if (err) {
return err;
+ }
return OK;
@@ -5326,15 +5455,15 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
// while() {}
bool is_do = tk.type == TK_CF_DO;
- BlockNode *do_block = NULL;
+ BlockNode *do_block = nullptr;
if (is_do) {
-
do_block = alloc_node<BlockNode>();
do_block->parent_block = p_block;
Error err = _parse_block(do_block, p_builtin_types, true, true, true);
- if (err)
+ if (err) {
return err;
+ }
tk = _get_token();
if (tk.type != TK_CF_WHILE) {
@@ -5356,8 +5485,9 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
cf->flow_op = FLOW_OP_WHILE;
}
Node *n = _parse_and_reduce_expression(p_block, p_builtin_types);
- if (!n)
+ if (!n) {
return ERR_PARSE_ERROR;
+ }
tk = _get_token();
if (tk.type != TK_PARENTHESIS_CLOSE) {
@@ -5372,10 +5502,10 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
p_block->statements.push_back(cf);
Error err = _parse_block(block, p_builtin_types, true, true, true);
- if (err)
+ if (err) {
return err;
+ }
} else {
-
cf->expressions.push_back(n);
cf->blocks.push_back(do_block);
p_block->statements.push_back(cf);
@@ -5407,8 +5537,9 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
}
Node *n = _parse_and_reduce_expression(init_block, p_builtin_types);
- if (!n)
+ if (!n) {
return ERR_PARSE_ERROR;
+ }
if (n->get_datatype() != TYPE_BOOL) {
_set_error("Middle expression is expected to be boolean.");
@@ -5424,8 +5555,9 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
cf->expressions.push_back(n);
n = _parse_and_reduce_expression(init_block, p_builtin_types);
- if (!n)
+ if (!n) {
return ERR_PARSE_ERROR;
+ }
cf->expressions.push_back(n);
@@ -5441,11 +5573,11 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
p_block->statements.push_back(cf);
Error err = _parse_block(block, p_builtin_types, true, true, true);
- if (err)
+ if (err) {
return err;
+ }
} else if (tk.type == TK_CF_RETURN) {
-
//check return type
BlockNode *b = p_block;
while (b && !b->parent_function) {
@@ -5471,8 +5603,9 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
} else {
_set_tkpos(pos); //rollback, wants expression
Node *expr = _parse_and_reduce_expression(p_block, p_builtin_types);
- if (!expr)
+ if (!expr) {
return ERR_PARSE_ERROR;
+ }
if (b->parent_function->return_type != expr->get_datatype()) {
_set_error("Expected return expression of type '" + get_datatype_name(b->parent_function->return_type) + "'");
@@ -5498,7 +5631,6 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
block = block->parent_block;
}
} else if (tk.type == TK_CF_DISCARD) {
-
//check return type
BlockNode *b = p_block;
while (b && !b->parent_function) {
@@ -5526,7 +5658,6 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
p_block->statements.push_back(flow);
} else if (tk.type == TK_CF_BREAK) {
-
if (!p_can_break) {
//all is good
_set_error("Breaking is not allowed here");
@@ -5553,7 +5684,6 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
}
} else if (tk.type == TK_CF_CONTINUE) {
-
if (!p_can_continue) {
//all is good
_set_error("Continuing is not allowed here");
@@ -5572,12 +5702,12 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
p_block->statements.push_back(flow);
} else {
-
//nothing else, so expression
_set_tkpos(pos); //rollback
Node *expr = _parse_and_reduce_expression(p_block, p_builtin_types);
- if (!expr)
+ if (!expr) {
return ERR_PARSE_ERROR;
+ }
p_block->statements.push_back(expr);
tk = _get_token();
@@ -5587,15 +5717,15 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
}
}
- if (p_just_one)
+ if (p_just_one) {
break;
+ }
}
return OK;
}
String ShaderLanguage::_get_shader_type_list(const Set<String> &p_shader_types) const {
-
// Return a list of shader types as an human-readable string
String valid_types;
for (const Set<String>::Element *E = p_shader_types.front(); E; E = E->next()) {
@@ -5651,7 +5781,6 @@ Error ShaderLanguage::_validate_datatype(DataType p_type) {
}
Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types) {
-
Token tk = _get_token();
if (tk.type != TK_SHADER_TYPE) {
@@ -5685,16 +5814,15 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
int texture_uniforms = 0;
int uniforms = 0;
+ int instance_index = 0;
+ ShaderNode::Uniform::Scope uniform_scope = ShaderNode::Uniform::SCOPE_LOCAL;
while (tk.type != TK_EOF) {
-
switch (tk.type) {
case TK_RENDER_MODE: {
-
while (true) {
-
StringName mode;
- _get_completable_identifier(NULL, COMPLETION_RENDER_MODE, mode);
+ _get_completable_identifier(nullptr, COMPLETION_RENDER_MODE, mode);
if (mode == StringName()) {
_set_error("Expected identifier for render mode");
@@ -5853,9 +5981,28 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
shader->vstructs.push_back(st); // struct's order is important!
} break;
+ case TK_GLOBAL: {
+ tk = _get_token();
+ if (tk.type != TK_UNIFORM) {
+ _set_error("Expected 'uniform' after 'global'");
+ return ERR_PARSE_ERROR;
+ }
+ uniform_scope = ShaderNode::Uniform::SCOPE_GLOBAL;
+ };
+ [[fallthrough]];
+ case TK_INSTANCE: {
+ if (uniform_scope == ShaderNode::Uniform::SCOPE_LOCAL) {
+ tk = _get_token();
+ if (tk.type != TK_UNIFORM) {
+ _set_error("Expected 'uniform' after 'instance'");
+ return ERR_PARSE_ERROR;
+ }
+ uniform_scope = ShaderNode::Uniform::SCOPE_INSTANCE;
+ }
+ };
+ [[fallthrough]];
case TK_UNIFORM:
case TK_VARYING: {
-
bool uniform = tk.type == TK_UNIFORM;
DataPrecision precision = PRECISION_DEFAULT;
DataInterpolation interpolation = INTERPOLATION_SMOOTH;
@@ -5898,7 +6045,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
name = tk.text;
- if (_find_identifier(NULL, false, Map<StringName, BuiltInInfo>(), name)) {
+ if (_find_identifier(nullptr, false, Map<StringName, BuiltInInfo>(), name)) {
_set_error("Redefinition of '" + String(name) + "'");
return ERR_PARSE_ERROR;
}
@@ -5909,26 +6056,50 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
if (uniform) {
+ if (uniform_scope == ShaderNode::Uniform::SCOPE_GLOBAL) {
+ //validate global uniform
+ DataType gvtype = global_var_get_type_func(name);
+ if (gvtype == TYPE_MAX) {
+ _set_error("Global uniform '" + String(name) + "' does not exist. Create it in Project Settings.");
+ return ERR_PARSE_ERROR;
+ }
+ if (type != gvtype) {
+ _set_error("Global uniform '" + String(name) + "' must be of type '" + get_datatype_name(gvtype) + "'.");
+ return ERR_PARSE_ERROR;
+ }
+ }
ShaderNode::Uniform uniform2;
if (is_sampler_type(type)) {
+ if (uniform_scope == ShaderNode::Uniform::SCOPE_INSTANCE) {
+ _set_error("Uniforms with 'instance' qualifiers can't be of sampler type.");
+ return ERR_PARSE_ERROR;
+ }
uniform2.texture_order = texture_uniforms++;
uniform2.order = -1;
if (_validate_datatype(type) != OK) {
return ERR_PARSE_ERROR;
}
} else {
+ if (uniform_scope == ShaderNode::Uniform::SCOPE_INSTANCE && (type == TYPE_MAT2 || type == TYPE_MAT3 || type == TYPE_MAT4)) {
+ _set_error("Uniforms with 'instance' qualifiers can't be of matrix type.");
+ return ERR_PARSE_ERROR;
+ }
+
uniform2.texture_order = -1;
uniform2.order = uniforms++;
}
uniform2.type = type;
+ uniform2.scope = uniform_scope;
uniform2.precision = precision;
//todo parse default value
tk = _get_token();
+ int custom_instance_index = -1;
+
if (tk.type == TK_COLON) {
//hint
do {
@@ -5964,7 +6135,6 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
uniform2.hint = ShaderNode::Uniform::HINT_COLOR;
} else if (tk.type == TK_HINT_RANGE) {
-
uniform2.hint = ShaderNode::Uniform::HINT_RANGE;
if (type != TYPE_FLOAT && type != TYPE_INT) {
_set_error("Range hint is for float and int only");
@@ -6039,7 +6209,44 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
if (tk.type != TK_PARENTHESIS_CLOSE) {
- _set_error("Expected ','");
+ _set_error("Expected ')'");
+ return ERR_PARSE_ERROR;
+ }
+ } else if (tk.type == TK_HINT_INSTANCE_INDEX) {
+ if (custom_instance_index != -1) {
+ _set_error("Can only specify 'instance_index' once.");
+ return ERR_PARSE_ERROR;
+ }
+
+ tk = _get_token();
+ if (tk.type != TK_PARENTHESIS_OPEN) {
+ _set_error("Expected '(' after 'instance_index'");
+ return ERR_PARSE_ERROR;
+ }
+
+ tk = _get_token();
+
+ if (tk.type == TK_OP_SUB) {
+ _set_error("The instance index can't be negative.");
+ return ERR_PARSE_ERROR;
+ }
+
+ if (tk.type != TK_INT_CONSTANT) {
+ _set_error("Expected integer constant");
+ return ERR_PARSE_ERROR;
+ }
+
+ custom_instance_index = tk.constant;
+
+ if (custom_instance_index >= MAX_INSTANCE_UNIFORM_INDICES) {
+ _set_error("Allowed instance uniform indices are 0-" + itos(MAX_INSTANCE_UNIFORM_INDICES - 1));
+ return ERR_PARSE_ERROR;
+ }
+
+ tk = _get_token();
+
+ if (tk.type != TK_PARENTHESIS_CLOSE) {
+ _set_error("Expected ')'");
return ERR_PARSE_ERROR;
}
} else if (tk.type == TK_FILTER_LINEAR) {
@@ -6072,11 +6279,25 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
} while (tk.type == TK_COMMA);
}
- if (tk.type == TK_OP_ASSIGN) {
+ if (uniform_scope == ShaderNode::Uniform::SCOPE_INSTANCE) {
+ if (custom_instance_index >= 0) {
+ uniform2.instance_index = custom_instance_index;
+ } else {
+ uniform2.instance_index = instance_index++;
+ if (instance_index > MAX_INSTANCE_UNIFORM_INDICES) {
+ _set_error("Too many 'instance' uniforms in shader, maximum supported is " + itos(MAX_INSTANCE_UNIFORM_INDICES));
+ return ERR_PARSE_ERROR;
+ }
+ }
+ }
+
+ //reset scope for next uniform
- Node *expr = _parse_and_reduce_expression(NULL, Map<StringName, BuiltInInfo>());
- if (!expr)
+ if (tk.type == TK_OP_ASSIGN) {
+ Node *expr = _parse_and_reduce_expression(nullptr, Map<StringName, BuiltInInfo>());
+ if (!expr) {
return ERR_PARSE_ERROR;
+ }
if (expr->type != Node::TYPE_CONSTANT) {
_set_error("Expected constant expression after '='");
return ERR_PARSE_ERROR;
@@ -6094,13 +6315,14 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
shader->uniforms[name] = uniform2;
+ //reset scope for next uniform
+ uniform_scope = ShaderNode::Uniform::SCOPE_LOCAL;
if (tk.type != TK_SEMICOLON) {
_set_error("Expected ';'");
return ERR_PARSE_ERROR;
}
} else {
-
ShaderNode::Varying varying;
varying.type = type;
varying.precision = precision;
@@ -6166,7 +6388,6 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
is_struct = true;
struct_name = tk.text;
} else {
-
if (!is_token_datatype(tk.type)) {
_set_error("Expected constant, function, uniform or varying");
return ERR_PARSE_ERROR;
@@ -6191,14 +6412,14 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
_set_tkpos(prev_pos);
- _get_completable_identifier(NULL, COMPLETION_MAIN_FUNCTION, name);
+ _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(NULL, false, Map<StringName, BuiltInInfo>(), name)) {
+ if (_find_identifier(nullptr, false, Map<StringName, BuiltInInfo>(), name)) {
_set_error("Redefinition of '" + String(name) + "'");
return ERR_PARSE_ERROR;
}
@@ -6219,22 +6440,23 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
while (true) {
ShaderNode::Constant constant;
+ constant.name = name;
constant.type = is_struct ? TYPE_STRUCT : type;
constant.type_str = struct_name;
constant.precision = precision;
- constant.initializer = NULL;
+ constant.initializer = nullptr;
if (tk.type == TK_OP_ASSIGN) {
-
if (!is_constant) {
_set_error("Expected 'const' keyword before constant definition");
return ERR_PARSE_ERROR;
}
//variable created with assignment! must parse an expression
- Node *expr = _parse_and_reduce_expression(NULL, Map<StringName, BuiltInInfo>());
- if (!expr)
+ Node *expr = _parse_and_reduce_expression(nullptr, Map<StringName, BuiltInInfo>());
+ if (!expr) {
return ERR_PARSE_ERROR;
+ }
if (expr->type == Node::TYPE_OPERATOR && ((OperatorNode *)expr)->op == OP_CALL) {
_set_error("Expected constant expression after '='");
return ERR_PARSE_ERROR;
@@ -6258,6 +6480,8 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
shader->constants[name] = constant;
+ shader->vconstants.push_back(constant);
+
if (tk.type == TK_COMMA) {
tk = _get_token();
if (tk.type != TK_IDENTIFIER) {
@@ -6266,7 +6490,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
name = tk.text;
- if (_find_identifier(NULL, false, Map<StringName, BuiltInInfo>(), name)) {
+ if (_find_identifier(nullptr, false, Map<StringName, BuiltInInfo>(), name)) {
_set_error("Redefinition of '" + String(name) + "'");
return ERR_PARSE_ERROR;
}
@@ -6405,7 +6629,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
pname = tk.text;
ShaderLanguage::IdentifierType itype;
- if (_find_identifier(func_node->body, false, builtin_types, pname, (ShaderLanguage::DataType *)0, &itype)) {
+ if (_find_identifier(func_node->body, false, builtin_types, pname, (ShaderLanguage::DataType *)nullptr, &itype)) {
if (itype != IDENTIFIER_FUNCTION) {
_set_error("Redefinition of '" + String(pname) + "'");
return ERR_PARSE_ERROR;
@@ -6467,11 +6691,11 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
current_function = name;
Error err = _parse_block(func_node->body, builtin_types);
- if (err)
+ if (err) {
return err;
+ }
if (func_node->return_type != DataType::TYPE_VOID) {
-
BlockNode *block = func_node->body;
if (_find_last_flow_op_in_block(block, FlowOperation::FLOW_OP_RETURN) != OK) {
_set_error("Expected at least one return statement in a non-void function.");
@@ -6489,7 +6713,6 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
bool ShaderLanguage::has_builtin(const Map<StringName, ShaderLanguage::FunctionInfo> &p_functions, const StringName &p_name) {
-
if (p_functions.has("vertex")) {
if (p_functions["vertex"].built_ins.has(p_name)) {
return true;
@@ -6509,7 +6732,6 @@ bool ShaderLanguage::has_builtin(const Map<StringName, ShaderLanguage::FunctionI
}
Error ShaderLanguage::_find_last_flow_op_in_op(ControlFlowNode *p_flow, FlowOperation p_op) {
-
bool found = false;
for (int i = p_flow->blocks.size() - 1; i >= 0; i--) {
@@ -6528,11 +6750,9 @@ Error ShaderLanguage::_find_last_flow_op_in_op(ControlFlowNode *p_flow, FlowOper
}
Error ShaderLanguage::_find_last_flow_op_in_block(BlockNode *p_block, FlowOperation p_op) {
-
bool found = false;
for (int i = p_block->statements.size() - 1; i >= 0; i--) {
-
if (p_block->statements[i]->type == Node::TYPE_CONTROL_FLOW) {
ControlFlowNode *flow = (ControlFlowNode *)p_block->statements[i];
if (flow->flow_op == p_op) {
@@ -6561,7 +6781,6 @@ Error ShaderLanguage::_find_last_flow_op_in_block(BlockNode *p_block, FlowOperat
// skips over whitespace and /* */ and // comments
static int _get_first_ident_pos(const String &p_code) {
-
int idx = 0;
#define GETCHAR(m_idx) (((idx + m_idx) < p_code.length()) ? p_code[idx + m_idx] : CharType(0))
@@ -6570,7 +6789,9 @@ static int _get_first_ident_pos(const String &p_code) {
if (GETCHAR(0) == '/' && GETCHAR(1) == '/') {
idx += 2;
while (true) {
- if (GETCHAR(0) == 0) return 0;
+ if (GETCHAR(0) == 0) {
+ return 0;
+ }
if (GETCHAR(0) == '\n') {
idx++;
break; // loop
@@ -6580,7 +6801,9 @@ static int _get_first_ident_pos(const String &p_code) {
} else if (GETCHAR(0) == '/' && GETCHAR(1) == '*') {
idx += 2;
while (true) {
- if (GETCHAR(0) == 0) return 0;
+ if (GETCHAR(0) == 0) {
+ return 0;
+ }
if (GETCHAR(0) == '*' && GETCHAR(1) == '/') {
idx += 2;
break; // loop
@@ -6605,13 +6828,11 @@ static int _get_first_ident_pos(const String &p_code) {
}
String ShaderLanguage::get_shader_type(const String &p_code) {
-
bool reading_type = false;
String cur_identifier;
for (int i = _get_first_ident_pos(p_code); i < p_code.length(); i++) {
-
if (p_code[i] == ';') {
break;
@@ -6633,19 +6854,20 @@ String ShaderLanguage::get_shader_type(const String &p_code) {
}
}
- if (reading_type)
+ if (reading_type) {
return cur_identifier;
+ }
return String();
}
-Error ShaderLanguage::compile(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types) {
-
+Error ShaderLanguage::compile(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types, GlobalVariableGetTypeFunc p_global_variable_type_func) {
clear();
code = p_code;
+ global_var_get_type_func = p_global_variable_type_func;
- nodes = NULL;
+ nodes = nullptr;
shader = alloc_node<ShaderNode>();
Error err = _parse_shader(p_functions, p_render_modes, p_shader_types);
@@ -6656,19 +6878,18 @@ Error ShaderLanguage::compile(const String &p_code, const Map<StringName, Functi
return OK;
}
-Error ShaderLanguage::complete(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types, List<ScriptCodeCompletionOption> *r_options, String &r_call_hint) {
-
+Error ShaderLanguage::complete(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types, GlobalVariableGetTypeFunc p_global_variable_type_func, List<ScriptCodeCompletionOption> *r_options, String &r_call_hint) {
clear();
code = p_code;
- nodes = NULL;
+ nodes = nullptr;
+ global_var_get_type_func = p_global_variable_type_func;
shader = alloc_node<ShaderNode>();
_parse_shader(p_functions, p_render_modes, p_shader_types);
switch (completion_type) {
-
case COMPLETION_NONE: {
//do nothing
return OK;
@@ -6682,7 +6903,6 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
return OK;
} break;
case COMPLETION_STRUCT: {
-
if (shader->structs.has(completion_struct)) {
StructNode *node = shader->structs[completion_struct].shader_struct;
for (int i = 0; i < node->members.size(); i++) {
@@ -6694,7 +6914,6 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
return OK;
} break;
case COMPLETION_MAIN_FUNCTION: {
-
for (const Map<StringName, FunctionInfo>::Element *E = p_functions.front(); E; E = E->next()) {
ScriptCodeCompletionOption option(E->key(), ScriptCodeCompletionOption::KIND_FUNCTION);
r_options->push_back(option);
@@ -6704,7 +6923,6 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
} break;
case COMPLETION_IDENTIFIER:
case COMPLETION_FUNCTION_CALL: {
-
bool comp_ident = completion_type == COMPLETION_IDENTIFIER;
Map<String, ScriptCodeCompletionOption::Kind> matches;
StringName skip_function;
@@ -6714,7 +6932,6 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
while (block) {
if (comp_ident) {
for (const Map<StringName, BlockNode::Variable>::Element *E = block->variables.front(); E; E = E->next()) {
-
if (E->get().line < completion_line) {
matches.insert(E->key(), ScriptCodeCompletionOption::KIND_VARIABLE);
}
@@ -6762,8 +6979,9 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
}
for (int i = 0; i < shader->functions.size(); i++) {
- if (!shader->functions[i].callable || shader->functions[i].name == skip_function)
+ if (!shader->functions[i].callable || shader->functions[i].name == skip_function) {
continue;
+ }
matches.insert(String(shader->functions[i].name), ScriptCodeCompletionOption::KIND_FUNCTION);
}
@@ -6806,12 +7024,11 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
return OK;
} break;
case COMPLETION_CALL_ARGUMENTS: {
-
for (int i = 0; i < shader->functions.size(); i++) {
- if (!shader->functions[i].callable)
+ if (!shader->functions[i].callable) {
continue;
+ }
if (shader->functions[i].name == completion_function) {
-
String calltip;
calltip += get_datatype_name(shader->functions[i].function->return_type);
@@ -6820,11 +7037,11 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
calltip += "(";
for (int j = 0; j < shader->functions[i].function->arguments.size(); j++) {
-
- if (j > 0)
+ if (j > 0) {
calltip += ", ";
- else
+ } else {
calltip += " ";
+ }
if (j == completion_argument) {
calltip += CharType(0xFFFF);
@@ -6847,8 +7064,9 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
}
}
- if (shader->functions[i].function->arguments.size())
+ if (shader->functions[i].function->arguments.size()) {
calltip += " ";
+ }
calltip += ")";
r_call_hint = calltip;
@@ -6862,7 +7080,6 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
bool low_end = RenderingServer::get_singleton()->is_low_end();
while (builtin_func_defs[idx].name) {
-
if (low_end && builtin_func_defs[idx].high_end) {
idx++;
continue;
@@ -6879,14 +7096,14 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
}
if (completion_function == builtin_func_defs[idx].name) {
-
if (builtin_func_defs[idx].tag != completion_class) {
idx++;
continue;
}
- if (calltip.length())
+ if (calltip.length()) {
calltip += "\n";
+ }
calltip += get_datatype_name(builtin_func_defs[idx].rettype);
calltip += " ";
@@ -6895,14 +7112,15 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
bool found_arg = false;
for (int i = 0; i < 4; i++) {
-
- if (builtin_func_defs[idx].args[i] == TYPE_VOID)
+ if (builtin_func_defs[idx].args[i] == TYPE_VOID) {
break;
+ }
- if (i > 0)
+ if (i > 0) {
calltip += ", ";
- else
+ } else {
calltip += " ";
+ }
if (i == completion_argument) {
calltip += CharType(0xFFFF);
@@ -6921,8 +7139,9 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
found_arg = true;
}
- if (found_arg)
+ if (found_arg) {
calltip += " ";
+ }
calltip += ")";
}
idx++;
@@ -6934,7 +7153,6 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
} break;
case COMPLETION_INDEX: {
-
const char colv[4] = { 'r', 'g', 'b', 'a' };
const char coordv[4] = { 'x', 'y', 'z', 'w' };
const char coordt[4] = { 's', 't', 'p', 'q' };
@@ -6953,7 +7171,6 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
case TYPE_IVEC3:
case TYPE_UVEC3:
case TYPE_VEC3: {
-
limit = 3;
} break;
@@ -6961,13 +7178,18 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
case TYPE_IVEC4:
case TYPE_UVEC4:
case TYPE_VEC4: {
-
limit = 4;
} break;
- case TYPE_MAT2: limit = 2; break;
- case TYPE_MAT3: limit = 3; break;
- case TYPE_MAT4: limit = 4; break;
+ case TYPE_MAT2:
+ limit = 2;
+ break;
+ case TYPE_MAT3:
+ limit = 3;
+ break;
+ case TYPE_MAT4:
+ limit = 4;
+ break;
default: {
}
}
@@ -6985,27 +7207,22 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
}
String ShaderLanguage::get_error_text() {
-
return error_str;
}
int ShaderLanguage::get_error_line() {
-
return error_line;
}
ShaderLanguage::ShaderNode *ShaderLanguage::get_shader() {
-
return shader;
}
ShaderLanguage::ShaderLanguage() {
-
- nodes = NULL;
+ nodes = nullptr;
completion_class = TAG_GLOBAL;
}
ShaderLanguage::~ShaderLanguage() {
-
clear();
}
diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h
index 9124bee633..020a5e3e6f 100644
--- a/servers/rendering/shader_language.h
+++ b/servers/rendering/shader_language.h
@@ -40,7 +40,6 @@
#include "core/variant.h"
class ShaderLanguage {
-
public:
enum TokenType {
TK_EMPTY,
@@ -79,6 +78,7 @@ public:
TK_TYPE_ISAMPLER3D,
TK_TYPE_USAMPLER3D,
TK_TYPE_SAMPLERCUBE,
+ TK_TYPE_SAMPLERCUBEARRAY,
TK_INTERPOLATION_FLAT,
TK_INTERPOLATION_SMOOTH,
TK_CONST,
@@ -143,6 +143,8 @@ public:
TK_SEMICOLON,
TK_PERIOD,
TK_UNIFORM,
+ TK_INSTANCE,
+ TK_GLOBAL,
TK_VARYING,
TK_ARG_IN,
TK_ARG_OUT,
@@ -162,6 +164,7 @@ public:
TK_HINT_BLACK_ALBEDO_TEXTURE,
TK_HINT_COLOR,
TK_HINT_RANGE,
+ TK_HINT_INSTANCE_INDEX,
TK_FILTER_NEAREST,
TK_FILTER_LINEAR,
TK_FILTER_NEAREST_MIPMAP,
@@ -215,7 +218,9 @@ public:
TYPE_ISAMPLER3D,
TYPE_USAMPLER3D,
TYPE_SAMPLERCUBE,
+ TYPE_SAMPLERCUBEARRAY,
TYPE_STRUCT,
+ TYPE_MAX
};
enum DataPrecision {
@@ -317,8 +322,12 @@ public:
REPEAT_DEFAULT,
};
+ enum {
+ MAX_INSTANCE_UNIFORM_INDICES = 16
+ };
+
struct Node {
- Node *next;
+ Node *next = nullptr;
enum Type {
TYPE_SHADER,
@@ -342,7 +351,6 @@ public:
virtual String get_datatype_name() const { return ""; }
Node(Type t) :
- next(NULL),
type(t) {}
virtual ~Node() {}
};
@@ -358,41 +366,35 @@ public:
Node *nodes;
struct OperatorNode : public Node {
- DataType return_cache;
- DataPrecision return_precision_cache;
- Operator op;
+ DataType return_cache = TYPE_VOID;
+ DataPrecision return_precision_cache = PRECISION_DEFAULT;
+ Operator op = OP_EQUAL;
StringName struct_name;
Vector<Node *> arguments;
virtual DataType get_datatype() const { return return_cache; }
virtual String get_datatype_name() const { return String(struct_name); }
OperatorNode() :
- Node(TYPE_OPERATOR),
- return_cache(TYPE_VOID),
- return_precision_cache(PRECISION_DEFAULT),
- op(OP_EQUAL),
- struct_name("") {}
+ Node(TYPE_OPERATOR) {}
};
struct VariableNode : public Node {
- DataType datatype_cache;
+ DataType datatype_cache = TYPE_VOID;
StringName name;
StringName struct_name;
virtual DataType get_datatype() const { return datatype_cache; }
virtual String get_datatype_name() const { return String(struct_name); }
- bool is_const;
+ bool is_const = false;
VariableNode() :
- Node(TYPE_VARIABLE),
- datatype_cache(TYPE_VOID),
- is_const(false) {}
+ Node(TYPE_VARIABLE) {}
};
struct VariableDeclarationNode : public Node {
- DataPrecision precision;
- DataType datatype;
+ DataPrecision precision = PRECISION_DEFAULT;
+ DataType datatype = TYPE_VOID;
String struct_name;
- bool is_const;
+ bool is_const = false;
struct Declaration {
StringName name;
@@ -403,47 +405,38 @@ public:
virtual DataType get_datatype() const { return datatype; }
VariableDeclarationNode() :
- Node(TYPE_VARIABLE_DECLARATION),
- precision(PRECISION_DEFAULT),
- datatype(TYPE_VOID),
- is_const(false) {}
+ Node(TYPE_VARIABLE_DECLARATION) {}
};
struct ArrayNode : public Node {
- DataType datatype_cache;
+ DataType datatype_cache = TYPE_VOID;
StringName struct_name;
StringName name;
- Node *index_expression;
- Node *call_expression;
- bool is_const;
+ Node *index_expression = nullptr;
+ Node *call_expression = nullptr;
+ bool is_const = false;
virtual DataType get_datatype() const { return datatype_cache; }
virtual String get_datatype_name() const { return String(struct_name); }
ArrayNode() :
- Node(TYPE_ARRAY),
- datatype_cache(TYPE_VOID),
- index_expression(NULL),
- call_expression(NULL),
- is_const(false) {}
+ Node(TYPE_ARRAY) {}
};
struct ArrayConstructNode : public Node {
- DataType datatype;
+ DataType datatype = TYPE_VOID;
String struct_name;
Vector<Node *> initializer;
ArrayConstructNode() :
- Node(TYPE_ARRAY_CONSTRUCT),
- datatype(TYPE_VOID) {
- }
+ Node(TYPE_ARRAY_CONSTRUCT) {}
};
struct ArrayDeclarationNode : public Node {
- DataPrecision precision;
- DataType datatype;
+ DataPrecision precision = PRECISION_DEFAULT;
+ DataType datatype = TYPE_VOID;
String struct_name;
- bool is_const;
+ bool is_const = false;
struct Declaration {
StringName name;
@@ -455,14 +448,11 @@ public:
virtual DataType get_datatype() const { return datatype; }
ArrayDeclarationNode() :
- Node(TYPE_ARRAY_DECLARATION),
- precision(PRECISION_DEFAULT),
- datatype(TYPE_VOID),
- is_const(false) {}
+ Node(TYPE_ARRAY_DECLARATION) {}
};
struct ConstantNode : public Node {
- DataType datatype;
+ DataType datatype = TYPE_VOID;
union Value {
bool boolean;
@@ -475,15 +465,14 @@ public:
virtual DataType get_datatype() const { return datatype; }
ConstantNode() :
- Node(TYPE_CONSTANT),
- datatype(TYPE_VOID) {}
+ Node(TYPE_CONSTANT) {}
};
struct FunctionNode;
struct BlockNode : public Node {
- FunctionNode *parent_function;
- BlockNode *parent_block;
+ FunctionNode *parent_function = nullptr;
+ BlockNode *parent_block = nullptr;
enum BlockType {
BLOCK_TYPE_STANDART,
@@ -493,8 +482,8 @@ public:
BLOCK_TYPE_DEFAULT,
};
- int block_type;
- SubClassTag block_tag;
+ int block_type = BLOCK_TYPE_STANDART;
+ SubClassTag block_tag = SubClassTag::TAG_GLOBAL;
struct Variable {
DataType type;
@@ -507,63 +496,48 @@ public:
Map<StringName, Variable> variables;
List<Node *> statements;
- bool single_statement;
+ bool single_statement = false;
BlockNode() :
- Node(TYPE_BLOCK),
- parent_function(NULL),
- parent_block(NULL),
- block_type(BLOCK_TYPE_STANDART),
- block_tag(SubClassTag::TAG_GLOBAL),
- single_statement(false) {}
+ Node(TYPE_BLOCK) {}
};
struct ControlFlowNode : public Node {
- FlowOperation flow_op;
+ FlowOperation flow_op = FLOW_OP_IF;
Vector<Node *> expressions;
Vector<BlockNode *> blocks;
ControlFlowNode() :
- Node(TYPE_CONTROL_FLOW),
- flow_op(FLOW_OP_IF) {}
+ Node(TYPE_CONTROL_FLOW) {}
};
struct MemberNode : public Node {
- DataType basetype;
- bool basetype_const;
+ DataType basetype = TYPE_VOID;
+ bool basetype_const = false;
StringName base_struct_name;
DataPrecision precision;
- DataType datatype;
- int array_size;
+ DataType datatype = TYPE_VOID;
+ int array_size = 0;
StringName struct_name;
StringName name;
- Node *owner;
- Node *index_expression;
- bool has_swizzling_duplicates;
+ Node *owner = nullptr;
+ Node *index_expression = nullptr;
+ bool has_swizzling_duplicates = false;
virtual DataType get_datatype() const { return datatype; }
virtual String get_datatype_name() const { return String(struct_name); }
MemberNode() :
- Node(TYPE_MEMBER),
- basetype(TYPE_VOID),
- basetype_const(false),
- datatype(TYPE_VOID),
- array_size(0),
- owner(NULL),
- index_expression(NULL),
- has_swizzling_duplicates(false) {}
+ Node(TYPE_MEMBER) {}
};
struct StructNode : public Node {
-
List<MemberNode *> members;
StructNode() :
Node(TYPE_STRUCT) {}
};
struct FunctionNode : public Node {
-
struct Argument {
ArgumentQualifier qualifier;
StringName name;
@@ -581,24 +555,20 @@ public:
};
StringName name;
- DataType return_type;
+ DataType return_type = TYPE_VOID;
StringName return_struct_name;
- DataPrecision return_precision;
+ DataPrecision return_precision = PRECISION_DEFAULT;
Vector<Argument> arguments;
- BlockNode *body;
- bool can_discard;
+ BlockNode *body = nullptr;
+ bool can_discard = false;
FunctionNode() :
- Node(TYPE_FUNCTION),
- return_type(TYPE_VOID),
- return_precision(PRECISION_DEFAULT),
- body(NULL),
- can_discard(false) {}
+ Node(TYPE_FUNCTION) {}
};
struct ShaderNode : public Node {
-
struct Constant {
+ StringName name;
DataType type;
StringName type_str;
DataPrecision precision;
@@ -618,16 +588,12 @@ public:
};
struct Varying {
- DataType type;
- DataInterpolation interpolation;
- DataPrecision precision;
- int array_size;
+ DataType type = TYPE_VOID;
+ DataInterpolation interpolation = INTERPOLATION_FLAT;
+ DataPrecision precision = PRECISION_DEFAULT;
+ int array_size = 0;
- Varying() :
- type(TYPE_VOID),
- interpolation(INTERPOLATION_FLAT),
- precision(PRECISION_DEFAULT),
- array_size(0) {}
+ Varying() {}
};
struct Uniform {
@@ -650,24 +616,25 @@ public:
HINT_MAX
};
- int order;
- int texture_order;
- DataType type;
- DataPrecision precision;
+ enum Scope {
+ SCOPE_LOCAL,
+ SCOPE_INSTANCE,
+ SCOPE_GLOBAL,
+ };
+
+ int order = 0;
+ int texture_order = 0;
+ DataType type = TYPE_VOID;
+ DataPrecision precision = PRECISION_DEFAULT;
Vector<ConstantNode::Value> default_value;
- Hint hint;
- TextureFilter filter;
- TextureRepeat repeat;
+ Scope scope = SCOPE_LOCAL;
+ Hint hint = HINT_NONE;
+ TextureFilter filter = FILTER_DEFAULT;
+ TextureRepeat repeat = REPEAT_DEFAULT;
float hint_range[3];
+ int instance_index = 0;
- Uniform() :
- order(0),
- texture_order(0),
- type(TYPE_VOID),
- precision(PRECISION_DEFAULT),
- hint(HINT_NONE),
- filter(FILTER_DEFAULT),
- repeat(REPEAT_DEFAULT) {
+ Uniform() {
hint_range[0] = 0.0f;
hint_range[1] = 1.0f;
hint_range[2] = 0.001f;
@@ -681,6 +648,7 @@ public:
Vector<StringName> render_modes;
Vector<Function> functions;
+ Vector<Constant> vconstants;
Vector<Struct> vstructs;
ShaderNode() :
@@ -733,7 +701,7 @@ public:
static bool is_token_nonvoid_datatype(TokenType p_type);
static bool is_token_operator(TokenType p_type);
- static bool convert_constant(ConstantNode *p_constant, DataType p_to_type, ConstantNode::Value *p_value = NULL);
+ static bool convert_constant(ConstantNode *p_constant, DataType p_to_type, ConstantNode::Value *p_value = nullptr);
static DataType get_scalar_type(DataType p_type);
static int get_cardinality(DataType p_type);
static bool is_scalar_type(DataType p_type);
@@ -746,12 +714,10 @@ public:
static void get_builtin_funcs(List<String> *r_keywords);
struct BuiltInInfo {
- DataType type;
- bool constant;
+ DataType type = TYPE_VOID;
+ bool constant = false;
- BuiltInInfo() :
- type(TYPE_VOID),
- constant(false) {}
+ BuiltInInfo() {}
BuiltInInfo(DataType p_type, bool p_constant = false) :
type(p_type),
@@ -764,6 +730,8 @@ public:
};
static bool has_builtin(const Map<StringName, ShaderLanguage::FunctionInfo> &p_functions, const StringName &p_name);
+ typedef DataType (*GlobalVariableGetTypeFunc)(const StringName &p_name);
+
private:
struct KeyWord {
TokenType token;
@@ -772,6 +740,8 @@ private:
static const KeyWord keyword_list[];
+ GlobalVariableGetTypeFunc global_var_get_type_func;
+
bool error_set;
String error_str;
int error_line;
@@ -800,8 +770,9 @@ private:
}
void _set_error(const String &p_str) {
- if (error_set)
+ if (error_set) {
return;
+ }
error_line = tk_line;
error_set = true;
@@ -825,10 +796,10 @@ private:
IDENTIFIER_CONSTANT,
};
- bool _find_identifier(const BlockNode *p_block, bool p_allow_reassign, const Map<StringName, BuiltInInfo> &p_builtin_types, const StringName &p_identifier, DataType *r_data_type = NULL, IdentifierType *r_type = NULL, bool *r_is_const = NULL, int *r_array_size = NULL, StringName *r_struct_name = NULL);
+ bool _find_identifier(const BlockNode *p_block, bool p_allow_reassign, const Map<StringName, BuiltInInfo> &p_builtin_types, const StringName &p_identifier, DataType *r_data_type = nullptr, IdentifierType *r_type = nullptr, bool *r_is_const = nullptr, int *r_array_size = nullptr, StringName *r_struct_name = nullptr);
bool _is_operator_assign(Operator p_op) const;
- bool _validate_assign(Node *p_node, const Map<StringName, BuiltInInfo> &p_builtin_types, String *r_message = NULL);
- bool _validate_operator(OperatorNode *p_op, DataType *r_ret_type = NULL);
+ bool _validate_assign(Node *p_node, const Map<StringName, BuiltInInfo> &p_builtin_types, String *r_message = nullptr);
+ bool _validate_operator(OperatorNode *p_op, DataType *r_ret_type = nullptr);
struct BuiltinFuncDef {
enum { MAX_ARGS = 5 };
@@ -861,7 +832,7 @@ private:
bool _compare_datatypes_in_nodes(Node *a, Node *b) const;
bool _validate_function_call(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, OperatorNode *p_func, DataType *r_ret_type, StringName *r_ret_type_str);
- bool _parse_function_arguments(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, OperatorNode *p_func, int *r_complete_arg = NULL);
+ bool _parse_function_arguments(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, OperatorNode *p_func, int *r_complete_arg = nullptr);
bool _propagate_function_call_sampler_uniform_settings(StringName p_name, int p_argument, TextureFilter p_filter, TextureRepeat p_repeat);
bool _propagate_function_call_sampler_builtin_reference(StringName p_name, int p_argument, const StringName &p_builtin);
@@ -884,8 +855,8 @@ public:
void clear();
static String get_shader_type(const String &p_code);
- Error compile(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types);
- Error complete(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types, List<ScriptCodeCompletionOption> *r_options, String &r_call_hint);
+ Error compile(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types, GlobalVariableGetTypeFunc p_global_variable_type_func);
+ Error complete(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types, GlobalVariableGetTypeFunc p_global_variable_type_func, List<ScriptCodeCompletionOption> *r_options, String &r_call_hint);
String get_error_text();
int get_error_line();
diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp
index b144d6d612..2601efa9e2 100644
--- a/servers/rendering/shader_types.cpp
+++ b/servers/rendering/shader_types.cpp
@@ -31,12 +31,10 @@
#include "shader_types.h"
const Map<StringName, ShaderLanguage::FunctionInfo> &ShaderTypes::get_functions(RS::ShaderMode p_mode) {
-
return shader_modes[p_mode].functions;
}
const Vector<StringName> &ShaderTypes::get_modes(RS::ShaderMode p_mode) {
-
return shader_modes[p_mode].modes;
}
@@ -44,10 +42,9 @@ const Set<String> &ShaderTypes::get_types() {
return shader_types;
}
-ShaderTypes *ShaderTypes::singleton = NULL;
+ShaderTypes *ShaderTypes::singleton = nullptr;
static ShaderLanguage::BuiltInInfo constt(ShaderLanguage::DataType p_type) {
-
return ShaderLanguage::BuiltInInfo(p_type, true);
}
@@ -108,7 +105,11 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["ANISOTROPY"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["ANISOTROPY_FLOW"] = ShaderLanguage::TYPE_VEC2;
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SSS_STRENGTH"] = ShaderLanguage::TYPE_FLOAT;
- shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["TRANSMISSION"] = ShaderLanguage::TYPE_VEC3;
+ shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SSS_TRANSMITTANCE_COLOR"] = ShaderLanguage::TYPE_VEC4;
+ shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SSS_TRANSMITTANCE_DEPTH"] = ShaderLanguage::TYPE_FLOAT;
+ shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SSS_TRANSMITTANCE_CURVE"] = ShaderLanguage::TYPE_FLOAT;
+ shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SSS_TRANSMITTANCE_BOOST"] = ShaderLanguage::TYPE_FLOAT;
+ shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["BACKLIGHT"] = ShaderLanguage::TYPE_VEC3;
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["AO"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["AO_LIGHT_AFFECT"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["EMISSION"] = ShaderLanguage::TYPE_VEC3;
@@ -145,7 +146,7 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["LIGHT_COLOR"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["ATTENUATION"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["ALBEDO"] = constt(ShaderLanguage::TYPE_VEC3);
- shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["TRANSMISSION"] = constt(ShaderLanguage::TYPE_VEC3);
+ shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["BACKLIGHT"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["ROUGHNESS"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["DIFFUSE_LIGHT"] = ShaderLanguage::TYPE_VEC3;
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["SPECULAR_LIGHT"] = ShaderLanguage::TYPE_VEC3;
@@ -168,6 +169,8 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SPATIAL].modes.push_back("depth_test_disabled");
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back("sss_mode_skin");
+
shader_modes[RS::SHADER_SPATIAL].modes.push_back("cull_back");
shader_modes[RS::SHADER_SPATIAL].modes.push_back("cull_front");
shader_modes[RS::SHADER_SPATIAL].modes.push_back("cull_disabled");
@@ -297,18 +300,22 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT0_DIRECTION"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT0_ENERGY"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT0_COLOR"] = constt(ShaderLanguage::TYPE_VEC3);
+ shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT0_SIZE"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT1_ENABLED"] = constt(ShaderLanguage::TYPE_BOOL);
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT1_DIRECTION"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT1_ENERGY"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT1_COLOR"] = constt(ShaderLanguage::TYPE_VEC3);
+ shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT1_SIZE"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT2_ENABLED"] = constt(ShaderLanguage::TYPE_BOOL);
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT2_DIRECTION"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT2_ENERGY"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT2_COLOR"] = constt(ShaderLanguage::TYPE_VEC3);
+ shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT2_SIZE"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT3_ENABLED"] = constt(ShaderLanguage::TYPE_BOOL);
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT3_DIRECTION"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT3_ENERGY"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT3_COLOR"] = constt(ShaderLanguage::TYPE_VEC3);
+ shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT3_SIZE"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[RS::SHADER_SKY].functions["fragment"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC3;
shader_modes[RS::SHADER_SKY].functions["fragment"].built_ins["ALPHA"] = ShaderLanguage::TYPE_FLOAT;
diff --git a/servers/rendering/shader_types.h b/servers/rendering/shader_types.h
index 499a761265..7d8057a5c6 100644
--- a/servers/rendering/shader_types.h
+++ b/servers/rendering/shader_types.h
@@ -36,9 +36,7 @@
#include "shader_language.h"
class ShaderTypes {
-
struct Type {
-
Map<StringName, ShaderLanguage::FunctionInfo> functions;
Vector<StringName> modes;
};