summaryrefslogtreecommitdiff
path: root/servers/rendering
diff options
context:
space:
mode:
Diffstat (limited to 'servers/rendering')
-rw-r--r--servers/rendering/rasterizer.cpp6
-rw-r--r--servers/rendering/rasterizer.h63
-rw-r--r--servers/rendering/rasterizer_rd/light_cluster_builder.h16
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp12
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h2
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp428
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_effects_rd.h149
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp310
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h44
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp180
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_scene_rd.h113
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp38
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_storage_rd.h30
-rw-r--r--servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.cpp4
-rw-r--r--servers/rendering/rasterizer_rd/shader_compiler_rd.cpp16
-rw-r--r--servers/rendering/rasterizer_rd/shader_rd.cpp6
-rw-r--r--servers/rendering/rasterizer_rd/shaders/SCsub5
-rw-r--r--servers/rendering/rasterizer_rd/shaders/blur.glsl7
-rw-r--r--servers/rendering/rasterizer_rd/shaders/copy.glsl3
-rw-r--r--servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl805
-rw-r--r--servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl49
-rw-r--r--servers/rendering/rasterizer_rd/shaders/screen_space_reflection.glsl262
-rw-r--r--servers/rendering/rasterizer_rd/shaders/screen_space_reflection_filter.glsl164
-rw-r--r--servers/rendering/rasterizer_rd/shaders/screen_space_reflection_scale.glsl96
-rw-r--r--servers/rendering/rasterizer_rd/shaders/sky.glsl8
-rw-r--r--servers/rendering/rasterizer_rd/shaders/specular_merge.glsl59
-rw-r--r--servers/rendering/rasterizer_rd/shaders/subsurface_scattering.glsl198
-rw-r--r--servers/rendering/rendering_device.cpp6
-rw-r--r--servers/rendering/rendering_device.h2
-rw-r--r--servers/rendering/rendering_server_canvas.cpp36
-rw-r--r--servers/rendering/rendering_server_canvas.h2
-rw-r--r--servers/rendering/rendering_server_globals.cpp14
-rw-r--r--servers/rendering/rendering_server_raster.h10
-rw-r--r--servers/rendering/rendering_server_scene.cpp262
-rw-r--r--servers/rendering/rendering_server_scene.h18
-rw-r--r--servers/rendering/rendering_server_viewport.cpp67
-rw-r--r--servers/rendering/rendering_server_viewport.h12
-rw-r--r--servers/rendering/rendering_server_wrap_mt.cpp26
-rw-r--r--servers/rendering/rendering_server_wrap_mt.h10
-rw-r--r--servers/rendering/shader_language.cpp202
-rw-r--r--servers/rendering/shader_language.h26
-rw-r--r--servers/rendering/shader_types.cpp12
42 files changed, 3172 insertions, 606 deletions
diff --git a/servers/rendering/rasterizer.cpp b/servers/rendering/rasterizer.cpp
index a3f93a3f8c..f62e0a43a6 100644
--- a/servers/rendering/rasterizer.cpp
+++ b/servers/rendering/rasterizer.cpp
@@ -33,7 +33,7 @@
#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()) {
@@ -67,9 +67,9 @@ 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() {
diff --git a/servers/rendering/rasterizer.h b/servers/rendering/rasterizer.h
index eb33db04fc..cf0afe6097 100644
--- a/servers/rendering/rasterizer.h
+++ b/servers/rendering/rasterizer.h
@@ -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;
@@ -104,10 +106,11 @@ 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 shadow_filter_set(RS::ShadowFilter p_filter) = 0;
+
struct InstanceBase;
struct InstanceDependency {
-
void instance_notify_changed(bool p_aabb, bool p_dependencies);
void instance_notify_deleted(RID p_deleted);
@@ -119,7 +122,6 @@ public:
};
struct InstanceBase {
-
RS::InstanceType base_type;
RID base;
@@ -219,7 +221,7 @@ public:
baked_light = false;
dynamic_gi = false;
redraw_if_visible = false;
- lightmap_capture = NULL;
+ lightmap_capture = nullptr;
}
virtual ~InstanceBase() {
@@ -229,9 +231,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;
@@ -264,6 +268,9 @@ public:
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 bool free(RID p_rid) = 0;
virtual void update() = 0;
@@ -751,10 +758,10 @@ public:
energy = 1.0;
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;
@@ -1005,7 +1012,7 @@ public:
//must update rect
- if (commands == NULL) {
+ if (commands == nullptr) {
rect = Rect2();
rect_dirty = false;
@@ -1115,12 +1122,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 +1154,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);
@@ -1172,7 +1179,7 @@ public:
Command *n = c->next;
if (c == commands) {
memdelete(commands);
- commands = NULL;
+ commands = nullptr;
} else {
c->~Command();
}
@@ -1186,36 +1193,36 @@ 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();
@@ -1248,7 +1255,7 @@ public:
LightOccluderInstance() {
enabled = true;
- next = NULL;
+ next = nullptr;
light_mask = 1;
cull_cache = RS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED;
}
diff --git a/servers/rendering/rasterizer_rd/light_cluster_builder.h b/servers/rendering/rasterizer_rd/light_cluster_builder.h
index 3411ed07a0..50a68e03cb 100644
--- a/servers/rendering/rasterizer_rd/light_cluster_builder.h
+++ b/servers/rendering/rasterizer_rd/light_cluster_builder.h
@@ -170,17 +170,15 @@ 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;
}
diff --git a/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp
index 8d52ffd7b9..ba4f4c4acb 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp
+++ b/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp
@@ -1220,7 +1220,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 +1262,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));
@@ -1314,13 +1314,13 @@ 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;
@@ -1369,7 +1369,7 @@ void RasterizerCanvasRD::_render_items(RID p_to_render_target, int p_item_count,
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);
}
@@ -2532,7 +2532,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..83b431eaf6 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h
+++ b/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h
@@ -383,7 +383,7 @@ class RasterizerCanvasRD : public RasterizerCanvas {
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;
}
diff --git a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp
index 9ccc1f172e..79b1686232 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp
+++ b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp
@@ -50,6 +50,16 @@ static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_basis, float *p_ar
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];
+ }
+ }
+}
+
RID RasterizerEffectsRD::_get_uniform_set_from_image(RID p_image) {
if (image_to_uniform_set_cache.has(p_image)) {
@@ -120,6 +130,99 @@ RID RasterizerEffectsRD::_get_compute_uniform_set_from_texture(RID p_texture, bo
return uniform_set;
}
+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_rect_and_linearize(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, bool p_flip_y, float p_z_near, float p_z_far) {
+
+ zeromem(&blur.push_constant, sizeof(BlurPushConstant));
+ if (p_flip_y) {
+ blur.push_constant.flags |= BLUR_FLAG_FLIP_Y;
+ }
+
+ blur.push_constant.camera_z_near = p_z_near;
+ blur.push_constant.camera_z_far = p_z_far;
+
+ 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_LINEARIZE_DEPTH].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_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, bool p_flip_y, bool p_force_luminance) {
zeromem(&blur.push_constant, sizeof(BlurPushConstant));
@@ -218,6 +321,7 @@ void RasterizerEffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_framebuff
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
//HORIZONTAL
@@ -250,6 +354,212 @@ void RasterizerEffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_framebuff
RD::get_singleton()->draw_list_end();
}
+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;
+
+ { //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;
+
+ 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::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+}
+
void RasterizerEffectsRD::make_mipmap(RID p_source_rd_texture, RID p_dest_framebuffer, const Vector2 &p_pixel_size) {
zeromem(&blur.push_constant, sizeof(BlurPushConstant));
@@ -819,8 +1129,7 @@ void RasterizerEffectsRD::render_sky(RD::DrawListID p_list, float p_time, RID p_
RasterizerEffectsRD::RasterizerEffectsRD() {
- {
- // Initialize blur
+ { // 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");
@@ -837,6 +1146,7 @@ RasterizerEffectsRD::RasterizerEffectsRD() {
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_modes.push_back("\n#define MODE_LINEARIZE_DEPTH_COPY\n");
blur.shader.initialize(blur_modes);
zeromem(&blur.push_constant, sizeof(BlurPushConstant));
@@ -970,6 +1280,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 +1346,97 @@ 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 +1481,22 @@ 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);
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..c0c62eb0be 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h
+++ b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h
@@ -41,9 +41,14 @@
#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"
@@ -66,6 +71,7 @@ class RasterizerEffectsRD {
BLUR_MODE_SSAO_MERGE,
BLUR_MODE_SIMPLY_COPY,
BLUR_MODE_MIPMAP,
+ BLUR_MODE_LINEARIZE_DEPTH,
BLUR_MODE_MAX,
};
@@ -378,6 +384,127 @@ class RasterizerEffectsRD {
float pad[3];
};
+ enum SpecularMergeMode {
+ SPECULAR_MERGE_ADD,
+ SPECULAR_MERGE_SSR,
+ SPECULAR_MERGE_ADDITIVE_ADD,
+ SPECULAR_MERGE_ADDITIVE_SSR,
+ SPECULAR_MERGE_MAX
+ };
+
+ 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,17 +513,35 @@ 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 copy_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, bool p_flip_y, float p_z_near, float p_z_far);
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);
@@ -450,6 +595,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_scene_high_end_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp
index bf3cd045f1..ec05c9e964 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp
+++ b/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp
@@ -109,6 +109,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 +143,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;
@@ -321,7 +323,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
@@ -537,12 +539,20 @@ void RasterizerSceneHighEndRD::RenderBufferDataHighEnd::ensure_specular() {
specular = RD::get_singleton()->texture_create(tf, RD::TextureView());
- Vector<RID> fb;
- fb.push_back(color);
- fb.push_back(specular);
- fb.push_back(depth);
+ {
+ Vector<RID> fb;
+ fb.push_back(color);
+ fb.push_back(specular);
+ fb.push_back(depth);
- color_specular_fb = RD::get_singleton()->framebuffer_create(fb);
+ 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);
+ }
}
}
@@ -554,6 +564,7 @@ void RasterizerSceneHighEndRD::RenderBufferDataHighEnd::clear() {
}
color_specular_fb = RID();
+ specular_only_fb = RID();
color_fb = RID();
if (normal_buffer.is_valid()) {
@@ -935,7 +946,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
@@ -951,6 +962,10 @@ 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.shadow_filter_mode = shadow_filter_get();
+
+ scene_state.ubo.pancake_shadows = p_pancake_shadows;
+ scene_state.ubo.shadow_blocker_count = 16;
scene_state.ubo.screen_pixel_size[0] = p_screen_pixel_size.x;
scene_state.ubo.screen_pixel_size[1] = p_screen_pixel_size.y;
@@ -1074,12 +1089,12 @@ void RasterizerSceneHighEndRD::_add_geometry(InstanceBase *p_instance, uint32_t
}
}
- 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;
}
}
@@ -1203,7 +1218,7 @@ void RasterizerSceneHighEndRD::_fill_render_list(InstanceBase **p_cull_result, i
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);
@@ -1237,7 +1252,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);
@@ -1258,7 +1273,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: {
@@ -1470,11 +1485,49 @@ 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);
@@ -1498,12 +1551,49 @@ 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];
+
+ float softshadow_angle = storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
+ if (softshadow_angle > 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)
+ light_data.softshadow_angle = Math::tan(Math::deg2rad(softshadow_angle));
+ } else {
+ light_data.softshadow_angle = 0;
+ }
}
// Copy to SkyDirectionalLightData
@@ -1566,20 +1656,16 @@ 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;
@@ -1588,20 +1674,55 @@ void RasterizerSceneHighEndRD::_setup_lights(RID *p_light_cull_result, int p_lig
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;
+ 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);
+
+ if (size > 0.0) {
+
+ light_data.soft_shadow_size = size;
+ } else {
+ light_data.soft_shadow_size = 0.0;
+ }
+
} else if (type == RS::LIGHT_SPOT) {
+ //used for clamping in this light type
+ light_data.atlas_rect[2] += light_data.atlas_rect[0];
+ light_data.atlas_rect[3] += light_data.atlas_rect[1];
+
Transform modelview = (p_camera_inverse_transform * light_transform).inverse();
CameraMatrix bias;
bias.set_light_bias();
@@ -1610,7 +1731,17 @@ void RasterizerSceneHighEndRD::_setup_lights(RID *p_light_cull_result, int p_lig
CameraMatrix shadow_mtx = rectm * 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;
+ }
}
+ } else {
+ light_data.shadow_color_enabled[3] = 0;
}
light_instance_set_index(li, light_count);
@@ -1637,7 +1768,7 @@ 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) {
- RenderBufferDataHighEnd *render_buffer = NULL;
+ RenderBufferDataHighEnd *render_buffer = nullptr;
if (p_render_buffer.is_valid()) {
render_buffer = (RenderBufferDataHighEnd *)render_buffers_get_data(p_render_buffer);
}
@@ -1689,9 +1820,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 +1827,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 +1846,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
@@ -1779,6 +1914,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;
@@ -1845,22 +1988,22 @@ 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);
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(depth_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, using_ssao ? 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());
RD::get_singleton()->draw_list_end();
}
- 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 +2021,46 @@ 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);
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 +2077,23 @@ 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) {
+
+ if (using_sss) {
+ RENDER_TIMESTAMP("Sub Surface Scattering");
+ _process_sss(p_render_buffer, p_cam_projection);
+ }
- 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 (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, true);
+ } else {
+ //just mix specular back
+ RENDER_TIMESTAMP("Merge Specular");
+ storage->get_effects()->merge_specular(render_buffer->color_fb, render_buffer->specular, RID(), RID());
}
}
@@ -1929,7 +2106,7 @@ 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);
+ 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);
RD::get_singleton()->draw_list_end();
}
@@ -1937,13 +2114,13 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor
//_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);
+ directional_light = nullptr;
+ _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 != nullptr);
} 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);
+ _setup_directional_light(i, p_cam_transform.affine_inverse(), shadow_atlas != nullptr && 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 != nullptr);
}
}
#endif
@@ -2005,7 +2182,7 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor
//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");
@@ -2013,11 +2190,9 @@ void RasterizerSceneHighEndRD::_render_shadow(RID p_framebuffer, InstanceBase **
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();
@@ -2048,8 +2223,6 @@ void RasterizerSceneHighEndRD::_render_material(const Transform &p_cam_transform
render_pass++;
- scene_state.ubo.shadow_z_offset = 0;
- scene_state.ubo.shadow_z_slope_scale = 0;
scene_state.ubo.dual_paraboloid_side = 0;
_setup_environment(RID(), p_cam_projection, p_cam_transform, RID(), true, Vector2(1, 1), RID(), false, Color(), 0, 0);
@@ -2146,7 +2319,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);
}
@@ -2366,7 +2539,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 +2578,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);
@@ -2511,7 +2684,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 +2728,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 +2752,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) {
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..b4f5d25afd 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h
+++ b/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h
@@ -138,6 +138,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;
@@ -207,6 +208,7 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
RID depth_normal_roughness_fb;
RID color_fb;
RID color_specular_fb;
+ RID specular_only_fb;
int width, height;
void ensure_specular();
@@ -252,13 +254,19 @@ 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;
+ uint32_t mask;
+ uint32_t pad[3];
};
struct DirectionalLightData {
@@ -266,15 +274,30 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
float direction[3];
float energy;
float color[3];
+ float size;
float specular;
- float shadow_color[3];
uint32_t mask;
+ float softshadow_angle;
+ uint32_t pad[1];
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 {
@@ -323,12 +346,15 @@ 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 shadow_filter_mode;
+
+ uint32_t shadow_blocker_count;
+ uint32_t shadow_pad[3];
+
float ambient_light_color_energy[4];
float ambient_color_sky_mix;
@@ -489,7 +515,7 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
_FORCE_INLINE_ Element *add_element() {
if (element_count + alpha_element_count >= max_elements)
- return NULL;
+ return nullptr;
elements[element_count] = &base_elements[element_count];
return elements[element_count++];
}
@@ -497,7 +523,7 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
_FORCE_INLINE_ Element *add_alpha_element() {
if (element_count + alpha_element_count >= max_elements)
- return NULL;
+ return nullptr;
int idx = max_elements - alpha_element_count - 1;
elements[idx] = &base_elements[idx];
alpha_element_count++;
@@ -557,7 +583,7 @@ 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_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);
@@ -571,7 +597,7 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
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_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);
public:
diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp
index 517eea12f4..a0bbf8bd43 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp
+++ b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp
@@ -456,7 +456,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));
@@ -465,12 +465,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;
}
}
@@ -537,7 +537,7 @@ 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();
}
@@ -551,12 +551,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;
}
}
@@ -688,12 +688,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;
}
}
@@ -1231,6 +1231,26 @@ void RasterizerSceneRD::environment_glow_set_use_bicubic_upscale(bool p_enable)
glow_bicubic_upscale = p_enable;
}
+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);
@@ -1272,7 +1292,7 @@ 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 {
@@ -2012,7 +2032,7 @@ void RasterizerSceneRD::light_instance_set_transform(RID p_light_instance, const
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,6 +2048,9 @@ 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) {
@@ -3167,6 +3190,94 @@ 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_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) {
@@ -3459,6 +3570,23 @@ 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::shadow_filter_set(RS::ShadowFilter p_filter) {
+ shadow_filter = p_filter;
+}
+
int RasterizerSceneRD::get_roughness_layers() const {
return roughness_layers;
}
@@ -3469,7 +3597,7 @@ 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;
}
@@ -3504,12 +3632,15 @@ void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pas
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 +3655,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;
@@ -3562,7 +3694,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;
@@ -3641,26 +3773,33 @@ 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;
+
+ 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_fb, 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_fb, 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_to_rect_and_linearize(render_texture, atlas_fb, atlas_rect, true, znear, zfar);
+ } else {
+ storage->get_effects()->copy_to_rect(render_texture, atlas_fb, 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);
@@ -3798,7 +3937,7 @@ float RasterizerSceneRD::screen_space_roughness_limiter_get_curve() const {
return screen_space_roughness_limiter_curve;
}
-RasterizerSceneRD *RasterizerSceneRD::singleton = NULL;
+RasterizerSceneRD *RasterizerSceneRD::singleton = nullptr;
RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) {
storage = p_storage;
@@ -4012,6 +4151,11 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) {
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");
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");
+ shadow_filter = RS::ShadowFilter(int(GLOBAL_GET("rendering/quality/shadows/filter_mode")));
}
RasterizerSceneRD::~RasterizerSceneRD() {
diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h
index e26607aba5..3478c05fb1 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h
+++ b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h
@@ -79,7 +79,7 @@ protected:
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_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 _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;
@@ -525,6 +527,8 @@ 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::ShadowFilter shadow_filter = RS::SHADOW_FILTER_NONE;
+
/* DIRECTIONAL SHADOW */
struct DirectionalShadow {
@@ -568,10 +572,13 @@ private:
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 +588,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 +597,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;
@@ -657,11 +664,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;
@@ -688,6 +704,9 @@ 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;
@@ -733,6 +752,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;
@@ -832,7 +857,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 +865,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) {}
@@ -857,7 +885,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) {
@@ -903,11 +931,55 @@ public:
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_ 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) {
@@ -921,6 +993,12 @@ public:
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;
@@ -1084,13 +1162,24 @@ public:
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 shadow_filter_set(RS::ShadowFilter p_filter);
+ _FORCE_INLINE_ RS::ShadowFilter shadow_filter_get() const { return shadow_filter; }
+
int get_roughness_layers() const;
bool is_using_radiance_cubemap_array() const;
@@ -1099,7 +1188,9 @@ public:
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 83af15602c..0b26ec1be6 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp
+++ b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "rasterizer_storage_rd.h"
+
#include "core/engine.h"
#include "core/project_settings.h"
#include "servers/rendering/shader_language.h"
@@ -861,7 +862,7 @@ Size2 RasterizerStorageRD::texture_size_with_proxy(RID p_proxy) {
RID RasterizerStorageRD::shader_create() {
Shader shader;
- shader.data = NULL;
+ shader.data = nullptr;
shader.type = SHADER_TYPE_MAX;
return shader_owner.make_rid(shader);
@@ -889,7 +890,7 @@ void RasterizerStorageRD::shader_set_code(RID p_shader, const String &p_code) {
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()) {
@@ -898,7 +899,7 @@ void RasterizerStorageRD::shader_set_code(RID p_shader, const String &p_code) {
material->shader_type = new_type;
if (material->data) {
memdelete(material->data);
- material->data = NULL;
+ material->data = nullptr;
}
}
@@ -990,10 +991,10 @@ void RasterizerStorageRD::shader_set_data_request_function(ShaderType p_shader_t
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;
@@ -1025,12 +1026,12 @@ void RasterizerStorageRD::material_set_shader(RID p_material, RID p_shader) {
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;
}
@@ -1049,7 +1050,7 @@ 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->set_next_pass(material->next_pass);
@@ -1664,7 +1665,7 @@ void RasterizerStorageRD::MaterialData::update_textures(const Map<StringName, Va
RasterizerStorageRD *singleton = (RasterizerStorageRD *)RasterizerStorage::base_singleton;
#ifdef TOOLS_ENABLED
Texture *roughness_detect_texture = nullptr;
- RS::TextureDetectRoughnessChannel roughness_channel;
+ RS::TextureDetectRoughnessChannel roughness_channel = RS::TEXTURE_DETECT_ROUGNHESS_R;
Texture *normal_detect_texture = nullptr;
#endif
@@ -1769,10 +1770,10 @@ 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 */
@@ -3103,15 +3104,17 @@ 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);
}
@@ -3137,6 +3140,7 @@ 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++;
@@ -4452,10 +4456,10 @@ String RasterizerStorageRD::get_captured_timestamp_name(uint32_t p_index) const
RasterizerStorageRD::RasterizerStorageRD() {
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;
+ material_update_list = nullptr;
{ //create default textures
RD::TextureFormat tformat;
diff --git a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h
index e69be644d7..7573a0d70c 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h
+++ b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h
@@ -218,7 +218,7 @@ private:
struct Mesh {
struct Surface {
- RS::PrimitiveType primitive;
+ RS::PrimitiveType primitive = RS::PRIMITIVE_POINTS;
uint32_t format = 0;
RID vertex_buffer;
@@ -232,8 +232,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 +246,7 @@ private:
uint32_t index_count = 0;
struct LOD {
- float edge_length;
+ float edge_length = 0.0;
RID index_buffer;
RID index_array;
};
@@ -456,9 +456,9 @@ private:
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];
@@ -604,7 +604,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 +640,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);
@@ -926,6 +926,14 @@ public:
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;
@@ -1037,7 +1045,7 @@ public:
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;
+ return nullptr;
}
/* PARTICLES */
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..2bfdb7fffe 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
@@ -57,7 +57,7 @@ void RenderPipelineVertexFormatCacheRD::_clear() {
}
version_count = 0;
memfree(versions);
- versions = NULL;
+ versions = nullptr;
}
}
@@ -88,7 +88,7 @@ void RenderPipelineVertexFormatCacheRD::clear() {
RenderPipelineVertexFormatCacheRD::RenderPipelineVertexFormatCacheRD() {
version_count = 0;
- versions = NULL;
+ versions = nullptr;
input_mask = 0;
}
diff --git a/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp b/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp
index b3a4b0ede8..4a0b4f02b1 100644
--- a/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp
+++ b/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp
@@ -303,7 +303,7 @@ void ShaderCompilerRD::_dump_function_deps(const SL::ShaderNode *p_node, const S
_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()) {
@@ -572,7 +572,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
@@ -605,7 +605,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
_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);
@@ -798,12 +798,12 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
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);
}
- 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 += "]";
@@ -1025,7 +1025,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 += "]";
@@ -1048,7 +1048,7 @@ Error ShaderCompilerRD::compile(RS::ShaderMode p_mode, const String &p_code, Ide
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;
}
@@ -1066,7 +1066,7 @@ Error ShaderCompilerRD::compile(RS::ShaderMode p_mode, const String &p_code, Ide
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_rd.cpp b/servers/rendering/rasterizer_rd/shader_rd.cpp
index 3dcfd0faf9..d60a58813e 100644
--- a/servers/rendering/rasterizer_rd/shader_rd.cpp
+++ b/servers/rendering/rasterizer_rd/shader_rd.cpp
@@ -191,7 +191,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,7 +203,7 @@ void ShaderRD::_clear_version(Version *p_version) {
}
memdelete_arr(p_version->variants);
- p_version->variants = NULL;
+ p_version->variants = nullptr;
}
}
@@ -394,7 +394,7 @@ void ShaderRD::_compile_version(Version *p_version) {
}
}
memdelete_arr(p_version->variants);
- p_version->variants = NULL;
+ p_version->variants = nullptr;
return;
}
diff --git a/servers/rendering/rasterizer_rd/shaders/SCsub b/servers/rendering/rasterizer_rd/shaders/SCsub
index 6e852e2dc5..04a43e3251 100644
--- a/servers/rendering/rasterizer_rd/shaders/SCsub
+++ b/servers/rendering/rasterizer_rd/shaders/SCsub
@@ -22,3 +22,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
index 87c20ebaef..5dfdc614a4 100644
--- a/servers/rendering/rasterizer_rd/shaders/blur.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/blur.glsl
@@ -285,6 +285,13 @@ void main() {
frag_color = color;
#endif
+#ifdef MODE_LINEARIZE_DEPTH_COPY
+ float depth = texture(source_color, uv_interp, 0.0).r;
+ depth = depth * 2.0 - 1.0;
+ 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));
+ frag_color = vec4(depth / blur.camera_z_far);
+#endif
+
#ifdef MODE_SSAO_MERGE
vec4 color = texture(source_color, uv_interp, 0.0);
float ssao = texture(source_ssao, uv_interp, 0.0).r;
diff --git a/servers/rendering/rasterizer_rd/shaders/copy.glsl b/servers/rendering/rasterizer_rd/shaders/copy.glsl
index cbb9b546a3..2b541f2660 100644
--- a/servers/rendering/rasterizer_rd/shaders/copy.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/copy.glsl
@@ -57,6 +57,7 @@ void main() {
}
float depth = texture(source_cube, normal).r;
+ depth_buffer = depth;
// absolute values for direction cosines, bigger value equals closer to basis axis
vec3 unorm = abs(normal);
@@ -80,7 +81,7 @@ void main() {
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;
+ depth_buffer = (linear_depth * depth_fix) / params.z_far;
#endif
}
diff --git a/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl b/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl
index 07f4770b14..70ce8d61e4 100644
--- a/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl
@@ -244,19 +244,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,6 +261,14 @@ 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
}
/* clang-format off */
@@ -315,6 +317,11 @@ 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{
/* clang-format off */
@@ -434,9 +441,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 +481,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 +491,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 +552,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 +608,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 +628,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 +659,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 +673,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 +686,119 @@ LIGHT_SHADER_CODE
#ifndef USE_NO_SHADOWS
+const vec2 shadow_poisson_disk[16] = vec2[](
+ vec2(-0.94201624, -0.39906216),
+ vec2(0.94558609, -0.76890725),
+ vec2(-0.094184101, -0.92938870),
+ vec2(0.34495938, 0.29387760),
+ vec2(-0.91588581, 0.45771432),
+ vec2(-0.81544232, -0.87912464),
+ vec2(-0.38277543, 0.27676845),
+ vec2(0.97484398, 0.75648379),
+ vec2(0.44323325, -0.97511554),
+ vec2(0.53742981, -0.47373420),
+ vec2(-0.26496911, -0.41893023),
+ vec2(0.79197514, 0.19090188),
+ vec2(-0.24188840, 0.99706507),
+ vec2(-0.81409955, 0.91437590),
+ vec2(0.19984126, 0.78641367),
+ vec2(0.14383161, -0.14100790));
+
float sample_shadow(texture2D shadow, vec2 shadow_pixel_size, vec4 coord) {
- //todo optimize
vec2 pos = coord.xy;
float depth = coord.z;
-#ifdef SHADOW_MODE_PCF_13
+ switch (scene_data.shadow_filter_mode) {
+ case SHADOW_MODE_NO_FILTER: {
+ return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
+ };
+ case SHADOW_MODE_PCF5: {
+ 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);
+ };
+ case SHADOW_MODE_PCF13: {
+
+ 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));
+ 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);
+ };
+ }
- 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
+ return 0;
+}
-#ifdef SHADOW_MODE_PCF_5
+float sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex_scale) {
- 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);
+ //find blocker
+ float blocker_count = 0.0;
+ float blocker_average = 0.0;
-#endif
+ mat2 poisson_rotate;
-#if !defined(SHADOW_MODE_PCF_5) || !defined(SHADOW_MODE_PCF_13)
+ {
+ float r = dot(vec2(gl_FragCoord.xy), vec2(131.234, 583.123));
+ float sr = sin(r);
+ float cr = cos(r);
+ poisson_rotate = mat2(vec2(cr, -sr), vec2(sr, cr));
+ }
- return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
+ for (uint i = 0; i < scene_data.shadow_blocker_count; i++) {
+ vec2 suv = pssm_coord.xy + (poisson_rotate * shadow_poisson_disk[i]) * 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;
+ }
+ }
-#endif
+ 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.shadow_blocker_count; i++) {
+ vec2 suv = pssm_coord.xy + (poisson_rotate * shadow_poisson_disk[i]) * tex_scale;
+ s += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(suv, pssm_coord.z, 1.0));
+ }
+
+ return s / float(scene_data.shadow_blocker_count);
+
+ } 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,
+#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 +819,203 @@ 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 (lights.data[idx].soft_shadow_size > 0.0) {
+ //soft shadow
+
+ //find blocker
- if (splane.z >= 0.0) {
+ float blocker_count = 0.0;
+ float blocker_average = 0.0;
- splane.z += 1.0;
+ mat2 poisson_rotate;
- clamp_rect.y += clamp_rect.w;
+ {
+ float r = dot(vec2(gl_FragCoord.xy), vec2(131.234, 583.123));
+ float sr = sin(r);
+ float cr = cos(r);
+ poisson_rotate = 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;
+ bitangent *= lights.data[idx].soft_shadow_size;
+
+ for (uint i = 0; i < scene_data.shadow_blocker_count; i++) {
+ vec2 poisson = (poisson_rotate * shadow_poisson_disk[i]);
+ vec3 pos = splane.xyz + tangent * poisson.x + bitangent * poisson.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.shadow_blocker_count; i++) {
+
+ vec2 poisson = (poisson_rotate * shadow_poisson_disk[i]);
+ vec3 pos = splane.xyz + tangent * poisson.x + bitangent * poisson.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.shadow_blocker_count);
+
+ } else {
+ //no blockers found, so no shadow
+ shadow = 1.0;
+ }
} else {
- splane.z = 1.0 - splane.z;
+ splane.xyz = normalize(splane.xyz);
+ vec4 clamp_rect = lights.data[idx].atlas_rect;
+
+ 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_shadow(shadow_atlas, 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
+ {
+
+ //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);
+ splane = normalize(splane);
+
+ 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
- light_attenuation *= mix(shadow_color_enabled.rgb, vec3(1.0), shadow);
+ shadow_attenuation = mix(shadow_color_enabled.rgb, vec3(1.0), 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,
@@ -764,8 +1034,14 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
}
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,
+#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 +1068,135 @@ 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
+
+ float blocker_count = 0.0;
+ float blocker_average = 0.0;
+
+ mat2 poisson_rotate;
+
+ {
+ float r = dot(vec2(gl_FragCoord.xy), vec2(131.234, 583.123));
+ float sr = sin(r);
+ float cr = cos(r);
+ poisson_rotate = mat2(vec2(cr, -sr), vec2(sr, cr));
+ }
+
+ float uv_size = lights.data[idx].soft_shadow_size * z_norm;
+ for (uint i = 0; i < scene_data.shadow_blocker_count; i++) {
+ vec2 suv = splane.xy + (poisson_rotate * shadow_poisson_disk[i]) * uv_size;
+ suv = clamp(suv, lights.data[idx].atlas_rect.xy, lights.data[idx].atlas_rect.zw);
+ 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.shadow_blocker_count; i++) {
+ vec2 suv = splane.xy + (poisson_rotate * shadow_poisson_disk[i]) * uv_size;
+ suv = clamp(suv, lights.data[idx].atlas_rect.xy, lights.data[idx].atlas_rect.zw);
+ shadow += textureProj(sampler2DShadow(shadow_atlas, shadow_sampler), vec4(suv, z_norm, 1.0));
+ }
+
+ shadow /= float(scene_data.shadow_blocker_count);
+
+ } else {
+ //no blockers found, so no shadow
+ shadow = 1.0;
+ }
+
+ } else {
+ //hard shadow
+ splane.z = z_norm;
+ shadow = sample_shadow(shadow_atlas, scene_data.shadow_atlas_pixel_size, splane);
+ }
+
+ shadow_attenuation = mix(shadow_color_enabled.rgb, vec3(1.0), shadow);
+
+#ifdef LIGHT_TRANSMITTANCE_USED
+ {
+
+ vec4 splane = (lights.data[idx].shadow_matrix * vec4(vertex - normalize(normal_interp) * lights.data[idx].transmittance_bias, 1.0));
+ splane /= splane.w;
+
+ 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,
@@ -1185,7 +1565,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);
@@ -1254,6 +1638,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)
@@ -1462,58 +1854,250 @@ FRAGMENT_SHADER_CODE
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);
+ } else {
+ shadow = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, 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);
+ } else {
+ shadow = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, 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);
+ } else {
+ shadow = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, 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));
- }
- pssm_coord /= pssm_coord.w;
+ 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;
+ shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale);
+ } else {
+ shadow = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, pssm_coord);
+ }
+
+ 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;
- float shadow = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, pssm_coord);
+ 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);
+ } else {
+ shadow2 = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, 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);
+ } else {
+ shadow2 = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, 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);
+ } else {
+ shadow2 = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, 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,
@@ -1546,8 +2130,14 @@ FRAGMENT_SHADER_CODE
}
light_process_omni(light_index, vertex, view, normal, albedo, roughness, metallic, specular, specular_blob_intensity,
-#ifdef LIGHT_TRANSMISSION_USED
- transmission,
+#ifdef LIGHT_BACKLIGHT_USED
+ backlight,
+#endif
+#ifdef LIGHT_TRANSMITTANCE_USED
+ transmittance_color,
+ transmittance_depth,
+ transmittance_curve,
+ transmittance_boost,
#endif
#ifdef LIGHT_RIM_USED
rim,
@@ -1579,8 +2169,14 @@ FRAGMENT_SHADER_CODE
}
light_process_spot(light_index, vertex, view, normal, albedo, roughness, metallic, specular, specular_blob_intensity,
-#ifdef LIGHT_TRANSMISSION_USED
- transmission,
+#ifdef LIGHT_BACKLIGHT_USED
+ backlight,
+#endif
+#ifdef LIGHT_TRANSMITTANCE_USED
+ transmittance_color,
+ transmittance_depth,
+ transmittance_curve,
+ transmittance_boost,
#endif
#ifdef LIGHT_RIM_USED
rim,
@@ -1697,6 +2293,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..59f326bc9b 100644
--- a/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl
@@ -22,6 +22,10 @@ draw_call;
#define SAMPLER_NEAREST_WITH_MIPMAPS_ANISOTROPIC_REPEAT 10
#define SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_REPEAT 11
+#define SHADOW_MODE_NO_FILTER 0
+#define SHADOW_MODE_PCF5 1
+#define SHADOW_MODE_PCF13 2
+
layout(set = 0, binding = 1) uniform sampler material_samplers[12];
layout(set = 0, binding = 2) uniform sampler shadow_sampler;
@@ -37,13 +41,17 @@ 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 shadow_filter_mode;
+
+ uint shadow_blocker_count;
+ uint shadow_pad0;
+ uint shadow_pad1;
+ uint shadow_pad2;
+
vec4 ambient_light_color_energy;
float ambient_color_sky_mix;
@@ -134,21 +142,27 @@ layout(set = 0, binding = 4, std430) buffer Instances {
}
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; // used for spot
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
+ uint mask;
+ uint pad[3];
};
-layout(set = 0, binding = 5, std140) uniform Lights {
- LightData data[MAX_LIGHT_DATA_STRUCTS];
+layout(set = 0, binding = 5, std430) buffer Lights {
+ LightData data[];
}
lights;
@@ -173,18 +187,33 @@ struct DirectionalLightData {
vec3 direction;
float energy;
vec3 color;
+ float size;
float specular;
- vec3 shadow_color;
uint mask;
+ float softshadow_angle;
+ uint pad1;
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 {
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..e3c26c9b72
--- /dev/null
+++ b/servers/rendering/rasterizer_rd/shaders/screen_space_reflection.glsl
@@ -0,0 +1,262 @@
+/* clang-format off */
+[compute]
+
+#version 450
+
+VERSION_DEFINES
+
+
+
+layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
+
+/* clang-format on */
+
+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(greaterThan(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..1a5dd5ab55
--- /dev/null
+++ b/servers/rendering/rasterizer_rd/shaders/screen_space_reflection_filter.glsl
@@ -0,0 +1,164 @@
+/* clang-format off */
+[compute]
+
+#version 450
+
+VERSION_DEFINES
+
+
+
+layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
+
+/* clang-format on */
+
+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(greaterThan(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..cec6c14c76
--- /dev/null
+++ b/servers/rendering/rasterizer_rd/shaders/screen_space_reflection_scale.glsl
@@ -0,0 +1,96 @@
+/* clang-format off */
+[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_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(greaterThan(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..469925839a 100644
--- a/servers/rendering/rasterizer_rd/shaders/sky.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/sky.glsl
@@ -141,15 +141,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
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..b28250318e
--- /dev/null
+++ b/servers/rendering/rasterizer_rd/shaders/specular_merge.glsl
@@ -0,0 +1,59 @@
+/* clang-format off */
+[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]
+
+#version 450
+
+VERSION_DEFINES
+
+layout(location = 0) in vec2 uv_interp;
+/* clang-format on */
+
+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 = texture(ssr, uv_interp);
+ frag_color.rgb = mix(frag_color.rgb, ssr.rgb, ssr.a);
+#endif
+
+#ifdef MODE_MERGE
+ frag_color += texture(diffuse, uv_interp);
+#endif
+ //added using additive blend
+}
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..41f8fde3ca
--- /dev/null
+++ b/servers/rendering/rasterizer_rd/shaders/subsurface_scattering.glsl
@@ -0,0 +1,198 @@
+/* clang-format off */
+[compute]
+
+#version 450
+
+VERSION_DEFINES
+
+
+
+layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
+
+/* clang-format on */
+
+#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(greaterThan(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/rendering_device.cpp b/servers/rendering/rendering_device.cpp
index 3c1795161d..a3799b0e4d 100644
--- a/servers/rendering/rendering_device.cpp
+++ b/servers/rendering/rendering_device.cpp
@@ -30,14 +30,14 @@
#include "rendering_device.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;
diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h
index 4705bcaa75..a639ff3641 100644
--- a/servers/rendering/rendering_device.h
+++ b/servers/rendering/rendering_device.h
@@ -563,7 +563,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);
diff --git a/servers/rendering/rendering_server_canvas.cpp b/servers/rendering/rendering_server_canvas.cpp
index 261bd4c275..5d6dcfd2c1 100644
--- a/servers/rendering/rendering_server_canvas.cpp
+++ b/servers/rendering/rendering_server_canvas.cpp
@@ -43,14 +43,14 @@ void RenderingServerCanvas::_render_canvas_item_tree(RID p_to_render_target, Can
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])
@@ -78,7 +78,7 @@ 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++;
@@ -92,7 +92,7 @@ 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);
}
@@ -118,7 +118,7 @@ void RenderingServerCanvas::_cull_canvas_item(Item *p_canvas_item, const Transfo
ci->material_owner = p_material_owner;
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);
@@ -130,7 +130,7 @@ void RenderingServerCanvas::_cull_canvas_item(Item *p_canvas_item, const Transfo
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;
@@ -145,7 +145,7 @@ void RenderingServerCanvas::_cull_canvas_item(Item *p_canvas_item, const Transfo
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;
@@ -183,7 +183,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,7 +204,7 @@ 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++) {
@@ -265,30 +265,30 @@ 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);
}
}
}
@@ -946,12 +946,12 @@ void RenderingServerCanvas::canvas_item_set_copy_to_backbuffer(RID p_item, bool
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;
}
}
diff --git a/servers/rendering/rendering_server_canvas.h b/servers/rendering/rendering_server_canvas.h
index c79b74f287..9da11462db 100644
--- a/servers/rendering/rendering_server_canvas.h
+++ b/servers/rendering/rendering_server_canvas.h
@@ -59,7 +59,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);
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.h b/servers/rendering/rendering_server_raster.h
index 7c18bf91ce..1b9755397a 100644
--- a/servers/rendering/rendering_server_raster.h
+++ b/servers/rendering/rendering_server_raster.h
@@ -456,7 +456,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)
@@ -523,7 +523,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)
@@ -539,6 +541,8 @@ public:
BIND5(environment_set_fog_height, RID, bool, float, float, float)
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 +554,8 @@ 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(shadow_filter_set, ShadowFilter)
+
/* SCENARIO API */
#undef BINDBASE
diff --git a/servers/rendering/rendering_server_scene.cpp b/servers/rendering/rendering_server_scene.cpp
index 04e4b8dace..d66708587a 100644
--- a/servers/rendering/rendering_server_scene.cpp
+++ b/servers/rendering/rendering_server_scene.cpp
@@ -194,7 +194,7 @@ void *RenderingServerScene::_instance_pair(void *p_self, OctreeElementID, Instan
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) {
@@ -375,7 +375,7 @@ 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;
@@ -416,7 +416,7 @@ void RenderingServerScene::instance_set_base(RID p_instance, RID p_base) {
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_capture = nullptr;
instance->lightmap = RID();
}
@@ -429,7 +429,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();
@@ -533,7 +533,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: {
@@ -564,7 +564,7 @@ void RenderingServerScene::instance_set_scenario(RID p_instance, RID p_scenario)
}
}
- instance->scenario = NULL;
+ instance->scenario = nullptr;
}
if (p_scenario.is_valid()) {
@@ -720,7 +720,7 @@ void RenderingServerScene::instance_set_use_lightmap(RID p_instance, RID p_light
InstanceLightmapCaptureData *lightmap_capture = static_cast<InstanceLightmapCaptureData *>(((Instance *)instance->lightmap_capture)->base_data);
lightmap_capture->users.erase(instance);
instance->lightmap = RID();
- instance->lightmap_capture = NULL;
+ instance->lightmap_capture = nullptr;
}
if (p_lightmap_instance.is_valid()) {
@@ -744,16 +744,16 @@ void RenderingServerScene::instance_set_custom_aabb(RID p_instance, AABB p_aabb)
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;
}
}
@@ -1334,7 +1334,7 @@ void RenderingServerScene::_update_instance_lightmap_captures(Instance *p_instan
}
}
-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);
@@ -1347,16 +1347,18 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
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,8 +1367,8 @@ 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++) {
@@ -1379,7 +1381,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,7 +1401,7 @@ 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)) {
@@ -1408,7 +1410,7 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
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,11 +1419,13 @@ 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;
+
+ real_t min_distance_bias_scale = pancake_size > 0 ? distances[1] / 10.0 : 0;
for (int i = 0; i < splits; i++) {
@@ -1430,7 +1434,7 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
// 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) {
@@ -1439,8 +1443,8 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
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,26 +1462,27 @@ 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++) {
- float d_x = x_vec.dot(endpoints[j]);
- float d_y = y_vec.dot(endpoints[j]);
- float d_z = z_vec.dot(endpoints[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]);
if (j == 0 || d_x < x_min)
x_min = d_x;
@@ -1495,11 +1500,13 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
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];
@@ -1508,11 +1515,9 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
//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]);
+ real_t d = center.distance_to(endpoints[j]);
if (d > radius)
radius = d;
}
@@ -1525,18 +1530,35 @@ 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 +1588,10 @@ 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,8 +1603,91 @@ 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);
+ }
+
+ if (i == 0) {
+ //print_line("prev he: " + vp_he + " new he: " + camera_matrix_square.get_viewport_half_extents());
+ }
+ }
+
+ 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.
}
{
@@ -1592,11 +1698,19 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
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);
@@ -1614,9 +1728,9 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
//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.write[0] = light_transform.xform(Plane(Vector3(0, 0, z), radius));
@@ -1645,12 +1759,12 @@ 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);
@@ -1699,12 +1813,12 @@ 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;
@@ -1712,8 +1826,8 @@ bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, c
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);
@@ -1738,7 +1852,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;
@@ -1793,12 +1907,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 +1924,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 +1984,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
@@ -2112,7 +2224,7 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const
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));
}
@@ -2214,7 +2326,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));
}
}
@@ -2259,7 +2371,7 @@ void RenderingServerScene::render_empty_scene(RID p_render_buffers, RID p_scenar
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, environment, RID(), p_shadow_atlas, scenario->reflection_atlas, RID(), 0);
#endif
}
@@ -2324,7 +2436,7 @@ bool RenderingServerScene::_render_reflection_probe_step(Instance *p_instance, i
}
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 {
@@ -2827,7 +2939,7 @@ bool RenderingServerScene::free(RID p_rid) {
return true;
}
-RenderingServerScene *RenderingServerScene::singleton = NULL;
+RenderingServerScene *RenderingServerScene::singleton = nullptr;
RenderingServerScene::RenderingServerScene() {
diff --git a/servers/rendering/rendering_server_scene.h b/servers/rendering/rendering_server_scene.h
index 9e09136216..0970fed6c4 100644
--- a/servers/rendering/rendering_server_scene.h
+++ b/servers/rendering/rendering_server_scene.h
@@ -39,7 +39,7 @@
#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:
@@ -196,7 +196,7 @@ public:
update_item(this) {
octree_id = 0;
- scenario = NULL;
+ scenario = nullptr;
update_aabb = false;
update_dependencies = false;
@@ -213,9 +213,9 @@ public:
last_render_pass = 0;
last_frame_pass = 0;
version = 1;
- base_data = NULL;
+ base_data = nullptr;
- custom_aabb = NULL;
+ custom_aabb = nullptr;
}
~Instance() {
@@ -301,9 +301,9 @@ public:
InstanceLightData() {
shadow_dirty = true;
- D = NULL;
+ D = nullptr;
last_version = 0;
- baked_light = NULL;
+ baked_light = nullptr;
}
};
@@ -418,15 +418,15 @@ public:
_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();
diff --git a/servers/rendering/rendering_server_viewport.cpp b/servers/rendering/rendering_server_viewport.cpp
index f80b914760..87dcb772bc 100644
--- a/servers/rendering/rendering_server_viewport.cpp
+++ b/servers/rendering/rendering_server_viewport.cpp
@@ -62,24 +62,24 @@ 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) {
/* Camera should always be BEFORE any other 3D */
@@ -128,9 +128,9 @@ 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;
@@ -160,7 +160,7 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface
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;
@@ -169,7 +169,7 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface
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,7 +196,7 @@ 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");
@@ -249,7 +249,7 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface
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) {
@@ -293,17 +293,15 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface
void RenderingServerViewport::draw_viewports() {
-#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"));
@@ -367,38 +365,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
{
@@ -470,11 +471,11 @@ 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) {
diff --git a/servers/rendering/rendering_server_viewport.h b/servers/rendering/rendering_server_viewport.h
index f574c58d96..71d8408ed1 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:
@@ -47,7 +47,7 @@ public:
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;
@@ -127,7 +127,7 @@ public:
for (int i = 0; i < RS::VIEWPORT_RENDER_INFO_MAX; i++) {
render_info[i] = 0;
}
- use_arvr = false;
+ use_xr = false;
}
};
@@ -152,13 +152,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);
diff --git a/servers/rendering/rendering_server_wrap_mt.cpp b/servers/rendering/rendering_server_wrap_mt.cpp
index 5d6d523901..4ca13dbef9 100644
--- a/servers/rendering/rendering_server_wrap_mt.cpp
+++ b/servers/rendering/rendering_server_wrap_mt.cpp
@@ -126,17 +126,6 @@ void RenderingServerWrapMT::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();
@@ -161,6 +150,17 @@ 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) {
@@ -168,7 +168,7 @@ 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) {
@@ -178,7 +178,7 @@ RenderingServerWrapMT::RenderingServerWrapMT(RenderingServer *p_contained, bool
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");
diff --git a/servers/rendering/rendering_server_wrap_mt.h b/servers/rendering/rendering_server_wrap_mt.h
index bcd1344f44..9a98841b2c 100644
--- a/servers/rendering/rendering_server_wrap_mt.h
+++ b/servers/rendering/rendering_server_wrap_mt.h
@@ -370,7 +370,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)
@@ -437,7 +437,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)
@@ -454,6 +456,8 @@ public:
FUNC5(environment_set_fog_height, RID, bool, float, float, float)
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 +467,8 @@ 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(shadow_filter_set, ShadowFilter)
+
FUNCRID(scenario)
FUNC2(scenario_set_debug, RID, ScenarioDebugMode)
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index 300c38db22..76a81a4a1c 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -328,7 +328,7 @@ 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() {
@@ -879,7 +879,7 @@ 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();
@@ -913,7 +913,7 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea
return true;
}
- FunctionNode *function = NULL;
+ FunctionNode *function = nullptr;
while (p_block) {
@@ -2107,14 +2107,14 @@ 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) {
@@ -3150,7 +3150,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
while (true) {
- Node *expr = NULL;
+ Node *expr = nullptr;
TkPos prepos = _get_tkpos();
Token tk = _get_token();
TkPos pos = _get_tkpos();
@@ -3162,14 +3162,14 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
expr = _parse_and_reduce_expression(p_block, p_builtin_types);
if (!expr)
- return NULL;
+ 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) {
@@ -3214,7 +3214,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
//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
@@ -3234,7 +3234,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;
@@ -3250,11 +3250,11 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
if (!ok)
- return NULL;
+ 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);
@@ -3265,7 +3265,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
StringName identifier;
- StructNode *pstruct = NULL;
+ StructNode *pstruct = nullptr;
bool struct_init = false;
_get_completable_identifier(p_block, COMPLETION_IDENTIFIER, identifier);
@@ -3317,7 +3317,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
} 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 +3335,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 +3343,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 +3383,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;
}
}
@@ -3396,12 +3396,12 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
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();
@@ -3419,30 +3419,30 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
_set_error("Expected '}' or ','");
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 +3450,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 +3458,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 +3482,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;
}
@@ -3514,11 +3514,11 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
if (!ok)
- return NULL;
+ 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) {
@@ -3529,7 +3529,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
if (call_function) {
//get current base function
- FunctionNode *base_function = NULL;
+ FunctionNode *base_function = nullptr;
{
BlockNode *b = p_block;
@@ -3544,7 +3544,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 +3556,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 +3584,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 +3599,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 +3653,30 @@ 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) {
@@ -3685,17 +3685,17 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
call_expression = _parse_and_reduce_expression(p_block, p_builtin_types);
p_block->block_tag = SubClassTag::TAG_GLOBAL;
if (!call_expression)
- return NULL;
+ 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;
+ 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 +3705,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 +3714,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;
}
}
@@ -3750,18 +3750,18 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
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);
+ 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.. */
@@ -3791,7 +3791,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;
@@ -4042,12 +4042,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>();
@@ -4066,16 +4066,16 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
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;
+ 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 +4085,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 +4094,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;
}
}
@@ -4120,11 +4120,11 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
Node *index = _parse_and_reduce_expression(p_block, p_builtin_types);
if (!index)
- return NULL;
+ 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,7 +4139,7 @@ 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;
}
}
@@ -4162,7 +4162,7 @@ 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;
}
}
@@ -4184,7 +4184,7 @@ 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;
}
}
@@ -4199,7 +4199,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
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,7 +4213,7 @@ 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) {
@@ -4224,12 +4224,12 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
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 {
@@ -4287,7 +4287,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
case TK_COLON: o.op = OP_SELECT_ELSE; break;
default: {
_set_error("Invalid token for operator: " + get_token_text(tk));
- return NULL;
+ return nullptr;
}
}
@@ -4379,7 +4379,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,7 +4392,7 @@ 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..
@@ -4405,7 +4405,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
if (expr_pos == expression.size()) {
//can happen..
_set_error("Unexpected end of expression...");
- return NULL;
+ return nullptr;
}
}
@@ -4417,7 +4417,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
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);
@@ -4433,7 +4433,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
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);
}
@@ -4442,12 +4442,12 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
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>();
@@ -4467,7 +4467,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
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++) {
@@ -4478,7 +4478,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
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>();
@@ -4487,7 +4487,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
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)) {
@@ -4496,7 +4496,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
if (!_validate_assign(expression[next_op - 1].node, p_builtin_types, &assign_message)) {
_set_error(assign_message);
- return NULL;
+ return nullptr;
}
}
@@ -4528,7 +4528,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);
@@ -4658,7 +4658,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_and_reduce_expression(BlockNode *p_
ShaderLanguage::Node *expr = _parse_expression(p_block, p_builtin_types);
if (!expr) //errored
- return NULL;
+ return nullptr;
expr = _reduce_expression(p_block, expr);
@@ -4741,7 +4741,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
tk = _get_token();
- Node *vardecl = NULL;
+ Node *vardecl = nullptr;
while (true) {
@@ -4752,7 +4752,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;
@@ -5025,7 +5025,7 @@ 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);
@@ -5061,7 +5061,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);
}
@@ -5326,7 +5326,7 @@ 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>();
@@ -5694,7 +5694,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
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");
@@ -5898,7 +5898,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;
}
@@ -6074,7 +6074,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
if (tk.type == TK_OP_ASSIGN) {
- Node *expr = _parse_and_reduce_expression(NULL, Map<StringName, BuiltInInfo>());
+ Node *expr = _parse_and_reduce_expression(nullptr, Map<StringName, BuiltInInfo>());
if (!expr)
return ERR_PARSE_ERROR;
if (expr->type != Node::TYPE_CONSTANT) {
@@ -6191,14 +6191,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;
}
@@ -6222,7 +6222,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
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) {
@@ -6232,7 +6232,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
//variable created with assignment! must parse an expression
- Node *expr = _parse_and_reduce_expression(NULL, Map<StringName, BuiltInInfo>());
+ 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) {
@@ -6266,7 +6266,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 +6405,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;
@@ -6645,7 +6645,7 @@ Error ShaderLanguage::compile(const String &p_code, const Map<StringName, Functi
code = p_code;
- nodes = NULL;
+ nodes = nullptr;
shader = alloc_node<ShaderNode>();
Error err = _parse_shader(p_functions, p_render_modes, p_shader_types);
@@ -6662,7 +6662,7 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
code = p_code;
- nodes = NULL;
+ nodes = nullptr;
shader = alloc_node<ShaderNode>();
_parse_shader(p_functions, p_render_modes, p_shader_types);
@@ -7001,7 +7001,7 @@ ShaderLanguage::ShaderNode *ShaderLanguage::get_shader() {
ShaderLanguage::ShaderLanguage() {
- nodes = NULL;
+ nodes = nullptr;
completion_class = TAG_GLOBAL;
}
diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h
index 9124bee633..beabae0dda 100644
--- a/servers/rendering/shader_language.h
+++ b/servers/rendering/shader_language.h
@@ -342,7 +342,7 @@ public:
virtual String get_datatype_name() const { return ""; }
Node(Type t) :
- next(NULL),
+ next(nullptr),
type(t) {}
virtual ~Node() {}
};
@@ -423,8 +423,8 @@ public:
ArrayNode() :
Node(TYPE_ARRAY),
datatype_cache(TYPE_VOID),
- index_expression(NULL),
- call_expression(NULL),
+ index_expression(nullptr),
+ call_expression(nullptr),
is_const(false) {}
};
@@ -511,8 +511,8 @@ public:
BlockNode() :
Node(TYPE_BLOCK),
- parent_function(NULL),
- parent_block(NULL),
+ parent_function(nullptr),
+ parent_block(nullptr),
block_type(BLOCK_TYPE_STANDART),
block_tag(SubClassTag::TAG_GLOBAL),
single_statement(false) {}
@@ -550,8 +550,8 @@ public:
basetype_const(false),
datatype(TYPE_VOID),
array_size(0),
- owner(NULL),
- index_expression(NULL),
+ owner(nullptr),
+ index_expression(nullptr),
has_swizzling_duplicates(false) {}
};
@@ -592,7 +592,7 @@ public:
Node(TYPE_FUNCTION),
return_type(TYPE_VOID),
return_precision(PRECISION_DEFAULT),
- body(NULL),
+ body(nullptr),
can_discard(false) {}
};
@@ -733,7 +733,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);
@@ -825,10 +825,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 +861,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);
diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp
index b144d6d612..de69fea16f 100644
--- a/servers/rendering/shader_types.cpp
+++ b/servers/rendering/shader_types.cpp
@@ -44,7 +44,7 @@ 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) {
@@ -108,7 +108,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 +149,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 +172,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");