summaryrefslogtreecommitdiff
path: root/servers/rendering
diff options
context:
space:
mode:
Diffstat (limited to 'servers/rendering')
-rw-r--r--servers/rendering/rasterizer.cpp2
-rw-r--r--servers/rendering/rasterizer.h35
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp343
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h22
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp39
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_effects_rd.h10
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_rd.cpp2
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_rd.h2
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp41
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h8
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp2
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_scene_rd.h4
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp97
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_storage_rd.h10
-rw-r--r--servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h2
-rw-r--r--servers/rendering/rasterizer_rd/shader_compiler_rd.cpp2
-rw-r--r--servers/rendering/rasterizer_rd/shader_compiler_rd.h2
-rw-r--r--servers/rendering/rasterizer_rd/shader_rd.cpp2
-rw-r--r--servers/rendering/rasterizer_rd/shader_rd.h8
-rw-r--r--servers/rendering/rasterizer_rd/shaders/canvas.glsl226
-rw-r--r--servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl9
-rw-r--r--servers/rendering/rasterizer_rd/shaders/copy.glsl28
-rw-r--r--servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl110
-rw-r--r--servers/rendering/rendering_device.h4
-rw-r--r--servers/rendering/rendering_server_canvas.cpp188
-rw-r--r--servers/rendering/rendering_server_canvas.h15
-rw-r--r--servers/rendering/rendering_server_raster.cpp4
-rw-r--r--servers/rendering/rendering_server_raster.h12
-rw-r--r--servers/rendering/rendering_server_scene.h6
-rw-r--r--servers/rendering/rendering_server_viewport.cpp154
-rw-r--r--servers/rendering/rendering_server_viewport.h13
-rw-r--r--servers/rendering/rendering_server_wrap_mt.cpp2
-rw-r--r--servers/rendering/rendering_server_wrap_mt.h14
-rw-r--r--servers/rendering/shader_language.cpp2
-rw-r--r--servers/rendering/shader_language.h12
-rw-r--r--servers/rendering/shader_types.cpp8
-rw-r--r--servers/rendering/shader_types.h2
37 files changed, 1151 insertions, 291 deletions
diff --git a/servers/rendering/rasterizer.cpp b/servers/rendering/rasterizer.cpp
index 566a14b655..32084c8a3e 100644
--- a/servers/rendering/rasterizer.cpp
+++ b/servers/rendering/rasterizer.cpp
@@ -31,7 +31,7 @@
#include "rasterizer.h"
#include "core/os/os.h"
-#include "core/print_string.h"
+#include "core/string/print_string.h"
Rasterizer *(*Rasterizer::_create_func)() = nullptr;
diff --git a/servers/rendering/rasterizer.h b/servers/rendering/rasterizer.h
index 4ece811a1e..efaa8f138a 100644
--- a/servers/rendering/rasterizer.h
+++ b/servers/rendering/rasterizer.h
@@ -32,8 +32,8 @@
#define RASTERIZER_H
#include "core/math/camera_matrix.h"
-#include "core/pair.h"
-#include "core/self_list.h"
+#include "core/templates/pair.h"
+#include "core/templates/self_list.h"
#include "servers/rendering_server.h"
class RasterizerScene {
@@ -815,7 +815,8 @@ public:
CANVAS_RECT_FLIP_H = 4,
CANVAS_RECT_FLIP_V = 8,
CANVAS_RECT_TRANSPOSE = 16,
- CANVAS_RECT_CLIP_UV = 32
+ CANVAS_RECT_CLIP_UV = 32,
+ CANVAS_RECT_IS_GROUP = 64,
};
struct Light {
@@ -831,7 +832,9 @@ public:
int layer_max;
int item_mask;
int item_shadow_mask;
+ float directional_distance;
RS::CanvasLightMode mode;
+ RS::CanvasLightBlendMode blend_mode;
RID texture;
Vector2 texture_offset;
RID canvas;
@@ -853,7 +856,7 @@ public:
Light *shadows_next_ptr;
Light *filter_next_ptr;
Light *next_ptr;
- Light *mask_next_ptr;
+ Light *directional_next_ptr;
RID light_internal;
uint64_t version;
@@ -874,16 +877,18 @@ public:
scale = 1.0;
energy = 1.0;
item_shadow_mask = 1;
- mode = RS::CANVAS_LIGHT_MODE_ADD;
+ mode = RS::CANVAS_LIGHT_MODE_POINT;
+ blend_mode = RS::CANVAS_LIGHT_BLEND_MODE_ADD;
// texture_cache = nullptr;
next_ptr = nullptr;
- mask_next_ptr = nullptr;
+ directional_next_ptr = nullptr;
filter_next_ptr = nullptr;
use_shadow = false;
shadow_buffer_size = 2048;
shadow_filter = RS::CANVAS_LIGHT_FILTER_NONE;
shadow_smooth = 0.0;
render_index_cache = -1;
+ directional_distance = 10000.0;
}
};
@@ -1060,7 +1065,16 @@ public:
bool visible;
bool behind;
bool update_when_visible;
- //RS::MaterialBlendMode blend_mode;
+
+ struct CanvasGroup {
+ RS::CanvasGroupMode mode;
+ bool fit_empty;
+ float fit_margin;
+ bool blur_mipmaps;
+ float clear_margin;
+ };
+
+ CanvasGroup *canvas_group = nullptr;
int light_mask;
int z_final;
@@ -1084,6 +1098,7 @@ public:
Rect2 final_clip_rect;
Item *final_clip_owner;
Item *material_owner;
+ Item *canvas_group_owner;
ViewportRender *vp_render;
bool distance_field;
bool light_masked;
@@ -1242,6 +1257,8 @@ public:
}
void clear() {
+ // The first one is always allocated on heap
+ // the rest go in the blocks
Command *c = commands;
while (c) {
Command *n = c->next;
@@ -1282,6 +1299,7 @@ public:
vp_render = nullptr;
next = nullptr;
final_clip_owner = nullptr;
+ canvas_group_owner = nullptr;
clip = false;
final_modulate = Color(1, 1, 1, 1);
visible = true;
@@ -1308,7 +1326,7 @@ public:
}
};
- virtual void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, const Transform2D &p_canvas_transform, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat) = 0;
+ virtual void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_list, const Transform2D &p_canvas_transform, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel) = 0;
virtual void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) = 0;
struct LightOccluderInstance {
@@ -1336,6 +1354,7 @@ public:
virtual void light_set_texture(RID p_rid, RID p_texture) = 0;
virtual void light_set_use_shadow(RID p_rid, bool p_enable) = 0;
virtual void light_update_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders) = 0;
+ virtual void light_update_directional_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_cull_distance, const Rect2 &p_clip_rect, LightOccluderInstance *p_occluders) = 0;
virtual RID occluder_polygon_create() = 0;
virtual void occluder_polygon_set_shape_as_lines(RID p_occluder, const Vector<Vector2> &p_lines) = 0;
diff --git a/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp
index 28674b118c..5d9e68f2b4 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp
+++ b/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp
@@ -29,8 +29,8 @@
/*************************************************************************/
#include "rasterizer_canvas_rd.h"
+#include "core/config/project_settings.h"
#include "core/math/math_funcs.h"
-#include "core/project_settings.h"
#include "rasterizer_rd.h"
void RasterizerCanvasRD::_update_transform_2d_to_mat4(const Transform2D &p_transform, float *p_mat4) {
@@ -328,7 +328,7 @@ void RasterizerCanvasRD::_bind_canvas_texture(RD::DrawListID p_draw_list, RID p_
bool use_normal;
bool use_specular;
- bool success = storage->canvas_texture_get_unifom_set(p_texture, p_base_filter, p_base_repeat, shader.default_version_rd_shader, CANVAS_TEXTURE_UNIFORM_SET, uniform_set, size, specular_shininess, use_normal, use_specular);
+ bool success = storage->canvas_texture_get_uniform_set(p_texture, p_base_filter, p_base_repeat, shader.default_version_rd_shader, CANVAS_TEXTURE_UNIFORM_SET, uniform_set, size, specular_shininess, use_normal, use_specular);
//something odd happened
if (!success) {
_bind_canvas_texture(p_draw_list, default_canvas_texture, p_base_filter, p_base_repeat, r_last_texture, push_constant, r_texpixel_size);
@@ -416,10 +416,6 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_
light_count++;
- if (light->mode == RS::CANVAS_LIGHT_MODE_MASK) {
- base_flags |= FLAGS_USING_LIGHT_MASK;
- }
-
if (light_count == MAX_LIGHTS_PER_ITEM) {
break;
}
@@ -430,7 +426,7 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_
base_flags |= light_count << FLAGS_LIGHT_COUNT_SHIFT;
}
- light_mode = light_count > 0 ? PIPELINE_LIGHT_MODE_ENABLED : PIPELINE_LIGHT_MODE_DISABLED;
+ light_mode = (light_count > 0 || using_directional_lights) ? PIPELINE_LIGHT_MODE_ENABLED : PIPELINE_LIGHT_MODE_DISABLED;
PipelineVariants *pipeline_variants = p_pipeline_variants;
@@ -1102,28 +1098,36 @@ RID RasterizerCanvasRD::_create_base_uniform_set(RID p_to_render_target, bool p_
return uniform_set;
}
-void RasterizerCanvasRD::_render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights) {
+void RasterizerCanvasRD::_render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool p_to_backbuffer) {
Item *current_clip = nullptr;
Transform2D canvas_transform_inverse = p_canvas_transform_inverse;
- RID framebuffer = storage->render_target_get_rd_framebuffer(p_to_render_target);
-
- Vector<Color> clear_colors;
+ RID framebuffer;
+ RID fb_uniform_set;
bool clear = false;
- if (storage->render_target_is_clear_requested(p_to_render_target)) {
- clear = true;
- clear_colors.push_back(storage->render_target_get_clear_request_color(p_to_render_target));
- storage->render_target_disable_clear_request(p_to_render_target);
- }
+ Vector<Color> clear_colors;
+
+ if (p_to_backbuffer) {
+ framebuffer = storage->render_target_get_rd_backbuffer_framebuffer(p_to_render_target);
+ fb_uniform_set = storage->render_target_get_backbuffer_uniform_set(p_to_render_target);
+ } else {
+ framebuffer = storage->render_target_get_rd_framebuffer(p_to_render_target);
+
+ if (storage->render_target_is_clear_requested(p_to_render_target)) {
+ clear = true;
+ clear_colors.push_back(storage->render_target_get_clear_request_color(p_to_render_target));
+ storage->render_target_disable_clear_request(p_to_render_target);
+ }
#ifndef _MSC_VER
#warning TODO obtain from framebuffer format eventually when this is implemented
#endif
- RID fb_uniform_set = storage->render_target_get_framebuffer_uniform_set(p_to_render_target);
+ fb_uniform_set = storage->render_target_get_framebuffer_uniform_set(p_to_render_target);
+ }
if (fb_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(fb_uniform_set)) {
- fb_uniform_set = _create_base_uniform_set(p_to_render_target, false);
+ fb_uniform_set = _create_base_uniform_set(p_to_render_target, p_to_backbuffer);
}
RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer);
@@ -1152,10 +1156,16 @@ void RasterizerCanvasRD::_render_items(RID p_to_render_target, int p_item_count,
}
}
- if (ci->material != prev_material) {
+ RID material = ci->material;
+
+ if (material.is_null() && ci->canvas_group != nullptr) {
+ material = default_canvas_group_material;
+ }
+
+ if (material != prev_material) {
MaterialData *material_data = nullptr;
- if (ci->material.is_valid()) {
- material_data = (MaterialData *)storage->material_get_data(ci->material, RasterizerStorageRD::SHADER_TYPE_2D);
+ if (material.is_valid()) {
+ material_data = (MaterialData *)storage->material_get_data(material, RasterizerStorageRD::SHADER_TYPE_2D);
}
if (material_data) {
@@ -1174,55 +1184,89 @@ void RasterizerCanvasRD::_render_items(RID p_to_render_target, int p_item_count,
_render_item(draw_list, ci, fb_format, canvas_transform_inverse, current_clip, p_lights, pipeline_variants);
- prev_material = ci->material;
+ prev_material = material;
}
RD::get_singleton()->draw_list_end();
}
-void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, const Transform2D &p_canvas_transform, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat) {
+void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_light_list, const Transform2D &p_canvas_transform, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel) {
int item_count = 0;
//setup canvas state uniforms if needed
Transform2D canvas_transform_inverse = p_canvas_transform.affine_inverse();
+ //setup directional lights if exist
+
+ uint32_t light_count = 0;
+ uint32_t directional_light_count = 0;
{
- //update canvas state uniform buffer
- State::Buffer state_buffer;
+ Light *l = p_directional_light_list;
+ uint32_t index = 0;
- Size2i ssize = storage->render_target_get_size(p_to_render_target);
+ while (l) {
+ if (index == state.max_lights_per_render) {
+ l->render_index_cache = -1;
+ l = l->next_ptr;
+ continue;
+ }
- Transform screen_transform;
- screen_transform.translate(-(ssize.width / 2.0f), -(ssize.height / 2.0f), 0.0f);
- screen_transform.scale(Vector3(2.0f / ssize.width, 2.0f / ssize.height, 1.0f));
- _update_transform_to_mat4(screen_transform, state_buffer.screen_transform);
- _update_transform_2d_to_mat4(p_canvas_transform, state_buffer.canvas_transform);
+ CanvasLight *clight = canvas_light_owner.getornull(l->light_internal);
+ if (!clight) { //unused or invalid texture
+ l->render_index_cache = -1;
+ l = l->next_ptr;
+ ERR_CONTINUE(!clight);
+ }
- Transform2D normal_transform = p_canvas_transform;
- normal_transform.elements[0].normalize();
- normal_transform.elements[1].normalize();
- normal_transform.elements[2] = Vector2();
- _update_transform_2d_to_mat4(normal_transform, state_buffer.canvas_normal_transform);
+ Vector2 canvas_light_dir = l->xform_cache.elements[1].normalized();
- state_buffer.canvas_modulate[0] = p_modulate.r;
- state_buffer.canvas_modulate[1] = p_modulate.g;
- state_buffer.canvas_modulate[2] = p_modulate.b;
- state_buffer.canvas_modulate[3] = p_modulate.a;
+ state.light_uniforms[index].position[0] = -canvas_light_dir.x;
+ state.light_uniforms[index].position[1] = -canvas_light_dir.y;
- Size2 render_target_size = storage->render_target_get_size(p_to_render_target);
- state_buffer.screen_pixel_size[0] = 1.0 / render_target_size.x;
- state_buffer.screen_pixel_size[1] = 1.0 / render_target_size.y;
+ _update_transform_2d_to_mat2x4(clight->shadow.directional_xform, state.light_uniforms[index].shadow_matrix);
- state_buffer.time = state.time;
- RD::get_singleton()->buffer_update(state.canvas_state_buffer, 0, sizeof(State::Buffer), &state_buffer, true);
+ state.light_uniforms[index].height = l->height; //0..1 here
+
+ for (int i = 0; i < 4; i++) {
+ state.light_uniforms[index].shadow_color[i] = uint8_t(CLAMP(int32_t(l->shadow_color[i] * 255.0), 0, 255));
+ state.light_uniforms[index].color[i] = l->color[i];
+ }
+
+ state.light_uniforms[index].color[3] = l->energy; //use alpha for energy, so base color can go separate
+
+ if (state.shadow_fb.is_valid()) {
+ state.light_uniforms[index].shadow_pixel_size = (1.0 / state.shadow_texture_size) * (1.0 + l->shadow_smooth);
+ state.light_uniforms[index].shadow_z_far_inv = 1.0 / clight->shadow.z_far;
+ state.light_uniforms[index].shadow_y_ofs = clight->shadow.y_offset;
+ } else {
+ state.light_uniforms[index].shadow_pixel_size = 1.0;
+ state.light_uniforms[index].shadow_z_far_inv = 1.0;
+ state.light_uniforms[index].shadow_y_ofs = 0;
+ }
+
+ state.light_uniforms[index].flags = l->blend_mode << LIGHT_FLAGS_BLEND_SHIFT;
+ state.light_uniforms[index].flags |= l->shadow_filter << LIGHT_FLAGS_FILTER_SHIFT;
+ if (clight->shadow.enabled) {
+ state.light_uniforms[index].flags |= LIGHT_FLAGS_HAS_SHADOW;
+ }
+
+ l->render_index_cache = index;
+
+ index++;
+ l = l->next_ptr;
+ }
+
+ light_count = index;
+ directional_light_count = light_count;
+ using_directional_lights = directional_light_count > 0;
}
//setup lights if exist
{
Light *l = p_light_list;
- uint32_t index = 0;
+ uint32_t index = light_count;
while (l) {
if (index == state.max_lights_per_render) {
@@ -1264,7 +1308,7 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite
state.light_uniforms[index].shadow_y_ofs = 0;
}
- state.light_uniforms[index].flags |= l->mode << LIGHT_FLAGS_BLEND_SHIFT;
+ state.light_uniforms[index].flags = l->blend_mode << LIGHT_FLAGS_BLEND_SHIFT;
state.light_uniforms[index].flags |= l->shadow_filter << LIGHT_FLAGS_FILTER_SHIFT;
if (clight->shadow.enabled) {
state.light_uniforms[index].flags |= LIGHT_FLAGS_HAS_SHADOW;
@@ -1290,9 +1334,46 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite
l = l->next_ptr;
}
- if (index > 0) {
- RD::get_singleton()->buffer_update(state.lights_uniform_buffer, 0, sizeof(LightUniform) * index, &state.light_uniforms[0], true);
- }
+ light_count = index;
+ }
+
+ if (light_count > 0) {
+ RD::get_singleton()->buffer_update(state.lights_uniform_buffer, 0, sizeof(LightUniform) * light_count, &state.light_uniforms[0], true);
+ }
+
+ {
+ //update canvas state uniform buffer
+ State::Buffer state_buffer;
+
+ Size2i ssize = storage->render_target_get_size(p_to_render_target);
+
+ Transform screen_transform;
+ screen_transform.translate(-(ssize.width / 2.0f), -(ssize.height / 2.0f), 0.0f);
+ screen_transform.scale(Vector3(2.0f / ssize.width, 2.0f / ssize.height, 1.0f));
+ _update_transform_to_mat4(screen_transform, state_buffer.screen_transform);
+ _update_transform_2d_to_mat4(p_canvas_transform, state_buffer.canvas_transform);
+
+ Transform2D normal_transform = p_canvas_transform;
+ normal_transform.elements[0].normalize();
+ normal_transform.elements[1].normalize();
+ normal_transform.elements[2] = Vector2();
+ _update_transform_2d_to_mat4(normal_transform, state_buffer.canvas_normal_transform);
+
+ state_buffer.canvas_modulate[0] = p_modulate.r;
+ state_buffer.canvas_modulate[1] = p_modulate.g;
+ state_buffer.canvas_modulate[2] = p_modulate.b;
+ state_buffer.canvas_modulate[3] = p_modulate.a;
+
+ Size2 render_target_size = storage->render_target_get_size(p_to_render_target);
+ state_buffer.screen_pixel_size[0] = 1.0 / render_target_size.x;
+ state_buffer.screen_pixel_size[1] = 1.0 / render_target_size.y;
+
+ state_buffer.time = state.time;
+ state_buffer.use_pixel_snap = p_snap_2d_vertices_to_pixel;
+
+ state_buffer.directional_light_count = directional_light_count;
+
+ RD::get_singleton()->buffer_update(state.canvas_state_buffer, 0, sizeof(State::Buffer), &state_buffer, true);
}
{ //default filter/repeat
@@ -1306,8 +1387,10 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite
Rect2 back_buffer_rect;
bool backbuffer_copy = false;
+ Item *canvas_group_owner = nullptr;
+
while (ci) {
- if (ci->copy_back_buffer) {
+ if (ci->copy_back_buffer && canvas_group_owner == nullptr) {
backbuffer_copy = true;
if (ci->copy_back_buffer->full) {
@@ -1320,7 +1403,7 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite
if (ci->material.is_valid()) {
MaterialData *md = (MaterialData *)storage->material_get_data(ci->material, RasterizerStorageRD::SHADER_TYPE_2D);
if (md && md->shader_data->valid) {
- if (md->shader_data->uses_screen_texture) {
+ if (md->shader_data->uses_screen_texture && canvas_group_owner == nullptr) {
if (!material_screen_texture_found) {
backbuffer_copy = true;
back_buffer_rect = Rect2();
@@ -1338,12 +1421,44 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite
}
}
+ if (ci->canvas_group_owner != nullptr) {
+ if (canvas_group_owner == nullptr) {
+ //Canvas group begins here, render until before this item
+ _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list);
+ item_count = 0;
+
+ Rect2i group_rect = ci->canvas_group_owner->global_rect_cache;
+
+ if (ci->canvas_group_owner->canvas_group->mode == RS::CANVAS_GROUP_MODE_OPAQUE) {
+ storage->render_target_copy_to_back_buffer(p_to_render_target, group_rect, false);
+ } else {
+ storage->render_target_clear_back_buffer(p_to_render_target, group_rect, Color(0, 0, 0, 0));
+ }
+
+ backbuffer_copy = false;
+ canvas_group_owner = ci->canvas_group_owner; //continue until owner found
+ }
+
+ ci->canvas_group_owner = nullptr; //must be cleared
+ }
+
+ if (ci == canvas_group_owner) {
+ _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, true);
+ item_count = 0;
+
+ if (ci->canvas_group->blur_mipmaps) {
+ storage->render_target_gen_back_buffer_mipmaps(p_to_render_target, ci->global_rect_cache);
+ }
+
+ canvas_group_owner = nullptr;
+ }
+
if (backbuffer_copy) {
//render anything pending, including clearing if no items
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list);
item_count = 0;
- storage->render_target_copy_to_back_buffer(p_to_render_target, back_buffer_rect);
+ storage->render_target_copy_to_back_buffer(p_to_render_target, back_buffer_rect, true);
backbuffer_copy = false;
material_screen_texture_found = true; //after a backbuffer copy, screen texture makes no further copies
@@ -1389,10 +1504,7 @@ void RasterizerCanvasRD::light_set_use_shadow(RID p_rid, bool p_enable) {
cl->shadow.enabled = p_enable;
}
-void RasterizerCanvasRD::light_update_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders) {
- CanvasLight *cl = canvas_light_owner.getornull(p_rid);
- ERR_FAIL_COND(!cl->shadow.enabled);
-
+void RasterizerCanvasRD::_update_shadow_atlas() {
if (state.shadow_fb == RID()) {
//ah, we lack the shadow texture..
RD::get_singleton()->free(state.shadow_texture); //erase placeholder
@@ -1424,6 +1536,12 @@ void RasterizerCanvasRD::light_update_shadow(RID p_rid, int p_shadow_index, cons
state.shadow_fb = RD::get_singleton()->framebuffer_create(fb_textures);
}
+}
+void RasterizerCanvasRD::light_update_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders) {
+ CanvasLight *cl = canvas_light_owner.getornull(p_rid);
+ ERR_FAIL_COND(!cl->shadow.enabled);
+
+ _update_shadow_atlas();
cl->shadow.z_far = p_far;
cl->shadow.y_offset = float(p_shadow_index * 2 + 1) / float(state.max_lights_per_render * 2);
@@ -1497,6 +1615,86 @@ void RasterizerCanvasRD::light_update_shadow(RID p_rid, int p_shadow_index, cons
}
}
+void RasterizerCanvasRD::light_update_directional_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_cull_distance, const Rect2 &p_clip_rect, LightOccluderInstance *p_occluders) {
+ CanvasLight *cl = canvas_light_owner.getornull(p_rid);
+ ERR_FAIL_COND(!cl->shadow.enabled);
+
+ _update_shadow_atlas();
+
+ Vector2 light_dir = p_light_xform.elements[1].normalized();
+
+ Vector2 center = p_clip_rect.position + p_clip_rect.size * 0.5;
+
+ float to_edge_distance = ABS(light_dir.dot(p_clip_rect.get_support(light_dir)) - light_dir.dot(center));
+
+ Vector2 from_pos = center - light_dir * (to_edge_distance + p_cull_distance);
+ float distance = to_edge_distance * 2.0 + p_cull_distance;
+ float half_size = p_clip_rect.size.length() * 0.5; //shadow length, must keep this no matter the angle
+
+ cl->shadow.z_far = distance;
+ cl->shadow.y_offset = float(p_shadow_index * 2 + 1) / float(state.max_lights_per_render * 2);
+
+ Transform2D to_light_xform;
+
+ to_light_xform[2] = from_pos;
+ to_light_xform[1] = light_dir;
+ to_light_xform[0] = -light_dir.tangent();
+
+ to_light_xform.invert();
+
+ Vector<Color> cc;
+ cc.push_back(Color(1, 1, 1, 1));
+
+ Rect2i rect(0, p_shadow_index * 2, state.shadow_texture_size, 2);
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(state.shadow_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, cc, 1.0, 0, rect);
+
+ CameraMatrix projection;
+ projection.set_orthogonal(-half_size, half_size, -0.5, 0.5, 0.0, distance);
+ projection = projection * CameraMatrix(Transform().looking_at(Vector3(0, 1, 0), Vector3(0, 0, -1)).affine_inverse());
+
+ ShadowRenderPushConstant push_constant;
+ for (int y = 0; y < 4; y++) {
+ for (int x = 0; x < 4; x++) {
+ push_constant.projection[y * 4 + x] = projection.matrix[y][x];
+ }
+ }
+
+ push_constant.direction[0] = 0.0;
+ push_constant.direction[1] = 1.0;
+ push_constant.z_far = distance;
+ push_constant.pad = 0;
+
+ LightOccluderInstance *instance = p_occluders;
+
+ while (instance) {
+ OccluderPolygon *co = occluder_polygon_owner.getornull(instance->occluder);
+
+ if (!co || co->index_array.is_null() || !(p_light_mask & instance->light_mask)) {
+ instance = instance->next;
+ continue;
+ }
+
+ _update_transform_2d_to_mat2x4(to_light_xform * instance->xform_cache, push_constant.modelview);
+
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, shadow_render.render_pipelines[co->cull_mode]);
+ RD::get_singleton()->draw_list_bind_vertex_array(draw_list, co->vertex_array);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, co->index_array);
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(ShadowRenderPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+
+ instance = instance->next;
+ }
+
+ RD::get_singleton()->draw_list_end();
+
+ Transform2D to_shadow;
+ to_shadow.elements[0].x = 1.0 / -(half_size * 2.0);
+ to_shadow.elements[2].x = 0.5;
+
+ cl->shadow.directional_xform = to_shadow * to_light_xform;
+}
+
RID RasterizerCanvasRD::occluder_polygon_create() {
OccluderPolygon occluder;
occluder.point_count = 0;
@@ -1672,10 +1870,11 @@ void RasterizerCanvasRD::ShaderData::set_code(const String &p_code) {
} break;
case BLEND_MODE_MIX: {
attachment.enable_blend = true;
- attachment.alpha_blend_op = RD::BLEND_OP_ADD;
attachment.color_blend_op = RD::BLEND_OP_ADD;
attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
+
+ attachment.alpha_blend_op = RD::BLEND_OP_ADD;
attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
@@ -2013,6 +2212,20 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) {
shader.default_version = shader.canvas_shader.version_create();
shader.default_version_rd_shader = shader.canvas_shader.version_get_shader(shader.default_version, SHADER_VARIANT_QUAD);
+ RD::PipelineColorBlendState blend_state;
+ RD::PipelineColorBlendState::Attachment blend_attachment;
+
+ blend_attachment.enable_blend = true;
+ blend_attachment.color_blend_op = RD::BLEND_OP_ADD;
+ blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
+ blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
+
+ blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD;
+ blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
+ blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
+
+ blend_state.attachments.push_back(blend_attachment);
+
for (int i = 0; i < PIPELINE_LIGHT_MODE_MAX; i++) {
for (int j = 0; j < PIPELINE_VARIANT_MAX; j++) {
RD::RenderPrimitive primitive[PIPELINE_VARIANT_MAX] = {
@@ -2054,7 +2267,7 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) {
};
RID shader_variant = shader.canvas_shader.version_get_shader(shader.default_version, shader_variants[i][j]);
- shader.pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_blend(), 0);
+ shader.pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0);
}
}
}
@@ -2260,6 +2473,13 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) {
state.time = 0;
+ {
+ default_canvas_group_shader = storage->shader_create();
+ storage->shader_set_code(default_canvas_group_shader, "shader_type canvas_item; \nvoid fragment() {\n\tvec4 c = textureLod(SCREEN_TEXTURE,SCREEN_UV,0.0); if (c.a > 0.0001) c.rgb/=c.a; COLOR *= c; \n}\n");
+ default_canvas_group_material = storage->material_create();
+ storage->material_set_shader(default_canvas_group_material, default_canvas_group_shader);
+ }
+
static_assert(sizeof(PushConstant) == 128);
}
@@ -2307,6 +2527,9 @@ void RasterizerCanvasRD::set_shadow_texture_size(int p_size) {
RasterizerCanvasRD::~RasterizerCanvasRD() {
//canvas state
+ storage->free(default_canvas_group_material);
+ storage->free(default_canvas_group_shader);
+
{
if (state.canvas_state_buffer.is_valid()) {
RD::get_singleton()->free(state.canvas_state_buffer);
@@ -2344,6 +2567,4 @@ RasterizerCanvasRD::~RasterizerCanvasRD() {
storage->free(default_canvas_texture);
//pipelines don't need freeing, they are all gone after shaders are gone
-
- RD::get_singleton()->free(state.default_transforms_uniform_set);
}
diff --git a/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h b/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h
index 5791efa4e5..b516f63cbf 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h
+++ b/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h
@@ -75,11 +75,9 @@ class RasterizerCanvasRD : public RasterizerCanvas {
FLAGS_CLIP_RECT_UV = (1 << 9),
FLAGS_TRANSPOSE_RECT = (1 << 10),
- FLAGS_USING_LIGHT_MASK = (1 << 11),
FLAGS_NINEPACH_DRAW_CENTER = (1 << 12),
FLAGS_USING_PARTICLES = (1 << 13),
- FLAGS_USE_PIXEL_SNAP = (1 << 14),
FLAGS_USE_SKELETON = (1 << 15),
FLAGS_NINEPATCH_H_MODE_SHIFT = 16,
@@ -270,6 +268,7 @@ class RasterizerCanvasRD : public RasterizerCanvas {
bool enabled = false;
float z_far;
float y_offset;
+ Transform2D directional_xform;
} shadow;
};
@@ -332,12 +331,13 @@ class RasterizerCanvasRD : public RasterizerCanvas {
float screen_transform[16];
float canvas_normal_transform[16];
float canvas_modulate[4];
+
float screen_pixel_size[2];
float time;
- float pad;
+ uint32_t use_pixel_snap;
- //uint32_t light_count;
- //uint32_t pad[3];
+ uint32_t directional_light_count;
+ uint32_t pad[3];
};
LightUniform *light_uniforms;
@@ -356,6 +356,7 @@ class RasterizerCanvasRD : public RasterizerCanvas {
uint32_t max_lights_per_item;
double time;
+
} state;
struct PushConstant {
@@ -389,8 +390,12 @@ class RasterizerCanvasRD : public RasterizerCanvas {
Item *items[MAX_RENDER_ITEMS];
+ bool using_directional_lights = false;
RID default_canvas_texture;
+ RID default_canvas_group_shader;
+ RID default_canvas_group_material;
+
RS::CanvasItemTextureFilter default_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR;
RS::CanvasItemTextureRepeat default_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED;
@@ -398,7 +403,7 @@ class RasterizerCanvasRD : public RasterizerCanvas {
inline void _bind_canvas_texture(RD::DrawListID p_draw_list, RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID &r_last_texture, PushConstant &push_constant, Size2 &r_texpixel_size); //recursive, so regular inline used instead.
void _render_item(RenderingDevice::DrawListID p_draw_list, const Item *p_item, RenderingDevice::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, Light *p_lights, PipelineVariants *p_pipeline_variants);
- void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights);
+ void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool p_to_backbuffer = false);
_FORCE_INLINE_ void _update_transform_2d_to_mat2x4(const Transform2D &p_transform, float *p_mat2x4);
_FORCE_INLINE_ void _update_transform_2d_to_mat2x3(const Transform2D &p_transform, float *p_mat2x3);
@@ -406,6 +411,8 @@ class RasterizerCanvasRD : public RasterizerCanvas {
_FORCE_INLINE_ void _update_transform_2d_to_mat4(const Transform2D &p_transform, float *p_mat4);
_FORCE_INLINE_ void _update_transform_to_mat4(const Transform &p_transform, float *p_mat4);
+ void _update_shadow_atlas();
+
public:
PolygonID request_polygon(const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>());
void free_polygon(PolygonID p_polygon);
@@ -414,12 +421,13 @@ public:
void light_set_texture(RID p_rid, RID p_texture);
void light_set_use_shadow(RID p_rid, bool p_enable);
void light_update_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders);
+ void light_update_directional_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_cull_distance, const Rect2 &p_clip_rect, LightOccluderInstance *p_occluders);
RID occluder_polygon_create();
void occluder_polygon_set_shape_as_lines(RID p_occluder, const Vector<Vector2> &p_lines);
void occluder_polygon_set_cull_mode(RID p_occluder, RS::CanvasOccluderPolygonCullMode p_mode);
- void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, const Transform2D &p_canvas_transform, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat);
+ void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_light_list, const Transform2D &p_canvas_transform, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel);
void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) {}
diff --git a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp
index 409cfdfecf..97c1e7ba70 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp
+++ b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp
@@ -30,8 +30,8 @@
#include "rasterizer_effects_rd.h"
+#include "core/config/project_settings.h"
#include "core/os/os.h"
-#include "core/project_settings.h"
#include "thirdparty/misc/cubemap_coeffs.h"
@@ -246,7 +246,7 @@ void RasterizerEffectsRD::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_fr
RD::get_singleton()->draw_list_end();
}
-void RasterizerEffectsRD::copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_all_source, bool p_8_bit_dst) {
+void RasterizerEffectsRD::copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_all_source, bool p_8_bit_dst, bool p_alpha_to_one) {
zeromem(&copy.push_constant, sizeof(CopyPushConstant));
if (p_flip_y) {
copy.push_constant.flags |= COPY_FLAG_FLIP_Y;
@@ -260,6 +260,10 @@ void RasterizerEffectsRD::copy_to_rect(RID p_source_rd_texture, RID p_dest_textu
copy.push_constant.flags |= COPY_FLAG_ALL_SOURCE;
}
+ if (p_alpha_to_one) {
+ copy.push_constant.flags |= COPY_FLAG_ALPHA_TO_ONE;
+ }
+
copy.push_constant.section[0] = 0;
copy.push_constant.section[1] = 0;
copy.push_constant.section[2] = p_rect.size.width;
@@ -354,6 +358,31 @@ void RasterizerEffectsRD::copy_depth_to_rect(RID p_source_rd_texture, RID p_dest
RD::get_singleton()->compute_list_end();
}
+void RasterizerEffectsRD::set_color(RID p_dest_texture, const Color &p_color, const Rect2i &p_region, bool p_8bit_dst) {
+ zeromem(&copy.push_constant, sizeof(CopyPushConstant));
+
+ copy.push_constant.section[0] = 0;
+ copy.push_constant.section[1] = 0;
+ copy.push_constant.section[2] = p_region.size.width;
+ copy.push_constant.section[3] = p_region.size.height;
+ copy.push_constant.target[0] = p_region.position.x;
+ copy.push_constant.target[1] = p_region.position.y;
+ copy.push_constant.set_color[0] = p_color.r;
+ copy.push_constant.set_color[1] = p_color.g;
+ copy.push_constant.set_color[2] = p_color.b;
+ copy.push_constant.set_color[3] = p_color.a;
+
+ int32_t x_groups = (p_region.size.width - 1) / 8 + 1;
+ int32_t y_groups = (p_region.size.height - 1) / 8 + 1;
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[p_8bit_dst ? COPY_MODE_SET_COLOR_8BIT : COPY_MODE_SET_COLOR]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_texture), 3);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
+ RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ RD::get_singleton()->compute_list_end();
+}
+
void RasterizerEffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_texture, RID p_back_texture, const Rect2i &p_region, bool p_8bit_dst) {
zeromem(&copy.push_constant, sizeof(CopyPushConstant));
@@ -369,7 +398,7 @@ void RasterizerEffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_texture,
RD::DrawListID compute_list = RD::get_singleton()->compute_list_begin();
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[p_8bit_dst ? COPY_MODE_GAUSSIAN_COPY_8BIT : COPY_MODE_GAUSSIAN_COPY]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_back_texture), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_back_texture), 3);
copy.push_constant.flags = base_flags | COPY_FLAG_HORIZONTAL;
RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
@@ -380,7 +409,7 @@ void RasterizerEffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_texture,
//VERTICAL
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_back_texture), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_texture), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_texture), 3);
copy.push_constant.flags = base_flags;
RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
@@ -1346,6 +1375,8 @@ RasterizerEffectsRD::RasterizerEffectsRD() {
copy_modes.push_back("\n#define MODE_SIMPLE_COPY\n");
copy_modes.push_back("\n#define MODE_SIMPLE_COPY\n#define DST_IMAGE_8BIT\n");
copy_modes.push_back("\n#define MODE_SIMPLE_COPY_DEPTH\n");
+ copy_modes.push_back("\n#define MODE_SET_COLOR\n");
+ copy_modes.push_back("\n#define MODE_SET_COLOR\n#define DST_IMAGE_8BIT\n");
copy_modes.push_back("\n#define MODE_MIPMAP\n");
copy_modes.push_back("\n#define MODE_LINEARIZE_DEPTH_COPY\n");
copy_modes.push_back("\n#define MODE_CUBEMAP_TO_PANORAMA\n");
diff --git a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h
index 679263fbf6..a0bdd59fd2 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h
+++ b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h
@@ -66,6 +66,8 @@ class RasterizerEffectsRD {
COPY_MODE_SIMPLY_COPY,
COPY_MODE_SIMPLY_COPY_8BIT,
COPY_MODE_SIMPLY_COPY_DEPTH,
+ COPY_MODE_SET_COLOR,
+ COPY_MODE_SET_COLOR_8BIT,
COPY_MODE_MIPMAP,
COPY_MODE_LINEARIZE_DEPTH,
COPY_MODE_CUBE_TO_PANORAMA,
@@ -83,7 +85,8 @@ class RasterizerEffectsRD {
COPY_FLAG_FLIP_Y = (1 << 5),
COPY_FLAG_FORCE_LUMINANCE = (1 << 6),
COPY_FLAG_ALL_SOURCE = (1 << 7),
- COPY_FLAG_HIGH_QUALITY_GLOW = (1 << 8)
+ COPY_FLAG_HIGH_QUALITY_GLOW = (1 << 8),
+ COPY_FLAG_ALPHA_TO_ONE = (1 << 9),
};
struct CopyPushConstant {
@@ -105,6 +108,8 @@ class RasterizerEffectsRD {
float camera_z_far;
float camera_z_near;
uint32_t pad2[2];
+ //SET color
+ float set_color[4];
};
struct Copy {
@@ -603,12 +608,13 @@ class RasterizerEffectsRD {
public:
void copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_alpha_to_zero = false, bool p_srgb = false, RID p_secondary = RID());
- void copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_all_source = false, bool p_8_bit_dst = false);
+ void copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_all_source = false, bool p_8_bit_dst = false, bool p_alpha_to_one = false);
void copy_cubemap_to_panorama(RID p_source_cube, RID p_dest_panorama, const Size2i &p_panorama_size, float p_lod, bool p_is_array);
void copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false);
void copy_depth_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, float p_z_near, float p_z_far);
void copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_uv_rect, RD::DrawListID p_draw_list, bool p_flip_y = false, bool p_panorama = false);
void gaussian_blur(RID p_source_rd_texture, RID p_texture, RID p_back_texture, const Rect2i &p_region, bool p_8bit_dst = false);
+ void set_color(RID p_dest_texture, const Color &p_color, const Rect2i &p_region, bool p_8bit_dst = false);
void gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_treshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
void cubemap_roughness(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size);
diff --git a/servers/rendering/rasterizer_rd/rasterizer_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_rd.cpp
index 509bd3ee73..5f8cf0ee8c 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_rd.cpp
+++ b/servers/rendering/rasterizer_rd/rasterizer_rd.cpp
@@ -30,7 +30,7 @@
#include "rasterizer_rd.h"
-#include "core/project_settings.h"
+#include "core/config/project_settings.h"
void RasterizerRD::prepare_for_blitting_render_targets() {
RD::get_singleton()->prepare_screen_for_drawing();
diff --git a/servers/rendering/rasterizer_rd/rasterizer_rd.h b/servers/rendering/rasterizer_rd/rasterizer_rd.h
index cdcc6bfd73..59fb8d2049 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_rd.h
+++ b/servers/rendering/rasterizer_rd/rasterizer_rd.h
@@ -32,7 +32,7 @@
#define RASTERIZER_RD_H
#include "core/os/os.h"
-#include "core/thread_work_pool.h"
+#include "core/templates/thread_work_pool.h"
#include "servers/rendering/rasterizer.h"
#include "servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h"
#include "servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h"
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 35b0591289..a275e46473 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp
+++ b/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp
@@ -29,7 +29,7 @@
/*************************************************************************/
#include "rasterizer_scene_high_end_rd.h"
-#include "core/project_settings.h"
+#include "core/config/project_settings.h"
#include "servers/rendering/rendering_device.h"
#include "servers/rendering/rendering_server_raster.h"
@@ -51,6 +51,7 @@ void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) {
int blend_mode = BLEND_MODE_MIX;
int depth_testi = DEPTH_TEST_ENABLED;
+ int alpha_antialiasing_mode = ALPHA_ANTIALIASING_OFF;
int cull = CULL_BACK;
uses_point_size = false;
@@ -82,6 +83,9 @@ void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) {
actions.render_mode_values["blend_sub"] = Pair<int *, int>(&blend_mode, BLEND_MODE_SUB);
actions.render_mode_values["blend_mul"] = Pair<int *, int>(&blend_mode, BLEND_MODE_MUL);
+ actions.render_mode_values["alpha_to_coverage"] = Pair<int *, int>(&alpha_antialiasing_mode, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE);
+ actions.render_mode_values["alpha_to_coverage_and_one"] = Pair<int *, int>(&alpha_antialiasing_mode, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE);
+
actions.render_mode_values["depth_draw_never"] = Pair<int *, int>(&depth_drawi, DEPTH_DRAW_DISABLED);
actions.render_mode_values["depth_draw_opaque"] = Pair<int *, int>(&depth_drawi, DEPTH_DRAW_OPAQUE);
actions.render_mode_values["depth_draw_always"] = Pair<int *, int>(&depth_drawi, DEPTH_DRAW_ALWAYS);
@@ -154,6 +158,11 @@ void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) {
//blend modes
+ // if any form of Alpha Antialiasing is enabled, set the blend mode to alpha to coverage
+ if (alpha_antialiasing_mode != ALPHA_ANTIALIASING_OFF) {
+ blend_mode = BLEND_MODE_ALPHA_TO_COVERAGE;
+ }
+
RD::PipelineColorBlendState::Attachment blend_attachment;
switch (blend_mode) {
@@ -199,6 +208,15 @@ void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) {
blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ZERO;
uses_blend_alpha = true; //force alpha used because of blend
} break;
+ case BLEND_MODE_ALPHA_TO_COVERAGE: {
+ blend_attachment.enable_blend = true;
+ blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD;
+ blend_attachment.color_blend_op = RD::BLEND_OP_ADD;
+ blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
+ blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
+ blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
+ blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ZERO;
+ }
}
RD::PipelineColorBlendState blend_state_blend;
@@ -245,8 +263,17 @@ void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) {
RD::PipelineColorBlendState blend_state;
RD::PipelineDepthStencilState depth_stencil = depth_stencil_state;
+ RD::PipelineMultisampleState multisample_state;
if (uses_alpha || uses_blend_alpha) {
+ // only allow these flags to go through if we have some form of msaa
+ if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE) {
+ multisample_state.enable_alpha_to_coverage = true;
+ } else if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE) {
+ multisample_state.enable_alpha_to_coverage = true;
+ multisample_state.enable_alpha_to_one = true;
+ }
+
if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS) {
blend_state = blend_state_blend;
if (depth_draw == DEPTH_DRAW_OPAQUE) {
@@ -286,7 +313,7 @@ void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) {
}
RID shader_variant = scene_singleton->shader.scene_shader.version_get_shader(version, k);
- pipelines[i][j][k].setup(shader_variant, primitive_rd, raster_state, RD::PipelineMultisampleState(), depth_stencil, blend_state, 0);
+ pipelines[i][j][k].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0);
}
}
}
@@ -2725,6 +2752,11 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag
actions.renames["POINT_SIZE"] = "gl_PointSize";
actions.renames["INSTANCE_ID"] = "gl_InstanceIndex";
+ actions.renames["ALPHA_SCISSOR_THRESHOLD"] = "alpha_scissor_threshold";
+ actions.renames["ALPHA_HASH_SCALE"] = "alpha_hash_scale";
+ actions.renames["ALPHA_ANTIALIASING_EDGE"] = "alpha_antialiasing_edge";
+ actions.renames["ALPHA_TEXTURE_COORDINATE"] = "alpha_texture_coordinate";
+
//builtins
actions.renames["TIME"] = "scene_data.time";
@@ -2793,6 +2825,11 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag
actions.usage_defines["INSTANCE_CUSTOM"] = "#define ENABLE_INSTANCE_CUSTOM\n";
actions.usage_defines["POSITION"] = "#define OVERRIDE_POSITION\n";
+ actions.usage_defines["ALPHA_SCISSOR_THRESHOLD"] = "#define ALPHA_SCISSOR_USED\n";
+ actions.usage_defines["ALPHA_HASH_SCALE"] = "#define ALPHA_HASH_USED\n";
+ actions.usage_defines["ALPHA_ANTIALIASING_EDGE"] = "#define ALPHA_ANTIALIASING_EDGE_USED\n";
+ actions.usage_defines["ALPHA_TEXTURE_COORDINATE"] = "@ALPHA_ANTIALIASING_EDGE";
+
actions.usage_defines["SSS_STRENGTH"] = "#define ENABLE_SSS\n";
actions.usage_defines["SSS_TRANSMITTANCE_DEPTH"] = "#define ENABLE_TRANSMITTANCE\n";
actions.usage_defines["BACKLIGHT"] = "#define LIGHT_BACKLIGHT_USED\n";
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 566022ae5b..db083a75cc 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h
+++ b/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h
@@ -83,6 +83,7 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
BLEND_MODE_ADD,
BLEND_MODE_SUB,
BLEND_MODE_MUL,
+ BLEND_MODE_ALPHA_TO_COVERAGE
};
enum DepthDraw {
@@ -110,6 +111,12 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
};
+ enum AlphaAntiAliasing {
+ ALPHA_ANTIALIASING_OFF,
+ ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE,
+ ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE
+ };
+
bool valid;
RID version;
uint32_t vertex_input_mask;
@@ -132,6 +139,7 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD {
bool uses_point_size;
bool uses_alpha;
bool uses_blend_alpha;
+ bool uses_alpha_clip;
bool uses_depth_pre_pass;
bool uses_discard;
bool uses_roughness;
diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp
index 0cae141138..e1be9b0ef4 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp
+++ b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp
@@ -30,8 +30,8 @@
#include "rasterizer_scene_rd.h"
+#include "core/config/project_settings.h"
#include "core/os/os.h"
-#include "core/project_settings.h"
#include "rasterizer_rd.h"
#include "servers/rendering/rendering_server_raster.h"
diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h
index 2ad712a9d3..3d5310bb7e 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h
+++ b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h
@@ -31,8 +31,8 @@
#ifndef RASTERIZER_SCENE_RD_H
#define RASTERIZER_SCENE_RD_H
-#include "core/local_vector.h"
-#include "core/rid_owner.h"
+#include "core/templates/local_vector.h"
+#include "core/templates/rid_owner.h"
#include "servers/rendering/rasterizer.h"
#include "servers/rendering/rasterizer_rd/light_cluster_builder.h"
#include "servers/rendering/rasterizer_rd/rasterizer_storage_rd.h"
diff --git a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp
index b47d724147..8bd4362637 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp
+++ b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp
@@ -30,9 +30,9 @@
#include "rasterizer_storage_rd.h"
-#include "core/engine.h"
+#include "core/config/engine.h"
+#include "core/config/project_settings.h"
#include "core/io/resource_loader.h"
-#include "core/project_settings.h"
#include "rasterizer_rd.h"
#include "servers/rendering/shader_language.h"
@@ -1265,7 +1265,7 @@ void RasterizerStorageRD::canvas_texture_set_texture_repeat(RID p_canvas_texture
ct->clear_sets();
}
-bool RasterizerStorageRD::canvas_texture_get_unifom_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular) {
+bool RasterizerStorageRD::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular) {
CanvasTexture *ct = nullptr;
Texture *t = texture_owner.getornull(p_texture);
@@ -6131,12 +6131,18 @@ void RasterizerStorageRD::_create_render_target_backbuffer(RenderTarget *rt) {
tf.width = rt->size.width;
tf.height = rt->size.height;
tf.type = RD::TEXTURE_TYPE_2D;
- tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
+ tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
tf.mipmaps = mipmaps_required;
rt->backbuffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
rt->backbuffer_mipmap0 = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rt->backbuffer, 0, 0);
+ {
+ Vector<RID> fb_tex;
+ fb_tex.push_back(rt->backbuffer_mipmap0);
+ rt->backbuffer_fb = RD::get_singleton()->framebuffer_create(fb_tex);
+ }
+
if (rt->framebuffer_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rt->framebuffer_uniform_set)) {
//the new one will require the backbuffer.
RD::get_singleton()->free(rt->framebuffer_uniform_set);
@@ -6245,6 +6251,17 @@ RID RasterizerStorageRD::render_target_get_rd_backbuffer(RID p_render_target) {
return rt->backbuffer;
}
+RID RasterizerStorageRD::render_target_get_rd_backbuffer_framebuffer(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ ERR_FAIL_COND_V(!rt, RID());
+
+ if (!rt->backbuffer.is_valid()) {
+ _create_render_target_backbuffer(rt);
+ }
+
+ return rt->backbuffer_fb;
+}
+
void RasterizerStorageRD::render_target_request_clear(RID p_render_target, const Color &p_clear_color) {
RenderTarget *rt = render_target_owner.getornull(p_render_target);
ERR_FAIL_COND(!rt);
@@ -6283,21 +6300,30 @@ void RasterizerStorageRD::render_target_do_clear_request(RID p_render_target) {
rt->clear_requested = false;
}
-void RasterizerStorageRD::render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region) {
+void RasterizerStorageRD::render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region, bool p_gen_mipmaps) {
RenderTarget *rt = render_target_owner.getornull(p_render_target);
ERR_FAIL_COND(!rt);
if (!rt->backbuffer.is_valid()) {
_create_render_target_backbuffer(rt);
}
- Rect2i region = p_region;
- if (region == Rect2i()) {
+ Rect2i region;
+ if (p_region == Rect2i()) {
region.size = rt->size;
+ } else {
+ region = Rect2i(Size2i(), rt->size).clip(p_region);
+ if (region.size == Size2i()) {
+ return; //nothing to do
+ }
}
//single texture copy for backbuffer
- RD::get_singleton()->texture_copy(rt->color, rt->backbuffer_mipmap0, Vector3(region.position.x, region.position.y, 0), Vector3(region.position.x, region.position.y, 0), Vector3(region.size.x, region.size.y, 1), 0, 0, 0, 0, true);
- //effects.copy(rt->color, rt->backbuffer_fb, blur_region);
+ //RD::get_singleton()->texture_copy(rt->color, rt->backbuffer_mipmap0, Vector3(region.position.x, region.position.y, 0), Vector3(region.position.x, region.position.y, 0), Vector3(region.size.x, region.size.y, 1), 0, 0, 0, 0, true);
+ effects.copy_to_rect(rt->color, rt->backbuffer_mipmap0, region, false, false, false, true, true);
+
+ if (!p_gen_mipmaps) {
+ return;
+ }
//then mipmap blur
RID prev_texture = rt->color; //use color, not backbuffer, as bb has mipmaps.
@@ -6314,6 +6340,59 @@ void RasterizerStorageRD::render_target_copy_to_back_buffer(RID p_render_target,
}
}
+void RasterizerStorageRD::render_target_clear_back_buffer(RID p_render_target, const Rect2i &p_region, const Color &p_color) {
+ RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ ERR_FAIL_COND(!rt);
+ if (!rt->backbuffer.is_valid()) {
+ _create_render_target_backbuffer(rt);
+ }
+
+ Rect2i region;
+ if (p_region == Rect2i()) {
+ region.size = rt->size;
+ } else {
+ region = Rect2i(Size2i(), rt->size).clip(p_region);
+ if (region.size == Size2i()) {
+ return; //nothing to do
+ }
+ }
+
+ //single texture copy for backbuffer
+ effects.set_color(rt->backbuffer_mipmap0, p_color, region, true);
+}
+
+void RasterizerStorageRD::render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region) {
+ RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ ERR_FAIL_COND(!rt);
+ if (!rt->backbuffer.is_valid()) {
+ _create_render_target_backbuffer(rt);
+ }
+
+ Rect2i region;
+ if (p_region == Rect2i()) {
+ region.size = rt->size;
+ } else {
+ region = Rect2i(Size2i(), rt->size).clip(p_region);
+ if (region.size == Size2i()) {
+ return; //nothing to do
+ }
+ }
+
+ //then mipmap blur
+ RID prev_texture = rt->backbuffer_mipmap0;
+
+ for (int i = 0; i < rt->backbuffer_mipmaps.size(); i++) {
+ region.position.x >>= 1;
+ region.position.y >>= 1;
+ region.size.x = MAX(1, region.size.x >> 1);
+ region.size.y = MAX(1, region.size.y >> 1);
+
+ const RenderTarget::BackbufferMipmap &mm = rt->backbuffer_mipmaps[i];
+ effects.gaussian_blur(prev_texture, mm.mipmap, mm.mipmap_copy, region, true);
+ prev_texture = mm.mipmap;
+ }
+}
+
RID RasterizerStorageRD::render_target_get_framebuffer_uniform_set(RID p_render_target) {
RenderTarget *rt = render_target_owner.getornull(p_render_target);
ERR_FAIL_COND_V(!rt, RID());
diff --git a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h
index 7caafca2e0..05cb1b4a73 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h
+++ b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h
@@ -31,7 +31,7 @@
#ifndef RASTERIZER_STORAGE_RD_H
#define RASTERIZER_STORAGE_RD_H
-#include "core/rid_owner.h"
+#include "core/templates/rid_owner.h"
#include "servers/rendering/rasterizer.h"
#include "servers/rendering/rasterizer_rd/rasterizer_effects_rd.h"
#include "servers/rendering/rasterizer_rd/shader_compiler_rd.h"
@@ -989,6 +989,7 @@ private:
bool flags[RENDER_TARGET_FLAG_MAX];
RID backbuffer; //used for effects
+ RID backbuffer_fb;
RID backbuffer_mipmap0;
struct BackbufferMipmap {
@@ -1184,7 +1185,7 @@ public:
virtual void canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter);
virtual void canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat);
- bool canvas_texture_get_unifom_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular);
+ bool canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular);
/* SHADER API */
@@ -1916,7 +1917,9 @@ public:
void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value);
bool render_target_was_used(RID p_render_target);
void render_target_set_as_unused(RID p_render_target);
- void render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region);
+ void render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region, bool p_gen_mipmaps);
+ void render_target_clear_back_buffer(RID p_render_target, const Rect2i &p_region, const Color &p_color);
+ void render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region);
RID render_target_get_back_buffer_uniform_set(RID p_render_target, RID p_base_shader);
@@ -1930,6 +1933,7 @@ public:
RID render_target_get_rd_framebuffer(RID p_render_target);
RID render_target_get_rd_texture(RID p_render_target);
RID render_target_get_rd_backbuffer(RID p_render_target);
+ RID render_target_get_rd_backbuffer_framebuffer(RID p_render_target);
RID render_target_get_framebuffer_uniform_set(RID p_render_target);
RID render_target_get_backbuffer_uniform_set(RID p_render_target);
diff --git a/servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h b/servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h
index cf15e79586..6a72dbc77c 100644
--- a/servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h
+++ b/servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h
@@ -31,7 +31,7 @@
#ifndef RENDER_PIPELINE_CACHE_RD_H
#define RENDER_PIPELINE_CACHE_RD_H
-#include "core/spin_lock.h"
+#include "core/os/spin_lock.h"
#include "servers/rendering/rendering_device.h"
class RenderPipelineVertexFormatCacheRD {
diff --git a/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp b/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp
index 0a0c343e57..1a33e9a567 100644
--- a/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp
+++ b/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp
@@ -30,8 +30,8 @@
#include "shader_compiler_rd.h"
+#include "core/config/project_settings.h"
#include "core/os/os.h"
-#include "core/project_settings.h"
#include "rasterizer_storage_rd.h"
#include "servers/rendering_server.h"
diff --git a/servers/rendering/rasterizer_rd/shader_compiler_rd.h b/servers/rendering/rasterizer_rd/shader_compiler_rd.h
index 565520ec65..694f8fff91 100644
--- a/servers/rendering/rasterizer_rd/shader_compiler_rd.h
+++ b/servers/rendering/rasterizer_rd/shader_compiler_rd.h
@@ -31,7 +31,7 @@
#ifndef SHADER_COMPILER_RD_H
#define SHADER_COMPILER_RD_H
-#include "core/pair.h"
+#include "core/templates/pair.h"
#include "servers/rendering/shader_language.h"
#include "servers/rendering/shader_types.h"
#include "servers/rendering_server.h"
diff --git a/servers/rendering/rasterizer_rd/shader_rd.cpp b/servers/rendering/rasterizer_rd/shader_rd.cpp
index 8c57651263..865a1e1bbe 100644
--- a/servers/rendering/rasterizer_rd/shader_rd.cpp
+++ b/servers/rendering/rasterizer_rd/shader_rd.cpp
@@ -30,7 +30,7 @@
#include "shader_rd.h"
-#include "core/string_builder.h"
+#include "core/string/string_builder.h"
#include "rasterizer_rd.h"
#include "servers/rendering/rendering_device.h"
diff --git a/servers/rendering/rasterizer_rd/shader_rd.h b/servers/rendering/rasterizer_rd/shader_rd.h
index d9bb068ba6..0c379db6f2 100644
--- a/servers/rendering/rasterizer_rd/shader_rd.h
+++ b/servers/rendering/rasterizer_rd/shader_rd.h
@@ -31,11 +31,11 @@
#ifndef SHADER_RD_H
#define SHADER_RD_H
-#include "core/hash_map.h"
-#include "core/map.h"
#include "core/os/mutex.h"
-#include "core/rid_owner.h"
-#include "core/variant.h"
+#include "core/templates/hash_map.h"
+#include "core/templates/map.h"
+#include "core/templates/rid_owner.h"
+#include "core/variant/variant.h"
#include <stdio.h>
/**
diff --git a/servers/rendering/rasterizer_rd/shaders/canvas.glsl b/servers/rendering/rasterizer_rd/shaders/canvas.glsl
index 04a37e501f..2a0f94e733 100644
--- a/servers/rendering/rasterizer_rd/shaders/canvas.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/canvas.glsl
@@ -144,7 +144,7 @@ VERTEX_SHADER_CODE
color_interp = color;
- if (bool(draw_data.flags & FLAGS_USE_PIXEL_SNAP)) {
+ if (canvas_data.use_pixel_snap) {
vertex = floor(vertex + 0.5);
// precision issue on some hardware creates artifacts within texture
// offset uv by a small amount to avoid
@@ -249,7 +249,7 @@ vec4 light_compute(
inout vec4 shadow_modulate,
vec2 screen_uv,
vec2 uv,
- vec4 color) {
+ vec4 color, bool is_directional) {
vec4 light = vec4(0.0);
/* clang-format off */
LIGHT_SHADER_CODE
@@ -302,6 +302,99 @@ float map_ninepatch_axis(float pixel, float draw_size, float tex_pixel_size, flo
#endif
+#ifdef USE_LIGHTING
+
+vec3 light_normal_compute(vec3 light_vec, vec3 normal, vec3 base_color, vec3 light_color, vec4 specular_shininess, bool specular_shininess_used) {
+ float cNdotL = max(0.0, dot(normal, light_vec));
+
+ if (specular_shininess_used) {
+ //blinn
+ vec3 view = vec3(0.0, 0.0, 1.0); // not great but good enough
+ vec3 half_vec = normalize(view + light_vec);
+
+ float cNdotV = max(dot(normal, view), 0.0);
+ float cNdotH = max(dot(normal, half_vec), 0.0);
+ float cVdotH = max(dot(view, half_vec), 0.0);
+ float cLdotH = max(dot(light_vec, half_vec), 0.0);
+ float shininess = exp2(15.0 * specular_shininess.a + 1.0) * 0.25;
+ float blinn = pow(cNdotH, shininess);
+ blinn *= (shininess + 8.0) * (1.0 / (8.0 * M_PI));
+ float s = (blinn) / max(4.0 * cNdotV * cNdotL, 0.75);
+
+ return specular_shininess.rgb * light_color * s + light_color * base_color * cNdotL;
+ } else {
+ return light_color * base_color * cNdotL;
+ }
+}
+
+//float distance = length(shadow_pos);
+vec4 light_shadow_compute(uint light_base, vec4 light_color, vec4 shadow_uv
+#ifdef LIGHT_SHADER_CODE_USED
+ ,
+ vec3 shadow_modulate
+#endif
+) {
+ float shadow;
+ uint shadow_mode = light_array.data[light_base].flags & LIGHT_FLAGS_FILTER_MASK;
+
+ if (shadow_mode == LIGHT_FLAGS_SHADOW_NEAREST) {
+ shadow = textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv, 0.0).x;
+ } else if (shadow_mode == LIGHT_FLAGS_SHADOW_PCF5) {
+ vec4 shadow_pixel_size = vec4(light_array.data[light_base].shadow_pixel_size, 0.0, 0.0, 0.0);
+ shadow = 0.0;
+ shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size * 2.0, 0.0).x;
+ shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size, 0.0).x;
+ shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv, 0.0).x;
+ shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size, 0.0).x;
+ shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size * 2.0, 0.0).x;
+ shadow /= 5.0;
+ } else { //PCF13
+ vec4 shadow_pixel_size = vec4(light_array.data[light_base].shadow_pixel_size, 0.0, 0.0, 0.0);
+ shadow = 0.0;
+ shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size * 6.0, 0.0).x;
+ shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size * 5.0, 0.0).x;
+ shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size * 4.0, 0.0).x;
+ shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size * 3.0, 0.0).x;
+ shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size * 2.0, 0.0).x;
+ shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size, 0.0).x;
+ shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv, 0.0).x;
+ shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size, 0.0).x;
+ shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size * 2.0, 0.0).x;
+ shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size * 3.0, 0.0).x;
+ shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size * 4.0, 0.0).x;
+ shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size * 5.0, 0.0).x;
+ shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size * 6.0, 0.0).x;
+ shadow /= 13.0;
+ }
+
+ vec4 shadow_color = unpackUnorm4x8(light_array.data[light_base].shadow_color);
+#ifdef LIGHT_SHADER_CODE_USED
+ shadow_color *= shadow_modulate;
+#endif
+
+ shadow_color.a *= light_color.a; //respect light alpha
+
+ return mix(light_color, shadow_color, shadow);
+}
+
+void light_blend_compute(uint light_base, vec4 light_color, inout vec3 color) {
+ uint blend_mode = light_array.data[light_base].flags & LIGHT_FLAGS_BLEND_MASK;
+
+ switch (blend_mode) {
+ case LIGHT_FLAGS_BLEND_MODE_ADD: {
+ color.rgb += light_color.rgb * light_color.a;
+ } break;
+ case LIGHT_FLAGS_BLEND_MODE_SUB: {
+ color.rgb -= light_color.rgb * light_color.a;
+ } break;
+ case LIGHT_FLAGS_BLEND_MODE_MIX: {
+ color.rgb = mix(color.rgb, light_color.rgb, light_color.a);
+ } break;
+ }
+}
+
+#endif
+
void main() {
vec4 color = color_interp;
vec2 uv = uv_interp;
@@ -332,6 +425,7 @@ void main() {
color *= texture(sampler2D(color_texture, texture_sampler), uv);
uint light_count = (draw_data.flags >> FLAGS_LIGHT_COUNT_SHIFT) & 0xF; //max 16 lights
+ bool using_light = light_count > 0 || canvas_data.directional_light_count > 0;
vec3 normal;
@@ -341,7 +435,7 @@ void main() {
bool normal_used = false;
#endif
- if (normal_used || (light_count > 0 && bool(draw_data.flags & FLAGS_DEFAULT_NORMAL_MAP_USED))) {
+ if (normal_used || (using_light && bool(draw_data.flags & FLAGS_DEFAULT_NORMAL_MAP_USED))) {
normal.xy = texture(sampler2D(normal_texture, texture_sampler), uv).xy * vec2(2.0, -2.0) - vec2(1.0, -1.0);
normal.z = sqrt(1.0 - dot(normal.xy, normal.xy));
normal_used = true;
@@ -358,7 +452,7 @@ void main() {
bool specular_shininess_used = false;
#endif
- if (specular_shininess_used || (light_count > 0 && normal_used && bool(draw_data.flags & FLAGS_DEFAULT_SPECULAR_MAP_USED))) {
+ if (specular_shininess_used || (using_light && normal_used && bool(draw_data.flags & FLAGS_DEFAULT_SPECULAR_MAP_USED))) {
specular_shininess = texture(sampler2D(specular_texture, texture_sampler), uv);
specular_shininess *= unpackUnorm4x8(draw_data.specular_shininess);
specular_shininess_used = true;
@@ -401,13 +495,52 @@ FRAGMENT_SHADER_CODE
normal = normalize((canvas_data.canvas_normal_transform * vec4(normal, 0.0)).xyz);
}
- vec4 base_color = color;
+ vec3 base_color = color.rgb;
if (bool(draw_data.flags & FLAGS_USING_LIGHT_MASK)) {
color = vec4(0.0); //invisible by default due to using light mask
}
color *= canvas_data.canvas_modulation;
#ifdef USE_LIGHTING
+
+ // Directional Lights
+
+ for (uint i = 0; i < canvas_data.directional_light_count; i++) {
+ uint light_base = i;
+
+ vec2 direction = light_array.data[light_base].position;
+ vec4 light_color = light_array.data[light_base].color;
+
+#ifdef LIGHT_SHADER_CODE_USED
+
+ vec4 shadow_modulate = vec4(1.0);
+ light_color = light_compute(light_vertex, direction, normal, light_color, light_color.a, specular_shininess, shadow_modulate, screen_uv, color, uv, true);
+#else
+
+ if (normal_used) {
+ vec3 light_vec = normalize(mix(vec3(direction, 0.0), vec3(0, 0, 1), light_array.data[light_base].height));
+ light_color.rgb = light_normal_compute(light_vec, normal, base_color, light_color.rgb, specular_shininess, specular_shininess_used);
+ }
+#endif
+
+ if (bool(light_array.data[light_base].flags & LIGHT_FLAGS_HAS_SHADOW)) {
+ vec2 shadow_pos = (vec4(shadow_vertex, 0.0, 1.0) * mat4(light_array.data[light_base].shadow_matrix[0], light_array.data[light_base].shadow_matrix[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))).xy; //multiply inverse given its transposed. Optimizer removes useless operations.
+
+ vec4 shadow_uv = vec4(shadow_pos.x, light_array.data[light_base].shadow_y_ofs, shadow_pos.y * light_array.data[light_base].shadow_zfar_inv, 1.0);
+
+ light_color = light_shadow_compute(light_base, light_color, shadow_uv
+#ifdef LIGHT_SHADER_CODE_USED
+ ,
+ shadow_modulate
+#endif
+ );
+ }
+
+ light_blend_compute(light_base, light_color, color.rgb);
+ }
+
+ // Positional Lights
+
for (uint i = 0; i < MAX_LIGHTS_PER_ITEM; i++) {
if (i >= light_count) {
break;
@@ -440,7 +573,7 @@ FRAGMENT_SHADER_CODE
vec3 light_position = vec3(light_array.data[light_base].position, light_array.data[light_base].height);
light_color.rgb *= light_base_color.rgb;
- light_color = light_compute(light_vertex, light_position, normal, light_color, light_base_color.a, specular_shininess, shadow_modulate, screen_uv, color, uv);
+ light_color = light_compute(light_vertex, light_position, normal, light_color, light_base_color.a, specular_shininess, shadow_modulate, screen_uv, color, uv, false);
#else
light_color.rgb *= light_base_color.rgb * light_base_color.a;
@@ -451,24 +584,7 @@ FRAGMENT_SHADER_CODE
vec3 light_vec = normalize(light_pos - pos);
float cNdotL = max(0.0, dot(normal, light_vec));
- if (specular_shininess_used) {
- //blinn
- vec3 view = vec3(0.0, 0.0, 1.0); // not great but good enough
- vec3 half_vec = normalize(view + light_vec);
-
- float cNdotV = max(dot(normal, view), 0.0);
- float cNdotH = max(dot(normal, half_vec), 0.0);
- float cVdotH = max(dot(view, half_vec), 0.0);
- float cLdotH = max(dot(light_vec, half_vec), 0.0);
- float shininess = exp2(15.0 * specular_shininess.a + 1.0) * 0.25;
- float blinn = pow(cNdotH, shininess);
- blinn *= (shininess + 8.0) * (1.0 / (8.0 * M_PI));
- float s = (blinn) / max(4.0 * cNdotV * cNdotL, 0.75);
-
- light_color.rgb = specular_shininess.rgb * light_base_color.rgb * s + light_color.rgb * cNdotL;
- } else {
- light_color.rgb *= cNdotL;
- }
+ light_color.rgb = light_normal_compute(light_vec, normal, base_color, light_color.rgb, specular_shininess, specular_shininess_used);
}
#endif
if (any(lessThan(tex_uv, vec2(0.0, 0.0))) || any(greaterThanEqual(tex_uv, vec2(1.0, 1.0)))) {
@@ -506,69 +622,17 @@ FRAGMENT_SHADER_CODE
distance *= light_array.data[light_base].shadow_zfar_inv;
//float distance = length(shadow_pos);
- float shadow;
- uint shadow_mode = light_array.data[light_base].flags & LIGHT_FLAGS_FILTER_MASK;
-
vec4 shadow_uv = vec4(tex_ofs, light_array.data[light_base].shadow_y_ofs, distance, 1.0);
- if (shadow_mode == LIGHT_FLAGS_SHADOW_NEAREST) {
- shadow = textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv, 0.0).x;
- } else if (shadow_mode == LIGHT_FLAGS_SHADOW_PCF5) {
- vec4 shadow_pixel_size = vec4(light_array.data[light_base].shadow_pixel_size, 0.0, 0.0, 0.0);
- shadow = 0.0;
- shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size * 2.0, 0.0).x;
- shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size, 0.0).x;
- shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv, 0.0).x;
- shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size, 0.0).x;
- shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size * 2.0, 0.0).x;
- shadow /= 5.0;
- } else { //PCF13
- vec4 shadow_pixel_size = vec4(light_array.data[light_base].shadow_pixel_size, 0.0, 0.0, 0.0);
- shadow = 0.0;
- shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size * 6.0, 0.0).x;
- shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size * 5.0, 0.0).x;
- shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size * 4.0, 0.0).x;
- shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size * 3.0, 0.0).x;
- shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size * 2.0, 0.0).x;
- shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size, 0.0).x;
- shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv, 0.0).x;
- shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size, 0.0).x;
- shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size * 2.0, 0.0).x;
- shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size * 3.0, 0.0).x;
- shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size * 4.0, 0.0).x;
- shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size * 5.0, 0.0).x;
- shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size * 6.0, 0.0).x;
- shadow /= 13.0;
- }
-
- vec4 shadow_color = unpackUnorm4x8(light_array.data[light_base].shadow_color);
+ light_color = light_shadow_compute(light_base, light_color, shadow_uv
#ifdef LIGHT_SHADER_CODE_USED
- shadow_color *= shadow_modulate;
+ ,
+ shadow_modulate
#endif
-
- shadow_color.a *= light_color.a; //respect light alpha
-
- light_color = mix(light_color, shadow_color, shadow);
- //light_color = mix(light_color, shadow_color, shadow);
+ );
}
- uint blend_mode = light_array.data[light_base].flags & LIGHT_FLAGS_BLEND_MASK;
-
- switch (blend_mode) {
- case LIGHT_FLAGS_BLEND_MODE_ADD: {
- color.rgb += light_color.rgb * light_color.a;
- } break;
- case LIGHT_FLAGS_BLEND_MODE_SUB: {
- color.rgb -= light_color.rgb * light_color.a;
- } break;
- case LIGHT_FLAGS_BLEND_MODE_MIX: {
- color.rgb = mix(color.rgb, light_color.rgb, light_color.a);
- } break;
- case LIGHT_FLAGS_BLEND_MODE_MASK: {
- light_color.a *= base_color.a;
- color.rgb = mix(color.rgb, light_color.rgb, light_color.a);
- } break;
- }
+ light_blend_compute(light_base, light_color, color.rgb);
}
#endif
diff --git a/servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl b/servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl
index e4dc326af6..bb39584cbb 100644
--- a/servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl
@@ -15,7 +15,6 @@
#define FLAGS_USING_LIGHT_MASK (1 << 11)
#define FLAGS_NINEPACH_DRAW_CENTER (1 << 12)
#define FLAGS_USING_PARTICLES (1 << 13)
-#define FLAGS_USE_PIXEL_SNAP (1 << 14)
#define FLAGS_NINEPATCH_H_MODE_SHIFT 16
#define FLAGS_NINEPATCH_V_MODE_SHIFT 18
@@ -67,8 +66,12 @@ layout(set = 0, binding = 1, std140) uniform CanvasData {
vec4 canvas_modulation;
vec2 screen_pixel_size;
float time;
- float time_pad;
- //uint light_count;
+ bool use_pixel_snap;
+
+ uint directional_light_count;
+ uint pad0;
+ uint pad1;
+ uint pad2;
}
canvas_data;
diff --git a/servers/rendering/rasterizer_rd/shaders/copy.glsl b/servers/rendering/rasterizer_rd/shaders/copy.glsl
index 355a2b9d75..cdd35dfb3f 100644
--- a/servers/rendering/rasterizer_rd/shaders/copy.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/copy.glsl
@@ -15,6 +15,7 @@ layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
#define FLAG_FORCE_LUMINANCE (1 << 6)
#define FLAG_COPY_ALL_SOURCE (1 << 7)
#define FLAG_HIGH_QUALITY_GLOW (1 << 8)
+#define FLAG_ALPHA_TO_ONE (1 << 9)
layout(push_constant, binding = 1, std430) uniform Params {
ivec4 section;
@@ -35,6 +36,8 @@ layout(push_constant, binding = 1, std430) uniform Params {
float camera_z_far;
float camera_z_near;
uint pad2[2];
+
+ vec4 set_color;
}
params;
@@ -42,7 +45,7 @@ params;
layout(set = 0, binding = 0) uniform samplerCubeArray source_color;
#elif defined(MODE_CUBEMAP_TO_PANORAMA)
layout(set = 0, binding = 0) uniform samplerCube source_color;
-#else
+#elif !defined(MODE_SET_COLOR)
layout(set = 0, binding = 0) uniform sampler2D source_color;
#endif
@@ -203,25 +206,24 @@ void main() {
}
color = textureLod(source_color, uv, 0.0);
- if (bool(params.flags & FLAG_FORCE_LUMINANCE)) {
- color.rgb = vec3(max(max(color.r, color.g), color.b));
- }
- imageStore(dest_buffer, pos + params.target, color);
-
} else {
color = texelFetch(source_color, pos + params.section.xy, 0);
- if (bool(params.flags & FLAG_FORCE_LUMINANCE)) {
- color.rgb = vec3(max(max(color.r, color.g), color.b));
- }
-
if (bool(params.flags & FLAG_FLIP_Y)) {
pos.y = params.section.w - pos.y - 1;
}
+ }
- imageStore(dest_buffer, pos + params.target, color);
+ if (bool(params.flags & FLAG_FORCE_LUMINANCE)) {
+ color.rgb = vec3(max(max(color.r, color.g), color.b));
+ }
+
+ if (bool(params.flags & FLAG_ALPHA_TO_ONE)) {
+ color.a = 1.0;
}
+ imageStore(dest_buffer, pos + params.target, color);
+
#endif
#ifdef MODE_SIMPLE_COPY_DEPTH
@@ -270,4 +272,8 @@ void main() {
#endif
imageStore(dest_buffer, pos + params.target, color);
#endif
+
+#ifdef MODE_SET_COLOR
+ imageStore(dest_buffer, pos + params.target, params.set_color);
+#endif
}
diff --git a/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl b/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl
index 455a3d4a3a..da3c60af04 100644
--- a/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl
@@ -361,6 +361,65 @@ layout(location = 0) out vec4 frag_color;
#endif // RENDER DEPTH
+#ifdef ALPHA_HASH_USED
+
+float hash_2d(vec2 p) {
+ return fract(1.0e4 * sin(17.0 * p.x + 0.1 * p.y) *
+ (0.1 + abs(sin(13.0 * p.y + p.x))));
+}
+
+float hash_3d(vec3 p) {
+ return hash_2d(vec2(hash_2d(p.xy), p.z));
+}
+
+float compute_alpha_hash_threshold(vec3 pos, float hash_scale) {
+ vec3 dx = dFdx(pos);
+ vec3 dy = dFdx(pos);
+ float delta_max_sqr = max(length(dx), length(dy));
+ float pix_scale = 1.0 / (hash_scale * delta_max_sqr);
+
+ vec2 pix_scales =
+ vec2(exp2(floor(log2(pix_scale))), exp2(ceil(log2(pix_scale))));
+
+ vec2 a_thresh = vec2(hash_3d(floor(pix_scales.x * pos.xyz)),
+ hash_3d(floor(pix_scales.y * pos.xyz)));
+
+ float lerp_factor = fract(log2(pix_scale));
+
+ float a_interp = (1.0 - lerp_factor) * a_thresh.x + lerp_factor * a_thresh.y;
+
+ float min_lerp = min(lerp_factor, 1.0 - lerp_factor);
+
+ vec3 cases = vec3(a_interp * a_interp / (2.0 * min_lerp * (1.0 - min_lerp)),
+ (a_interp - 0.5 * min_lerp) / (1.0 - min_lerp),
+ 1.0 - ((1.0 - a_interp) * (1.0 - a_interp) /
+ (2.0 * min_lerp * (1.0 - min_lerp))));
+
+ float alpha_hash_threshold =
+ (lerp_factor < (1.0 - min_lerp)) ? ((lerp_factor < min_lerp) ? cases.x : cases.y) : cases.z;
+
+ return clamp(alpha_hash_threshold, 0.0, 1.0);
+}
+
+#endif // ALPHA_HASH_USED
+
+#ifdef ALPHA_ANTIALIASING_EDGE_USED
+
+float calc_mip_level(vec2 texture_coord) {
+ vec2 dx = dFdx(texture_coord);
+ vec2 dy = dFdy(texture_coord);
+ float delta_max_sqr = max(dot(dx, dx), dot(dy, dy));
+ return max(0.0, 0.5 * log2(delta_max_sqr));
+}
+
+float compute_alpha_antialiasing_edge(float input_alpha, vec2 texture_coord, float alpha_edge) {
+ input_alpha *= 1.0 + max(0, calc_mip_level(texture_coord)) * 0.25; // 0.25 mip scale, magic number
+ input_alpha = (input_alpha - alpha_edge) / max(fwidth(input_alpha), 0.0001) + 0.5;
+ return clamp(input_alpha, 0.0, 1.0);
+}
+
+#endif // ALPHA_ANTIALIASING_USED
+
// This returns the G_GGX function divided by 2 cos_theta_m, where in practice cos_theta_m is either N.L or N.V.
// We're dividing this factor off because the overall term we'll end up looks like
// (see, for example, the first unnumbered equation in B. Burley, "Physically Based Shading at Disney", SIGGRAPH 2012):
@@ -1709,10 +1768,6 @@ void main() {
float alpha = 1.0;
-#if defined(ALPHA_SCISSOR_USED)
- float alpha_scissor = 0.5;
-#endif
-
#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED)
vec3 binormal = normalize(binormal_interp);
vec3 tangent = normalize(tangent_interp);
@@ -1749,6 +1804,19 @@ void main() {
float sss_strength = 0.0;
+#ifdef ALPHA_SCISSOR_USED
+ float alpha_scissor_threshold = 1.0;
+#endif // ALPHA_SCISSOR_USED
+
+#ifdef ALPHA_HASH_USED
+ float alpha_hash_scale = 1.0;
+#endif // ALPHA_HASH_USED
+
+#ifdef ALPHA_ANTIALIASING_EDGE_USED
+ float alpha_antialiasing_edge = 0.0;
+ vec2 alpha_texture_coordinate = vec2(0.0, 0.0);
+#endif // ALPHA_ANTIALIASING_EDGE_USED
+
{
/* clang-format off */
@@ -1757,7 +1825,7 @@ FRAGMENT_SHADER_CODE
/* clang-format on */
}
-#if defined(LIGHT_TRANSMITTANCE_USED)
+#ifdef LIGHT_TRANSMITTANCE_USED
#ifdef SSS_MODE_SKIN
transmittance_color.a = sss_strength;
#else
@@ -1765,25 +1833,43 @@ FRAGMENT_SHADER_CODE
#endif
#endif
-#if !defined(USE_SHADOW_TO_OPACITY)
+#ifndef USE_SHADOW_TO_OPACITY
-#if defined(ALPHA_SCISSOR_USED)
- if (alpha < alpha_scissor) {
+#ifdef ALPHA_SCISSOR_USED
+ if (alpha < alpha_scissor_threshold) {
discard;
}
#endif // ALPHA_SCISSOR_USED
-#ifdef USE_OPAQUE_PREPASS
+// alpha hash can be used in unison with alpha antialiasing
+#ifdef ALPHA_HASH_USED
+ if (alpha < compute_alpha_hash_threshold(vertex, alpha_hash_scale)) {
+ discard;
+ }
+#endif // ALPHA_HASH_USED
+
+// If we are not edge antialiasing, we need to remove the output alpha channel from scissor and hash
+#if (defined(ALPHA_SCISSOR_USED) || defined(ALPHA_HASH_USED)) && !defined(ALPHA_ANTIALIASING_EDGE_USED)
+ alpha = 1.0;
+#endif
+
+#ifdef ALPHA_ANTIALIASING_EDGE_USED
+// If alpha scissor is used, we must further the edge threshold, otherwise we wont get any edge feather
+#ifdef ALPHA_SCISSOR_USED
+ alpha_antialiasing_edge = clamp(alpha_scissor_threshold + alpha_antialiasing_edge, 0.0, 1.0);
+#endif
+ alpha = compute_alpha_antialiasing_edge(alpha, alpha_texture_coordinate, alpha_antialiasing_edge);
+#endif // ALPHA_ANTIALIASING_EDGE_USED
+#ifdef USE_OPAQUE_PREPASS
if (alpha < opaque_prepass_threshold) {
discard;
}
-
#endif // USE_OPAQUE_PREPASS
#endif // !USE_SHADOW_TO_OPACITY
-#if defined(NORMALMAP_USED)
+#ifdef NORMALMAP_USED
normalmap.xy = normalmap.xy * 2.0 - 1.0;
normalmap.z = sqrt(max(0.0, 1.0 - dot(normalmap.xy, normalmap.xy))); //always ignore Z, as it can be RG packed, Z may be pos/neg, etc.
@@ -1792,7 +1878,7 @@ FRAGMENT_SHADER_CODE
#endif
-#if defined(LIGHT_ANISOTROPY_USED)
+#ifdef LIGHT_ANISOTROPY_USED
if (anisotropy > 0.01) {
//rotation matrix
diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h
index 6df66e7b20..f1f8b3cda0 100644
--- a/servers/rendering/rendering_device.h
+++ b/servers/rendering/rendering_device.h
@@ -31,8 +31,8 @@
#ifndef RENDERING_DEVICE_H
#define RENDERING_DEVICE_H
-#include "core/class_db.h"
-#include "core/typed_array.h"
+#include "core/object/class_db.h"
+#include "core/variant/typed_array.h"
#include "servers/display_server.h"
class RDTextureFormat;
diff --git a/servers/rendering/rendering_server_canvas.cpp b/servers/rendering/rendering_server_canvas.cpp
index b0bff8b2c2..5a12be5659 100644
--- a/servers/rendering/rendering_server_canvas.cpp
+++ b/servers/rendering/rendering_server_canvas.cpp
@@ -37,7 +37,7 @@
static const int z_range = RS::CANVAS_ITEM_Z_MAX - RS::CANVAS_ITEM_Z_MIN + 1;
-void RenderingServerCanvas::_render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RasterizerCanvas::Light *p_lights, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat) {
+void RenderingServerCanvas::_render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RasterizerCanvas::Light *p_lights, RasterizerCanvas::Light *p_directional_lights, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel) {
RENDER_TIMESTAMP("Cull CanvasItem Tree");
memset(z_list, 0, z_range * sizeof(RasterizerCanvas::Item *));
@@ -68,7 +68,7 @@ void RenderingServerCanvas::_render_canvas_item_tree(RID p_to_render_target, Can
RENDER_TIMESTAMP("Render Canvas Items");
- RSG::canvas_render->canvas_render_items(p_to_render_target, list, p_modulate, p_lights, p_transform, p_default_filter, p_default_repeat);
+ RSG::canvas_render->canvas_render_items(p_to_render_target, list, p_modulate, p_lights, p_directional_lights, p_transform, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel);
}
void _collect_ysort_children(RenderingServerCanvas::Item *p_canvas_item, Transform2D p_transform, RenderingServerCanvas::Item *p_material_owner, RenderingServerCanvas::Item **r_items, int &r_index) {
@@ -113,7 +113,12 @@ void RenderingServerCanvas::_cull_canvas_item(Item *p_canvas_item, const Transfo
}
Rect2 rect = ci->get_rect();
- Transform2D xform = p_transform * ci->xform;
+ Transform2D xform = ci->xform;
+ if (snapping_2d_transforms_to_pixel) {
+ xform.elements[2] = xform.elements[2].floor();
+ }
+ xform = p_transform * xform;
+
Rect2 global_rect = xform.xform(rect);
global_rect.position += p_clip_rect.position;
@@ -167,8 +172,15 @@ void RenderingServerCanvas::_cull_canvas_item(Item *p_canvas_item, const Transfo
p_z = ci->z_index;
}
+ RasterizerCanvas::Item *canvas_group_from = nullptr;
+ bool use_canvas_group = ci->canvas_group != nullptr && (ci->canvas_group->fit_empty || ci->commands != nullptr);
+ if (use_canvas_group) {
+ int zidx = p_z - RS::CANVAS_ITEM_Z_MIN;
+ canvas_group_from = z_last_list[zidx];
+ }
+
for (int i = 0; i < child_item_count; i++) {
- if (!child_items[i]->behind || (ci->sort_y && child_items[i]->sort_y)) {
+ if ((!child_items[i]->behind && !use_canvas_group) || (ci->sort_y && child_items[i]->sort_y)) {
continue;
}
if (ci->sort_y) {
@@ -182,6 +194,70 @@ void RenderingServerCanvas::_cull_canvas_item(Item *p_canvas_item, const Transfo
ci->copy_back_buffer->screen_rect = xform.xform(ci->copy_back_buffer->rect).clip(p_clip_rect);
}
+ if (use_canvas_group) {
+ int zidx = p_z - RS::CANVAS_ITEM_Z_MIN;
+ if (canvas_group_from == nullptr) {
+ // no list before processing this item, means must put stuff in group from the beginning of list.
+ canvas_group_from = z_list[zidx];
+ } else {
+ // there was a list before processing, so begin group from this one.
+ canvas_group_from = canvas_group_from->next;
+ }
+
+ if (canvas_group_from) {
+ // Has a place to begin the group from!
+
+ //compute a global rect (in global coords) for children in the same z layer
+ Rect2 rect_accum;
+ RasterizerCanvas::Item *c = canvas_group_from;
+ while (c) {
+ if (c == canvas_group_from) {
+ rect_accum = c->global_rect_cache;
+ } else {
+ rect_accum = rect_accum.merge(c->global_rect_cache);
+ }
+
+ c = c->next;
+ }
+
+ // We have two choices now, if user has drawn something, we must assume users wants to draw the "mask", so compute the size based on this.
+ // If nothing has been drawn, we just take it over and draw it ourselves.
+ if (ci->canvas_group->fit_empty && (ci->commands == nullptr ||
+ (ci->commands->next == nullptr && ci->commands->type == Item::Command::TYPE_RECT && (static_cast<Item::CommandRect *>(ci->commands)->flags & RasterizerCanvas::CANVAS_RECT_IS_GROUP)))) {
+ // No commands, or sole command is the one used to draw, so we (re)create the draw command.
+ ci->clear();
+
+ if (rect_accum == Rect2()) {
+ rect_accum.size = Size2(1, 1);
+ }
+
+ rect_accum = rect_accum.grow(ci->canvas_group->fit_margin);
+
+ //draw it?
+ RasterizerCanvas::Item::CommandRect *crect = ci->alloc_command<RasterizerCanvas::Item::CommandRect>();
+
+ crect->flags = RasterizerCanvas::CANVAS_RECT_IS_GROUP; // so we can recognize it later
+ crect->rect = xform.affine_inverse().xform(rect_accum);
+ crect->modulate = Color(1, 1, 1, 1);
+
+ //the global rect is used to do the copying, so update it
+ global_rect = rect_accum.grow(ci->canvas_group->clear_margin); //grow again by clear margin
+ global_rect.position += p_clip_rect.position;
+ } else {
+ global_rect.position -= p_clip_rect.position;
+
+ global_rect = global_rect.merge(rect_accum); //must use both rects for this
+ global_rect = global_rect.grow(ci->canvas_group->clear_margin); //grow by clear margin
+
+ global_rect.position += p_clip_rect.position;
+ }
+
+ // Very important that this is cleared after used in RasterizerCanvas to avoid
+ // potential crashes.
+ canvas_group_from->canvas_group_owner = ci;
+ }
+ }
+
if (ci->update_when_visible) {
RenderingServerRaster::redraw_request();
}
@@ -211,7 +287,7 @@ void RenderingServerCanvas::_cull_canvas_item(Item *p_canvas_item, const Transfo
}
for (int i = 0; i < child_item_count; i++) {
- if (child_items[i]->behind || (ci->sort_y && child_items[i]->sort_y)) {
+ if (child_items[i]->behind || use_canvas_group || (ci->sort_y && child_items[i]->sort_y)) {
continue;
}
if (ci->sort_y) {
@@ -222,30 +298,11 @@ void RenderingServerCanvas::_cull_canvas_item(Item *p_canvas_item, const Transfo
}
}
-void RenderingServerCanvas::_light_mask_canvas_items(int p_z, RasterizerCanvas::Item *p_canvas_item, RasterizerCanvas::Light *p_masked_lights) {
- if (!p_masked_lights) {
- return;
- }
-
- RasterizerCanvas::Item *ci = p_canvas_item;
-
- while (ci) {
- RasterizerCanvas::Light *light = p_masked_lights;
- while (light) {
- if (ci->light_mask & light->item_mask && p_z >= light->z_min && p_z <= light->z_max && ci->global_rect_cache.intersects_transformed(light->xform_cache, light->rect_cache)) {
- ci->light_masked = true;
- }
-
- light = light->mask_next_ptr;
- }
-
- ci = ci->next;
- }
-}
-
-void RenderingServerCanvas::render_canvas(RID p_render_target, Canvas *p_canvas, const Transform2D &p_transform, RasterizerCanvas::Light *p_lights, RasterizerCanvas::Light *p_masked_lights, const Rect2 &p_clip_rect, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat) {
+void RenderingServerCanvas::render_canvas(RID p_render_target, Canvas *p_canvas, const Transform2D &p_transform, RasterizerCanvas::Light *p_lights, RasterizerCanvas::Light *p_directional_lights, const Rect2 &p_clip_rect, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_transforms_to_pixel, bool p_snap_2d_vertices_to_pixel) {
RENDER_TIMESTAMP(">Render Canvas");
+ snapping_2d_transforms_to_pixel = p_snap_2d_transforms_to_pixel;
+
if (p_canvas->children_order_dirty) {
p_canvas->child_items.sort();
p_canvas->children_order_dirty = false;
@@ -263,26 +320,26 @@ void RenderingServerCanvas::render_canvas(RID p_render_target, Canvas *p_canvas,
}
if (!has_mirror) {
- _render_canvas_item_tree(p_render_target, ci, l, nullptr, p_transform, p_clip_rect, p_canvas->modulate, p_lights, p_default_filter, p_default_repeat);
+ _render_canvas_item_tree(p_render_target, ci, l, nullptr, p_transform, p_clip_rect, p_canvas->modulate, p_lights, p_directional_lights, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel);
} 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, nullptr, 0, ci2.item, p_transform, p_clip_rect, p_canvas->modulate, p_lights, p_default_filter, p_default_repeat);
+ _render_canvas_item_tree(p_render_target, nullptr, 0, ci2.item, p_transform, p_clip_rect, p_canvas->modulate, p_lights, p_directional_lights, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel);
//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, nullptr, 0, ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights, p_default_filter, p_default_repeat);
+ _render_canvas_item_tree(p_render_target, nullptr, 0, ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights, p_directional_lights, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel);
}
if (ci2.mirror.y != 0) {
Transform2D xform2 = p_transform * Transform2D(0, Vector2(0, ci2.mirror.y));
- _render_canvas_item_tree(p_render_target, nullptr, 0, ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights, p_default_filter, p_default_repeat);
+ _render_canvas_item_tree(p_render_target, nullptr, 0, ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights, p_directional_lights, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel);
}
if (ci2.mirror.y != 0 && ci2.mirror.x != 0) {
Transform2D xform2 = p_transform * Transform2D(0, ci2.mirror);
- _render_canvas_item_tree(p_render_target, nullptr, 0, ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights, p_default_filter, p_default_repeat);
+ _render_canvas_item_tree(p_render_target, nullptr, 0, ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights, p_directional_lights, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel);
}
}
}
@@ -935,19 +992,65 @@ void RenderingServerCanvas::canvas_item_set_use_parent_material(RID p_item, bool
canvas_item->use_parent_material = p_enable;
}
+void RenderingServerCanvas::canvas_item_set_canvas_group_mode(RID p_item, RS::CanvasGroupMode p_mode, float p_clear_margin, bool p_fit_empty, float p_fit_margin, bool p_blur_mipmaps) {
+ Item *canvas_item = canvas_item_owner.getornull(p_item);
+ ERR_FAIL_COND(!canvas_item);
+
+ if (p_mode == RS::CANVAS_GROUP_MODE_DISABLED) {
+ if (canvas_item->canvas_group != nullptr) {
+ memdelete(canvas_item->canvas_group);
+ canvas_item->canvas_group = nullptr;
+ }
+ } else {
+ if (canvas_item->canvas_group == nullptr) {
+ canvas_item->canvas_group = memnew(RasterizerCanvas::Item::CanvasGroup);
+ }
+ canvas_item->canvas_group->mode = p_mode;
+ canvas_item->canvas_group->fit_empty = p_fit_empty;
+ canvas_item->canvas_group->fit_margin = p_fit_margin;
+ canvas_item->canvas_group->blur_mipmaps = p_blur_mipmaps;
+ canvas_item->canvas_group->clear_margin = p_clear_margin;
+ }
+}
+
RID RenderingServerCanvas::canvas_light_create() {
RasterizerCanvas::Light *clight = memnew(RasterizerCanvas::Light);
clight->light_internal = RSG::canvas_render->light_create();
return canvas_light_owner.make_rid(clight);
}
+void RenderingServerCanvas::canvas_light_set_mode(RID p_light, RS::CanvasLightMode p_mode) {
+ RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light);
+ ERR_FAIL_COND(!clight);
+
+ if (clight->mode == p_mode) {
+ return;
+ }
+
+ RID canvas = clight->canvas;
+
+ if (canvas.is_valid()) {
+ canvas_light_attach_to_canvas(p_light, RID());
+ }
+
+ clight->mode = p_mode;
+
+ if (canvas.is_valid()) {
+ canvas_light_attach_to_canvas(p_light, canvas);
+ }
+}
+
void RenderingServerCanvas::canvas_light_attach_to_canvas(RID p_light, RID p_canvas) {
RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light);
ERR_FAIL_COND(!clight);
if (clight->canvas.is_valid()) {
Canvas *canvas = canvas_owner.getornull(clight->canvas);
- canvas->lights.erase(clight);
+ if (clight->mode == RS::CANVAS_LIGHT_MODE_POINT) {
+ canvas->lights.erase(clight);
+ } else {
+ canvas->directional_lights.erase(clight);
+ }
}
if (!canvas_owner.owns(p_canvas)) {
@@ -958,7 +1061,11 @@ void RenderingServerCanvas::canvas_light_attach_to_canvas(RID p_light, RID p_can
if (clight->canvas.is_valid()) {
Canvas *canvas = canvas_owner.getornull(clight->canvas);
- canvas->lights.insert(clight);
+ if (clight->mode == RS::CANVAS_LIGHT_MODE_POINT) {
+ canvas->lights.insert(clight);
+ } else {
+ canvas->directional_lights.insert(clight);
+ }
}
}
@@ -969,7 +1076,7 @@ void RenderingServerCanvas::canvas_light_set_enabled(RID p_light, bool p_enabled
clight->enabled = p_enabled;
}
-void RenderingServerCanvas::canvas_light_set_scale(RID p_light, float p_scale) {
+void RenderingServerCanvas::canvas_light_set_texture_scale(RID p_light, float p_scale) {
RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light);
ERR_FAIL_COND(!clight);
@@ -1053,11 +1160,18 @@ void RenderingServerCanvas::canvas_light_set_item_shadow_cull_mask(RID p_light,
clight->item_shadow_mask = p_mask;
}
-void RenderingServerCanvas::canvas_light_set_mode(RID p_light, RS::CanvasLightMode p_mode) {
+void RenderingServerCanvas::canvas_light_set_directional_distance(RID p_light, float p_distance) {
RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light);
ERR_FAIL_COND(!clight);
- clight->mode = p_mode;
+ clight->directional_distance = p_distance;
+}
+
+void RenderingServerCanvas::canvas_light_set_blend_mode(RID p_light, RS::CanvasLightBlendMode p_mode) {
+ RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light);
+ ERR_FAIL_COND(!clight);
+
+ clight->blend_mode = p_mode;
}
void RenderingServerCanvas::canvas_light_set_shadow_enabled(RID p_light, bool p_enabled) {
diff --git a/servers/rendering/rendering_server_canvas.h b/servers/rendering/rendering_server_canvas.h
index 16edfd54e1..36e2f77e95 100644
--- a/servers/rendering/rendering_server_canvas.h
+++ b/servers/rendering/rendering_server_canvas.h
@@ -116,6 +116,7 @@ public:
};
Set<RasterizerCanvas::Light *> lights;
+ Set<RasterizerCanvas::Light *> directional_lights;
Set<RasterizerCanvas::LightOccluderInstance *> occluders;
@@ -152,17 +153,17 @@ public:
RID_PtrOwner<RasterizerCanvas::Light> canvas_light_owner;
bool disable_scale;
+ bool snapping_2d_transforms_to_pixel = false;
private:
- void _render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RasterizerCanvas::Light *p_lights, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat);
+ void _render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RasterizerCanvas::Light *p_lights, RasterizerCanvas::Light *p_directional_lights, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel);
void _cull_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RasterizerCanvas::Item **z_list, RasterizerCanvas::Item **z_last_list, Item *p_canvas_clip, Item *p_material_owner);
- void _light_mask_canvas_items(int p_z, RasterizerCanvas::Item *p_canvas_item, RasterizerCanvas::Light *p_masked_lights);
RasterizerCanvas::Item **z_list;
RasterizerCanvas::Item **z_last_list;
public:
- void render_canvas(RID p_render_target, Canvas *p_canvas, const Transform2D &p_transform, RasterizerCanvas::Light *p_lights, RasterizerCanvas::Light *p_masked_lights, const Rect2 &p_clip_rect, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat);
+ void render_canvas(RID p_render_target, Canvas *p_canvas, const Transform2D &p_transform, RasterizerCanvas::Light *p_lights, RasterizerCanvas::Light *p_directional_lights, const Rect2 &p_clip_rect, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_transforms_to_pixel, bool p_snap_2d_vertices_to_pixel);
RID canvas_create();
void canvas_set_item_mirroring(RID p_canvas, RID p_item, const Point2 &p_mirroring);
@@ -216,10 +217,13 @@ public:
void canvas_item_set_use_parent_material(RID p_item, bool p_enable);
+ void canvas_item_set_canvas_group_mode(RID p_item, RS::CanvasGroupMode p_mode, float p_clear_margin = 5.0, bool p_fit_empty = false, float p_fit_margin = 0.0, bool p_blur_mipmaps = false);
+
RID canvas_light_create();
+ void canvas_light_set_mode(RID p_light, RS::CanvasLightMode p_mode);
void canvas_light_attach_to_canvas(RID p_light, RID p_canvas);
void canvas_light_set_enabled(RID p_light, bool p_enabled);
- void canvas_light_set_scale(RID p_light, float p_scale);
+ void canvas_light_set_texture_scale(RID p_light, float p_scale);
void canvas_light_set_transform(RID p_light, const Transform2D &p_transform);
void canvas_light_set_texture(RID p_light, RID p_texture);
void canvas_light_set_texture_offset(RID p_light, const Vector2 &p_offset);
@@ -230,8 +234,9 @@ public:
void canvas_light_set_layer_range(RID p_light, int p_min_layer, int p_max_layer);
void canvas_light_set_item_cull_mask(RID p_light, int p_mask);
void canvas_light_set_item_shadow_cull_mask(RID p_light, int p_mask);
+ void canvas_light_set_directional_distance(RID p_light, float p_distance);
- void canvas_light_set_mode(RID p_light, RS::CanvasLightMode p_mode);
+ void canvas_light_set_blend_mode(RID p_light, RS::CanvasLightBlendMode p_mode);
void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled);
void canvas_light_set_shadow_filter(RID p_light, RS::CanvasLightShadowFilter p_filter);
diff --git a/servers/rendering/rendering_server_raster.cpp b/servers/rendering/rendering_server_raster.cpp
index cbc91497ba..94cfb6b752 100644
--- a/servers/rendering/rendering_server_raster.cpp
+++ b/servers/rendering/rendering_server_raster.cpp
@@ -30,10 +30,10 @@
#include "rendering_server_raster.h"
+#include "core/config/project_settings.h"
#include "core/io/marshalls.h"
#include "core/os/os.h"
-#include "core/project_settings.h"
-#include "core/sort_array.h"
+#include "core/templates/sort_array.h"
#include "rendering_server_canvas.h"
#include "rendering_server_globals.h"
#include "rendering_server_scene.h"
diff --git a/servers/rendering/rendering_server_raster.h b/servers/rendering/rendering_server_raster.h
index 5744b40321..daad706f8e 100644
--- a/servers/rendering/rendering_server_raster.h
+++ b/servers/rendering/rendering_server_raster.h
@@ -528,6 +528,8 @@ public:
BIND2(viewport_remove_canvas, RID, RID)
BIND3(viewport_set_canvas_transform, RID, RID, const Transform2D &)
BIND2(viewport_set_transparent_background, RID, bool)
+ BIND2(viewport_set_snap_2d_transforms_to_pixel, RID, bool)
+ BIND2(viewport_set_snap_2d_vertices_to_pixel, RID, bool)
BIND2(viewport_set_default_canvas_item_texture_filter, RID, CanvasItemTextureFilter)
BIND2(viewport_set_default_canvas_item_texture_repeat, RID, CanvasItemTextureRepeat)
@@ -743,10 +745,15 @@ public:
BIND2(canvas_item_set_use_parent_material, RID, bool)
+ BIND6(canvas_item_set_canvas_group_mode, RID, CanvasGroupMode, float, bool, float, bool)
+
BIND0R(RID, canvas_light_create)
+
+ BIND2(canvas_light_set_mode, RID, CanvasLightMode)
+
BIND2(canvas_light_attach_to_canvas, RID, RID)
BIND2(canvas_light_set_enabled, RID, bool)
- BIND2(canvas_light_set_scale, RID, float)
+ BIND2(canvas_light_set_texture_scale, RID, float)
BIND2(canvas_light_set_transform, RID, const Transform2D &)
BIND2(canvas_light_set_texture, RID, RID)
BIND2(canvas_light_set_texture_offset, RID, const Vector2 &)
@@ -757,8 +764,9 @@ public:
BIND3(canvas_light_set_layer_range, RID, int, int)
BIND2(canvas_light_set_item_cull_mask, RID, int)
BIND2(canvas_light_set_item_shadow_cull_mask, RID, int)
+ BIND2(canvas_light_set_directional_distance, RID, float)
- BIND2(canvas_light_set_mode, RID, CanvasLightMode)
+ BIND2(canvas_light_set_blend_mode, RID, CanvasLightBlendMode)
BIND2(canvas_light_set_shadow_enabled, RID, bool)
BIND2(canvas_light_set_shadow_filter, RID, CanvasLightShadowFilter)
diff --git a/servers/rendering/rendering_server_scene.h b/servers/rendering/rendering_server_scene.h
index 1b0a617627..a30aac3bb1 100644
--- a/servers/rendering/rendering_server_scene.h
+++ b/servers/rendering/rendering_server_scene.h
@@ -33,13 +33,13 @@
#include "servers/rendering/rasterizer.h"
-#include "core/local_vector.h"
#include "core/math/geometry_3d.h"
#include "core/math/octree.h"
#include "core/os/semaphore.h"
#include "core/os/thread.h"
-#include "core/rid_owner.h"
-#include "core/self_list.h"
+#include "core/templates/local_vector.h"
+#include "core/templates/rid_owner.h"
+#include "core/templates/self_list.h"
#include "servers/xr/xr_interface.h"
class RenderingServerScene {
diff --git a/servers/rendering/rendering_server_viewport.cpp b/servers/rendering/rendering_server_viewport.cpp
index a8dbe1e254..c6682b1fcd 100644
--- a/servers/rendering/rendering_server_viewport.cpp
+++ b/servers/rendering/rendering_server_viewport.cpp
@@ -30,7 +30,7 @@
#include "rendering_server_viewport.h"
-#include "core/project_settings.h"
+#include "core/config/project_settings.h"
#include "rendering_server_canvas.h"
#include "rendering_server_globals.h"
#include "rendering_server_scene.h"
@@ -40,11 +40,21 @@ static Transform2D _canvas_get_transform(RenderingServerViewport::Viewport *p_vi
float scale = 1.0;
if (p_viewport->canvas_map.has(p_canvas->parent)) {
- xf = xf * p_viewport->canvas_map[p_canvas->parent].transform;
+ Transform2D c_xform = p_viewport->canvas_map[p_canvas->parent].transform;
+ if (p_viewport->snap_2d_transforms_to_pixel) {
+ c_xform.elements[2] = c_xform.elements[2].floor();
+ }
+ xf = xf * c_xform;
scale = p_canvas->parent_scale;
}
- xf = xf * p_canvas_data->transform;
+ Transform2D c_xform = p_canvas_data->transform;
+
+ if (p_viewport->snap_2d_transforms_to_pixel) {
+ c_xform.elements[2] = c_xform.elements[2].floor();
+ }
+
+ xf = xf * c_xform;
if (scale != 1.0 && !RSG::canvas->disable_scale) {
Vector2 pivot = p_vp_size * 0.5;
@@ -132,11 +142,15 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface::
Rect2 clip_rect(0, 0, p_viewport->size.x, p_viewport->size.y);
RasterizerCanvas::Light *lights = nullptr;
RasterizerCanvas::Light *lights_with_shadow = nullptr;
- RasterizerCanvas::Light *lights_with_mask = nullptr;
+
+ RasterizerCanvas::Light *directional_lights = nullptr;
+ RasterizerCanvas::Light *directional_lights_with_shadow = nullptr;
+
Rect2 shadow_rect;
int light_count = 0;
int shadow_count = 0;
+ int directional_light_count = 0;
RENDER_TIMESTAMP("Cull Canvas Lights");
for (Map<RID, Viewport::CanvasData>::Element *E = p_viewport->canvas_map.front(); E; E = E->next()) {
@@ -176,10 +190,6 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface::
lights_with_shadow = cl;
cl->radius_cache = cl->rect_cache.size.length();
}
- if (cl->mode == RS::CANVAS_LIGHT_MODE_MASK) {
- cl->mask_next_ptr = lights_with_mask;
- lights_with_mask = cl;
- }
light_count++;
}
@@ -189,6 +199,26 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface::
}
}
+ for (Set<RasterizerCanvas::Light *>::Element *F = canvas->directional_lights.front(); F; F = F->next()) {
+ RasterizerCanvas::Light *cl = F->get();
+ if (cl->enabled) {
+ cl->filter_next_ptr = directional_lights;
+ directional_lights = cl;
+ cl->xform_cache = xf * cl->xform;
+ cl->xform_cache.elements[2] = Vector2(); //translation is pointless
+ if (cl->use_shadow) {
+ cl->shadows_next_ptr = directional_lights_with_shadow;
+ directional_lights_with_shadow = cl;
+ }
+
+ directional_light_count++;
+
+ if (directional_light_count == RS::MAX_2D_DIRECTIONAL_LIGHTS) {
+ break;
+ }
+ }
+ }
+
canvas_map[Viewport::CanvasKey(E->key(), E->get().layer, E->get().sublayer)] = &E->get();
}
@@ -230,6 +260,90 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface::
RENDER_TIMESTAMP("<End rendering 2D Shadows");
}
+ if (directional_lights_with_shadow) {
+ //update shadows if any
+ RasterizerCanvas::Light *light = directional_lights_with_shadow;
+ while (light) {
+ Vector2 light_dir = -light->xform_cache.elements[1].normalized(); // Y is light direction
+ float cull_distance = light->directional_distance;
+
+ Vector2 light_dir_sign;
+ light_dir_sign.x = (ABS(light_dir.x) < CMP_EPSILON) ? 0.0 : ((light_dir.x > 0.0) ? 1.0 : -1.0);
+ light_dir_sign.y = (ABS(light_dir.y) < CMP_EPSILON) ? 0.0 : ((light_dir.y > 0.0) ? 1.0 : -1.0);
+
+ Vector2 points[6];
+ int point_count = 0;
+
+ for (int j = 0; j < 4; j++) {
+ static const Vector2 signs[4] = { Vector2(1, 1), Vector2(1, 0), Vector2(0, 0), Vector2(0, 1) };
+ Vector2 sign_cmp = signs[j] * 2.0 - Vector2(1.0, 1.0);
+ Vector2 point = clip_rect.position + clip_rect.size * signs[j];
+
+ if (sign_cmp == light_dir_sign) {
+ //both point in same direction, plot offseted
+ points[point_count++] = point + light_dir * cull_distance;
+ } else if (sign_cmp.x == light_dir_sign.x || sign_cmp.y == light_dir_sign.y) {
+ int next_j = (j + 1) % 4;
+ Vector2 next_sign_cmp = signs[next_j] * 2.0 - Vector2(1.0, 1.0);
+
+ //one point in the same direction, plot segment
+
+ if (next_sign_cmp.x == light_dir_sign.x || next_sign_cmp.y == light_dir_sign.y) {
+ if (light_dir_sign.x != 0.0 || light_dir_sign.y != 0.0) {
+ points[point_count++] = point;
+ }
+ points[point_count++] = point + light_dir * cull_distance;
+ } else {
+ points[point_count++] = point + light_dir * cull_distance;
+ if (light_dir_sign.x != 0.0 || light_dir_sign.y != 0.0) {
+ points[point_count++] = point;
+ }
+ }
+ } else {
+ //plot normally
+ points[point_count++] = point;
+ }
+ }
+
+ Vector2 xf_points[6];
+
+ RasterizerCanvas::LightOccluderInstance *occluders = nullptr;
+
+ RENDER_TIMESTAMP(">Render Directional 2D Shadows");
+
+ //make list of occluders
+ int occ_cullded = 0;
+ for (Map<RID, Viewport::CanvasData>::Element *E = p_viewport->canvas_map.front(); E; E = E->next()) {
+ RenderingServerCanvas::Canvas *canvas = static_cast<RenderingServerCanvas::Canvas *>(E->get().canvas);
+ Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E->get(), clip_rect.size);
+
+ for (Set<RasterizerCanvas::LightOccluderInstance *>::Element *F = canvas->occluders.front(); F; F = F->next()) {
+ if (!F->get()->enabled) {
+ continue;
+ }
+ F->get()->xform_cache = xf * F->get()->xform;
+ Transform2D localizer = F->get()->xform_cache.affine_inverse();
+
+ for (int j = 0; j < point_count; j++) {
+ xf_points[j] = localizer.xform(points[j]);
+ }
+ if (F->get()->aabb_cache.intersects_filled_polygon(xf_points, point_count)) {
+ F->get()->next = occluders;
+ occluders = F->get();
+ occ_cullded++;
+ }
+ }
+ }
+
+ RSG::canvas_render->light_update_directional_shadow(light->light_internal, shadow_count++, light->xform_cache, light->item_shadow_mask, cull_distance, clip_rect, occluders);
+
+ light = light->shadows_next_ptr;
+ }
+
+ //RSG::canvas_render->reset_canvas();
+ RENDER_TIMESTAMP("<Render Directional 2D Shadows");
+ }
+
if (scenario_draw_canvas_bg && canvas_map.front() && canvas_map.front()->key().get_layer() > scenario_canvas_max_layer) {
if (!can_draw_3d) {
RSG::scene->render_empty_scene(p_viewport->render_buffers, p_viewport->scenario, p_viewport->shadow_atlas);
@@ -245,6 +359,7 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface::
Transform2D xform = _canvas_get_transform(p_viewport, canvas, E->get(), clip_rect.size);
RasterizerCanvas::Light *canvas_lights = nullptr;
+ RasterizerCanvas::Light *canvas_directional_lights = nullptr;
RasterizerCanvas::Light *ptr = lights;
while (ptr) {
@@ -255,7 +370,16 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface::
ptr = ptr->filter_next_ptr;
}
- RSG::canvas->render_canvas(p_viewport->render_target, canvas, xform, canvas_lights, lights_with_mask, clip_rect, p_viewport->texture_filter, p_viewport->texture_repeat);
+ ptr = directional_lights;
+ while (ptr) {
+ if (E->get()->layer >= ptr->layer_min && E->get()->layer <= ptr->layer_max) {
+ ptr->next_ptr = canvas_directional_lights;
+ canvas_directional_lights = ptr;
+ }
+ ptr = ptr->filter_next_ptr;
+ }
+
+ RSG::canvas->render_canvas(p_viewport->render_target, canvas, xform, canvas_lights, canvas_directional_lights, clip_rect, p_viewport->texture_filter, p_viewport->texture_repeat, p_viewport->snap_2d_transforms_to_pixel, p_viewport->snap_2d_vertices_to_pixel);
i++;
if (scenario_draw_canvas_bg && E->key().get_layer() >= scenario_canvas_max_layer) {
@@ -774,6 +898,18 @@ float RenderingServerViewport::viewport_get_measured_render_time_gpu(RID p_viewp
return double((viewport->time_gpu_end - viewport->time_gpu_begin) / 1000) / 1000.0;
}
+void RenderingServerViewport::viewport_set_snap_2d_transforms_to_pixel(RID p_viewport, bool p_enabled) {
+ Viewport *viewport = viewport_owner.getornull(p_viewport);
+ ERR_FAIL_COND(!viewport);
+ viewport->snap_2d_transforms_to_pixel = p_enabled;
+}
+
+void RenderingServerViewport::viewport_set_snap_2d_vertices_to_pixel(RID p_viewport, bool p_enabled) {
+ Viewport *viewport = viewport_owner.getornull(p_viewport);
+ ERR_FAIL_COND(!viewport);
+ viewport->snap_2d_vertices_to_pixel = p_enabled;
+}
+
void RenderingServerViewport::viewport_set_default_canvas_item_texture_filter(RID p_viewport, RS::CanvasItemTextureFilter p_filter) {
ERR_FAIL_COND_MSG(p_filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, "Viewport does not accept DEFAULT as texture filter (it's the topmost choice already).)");
Viewport *viewport = viewport_owner.getornull(p_viewport);
diff --git a/servers/rendering/rendering_server_viewport.h b/servers/rendering/rendering_server_viewport.h
index 161ae94fb0..081f63690b 100644
--- a/servers/rendering/rendering_server_viewport.h
+++ b/servers/rendering/rendering_server_viewport.h
@@ -31,8 +31,8 @@
#ifndef VISUALSERVERVIEWPORT_H
#define VISUALSERVERVIEWPORT_H
-#include "core/rid_owner.h"
-#include "core/self_list.h"
+#include "core/templates/rid_owner.h"
+#include "core/templates/self_list.h"
#include "rasterizer.h"
#include "servers/rendering_server.h"
#include "servers/xr/xr_interface.h"
@@ -70,6 +70,9 @@ public:
bool disable_environment;
bool measure_render_time;
+ bool snap_2d_transforms_to_pixel;
+ bool snap_2d_vertices_to_pixel;
+
uint64_t time_cpu_begin;
uint64_t time_cpu_end;
@@ -136,6 +139,9 @@ public:
screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED;
use_debanding = false;
+ snap_2d_transforms_to_pixel = false;
+ snap_2d_vertices_to_pixel = false;
+
for (int i = 0; i < RS::VIEWPORT_RENDER_INFO_MAX; i++) {
render_info[i] = 0;
}
@@ -220,6 +226,9 @@ public:
float viewport_get_measured_render_time_cpu(RID p_viewport) const;
float viewport_get_measured_render_time_gpu(RID p_viewport) const;
+ void viewport_set_snap_2d_transforms_to_pixel(RID p_viewport, bool p_enabled);
+ void viewport_set_snap_2d_vertices_to_pixel(RID p_viewport, bool p_enabled);
+
void viewport_set_default_canvas_item_texture_filter(RID p_viewport, RS::CanvasItemTextureFilter p_filter);
void viewport_set_default_canvas_item_texture_repeat(RID p_viewport, RS::CanvasItemTextureRepeat p_repeat);
diff --git a/servers/rendering/rendering_server_wrap_mt.cpp b/servers/rendering/rendering_server_wrap_mt.cpp
index ab9856e06e..40ad228fd0 100644
--- a/servers/rendering/rendering_server_wrap_mt.cpp
+++ b/servers/rendering/rendering_server_wrap_mt.cpp
@@ -29,8 +29,8 @@
/*************************************************************************/
#include "rendering_server_wrap_mt.h"
+#include "core/config/project_settings.h"
#include "core/os/os.h"
-#include "core/project_settings.h"
#include "servers/display_server.h"
void RenderingServerWrapMT::thread_exit() {
diff --git a/servers/rendering/rendering_server_wrap_mt.h b/servers/rendering/rendering_server_wrap_mt.h
index 1836f99c99..d27b851d1d 100644
--- a/servers/rendering/rendering_server_wrap_mt.h
+++ b/servers/rendering/rendering_server_wrap_mt.h
@@ -31,8 +31,8 @@
#ifndef RENDERING_SERVER_WRAP_MT_H
#define RENDERING_SERVER_WRAP_MT_H
-#include "core/command_queue_mt.h"
#include "core/os/thread.h"
+#include "core/templates/command_queue_mt.h"
#include "servers/rendering_server.h"
class RenderingServerWrapMT : public RenderingServer {
@@ -431,6 +431,8 @@ public:
FUNC2(viewport_remove_canvas, RID, RID)
FUNC3(viewport_set_canvas_transform, RID, RID, const Transform2D &)
FUNC2(viewport_set_transparent_background, RID, bool)
+ FUNC2(viewport_set_snap_2d_transforms_to_pixel, RID, bool)
+ FUNC2(viewport_set_snap_2d_vertices_to_pixel, RID, bool)
FUNC2(viewport_set_default_canvas_item_texture_filter, RID, CanvasItemTextureFilter)
FUNC2(viewport_set_default_canvas_item_texture_repeat, RID, CanvasItemTextureRepeat)
@@ -642,10 +644,15 @@ public:
FUNC2(canvas_item_set_use_parent_material, RID, bool)
+ FUNC6(canvas_item_set_canvas_group_mode, RID, CanvasGroupMode, float, bool, float, bool)
+
FUNC0R(RID, canvas_light_create)
+
+ FUNC2(canvas_light_set_mode, RID, CanvasLightMode)
+
FUNC2(canvas_light_attach_to_canvas, RID, RID)
FUNC2(canvas_light_set_enabled, RID, bool)
- FUNC2(canvas_light_set_scale, RID, float)
+ FUNC2(canvas_light_set_texture_scale, RID, float)
FUNC2(canvas_light_set_transform, RID, const Transform2D &)
FUNC2(canvas_light_set_texture, RID, RID)
FUNC2(canvas_light_set_texture_offset, RID, const Vector2 &)
@@ -656,8 +663,9 @@ public:
FUNC3(canvas_light_set_layer_range, RID, int, int)
FUNC2(canvas_light_set_item_cull_mask, RID, int)
FUNC2(canvas_light_set_item_shadow_cull_mask, RID, int)
+ FUNC2(canvas_light_set_directional_distance, RID, float)
- FUNC2(canvas_light_set_mode, RID, CanvasLightMode)
+ FUNC2(canvas_light_set_blend_mode, RID, CanvasLightBlendMode)
FUNC2(canvas_light_set_shadow_enabled, RID, bool)
FUNC2(canvas_light_set_shadow_filter, RID, CanvasLightShadowFilter)
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index 1883b6b338..046c6ba580 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -30,7 +30,7 @@
#include "shader_language.h"
#include "core/os/os.h"
-#include "core/print_string.h"
+#include "core/string/print_string.h"
#include "servers/rendering_server.h"
static bool _is_text_char(char32_t c) {
diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h
index 3c0a10809b..3a9f408dc0 100644
--- a/servers/rendering/shader_language.h
+++ b/servers/rendering/shader_language.h
@@ -31,13 +31,13 @@
#ifndef SHADER_LANGUAGE_H
#define SHADER_LANGUAGE_H
-#include "core/list.h"
-#include "core/map.h"
-#include "core/script_language.h"
-#include "core/string_name.h"
+#include "core/object/script_language.h"
+#include "core/string/string_name.h"
+#include "core/string/ustring.h"
+#include "core/templates/list.h"
+#include "core/templates/map.h"
#include "core/typedefs.h"
-#include "core/ustring.h"
-#include "core/variant.h"
+#include "core/variant/variant.h"
class ShaderLanguage {
public:
diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp
index 48eaf1dd13..4d21807735 100644
--- a/servers/rendering/shader_types.cpp
+++ b/servers/rendering/shader_types.cpp
@@ -134,6 +134,11 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["IRRADIANCE"] = ShaderLanguage::TYPE_VEC4;
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].can_discard = true;
+ shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["ALPHA_SCISSOR_THRESHOLD"] = ShaderLanguage::TYPE_FLOAT;
+ shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["ALPHA_HASH_SCALE"] = ShaderLanguage::TYPE_FLOAT;
+ shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["ALPHA_ANTIALIASING_EDGE"] = ShaderLanguage::TYPE_FLOAT;
+ shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["ALPHA_TEXTURE_COORDINATE"] = ShaderLanguage::TYPE_VEC2;
+
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["WORLD_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["INV_CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
@@ -206,6 +211,9 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SPATIAL].modes.push_back("vertex_lighting");
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back("alpha_to_coverage");
+ shader_modes[RS::SHADER_SPATIAL].modes.push_back("alpha_to_coverage_and_one");
+
/************ CANVAS ITEM **************************/
shader_modes[RS::SHADER_CANVAS_ITEM].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
diff --git a/servers/rendering/shader_types.h b/servers/rendering/shader_types.h
index 7d8057a5c6..50f910babb 100644
--- a/servers/rendering/shader_types.h
+++ b/servers/rendering/shader_types.h
@@ -31,7 +31,7 @@
#ifndef SHADERTYPES_H
#define SHADERTYPES_H
-#include "core/ordered_hash_map.h"
+#include "core/templates/ordered_hash_map.h"
#include "servers/rendering_server.h"
#include "shader_language.h"