mirror of
https://github.com/godotengine/godot.git
synced 2024-11-22 04:06:14 +00:00
Implement signed distance fields for 2D shaders
This commit is contained in:
parent
4e5625ce30
commit
1bcf3c305b
@ -511,6 +511,11 @@ void EditorNode::_notification(int p_what) {
|
||||
scene_root->set_snap_2d_transforms_to_pixel(snap_2d_transforms);
|
||||
bool snap_2d_vertices = GLOBAL_GET("rendering/quality/2d/snap_2d_vertices_to_pixel");
|
||||
scene_root->set_snap_2d_vertices_to_pixel(snap_2d_vertices);
|
||||
|
||||
Viewport::SDFOversize sdf_oversize = Viewport::SDFOversize(int(GLOBAL_GET("rendering/quality/2d_sdf/oversize")));
|
||||
scene_root->set_sdf_oversize(sdf_oversize);
|
||||
Viewport::SDFScale sdf_scale = Viewport::SDFScale(int(GLOBAL_GET("rendering/quality/2d_sdf/scale")));
|
||||
scene_root->set_sdf_scale(sdf_scale);
|
||||
}
|
||||
|
||||
ResourceImporterTexture::get_singleton()->update_imports();
|
||||
|
@ -265,6 +265,14 @@ String LightOccluder2D::get_configuration_warning() const {
|
||||
return warning;
|
||||
}
|
||||
|
||||
void LightOccluder2D::set_as_sdf_collision(bool p_enable) {
|
||||
sdf_collision = p_enable;
|
||||
RS::get_singleton()->canvas_light_occluder_set_as_sdf_collision(occluder, sdf_collision);
|
||||
}
|
||||
bool LightOccluder2D::is_set_as_sdf_collision() const {
|
||||
return sdf_collision;
|
||||
}
|
||||
|
||||
void LightOccluder2D::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_occluder_polygon", "polygon"), &LightOccluder2D::set_occluder_polygon);
|
||||
ClassDB::bind_method(D_METHOD("get_occluder_polygon"), &LightOccluder2D::get_occluder_polygon);
|
||||
@ -272,14 +280,20 @@ void LightOccluder2D::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_occluder_light_mask", "mask"), &LightOccluder2D::set_occluder_light_mask);
|
||||
ClassDB::bind_method(D_METHOD("get_occluder_light_mask"), &LightOccluder2D::get_occluder_light_mask);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_as_sdf_collision", "enable"), &LightOccluder2D::set_as_sdf_collision);
|
||||
ClassDB::bind_method(D_METHOD("is_set_as_sdf_collision"), &LightOccluder2D::is_set_as_sdf_collision);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "occluder", PROPERTY_HINT_RESOURCE_TYPE, "OccluderPolygon2D"), "set_occluder_polygon", "get_occluder_polygon");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sdf_collision"), "set_as_sdf_collision", "is_set_as_sdf_collision");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "light_mask", PROPERTY_HINT_LAYERS_2D_RENDER), "set_occluder_light_mask", "get_occluder_light_mask");
|
||||
}
|
||||
|
||||
LightOccluder2D::LightOccluder2D() {
|
||||
occluder = RS::get_singleton()->canvas_light_occluder_create();
|
||||
mask = 1;
|
||||
|
||||
set_notify_transform(true);
|
||||
set_as_sdf_collision(true);
|
||||
}
|
||||
|
||||
LightOccluder2D::~LightOccluder2D() {
|
||||
|
@ -84,7 +84,7 @@ class LightOccluder2D : public Node2D {
|
||||
bool enabled;
|
||||
int mask;
|
||||
Ref<OccluderPolygon2D> occluder_polygon;
|
||||
|
||||
bool sdf_collision;
|
||||
void _poly_changed();
|
||||
|
||||
protected:
|
||||
@ -103,6 +103,9 @@ public:
|
||||
void set_occluder_light_mask(int p_mask);
|
||||
int get_occluder_light_mask() const;
|
||||
|
||||
void set_as_sdf_collision(bool p_enable);
|
||||
bool is_set_as_sdf_collision() const;
|
||||
|
||||
String get_configuration_warning() const override;
|
||||
|
||||
LightOccluder2D();
|
||||
|
@ -1397,6 +1397,14 @@ SceneTree::SceneTree() {
|
||||
bool snap_2d_vertices = GLOBAL_DEF("rendering/quality/2d/snap_2d_vertices_to_pixel", false);
|
||||
root->set_snap_2d_vertices_to_pixel(snap_2d_vertices);
|
||||
|
||||
Viewport::SDFOversize sdf_oversize = Viewport::SDFOversize(int(GLOBAL_DEF("rendering/quality/2d_sdf/oversize", 1)));
|
||||
root->set_sdf_oversize(sdf_oversize);
|
||||
Viewport::SDFScale sdf_scale = Viewport::SDFScale(int(GLOBAL_DEF("rendering/quality/2d_sdf/scale", 1)));
|
||||
root->set_sdf_scale(sdf_scale);
|
||||
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/2d_sdf/oversize", PropertyInfo(Variant::INT, "rendering/quality/2d_sdf/oversize", PROPERTY_HINT_ENUM, "100%,120%,150%,200%"));
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/2d_sdf/scale", PropertyInfo(Variant::INT, "rendering/quality/2d_sdf/scale", PROPERTY_HINT_ENUM, "100%,50%,25%"));
|
||||
|
||||
{ //load default fallback environment
|
||||
//get possible extensions
|
||||
List<String> exts;
|
||||
|
@ -3383,6 +3383,24 @@ void Viewport::pass_mouse_focus_to(Viewport *p_viewport, Control *p_control) {
|
||||
}
|
||||
}
|
||||
|
||||
void Viewport::set_sdf_oversize(SDFOversize p_sdf_oversize) {
|
||||
ERR_FAIL_INDEX(p_sdf_oversize, SDF_OVERSIZE_MAX);
|
||||
sdf_oversize = p_sdf_oversize;
|
||||
RS::get_singleton()->viewport_set_sdf_oversize_and_scale(viewport, RS::ViewportSDFOversize(sdf_oversize), RS::ViewportSDFScale(sdf_scale));
|
||||
}
|
||||
Viewport::SDFOversize Viewport::get_sdf_oversize() const {
|
||||
return sdf_oversize;
|
||||
}
|
||||
|
||||
void Viewport::set_sdf_scale(SDFScale p_sdf_scale) {
|
||||
ERR_FAIL_INDEX(p_sdf_scale, SDF_SCALE_MAX);
|
||||
sdf_scale = p_sdf_scale;
|
||||
RS::get_singleton()->viewport_set_sdf_oversize_and_scale(viewport, RS::ViewportSDFOversize(sdf_oversize), RS::ViewportSDFScale(sdf_scale));
|
||||
}
|
||||
Viewport::SDFScale Viewport::get_sdf_scale() const {
|
||||
return sdf_scale;
|
||||
}
|
||||
|
||||
void Viewport::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_world_2d", "world_2d"), &Viewport::set_world_2d);
|
||||
ClassDB::bind_method(D_METHOD("get_world_2d"), &Viewport::get_world_2d);
|
||||
@ -3482,6 +3500,12 @@ void Viewport::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_default_canvas_item_texture_repeat", "mode"), &Viewport::set_default_canvas_item_texture_repeat);
|
||||
ClassDB::bind_method(D_METHOD("get_default_canvas_item_texture_repeat"), &Viewport::get_default_canvas_item_texture_repeat);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_sdf_oversize", "oversize"), &Viewport::set_sdf_oversize);
|
||||
ClassDB::bind_method(D_METHOD("get_sdf_oversize"), &Viewport::get_sdf_oversize);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_sdf_scale", "scale"), &Viewport::set_sdf_scale);
|
||||
ClassDB::bind_method(D_METHOD("get_sdf_scale"), &Viewport::get_sdf_scale);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "own_world_3d"), "set_use_own_world_3d", "is_using_own_world_3d");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "world_3d", PROPERTY_HINT_RESOURCE_TYPE, "World3D"), "set_world_3d", "get_world_3d");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "world_2d", PROPERTY_HINT_RESOURCE_TYPE, "World2D", 0), "set_world_2d", "get_world_2d");
|
||||
@ -3506,6 +3530,9 @@ void Viewport::_bind_methods() {
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gui_disable_input"), "set_disable_input", "is_input_disabled");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gui_snap_controls_to_pixels"), "set_snap_controls_to_pixels", "is_snap_controls_to_pixels_enabled");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gui_embed_subwindows"), "set_embed_subwindows_hint", "get_embed_subwindows_hint");
|
||||
ADD_GROUP("SDF", "sdf_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "sdf_oversize", PROPERTY_HINT_ENUM, "100%,120%,150%,200%"), "set_sdf_oversize", "get_sdf_oversize");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "sdf_scale", PROPERTY_HINT_ENUM, "100%,50%,25%"), "set_sdf_scale", "get_sdf_scale");
|
||||
ADD_GROUP("Shadow Atlas", "shadow_atlas_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_atlas_size"), "set_shadow_atlas_size", "get_shadow_atlas_size");
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::INT, "shadow_atlas_quad_0", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), "set_shadow_atlas_quadrant_subdiv", "get_shadow_atlas_quadrant_subdiv", 0);
|
||||
@ -3575,6 +3602,17 @@ void Viewport::_bind_methods() {
|
||||
BIND_ENUM_CONSTANT(DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
|
||||
BIND_ENUM_CONSTANT(DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_MIRROR);
|
||||
BIND_ENUM_CONSTANT(DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_MAX);
|
||||
|
||||
BIND_ENUM_CONSTANT(SDF_OVERSIZE_100_PERCENT);
|
||||
BIND_ENUM_CONSTANT(SDF_OVERSIZE_120_PERCENT);
|
||||
BIND_ENUM_CONSTANT(SDF_OVERSIZE_150_PERCENT);
|
||||
BIND_ENUM_CONSTANT(SDF_OVERSIZE_200_PERCENT);
|
||||
BIND_ENUM_CONSTANT(SDF_OVERSIZE_MAX);
|
||||
|
||||
BIND_ENUM_CONSTANT(SDF_SCALE_100_PERCENT);
|
||||
BIND_ENUM_CONSTANT(SDF_SCALE_50_PERCENT);
|
||||
BIND_ENUM_CONSTANT(SDF_SCALE_25_PERCENT);
|
||||
BIND_ENUM_CONSTANT(SDF_SCALE_MAX);
|
||||
}
|
||||
|
||||
Viewport::Viewport() {
|
||||
@ -3661,6 +3699,10 @@ Viewport::Viewport() {
|
||||
|
||||
default_canvas_item_texture_filter = DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_LINEAR;
|
||||
default_canvas_item_texture_repeat = DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_DISABLED;
|
||||
|
||||
sdf_oversize = SDF_OVERSIZE_120_PERCENT;
|
||||
sdf_scale = SDF_SCALE_50_PERCENT;
|
||||
set_sdf_oversize(SDF_OVERSIZE_120_PERCENT); //set to server
|
||||
}
|
||||
|
||||
Viewport::~Viewport() {
|
||||
|
@ -159,6 +159,21 @@ public:
|
||||
DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_MAX,
|
||||
};
|
||||
|
||||
enum SDFOversize {
|
||||
SDF_OVERSIZE_100_PERCENT,
|
||||
SDF_OVERSIZE_120_PERCENT,
|
||||
SDF_OVERSIZE_150_PERCENT,
|
||||
SDF_OVERSIZE_200_PERCENT,
|
||||
SDF_OVERSIZE_MAX
|
||||
};
|
||||
|
||||
enum SDFScale {
|
||||
SDF_SCALE_100_PERCENT,
|
||||
SDF_SCALE_50_PERCENT,
|
||||
SDF_SCALE_25_PERCENT,
|
||||
SDF_SCALE_MAX
|
||||
};
|
||||
|
||||
enum {
|
||||
SUBWINDOW_CANVAS_LAYER = 1024
|
||||
};
|
||||
@ -285,6 +300,9 @@ private:
|
||||
Ref<ViewportTexture> default_texture;
|
||||
Set<ViewportTexture *> viewport_textures;
|
||||
|
||||
SDFOversize sdf_oversize;
|
||||
SDFScale sdf_scale;
|
||||
|
||||
enum SubWindowDrag {
|
||||
SUB_WINDOW_DRAG_DISABLED,
|
||||
SUB_WINDOW_DRAG_MOVE,
|
||||
@ -572,6 +590,12 @@ public:
|
||||
|
||||
bool gui_is_dragging() const;
|
||||
|
||||
void set_sdf_oversize(SDFOversize p_sdf_oversize);
|
||||
SDFOversize get_sdf_oversize() const;
|
||||
|
||||
void set_sdf_scale(SDFScale p_sdf_scale);
|
||||
SDFScale get_sdf_scale() const;
|
||||
|
||||
void set_default_canvas_item_texture_filter(DefaultCanvasItemTextureFilter p_filter);
|
||||
DefaultCanvasItemTextureFilter get_default_canvas_item_texture_filter() const;
|
||||
|
||||
@ -650,6 +674,8 @@ VARIANT_ENUM_CAST(Viewport::ShadowAtlasQuadrantSubdiv);
|
||||
VARIANT_ENUM_CAST(Viewport::MSAA);
|
||||
VARIANT_ENUM_CAST(Viewport::ScreenSpaceAA);
|
||||
VARIANT_ENUM_CAST(Viewport::DebugDraw);
|
||||
VARIANT_ENUM_CAST(Viewport::SDFScale);
|
||||
VARIANT_ENUM_CAST(Viewport::SDFOversize);
|
||||
VARIANT_ENUM_CAST(SubViewport::ClearMode);
|
||||
VARIANT_ENUM_CAST(Viewport::RenderInfo);
|
||||
VARIANT_ENUM_CAST(Viewport::DefaultCanvasItemTextureFilter);
|
||||
|
@ -752,6 +752,9 @@ public:
|
||||
virtual void render_target_disable_clear_request(RID p_render_target) = 0;
|
||||
virtual void render_target_do_clear_request(RID p_render_target) = 0;
|
||||
|
||||
virtual void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) = 0;
|
||||
virtual Rect2i render_target_get_sdf_rect(RID p_render_target) const = 0;
|
||||
|
||||
virtual RS::InstanceType get_base_type(RID p_rid) const = 0;
|
||||
virtual bool free(RID p_rid) = 0;
|
||||
|
||||
@ -1324,7 +1327,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
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_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, bool &r_sdf_used) = 0;
|
||||
virtual void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) = 0;
|
||||
|
||||
struct LightOccluderInstance {
|
||||
@ -1336,12 +1339,14 @@ public:
|
||||
Transform2D xform;
|
||||
Transform2D xform_cache;
|
||||
int light_mask;
|
||||
bool sdf_collision;
|
||||
RS::CanvasOccluderPolygonCullMode cull_cache;
|
||||
|
||||
LightOccluderInstance *next;
|
||||
|
||||
LightOccluderInstance() {
|
||||
enabled = true;
|
||||
sdf_collision = false;
|
||||
next = nullptr;
|
||||
light_mask = 1;
|
||||
cull_cache = RS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED;
|
||||
@ -1354,8 +1359,10 @@ public:
|
||||
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 void render_sdf(RID p_render_target, 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;
|
||||
virtual void occluder_polygon_set_shape(RID p_occluder, const Vector<Vector2> &p_points, bool p_closed) = 0;
|
||||
virtual void occluder_polygon_set_cull_mode(RID p_occluder, RS::CanvasOccluderPolygonCullMode p_mode) = 0;
|
||||
virtual void set_shadow_texture_size(int p_size) = 0;
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
|
||||
#include "rasterizer_canvas_rd.h"
|
||||
#include "core/config/project_settings.h"
|
||||
#include "core/math/geometry_2d.h"
|
||||
#include "core/math/math_funcs.h"
|
||||
#include "rasterizer_rd.h"
|
||||
|
||||
@ -1050,11 +1051,20 @@ RID RasterizerCanvasRD::_create_base_uniform_set(RID p_to_render_target, bool p_
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
|
||||
{
|
||||
RD::Uniform u;
|
||||
u.type = RD::UNIFORM_TYPE_TEXTURE;
|
||||
u.binding = 7;
|
||||
RID sdf = storage->render_target_get_sdf_texture(p_to_render_target);
|
||||
u.ids.push_back(sdf);
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
|
||||
{
|
||||
//needs samplers for the material (uses custom textures) create them
|
||||
RD::Uniform u;
|
||||
u.type = RD::UNIFORM_TYPE_SAMPLER;
|
||||
u.binding = 7;
|
||||
u.binding = 8;
|
||||
u.ids.resize(12);
|
||||
RID *ids_ptr = u.ids.ptrw();
|
||||
ids_ptr[0] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
@ -1075,7 +1085,7 @@ RID RasterizerCanvasRD::_create_base_uniform_set(RID p_to_render_target, bool p_
|
||||
{
|
||||
RD::Uniform u;
|
||||
u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
|
||||
u.binding = 8;
|
||||
u.binding = 9;
|
||||
u.ids.push_back(storage->global_variables_get_storage_buffer());
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
@ -1182,7 +1192,8 @@ void RasterizerCanvasRD::_render_items(RID p_to_render_target, int p_item_count,
|
||||
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, 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) {
|
||||
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, bool &r_sdf_used) {
|
||||
r_sdf_used = false;
|
||||
int item_count = 0;
|
||||
|
||||
//setup canvas state uniforms if needed
|
||||
@ -1365,6 +1376,25 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite
|
||||
|
||||
state_buffer.directional_light_count = directional_light_count;
|
||||
|
||||
Vector2 canvas_scale = p_canvas_transform.get_scale();
|
||||
|
||||
state_buffer.sdf_to_screen[0] = render_target_size.width / canvas_scale.x;
|
||||
state_buffer.sdf_to_screen[1] = render_target_size.height / canvas_scale.y;
|
||||
|
||||
state_buffer.screen_to_sdf[0] = 1.0 / state_buffer.sdf_to_screen[0];
|
||||
state_buffer.screen_to_sdf[1] = 1.0 / state_buffer.sdf_to_screen[1];
|
||||
|
||||
Rect2 sdf_rect = storage->render_target_get_sdf_rect(p_to_render_target);
|
||||
Rect2 sdf_tex_rect(sdf_rect.position / canvas_scale, sdf_rect.size / canvas_scale);
|
||||
|
||||
state_buffer.sdf_to_tex[0] = 1.0 / sdf_tex_rect.size.width;
|
||||
state_buffer.sdf_to_tex[1] = 1.0 / sdf_tex_rect.size.height;
|
||||
state_buffer.sdf_to_tex[2] = -sdf_tex_rect.position.x / sdf_tex_rect.size.width;
|
||||
state_buffer.sdf_to_tex[3] = -sdf_tex_rect.position.y / sdf_tex_rect.size.height;
|
||||
|
||||
//print_line("w: " + itos(ssize.width) + " s: " + rtos(canvas_scale));
|
||||
state_buffer.tex_to_sdf = 1.0 / ((canvas_scale.x + canvas_scale.y) * 0.5);
|
||||
|
||||
RD::get_singleton()->buffer_update(state.canvas_state_buffer, 0, sizeof(State::Buffer), &state_buffer, true);
|
||||
}
|
||||
|
||||
@ -1402,6 +1432,9 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite
|
||||
}
|
||||
}
|
||||
|
||||
if (md->shader_data->uses_sdf) {
|
||||
r_sdf_used = true;
|
||||
}
|
||||
if (md->last_frame != RasterizerRD::singleton->get_frame_number()) {
|
||||
md->last_frame = RasterizerRD::singleton->get_frame_number();
|
||||
if (!RD::get_singleton()->uniform_set_is_valid(md->uniform_set)) {
|
||||
@ -1687,18 +1720,102 @@ void RasterizerCanvasRD::light_update_directional_shadow(RID p_rid, int p_shadow
|
||||
cl->shadow.directional_xform = to_shadow * to_light_xform;
|
||||
}
|
||||
|
||||
void RasterizerCanvasRD::render_sdf(RID p_render_target, LightOccluderInstance *p_occluders) {
|
||||
RID fb = storage->render_target_get_sdf_framebuffer(p_render_target);
|
||||
Rect2i rect = storage->render_target_get_sdf_rect(p_render_target);
|
||||
|
||||
Transform2D to_sdf;
|
||||
to_sdf.elements[0] *= rect.size.width;
|
||||
to_sdf.elements[1] *= rect.size.height;
|
||||
to_sdf.elements[2] = rect.position;
|
||||
|
||||
Transform2D to_clip;
|
||||
to_clip.elements[0] *= 2.0;
|
||||
to_clip.elements[1] *= 2.0;
|
||||
to_clip.elements[2] = -Vector2(1.0, 1.0);
|
||||
|
||||
to_clip = to_clip * to_sdf.affine_inverse();
|
||||
|
||||
Vector<Color> cc;
|
||||
cc.push_back(Color(0, 0, 0, 0));
|
||||
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, cc);
|
||||
|
||||
CameraMatrix projection;
|
||||
|
||||
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] = 0.0;
|
||||
push_constant.z_far = 0;
|
||||
push_constant.pad = 0;
|
||||
|
||||
LightOccluderInstance *instance = p_occluders;
|
||||
|
||||
while (instance) {
|
||||
OccluderPolygon *co = occluder_polygon_owner.getornull(instance->occluder);
|
||||
|
||||
if (!co || co->sdf_index_array.is_null()) {
|
||||
instance = instance->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
_update_transform_2d_to_mat2x4(to_clip * instance->xform_cache, push_constant.modelview);
|
||||
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, shadow_render.sdf_render_pipelines[co->sdf_is_lines ? SHADOW_RENDER_SDF_LINES : SHADOW_RENDER_SDF_TRIANGLES]);
|
||||
RD::get_singleton()->draw_list_bind_vertex_array(draw_list, co->sdf_vertex_array);
|
||||
RD::get_singleton()->draw_list_bind_index_array(draw_list, co->sdf_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();
|
||||
|
||||
storage->render_target_sdf_process(p_render_target); //done rendering, process it
|
||||
}
|
||||
|
||||
RID RasterizerCanvasRD::occluder_polygon_create() {
|
||||
OccluderPolygon occluder;
|
||||
occluder.point_count = 0;
|
||||
occluder.line_point_count = 0;
|
||||
occluder.sdf_point_count = 0;
|
||||
occluder.sdf_index_count = 0;
|
||||
occluder.cull_mode = RS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED;
|
||||
return occluder_polygon_owner.make_rid(occluder);
|
||||
}
|
||||
|
||||
void RasterizerCanvasRD::occluder_polygon_set_shape_as_lines(RID p_occluder, const Vector<Vector2> &p_lines) {
|
||||
void RasterizerCanvasRD::occluder_polygon_set_shape(RID p_occluder, const Vector<Vector2> &p_points, bool p_closed) {
|
||||
OccluderPolygon *oc = occluder_polygon_owner.getornull(p_occluder);
|
||||
ERR_FAIL_COND(!oc);
|
||||
|
||||
if (oc->point_count != p_lines.size() && oc->vertex_array.is_valid()) {
|
||||
Vector<Vector2> lines;
|
||||
int lc = p_points.size() * 2;
|
||||
|
||||
lines.resize(lc - (p_closed ? 0 : 2));
|
||||
{
|
||||
Vector2 *w = lines.ptrw();
|
||||
const Vector2 *r = p_points.ptr();
|
||||
|
||||
int max = lc / 2;
|
||||
if (!p_closed) {
|
||||
max--;
|
||||
}
|
||||
for (int i = 0; i < max; i++) {
|
||||
Vector2 a = r[i];
|
||||
Vector2 b = r[(i + 1) % (lc / 2)];
|
||||
w[i * 2 + 0] = a;
|
||||
w[i * 2 + 1] = b;
|
||||
}
|
||||
}
|
||||
|
||||
if (oc->line_point_count != lines.size() && oc->vertex_array.is_valid()) {
|
||||
RD::get_singleton()->free(oc->vertex_array);
|
||||
RD::get_singleton()->free(oc->vertex_buffer);
|
||||
RD::get_singleton()->free(oc->index_array);
|
||||
@ -1708,12 +1825,14 @@ void RasterizerCanvasRD::occluder_polygon_set_shape_as_lines(RID p_occluder, con
|
||||
oc->vertex_buffer = RID();
|
||||
oc->index_array = RID();
|
||||
oc->index_buffer = RID();
|
||||
|
||||
oc->line_point_count = lines.size();
|
||||
}
|
||||
|
||||
if (p_lines.size()) {
|
||||
if (lines.size()) {
|
||||
Vector<uint8_t> geometry;
|
||||
Vector<uint8_t> indices;
|
||||
int lc = p_lines.size();
|
||||
lc = lines.size();
|
||||
|
||||
geometry.resize(lc * 6 * sizeof(float));
|
||||
indices.resize(lc * 3 * sizeof(uint16_t));
|
||||
@ -1724,7 +1843,7 @@ void RasterizerCanvasRD::occluder_polygon_set_shape_as_lines(RID p_occluder, con
|
||||
uint8_t *iw = indices.ptrw();
|
||||
uint16_t *iwptr = (uint16_t *)iw;
|
||||
|
||||
const Vector2 *lr = p_lines.ptr();
|
||||
const Vector2 *lr = lines.ptr();
|
||||
|
||||
const int POLY_HEIGHT = 16384;
|
||||
|
||||
@ -1778,6 +1897,62 @@ void RasterizerCanvasRD::occluder_polygon_set_shape_as_lines(RID p_occluder, con
|
||||
RD::get_singleton()->buffer_update(oc->index_buffer, 0, indices.size(), ir);
|
||||
}
|
||||
}
|
||||
|
||||
// sdf
|
||||
|
||||
Vector<int> sdf_indices;
|
||||
|
||||
if (p_closed) {
|
||||
sdf_indices = Geometry2D::triangulate_polygon(p_points);
|
||||
oc->sdf_is_lines = false;
|
||||
} else {
|
||||
int max = p_points.size();
|
||||
sdf_indices.resize(max * 2);
|
||||
|
||||
int *iw = sdf_indices.ptrw();
|
||||
for (int i = 0; i < max; i++) {
|
||||
iw[i * 2 + 0] = i;
|
||||
iw[i * 2 + 1] = (i + 1) % max;
|
||||
}
|
||||
oc->sdf_is_lines = true;
|
||||
}
|
||||
|
||||
if (oc->sdf_index_count != sdf_indices.size() && oc->sdf_point_count != p_points.size() && oc->sdf_vertex_array.is_valid()) {
|
||||
RD::get_singleton()->free(oc->sdf_vertex_array);
|
||||
RD::get_singleton()->free(oc->sdf_vertex_buffer);
|
||||
RD::get_singleton()->free(oc->sdf_index_array);
|
||||
RD::get_singleton()->free(oc->sdf_index_buffer);
|
||||
|
||||
oc->sdf_vertex_array = RID();
|
||||
oc->sdf_vertex_buffer = RID();
|
||||
oc->sdf_index_array = RID();
|
||||
oc->sdf_index_buffer = RID();
|
||||
|
||||
oc->sdf_index_count = sdf_indices.size();
|
||||
oc->sdf_point_count = p_points.size();
|
||||
|
||||
oc->sdf_is_lines = false;
|
||||
}
|
||||
|
||||
if (sdf_indices.size()) {
|
||||
if (oc->sdf_vertex_array.is_null()) {
|
||||
//create from scratch
|
||||
//vertices
|
||||
oc->sdf_vertex_buffer = RD::get_singleton()->vertex_buffer_create(p_points.size() * 2 * sizeof(real_t), p_points.to_byte_array());
|
||||
oc->sdf_index_buffer = RD::get_singleton()->index_buffer_create(sdf_indices.size(), RD::INDEX_BUFFER_FORMAT_UINT32, sdf_indices.to_byte_array());
|
||||
oc->sdf_index_array = RD::get_singleton()->index_array_create(oc->sdf_index_buffer, 0, sdf_indices.size());
|
||||
|
||||
Vector<RID> buffer;
|
||||
buffer.push_back(oc->sdf_vertex_buffer);
|
||||
oc->sdf_vertex_array = RD::get_singleton()->vertex_array_create(p_points.size(), shadow_render.sdf_vertex_format, buffer);
|
||||
//indices
|
||||
|
||||
} else {
|
||||
//update existing
|
||||
RD::get_singleton()->buffer_update(oc->vertex_buffer, 0, sizeof(real_t) * 2 * p_points.size(), p_points.ptr());
|
||||
RD::get_singleton()->buffer_update(oc->index_buffer, 0, sdf_indices.size() * sizeof(int32_t), sdf_indices.ptr());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RasterizerCanvasRD::occluder_polygon_set_cull_mode(RID p_occluder, RS::CanvasOccluderPolygonCullMode p_mode) {
|
||||
@ -1794,6 +1969,7 @@ void RasterizerCanvasRD::ShaderData::set_code(const String &p_code) {
|
||||
ubo_size = 0;
|
||||
uniforms.clear();
|
||||
uses_screen_texture = false;
|
||||
uses_sdf = false;
|
||||
|
||||
if (code == String()) {
|
||||
return; //just invalid, but no error
|
||||
@ -1801,7 +1977,6 @@ void RasterizerCanvasRD::ShaderData::set_code(const String &p_code) {
|
||||
|
||||
ShaderCompilerRD::GeneratedCode gen_code;
|
||||
|
||||
int light_mode = LIGHT_MODE_NORMAL;
|
||||
int blend_mode = BLEND_MODE_MIX;
|
||||
uses_screen_texture = false;
|
||||
|
||||
@ -1814,10 +1989,8 @@ void RasterizerCanvasRD::ShaderData::set_code(const String &p_code) {
|
||||
actions.render_mode_values["blend_premul_alpha"] = Pair<int *, int>(&blend_mode, BLEND_MODE_PMALPHA);
|
||||
actions.render_mode_values["blend_disabled"] = Pair<int *, int>(&blend_mode, BLEND_MODE_DISABLED);
|
||||
|
||||
actions.render_mode_values["unshaded"] = Pair<int *, int>(&light_mode, LIGHT_MODE_UNSHADED);
|
||||
actions.render_mode_values["light_only"] = Pair<int *, int>(&light_mode, LIGHT_MODE_LIGHT_ONLY);
|
||||
|
||||
actions.usage_flag_pointers["SCREEN_TEXTURE"] = &uses_screen_texture;
|
||||
actions.usage_flag_pointers["texture_sdf"] = &uses_sdf;
|
||||
|
||||
actions.uniforms = &uniforms;
|
||||
|
||||
@ -2038,6 +2211,7 @@ Variant RasterizerCanvasRD::ShaderData::get_default_parameter(const StringName &
|
||||
RasterizerCanvasRD::ShaderData::ShaderData() {
|
||||
valid = false;
|
||||
uses_screen_texture = false;
|
||||
uses_sdf = false;
|
||||
}
|
||||
|
||||
RasterizerCanvasRD::ShaderData::~ShaderData() {
|
||||
@ -2302,6 +2476,11 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) {
|
||||
actions.renames["LIGHT"] = "light";
|
||||
actions.renames["SHADOW_MODULATE"] = "shadow_modulate";
|
||||
|
||||
actions.renames["texture_sdf"] = "texture_sdf";
|
||||
actions.renames["texture_sdf_normal"] = "texture_sdf_normal";
|
||||
actions.renames["sdf_to_screen_uv"] = "sdf_to_screen_uv";
|
||||
actions.renames["screen_uv_to_sdf"] = "screen_uv_to_sdf";
|
||||
|
||||
actions.usage_defines["COLOR"] = "#define COLOR_USED\n";
|
||||
actions.usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n";
|
||||
actions.usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n";
|
||||
@ -2311,6 +2490,8 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) {
|
||||
actions.usage_defines["LIGHT"] = "#define LIGHT_SHADER_CODE_USED\n";
|
||||
|
||||
actions.render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n";
|
||||
actions.render_mode_defines["unshaded"] = "#define MODE_UNSHADED\n";
|
||||
actions.render_mode_defines["light_only"] = "#define MODE_LIGHT_ONLY\n";
|
||||
|
||||
actions.custom_samplers["TEXTURE"] = "texture_sampler";
|
||||
actions.custom_samplers["NORMAL_TEXTURE"] = "texture_sampler";
|
||||
@ -2331,7 +2512,8 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) {
|
||||
|
||||
{ //shadow rendering
|
||||
Vector<String> versions;
|
||||
versions.push_back(String()); //no versions
|
||||
versions.push_back("\n#define MODE_SHADOW\n"); //shadow
|
||||
versions.push_back("\n#define MODE_SDF\n"); //sdf
|
||||
shadow_render.shader.initialize(versions);
|
||||
|
||||
{
|
||||
@ -2352,16 +2534,34 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) {
|
||||
shadow_render.framebuffer_format = RD::get_singleton()->framebuffer_format_create(attachments);
|
||||
}
|
||||
|
||||
{
|
||||
Vector<RD::AttachmentFormat> attachments;
|
||||
|
||||
RD::AttachmentFormat af_color;
|
||||
af_color.format = RD::DATA_FORMAT_R8_UNORM;
|
||||
af_color.usage_flags = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
|
||||
attachments.push_back(af_color);
|
||||
|
||||
shadow_render.sdf_framebuffer_format = RD::get_singleton()->framebuffer_format_create(attachments);
|
||||
}
|
||||
|
||||
//pipelines
|
||||
Vector<RD::VertexAttribute> vf;
|
||||
RD::VertexAttribute vd;
|
||||
vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT;
|
||||
vd.format = sizeof(real_t) == sizeof(float) ? RD::DATA_FORMAT_R32G32B32_SFLOAT : RD::DATA_FORMAT_R64G64B64_SFLOAT;
|
||||
vd.location = 0;
|
||||
vd.offset = 0;
|
||||
vd.stride = sizeof(float) * 3;
|
||||
vd.stride = sizeof(real_t) * 3;
|
||||
vf.push_back(vd);
|
||||
shadow_render.vertex_format = RD::get_singleton()->vertex_format_create(vf);
|
||||
|
||||
vd.format = sizeof(real_t) == sizeof(float) ? RD::DATA_FORMAT_R32G32_SFLOAT : RD::DATA_FORMAT_R64G64_SFLOAT;
|
||||
vd.stride = sizeof(real_t) * 2;
|
||||
|
||||
vf.write[0] = vd;
|
||||
shadow_render.sdf_vertex_format = RD::get_singleton()->vertex_format_create(vf);
|
||||
|
||||
shadow_render.shader_version = shadow_render.shader.version_create();
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
@ -2371,7 +2571,11 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) {
|
||||
ds.enable_depth_write = true;
|
||||
ds.enable_depth_test = true;
|
||||
ds.depth_compare_operator = RD::COMPARE_OP_LESS;
|
||||
shadow_render.render_pipelines[i] = RD::get_singleton()->render_pipeline_create(shadow_render.shader.version_get_shader(shadow_render.shader_version, 0), shadow_render.framebuffer_format, shadow_render.vertex_format, RD::RENDER_PRIMITIVE_TRIANGLES, rs, RD::PipelineMultisampleState(), ds, RD::PipelineColorBlendState::create_disabled(), 0);
|
||||
shadow_render.render_pipelines[i] = RD::get_singleton()->render_pipeline_create(shadow_render.shader.version_get_shader(shadow_render.shader_version, SHADOW_RENDER_MODE_SHADOW), shadow_render.framebuffer_format, shadow_render.vertex_format, RD::RENDER_PRIMITIVE_TRIANGLES, rs, RD::PipelineMultisampleState(), ds, RD::PipelineColorBlendState::create_disabled(), 0);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
shadow_render.sdf_render_pipelines[i] = RD::get_singleton()->render_pipeline_create(shadow_render.shader.version_get_shader(shadow_render.shader_version, SHADOW_RENDER_MODE_SDF), shadow_render.sdf_framebuffer_format, shadow_render.sdf_vertex_format, i == 0 ? RD::RENDER_PRIMITIVE_TRIANGLES : RD::RENDER_PRIMITIVE_LINES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2482,7 +2686,7 @@ bool RasterizerCanvasRD::free(RID p_rid) {
|
||||
light_set_use_shadow(p_rid, false);
|
||||
canvas_light_owner.free(p_rid);
|
||||
} else if (occluder_polygon_owner.owns(p_rid)) {
|
||||
occluder_polygon_set_shape_as_lines(p_rid, Vector<Vector2>());
|
||||
occluder_polygon_set_shape(p_rid, Vector<Vector2>(), false);
|
||||
occluder_polygon_owner.free(p_rid);
|
||||
} else {
|
||||
return false;
|
||||
|
@ -161,12 +161,6 @@ class RasterizerCanvasRD : public RasterizerCanvas {
|
||||
BLEND_MODE_DISABLED,
|
||||
};
|
||||
|
||||
enum LightMode {
|
||||
LIGHT_MODE_NORMAL,
|
||||
LIGHT_MODE_UNSHADED,
|
||||
LIGHT_MODE_LIGHT_ONLY
|
||||
};
|
||||
|
||||
bool valid;
|
||||
RID version;
|
||||
PipelineVariants pipeline_variants;
|
||||
@ -181,7 +175,8 @@ class RasterizerCanvasRD : public RasterizerCanvas {
|
||||
String code;
|
||||
Map<StringName, RID> default_texture_params;
|
||||
|
||||
bool uses_screen_texture;
|
||||
bool uses_screen_texture = false;
|
||||
bool uses_sdf = false;
|
||||
|
||||
virtual void set_code(const String &p_Code);
|
||||
virtual void set_default_texture_param(const StringName &p_name, RID p_texture);
|
||||
@ -284,11 +279,19 @@ class RasterizerCanvasRD : public RasterizerCanvas {
|
||||
|
||||
struct OccluderPolygon {
|
||||
RS::CanvasOccluderPolygonCullMode cull_mode;
|
||||
int point_count;
|
||||
int line_point_count;
|
||||
RID vertex_buffer;
|
||||
RID vertex_array;
|
||||
RID index_buffer;
|
||||
RID index_array;
|
||||
|
||||
int sdf_point_count;
|
||||
int sdf_index_count;
|
||||
RID sdf_vertex_buffer;
|
||||
RID sdf_vertex_array;
|
||||
RID sdf_index_buffer;
|
||||
RID sdf_index_array;
|
||||
bool sdf_is_lines;
|
||||
};
|
||||
|
||||
struct LightUniform {
|
||||
@ -310,12 +313,25 @@ class RasterizerCanvasRD : public RasterizerCanvas {
|
||||
|
||||
RID_Owner<OccluderPolygon> occluder_polygon_owner;
|
||||
|
||||
enum ShadowRenderMode {
|
||||
SHADOW_RENDER_MODE_SHADOW,
|
||||
SHADOW_RENDER_MODE_SDF,
|
||||
};
|
||||
|
||||
enum {
|
||||
SHADOW_RENDER_SDF_TRIANGLES,
|
||||
SHADOW_RENDER_SDF_LINES,
|
||||
};
|
||||
|
||||
struct {
|
||||
CanvasOcclusionShaderRD shader;
|
||||
RID shader_version;
|
||||
RID render_pipelines[3];
|
||||
RID sdf_render_pipelines[2];
|
||||
RD::VertexFormatID vertex_format;
|
||||
RD::VertexFormatID sdf_vertex_format;
|
||||
RD::FramebufferFormatID framebuffer_format;
|
||||
RD::FramebufferFormatID sdf_framebuffer_format;
|
||||
} shadow_render;
|
||||
|
||||
/***************/
|
||||
@ -336,8 +352,14 @@ class RasterizerCanvasRD : public RasterizerCanvas {
|
||||
float time;
|
||||
uint32_t use_pixel_snap;
|
||||
|
||||
float sdf_to_tex[4];
|
||||
float sdf_to_screen[2];
|
||||
float screen_to_sdf[2];
|
||||
|
||||
uint32_t directional_light_count;
|
||||
uint32_t pad[3];
|
||||
float tex_to_sdf;
|
||||
uint32_t pad1;
|
||||
uint32_t pad2;
|
||||
};
|
||||
|
||||
LightUniform *light_uniforms;
|
||||
@ -423,11 +445,13 @@ public:
|
||||
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);
|
||||
|
||||
virtual void render_sdf(RID p_render_target, 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_shape(RID p_occluder, const Vector<Vector2> &p_points, bool p_closed);
|
||||
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, 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_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, bool &r_sdf_used);
|
||||
|
||||
void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) {}
|
||||
|
||||
|
@ -6029,6 +6029,8 @@ void RasterizerStorageRD::_clear_render_target(RenderTarget *rt) {
|
||||
rt->backbuffer_uniform_set = RID(); //chain deleted
|
||||
}
|
||||
|
||||
_render_target_clear_sdf(rt);
|
||||
|
||||
rt->framebuffer = RID();
|
||||
rt->color = RID();
|
||||
}
|
||||
@ -6299,6 +6301,275 @@ void RasterizerStorageRD::render_target_do_clear_request(RID p_render_target) {
|
||||
rt->clear_requested = false;
|
||||
}
|
||||
|
||||
void RasterizerStorageRD::render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) {
|
||||
RenderTarget *rt = render_target_owner.getornull(p_render_target);
|
||||
ERR_FAIL_COND(!rt);
|
||||
if (rt->sdf_oversize == p_size && rt->sdf_scale == p_scale) {
|
||||
return;
|
||||
}
|
||||
|
||||
rt->sdf_oversize = p_size;
|
||||
rt->sdf_scale = p_scale;
|
||||
|
||||
_render_target_clear_sdf(rt);
|
||||
}
|
||||
|
||||
Rect2i RasterizerStorageRD::_render_target_get_sdf_rect(const RenderTarget *rt) const {
|
||||
Size2i margin;
|
||||
int scale;
|
||||
switch (rt->sdf_oversize) {
|
||||
case RS::VIEWPORT_SDF_OVERSIZE_100_PERCENT: {
|
||||
scale = 100;
|
||||
} break;
|
||||
case RS::VIEWPORT_SDF_OVERSIZE_120_PERCENT: {
|
||||
scale = 120;
|
||||
} break;
|
||||
case RS::VIEWPORT_SDF_OVERSIZE_150_PERCENT: {
|
||||
scale = 150;
|
||||
} break;
|
||||
case RS::VIEWPORT_SDF_OVERSIZE_200_PERCENT: {
|
||||
scale = 200;
|
||||
} break;
|
||||
default: {
|
||||
}
|
||||
}
|
||||
|
||||
margin = (rt->size * scale / 100) - rt->size;
|
||||
|
||||
Rect2i r(Vector2i(), rt->size);
|
||||
r.position -= margin;
|
||||
r.size += margin * 2;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
Rect2i RasterizerStorageRD::render_target_get_sdf_rect(RID p_render_target) const {
|
||||
const RenderTarget *rt = render_target_owner.getornull(p_render_target);
|
||||
ERR_FAIL_COND_V(!rt, Rect2i());
|
||||
|
||||
return _render_target_get_sdf_rect(rt);
|
||||
}
|
||||
|
||||
RID RasterizerStorageRD::render_target_get_sdf_texture(RID p_render_target) {
|
||||
RenderTarget *rt = render_target_owner.getornull(p_render_target);
|
||||
ERR_FAIL_COND_V(!rt, RID());
|
||||
if (rt->sdf_buffer_read.is_null()) {
|
||||
// no texture, create a dummy one for the 2D uniform set
|
||||
RD::TextureFormat tformat;
|
||||
tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
|
||||
tformat.width = 4;
|
||||
tformat.height = 4;
|
||||
tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT;
|
||||
tformat.type = RD::TEXTURE_TYPE_2D;
|
||||
|
||||
Vector<uint8_t> pv;
|
||||
pv.resize(16 * 4);
|
||||
zeromem(pv.ptrw(), 16 * 4);
|
||||
Vector<Vector<uint8_t>> vpv;
|
||||
|
||||
rt->sdf_buffer_read = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
|
||||
}
|
||||
|
||||
return rt->sdf_buffer_read;
|
||||
}
|
||||
|
||||
void RasterizerStorageRD::_render_target_allocate_sdf(RenderTarget *rt) {
|
||||
ERR_FAIL_COND(rt->sdf_buffer_write_fb.is_valid());
|
||||
if (rt->sdf_buffer_read.is_valid()) {
|
||||
RD::get_singleton()->free(rt->sdf_buffer_read);
|
||||
rt->sdf_buffer_read = RID();
|
||||
}
|
||||
|
||||
Size2i size = _render_target_get_sdf_rect(rt).size;
|
||||
|
||||
RD::TextureFormat tformat;
|
||||
tformat.format = RD::DATA_FORMAT_R8_UNORM;
|
||||
tformat.width = size.width;
|
||||
tformat.height = size.height;
|
||||
tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
tformat.type = RD::TEXTURE_TYPE_2D;
|
||||
|
||||
rt->sdf_buffer_write = RD::get_singleton()->texture_create(tformat, RD::TextureView());
|
||||
|
||||
{
|
||||
Vector<RID> write_fb;
|
||||
write_fb.push_back(rt->sdf_buffer_write);
|
||||
rt->sdf_buffer_write_fb = RD::get_singleton()->framebuffer_create(write_fb);
|
||||
}
|
||||
|
||||
int scale;
|
||||
switch (rt->sdf_scale) {
|
||||
case RS::VIEWPORT_SDF_SCALE_100_PERCENT: {
|
||||
scale = 100;
|
||||
} break;
|
||||
case RS::VIEWPORT_SDF_SCALE_50_PERCENT: {
|
||||
scale = 50;
|
||||
} break;
|
||||
case RS::VIEWPORT_SDF_SCALE_25_PERCENT: {
|
||||
scale = 25;
|
||||
} break;
|
||||
default: {
|
||||
scale = 100;
|
||||
} break;
|
||||
}
|
||||
|
||||
rt->process_size = size * scale / 100;
|
||||
rt->process_size.x = MAX(rt->process_size.x, 1);
|
||||
rt->process_size.y = MAX(rt->process_size.y, 1);
|
||||
|
||||
tformat.format = RD::DATA_FORMAT_R16G16_UINT;
|
||||
tformat.width = rt->process_size.width;
|
||||
tformat.height = rt->process_size.height;
|
||||
tformat.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT;
|
||||
|
||||
rt->sdf_buffer_process[0] = RD::get_singleton()->texture_create(tformat, RD::TextureView());
|
||||
rt->sdf_buffer_process[1] = RD::get_singleton()->texture_create(tformat, RD::TextureView());
|
||||
|
||||
tformat.format = RD::DATA_FORMAT_R16_UNORM;
|
||||
tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
|
||||
|
||||
rt->sdf_buffer_read = RD::get_singleton()->texture_create(tformat, RD::TextureView());
|
||||
|
||||
{
|
||||
Vector<RD::Uniform> uniforms;
|
||||
{
|
||||
RD::Uniform u;
|
||||
u.type = RD::UNIFORM_TYPE_IMAGE;
|
||||
u.binding = 1;
|
||||
u.ids.push_back(rt->sdf_buffer_write);
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
{
|
||||
RD::Uniform u;
|
||||
u.type = RD::UNIFORM_TYPE_IMAGE;
|
||||
u.binding = 2;
|
||||
u.ids.push_back(rt->sdf_buffer_read);
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
{
|
||||
RD::Uniform u;
|
||||
u.type = RD::UNIFORM_TYPE_IMAGE;
|
||||
u.binding = 3;
|
||||
u.ids.push_back(rt->sdf_buffer_process[0]);
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
{
|
||||
RD::Uniform u;
|
||||
u.type = RD::UNIFORM_TYPE_IMAGE;
|
||||
u.binding = 4;
|
||||
u.ids.push_back(rt->sdf_buffer_process[1]);
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
|
||||
rt->sdf_buffer_process_uniform_sets[0] = RD::get_singleton()->uniform_set_create(uniforms, rt_sdf.shader.version_get_shader(rt_sdf.shader_version, 0), 0);
|
||||
SWAP(uniforms.write[2].ids.write[0], uniforms.write[3].ids.write[0]);
|
||||
rt->sdf_buffer_process_uniform_sets[1] = RD::get_singleton()->uniform_set_create(uniforms, rt_sdf.shader.version_get_shader(rt_sdf.shader_version, 0), 0);
|
||||
}
|
||||
}
|
||||
|
||||
void RasterizerStorageRD::_render_target_clear_sdf(RenderTarget *rt) {
|
||||
if (rt->sdf_buffer_read.is_valid()) {
|
||||
RD::get_singleton()->free(rt->sdf_buffer_read);
|
||||
rt->sdf_buffer_read = RID();
|
||||
}
|
||||
if (rt->sdf_buffer_write_fb.is_valid()) {
|
||||
RD::get_singleton()->free(rt->sdf_buffer_write);
|
||||
RD::get_singleton()->free(rt->sdf_buffer_process[0]);
|
||||
RD::get_singleton()->free(rt->sdf_buffer_process[1]);
|
||||
rt->sdf_buffer_write = RID();
|
||||
rt->sdf_buffer_write_fb = RID();
|
||||
rt->sdf_buffer_process[0] = RID();
|
||||
rt->sdf_buffer_process[1] = RID();
|
||||
rt->sdf_buffer_process_uniform_sets[0] = RID();
|
||||
rt->sdf_buffer_process_uniform_sets[1] = RID();
|
||||
}
|
||||
}
|
||||
|
||||
RID RasterizerStorageRD::render_target_get_sdf_framebuffer(RID p_render_target) {
|
||||
RenderTarget *rt = render_target_owner.getornull(p_render_target);
|
||||
ERR_FAIL_COND_V(!rt, RID());
|
||||
|
||||
if (rt->sdf_buffer_write_fb.is_null()) {
|
||||
_render_target_allocate_sdf(rt);
|
||||
}
|
||||
|
||||
return rt->sdf_buffer_write_fb;
|
||||
}
|
||||
void RasterizerStorageRD::render_target_sdf_process(RID p_render_target) {
|
||||
RenderTarget *rt = render_target_owner.getornull(p_render_target);
|
||||
ERR_FAIL_COND(!rt);
|
||||
ERR_FAIL_COND(rt->sdf_buffer_write_fb.is_null());
|
||||
|
||||
RenderTargetSDF::PushConstant push_constant;
|
||||
|
||||
Rect2i r = _render_target_get_sdf_rect(rt);
|
||||
|
||||
push_constant.size[0] = r.size.width;
|
||||
push_constant.size[1] = r.size.height;
|
||||
push_constant.stride = 0;
|
||||
push_constant.shift = 0;
|
||||
push_constant.base_size[0] = r.size.width;
|
||||
push_constant.base_size[1] = r.size.height;
|
||||
|
||||
bool shrink = false;
|
||||
|
||||
switch (rt->sdf_scale) {
|
||||
case RS::VIEWPORT_SDF_SCALE_50_PERCENT: {
|
||||
push_constant.size[0] >>= 1;
|
||||
push_constant.size[1] >>= 1;
|
||||
push_constant.shift = 1;
|
||||
shrink = true;
|
||||
} break;
|
||||
case RS::VIEWPORT_SDF_SCALE_25_PERCENT: {
|
||||
push_constant.size[0] >>= 2;
|
||||
push_constant.size[1] >>= 2;
|
||||
push_constant.shift = 2;
|
||||
shrink = true;
|
||||
} break;
|
||||
default: {
|
||||
};
|
||||
}
|
||||
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
|
||||
/* Load */
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, rt_sdf.pipelines[shrink ? RenderTargetSDF::SHADER_LOAD_SHRINK : RenderTargetSDF::SHADER_LOAD]);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rt->sdf_buffer_process_uniform_sets[1], 0); //fill [0]
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(RenderTargetSDF::PushConstant));
|
||||
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.size[0], push_constant.size[1], 1, 8, 8, 1);
|
||||
|
||||
/* Process */
|
||||
|
||||
int stride = nearest_power_of_2_templated(MAX(push_constant.size[0], push_constant.size[1]) / 2);
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, rt_sdf.pipelines[RenderTargetSDF::SHADER_PROCESS]);
|
||||
|
||||
RD::get_singleton()->compute_list_add_barrier(compute_list);
|
||||
bool swap = false;
|
||||
|
||||
//jumpflood
|
||||
while (stride > 0) {
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rt->sdf_buffer_process_uniform_sets[swap ? 1 : 0], 0);
|
||||
push_constant.stride = stride;
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(RenderTargetSDF::PushConstant));
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.size[0], push_constant.size[1], 1, 8, 8, 1);
|
||||
stride /= 2;
|
||||
swap = !swap;
|
||||
RD::get_singleton()->compute_list_add_barrier(compute_list);
|
||||
}
|
||||
|
||||
/* Store */
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, rt_sdf.pipelines[shrink ? RenderTargetSDF::SHADER_STORE_SHRINK : RenderTargetSDF::SHADER_STORE]);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rt->sdf_buffer_process_uniform_sets[swap ? 1 : 0], 0);
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(RenderTargetSDF::PushConstant));
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.size[0], push_constant.size[1], 1, 8, 8, 1);
|
||||
|
||||
RD::get_singleton()->compute_list_end();
|
||||
}
|
||||
|
||||
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);
|
||||
@ -8155,6 +8426,24 @@ RasterizerStorageRD::RasterizerStorageRD() {
|
||||
particles_shader.copy_pipelines[i] = RD::get_singleton()->compute_pipeline_create(particles_shader.copy_shader.version_get_shader(particles_shader.copy_shader_version, i));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
Vector<String> sdf_modes;
|
||||
sdf_modes.push_back("\n#define MODE_LOAD\n");
|
||||
sdf_modes.push_back("\n#define MODE_LOAD_SHRINK\n");
|
||||
sdf_modes.push_back("\n#define MODE_PROCESS\n");
|
||||
sdf_modes.push_back("\n#define MODE_PROCESS_OPTIMIZED\n");
|
||||
sdf_modes.push_back("\n#define MODE_STORE\n");
|
||||
sdf_modes.push_back("\n#define MODE_STORE_SHRINK\n");
|
||||
|
||||
rt_sdf.shader.initialize(sdf_modes);
|
||||
|
||||
rt_sdf.shader_version = rt_sdf.shader.version_create();
|
||||
|
||||
for (int i = 0; i < RenderTargetSDF::SHADER_MAX; i++) {
|
||||
rt_sdf.pipelines[i] = RD::get_singleton()->compute_pipeline_create(rt_sdf.shader.version_get_shader(rt_sdf.shader_version, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RasterizerStorageRD::~RasterizerStorageRD() {
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "servers/rendering/rasterizer.h"
|
||||
#include "servers/rendering/rasterizer_rd/rasterizer_effects_rd.h"
|
||||
#include "servers/rendering/rasterizer_rd/shader_compiler_rd.h"
|
||||
#include "servers/rendering/rasterizer_rd/shaders/canvas_sdf.glsl.gen.h"
|
||||
#include "servers/rendering/rasterizer_rd/shaders/giprobe_sdf.glsl.gen.h"
|
||||
#include "servers/rendering/rasterizer_rd/shaders/particles.glsl.gen.h"
|
||||
#include "servers/rendering/rasterizer_rd/shaders/particles_copy.glsl.gen.h"
|
||||
@ -1003,6 +1004,15 @@ private:
|
||||
RID framebuffer_uniform_set;
|
||||
RID backbuffer_uniform_set;
|
||||
|
||||
RID sdf_buffer_write;
|
||||
RID sdf_buffer_write_fb;
|
||||
RID sdf_buffer_process[2];
|
||||
RID sdf_buffer_read;
|
||||
RID sdf_buffer_process_uniform_sets[2];
|
||||
RS::ViewportSDFOversize sdf_oversize = RS::VIEWPORT_SDF_OVERSIZE_120_PERCENT;
|
||||
RS::ViewportSDFScale sdf_scale = RS::VIEWPORT_SDF_SCALE_50_PERCENT;
|
||||
Size2i process_size;
|
||||
|
||||
//texture generated for this owner (nor RD).
|
||||
RID texture;
|
||||
bool was_used;
|
||||
@ -1012,11 +1022,38 @@ private:
|
||||
Color clear_color;
|
||||
};
|
||||
|
||||
RID_Owner<RenderTarget> render_target_owner;
|
||||
mutable RID_Owner<RenderTarget> render_target_owner;
|
||||
|
||||
void _clear_render_target(RenderTarget *rt);
|
||||
void _update_render_target(RenderTarget *rt);
|
||||
void _create_render_target_backbuffer(RenderTarget *rt);
|
||||
void _render_target_allocate_sdf(RenderTarget *rt);
|
||||
void _render_target_clear_sdf(RenderTarget *rt);
|
||||
Rect2i _render_target_get_sdf_rect(const RenderTarget *rt) const;
|
||||
|
||||
struct RenderTargetSDF {
|
||||
enum {
|
||||
SHADER_LOAD,
|
||||
SHADER_LOAD_SHRINK,
|
||||
SHADER_PROCESS,
|
||||
SHADER_PROCESS_OPTIMIZED,
|
||||
SHADER_STORE,
|
||||
SHADER_STORE_SHRINK,
|
||||
SHADER_MAX
|
||||
};
|
||||
|
||||
struct PushConstant {
|
||||
int32_t size[2];
|
||||
int32_t stride;
|
||||
int32_t shift;
|
||||
int32_t base_size[2];
|
||||
int32_t pad[2];
|
||||
};
|
||||
|
||||
CanvasSdfShaderRD shader;
|
||||
RID shader_version;
|
||||
RID pipelines[SHADER_MAX];
|
||||
} rt_sdf;
|
||||
|
||||
/* GLOBAL SHADER VARIABLES */
|
||||
|
||||
@ -1930,6 +1967,12 @@ public:
|
||||
virtual void render_target_disable_clear_request(RID p_render_target);
|
||||
virtual void render_target_do_clear_request(RID p_render_target);
|
||||
|
||||
virtual void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale);
|
||||
RID render_target_get_sdf_texture(RID p_render_target);
|
||||
RID render_target_get_sdf_framebuffer(RID p_render_target);
|
||||
void render_target_sdf_process(RID p_render_target);
|
||||
virtual Rect2i render_target_get_sdf_rect(RID p_render_target) const;
|
||||
|
||||
Size2 render_target_get_size(RID p_render_target);
|
||||
RID render_target_get_rd_framebuffer(RID p_render_target);
|
||||
RID render_target_get_rd_texture(RID p_render_target);
|
||||
|
@ -1072,6 +1072,11 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
|
||||
} else if (onode->op == SL::OP_CONSTRUCT) {
|
||||
code += String(vnode->name);
|
||||
} else {
|
||||
if (p_actions.usage_flag_pointers.has(vnode->name) && !used_flag_pointers.has(vnode->name)) {
|
||||
*p_actions.usage_flag_pointers[vnode->name] = true;
|
||||
used_flag_pointers.insert(vnode->name);
|
||||
}
|
||||
|
||||
if (internal_functions.has(vnode->name)) {
|
||||
code += vnode->name;
|
||||
is_texture_func = texture_functions.has(vnode->name);
|
||||
|
@ -5,6 +5,7 @@ Import("env")
|
||||
if "RD_GLSL" in env["BUILDERS"]:
|
||||
env.RD_GLSL("canvas.glsl")
|
||||
env.RD_GLSL("canvas_occlusion.glsl")
|
||||
env.RD_GLSL("canvas_sdf.glsl")
|
||||
env.RD_GLSL("copy.glsl")
|
||||
env.RD_GLSL("copy_to_fb.glsl")
|
||||
env.RD_GLSL("cubemap_roughness.glsl")
|
||||
|
@ -233,6 +233,30 @@ MATERIAL_UNIFORMS
|
||||
} material;
|
||||
#endif
|
||||
|
||||
vec2 screen_uv_to_sdf(vec2 p_uv) {
|
||||
return canvas_data.screen_to_sdf * p_uv;
|
||||
}
|
||||
|
||||
float texture_sdf(vec2 p_sdf) {
|
||||
vec2 uv = p_sdf * canvas_data.sdf_to_tex.xy + canvas_data.sdf_to_tex.zw;
|
||||
float d = texture(sampler2D(sdf_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), uv).r;
|
||||
d = d * SDF_MAX_LENGTH - 1.0;
|
||||
return d * canvas_data.tex_to_sdf;
|
||||
}
|
||||
|
||||
vec2 texture_sdf_normal(vec2 p_sdf) {
|
||||
vec2 uv = p_sdf * canvas_data.sdf_to_tex.xy + canvas_data.sdf_to_tex.zw;
|
||||
|
||||
const float EPSILON = 0.001;
|
||||
return normalize(vec2(
|
||||
texture(sampler2D(sdf_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), uv + vec2(EPSILON, 0.0)).r - texture(sampler2D(sdf_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), uv - vec2(EPSILON, 0.0)).r,
|
||||
texture(sampler2D(sdf_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), uv + vec2(0.0, EPSILON)).r - texture(sampler2D(sdf_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), uv - vec2(0.0, EPSILON)).r));
|
||||
}
|
||||
|
||||
vec2 sdf_to_screen_uv(vec2 p_sdf) {
|
||||
return p_sdf * canvas_data.sdf_to_screen;
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
FRAGMENT_SHADER_GLOBALS
|
||||
/* clang-format on */
|
||||
@ -500,8 +524,13 @@ FRAGMENT_SHADER_CODE
|
||||
color = vec4(0.0); //invisible by default due to using light mask
|
||||
}
|
||||
|
||||
#ifdef MODE_LIGHT_ONLY
|
||||
color = vec4(0.0);
|
||||
#else
|
||||
color *= canvas_data.canvas_modulation;
|
||||
#ifdef USE_LIGHTING
|
||||
#endif
|
||||
|
||||
#if defined(USE_LIGHTING) && !defined(MODE_UNSHADED)
|
||||
|
||||
// Directional Lights
|
||||
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
#version 450
|
||||
|
||||
VERSION_DEFINES
|
||||
|
||||
layout(location = 0) in highp vec3 vertex;
|
||||
|
||||
layout(push_constant, binding = 0, std430) uniform Constants {
|
||||
@ -13,12 +15,16 @@ layout(push_constant, binding = 0, std430) uniform Constants {
|
||||
}
|
||||
constants;
|
||||
|
||||
#ifdef MODE_SHADOW
|
||||
layout(location = 0) out highp float depth;
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
highp vec4 vtx = vec4(vertex, 1.0) * mat4(constants.modelview[0], constants.modelview[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));
|
||||
depth = dot(constants.direction, vtx.xy);
|
||||
|
||||
#ifdef MODE_SHADOW
|
||||
depth = dot(constants.direction, vtx.xy);
|
||||
#endif
|
||||
gl_Position = constants.projection * vtx;
|
||||
}
|
||||
|
||||
@ -26,6 +32,8 @@ void main() {
|
||||
|
||||
#version 450
|
||||
|
||||
VERSION_DEFINES
|
||||
|
||||
layout(push_constant, binding = 0, std430) uniform Constants {
|
||||
mat4 projection;
|
||||
mat2x4 modelview;
|
||||
@ -35,9 +43,17 @@ layout(push_constant, binding = 0, std430) uniform Constants {
|
||||
}
|
||||
constants;
|
||||
|
||||
#ifdef MODE_SHADOW
|
||||
layout(location = 0) in highp float depth;
|
||||
layout(location = 0) out highp float distance_buf;
|
||||
#else
|
||||
layout(location = 0) out highp float sdf_buf;
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
#ifdef MODE_SHADOW
|
||||
distance_buf = depth / constants.z_far;
|
||||
#else
|
||||
sdf_buf = 1.0;
|
||||
#endif
|
||||
}
|
||||
|
135
servers/rendering/rasterizer_rd/shaders/canvas_sdf.glsl
Normal file
135
servers/rendering/rasterizer_rd/shaders/canvas_sdf.glsl
Normal file
@ -0,0 +1,135 @@
|
||||
#[compute]
|
||||
|
||||
#version 450
|
||||
|
||||
VERSION_DEFINES
|
||||
|
||||
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
|
||||
|
||||
layout(r8, set = 0, binding = 1) uniform restrict readonly image2D src_pixels;
|
||||
layout(r16, set = 0, binding = 2) uniform restrict writeonly image2D dst_sdf;
|
||||
|
||||
layout(rg16i, set = 0, binding = 3) uniform restrict readonly iimage2D src_process;
|
||||
layout(rg16i, set = 0, binding = 4) uniform restrict writeonly iimage2D dst_process;
|
||||
|
||||
layout(push_constant, binding = 0, std430) uniform Params {
|
||||
ivec2 size;
|
||||
int stride;
|
||||
int shift;
|
||||
ivec2 base_size;
|
||||
uvec2 pad;
|
||||
}
|
||||
params;
|
||||
|
||||
#define SDF_MAX_LENGTH 16384.0
|
||||
|
||||
void main() {
|
||||
ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
|
||||
if (any(greaterThanEqual(pos, params.size))) { //too large, do nothing
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef MODE_LOAD
|
||||
|
||||
bool solid = imageLoad(src_pixels, pos).r > 0.5;
|
||||
imageStore(dst_process, pos, solid ? ivec4(pos, 0, 0) : ivec4(ivec2(32767), 0, 0));
|
||||
#endif
|
||||
|
||||
#ifdef MODE_LOAD_SHRINK
|
||||
|
||||
int s = 1 << params.shift;
|
||||
ivec2 base = pos << params.shift;
|
||||
ivec2 center = base + ivec2(params.shift);
|
||||
|
||||
ivec2 rel = ivec2(32767);
|
||||
float d = 1e20;
|
||||
for (int i = 0; i < s; i++) {
|
||||
for (int j = 0; j < s; j++) {
|
||||
ivec2 src_pos = base + ivec2(i, j);
|
||||
if (any(greaterThanEqual(src_pos, params.base_size))) {
|
||||
continue;
|
||||
}
|
||||
bool solid = imageLoad(src_pixels, src_pos).r > 0.5;
|
||||
if (solid) {
|
||||
float dist = length(vec2(src_pos - center));
|
||||
if (dist < d) {
|
||||
d = dist;
|
||||
rel = src_pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
imageStore(dst_process, pos, ivec4(rel, 0, 0));
|
||||
#endif
|
||||
|
||||
#ifdef MODE_PROCESS
|
||||
|
||||
ivec2 base = pos << params.shift;
|
||||
ivec2 center = base + ivec2(params.shift);
|
||||
|
||||
ivec2 rel = imageLoad(src_process, pos).xy;
|
||||
|
||||
if (center != rel) {
|
||||
//only process if it does not point to itself
|
||||
const int ofs_table_size = 8;
|
||||
const ivec2 ofs_table[ofs_table_size] = ivec2[](
|
||||
ivec2(-1, -1),
|
||||
ivec2(0, -1),
|
||||
ivec2(+1, -1),
|
||||
|
||||
ivec2(-1, 0),
|
||||
ivec2(+1, 0),
|
||||
|
||||
ivec2(-1, +1),
|
||||
ivec2(0, +1),
|
||||
ivec2(+1, +1));
|
||||
|
||||
float dist = length(vec2(rel - center));
|
||||
for (int i = 0; i < ofs_table_size; i++) {
|
||||
ivec2 src_pos = pos + ofs_table[i] * params.stride;
|
||||
if (any(lessThan(src_pos, ivec2(0))) || any(greaterThanEqual(src_pos, params.size))) {
|
||||
continue;
|
||||
}
|
||||
ivec2 src_rel = imageLoad(src_process, src_pos).xy;
|
||||
float src_dist = length(vec2(src_rel - center));
|
||||
if (src_dist < dist) {
|
||||
dist = src_dist;
|
||||
rel = src_rel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
imageStore(dst_process, pos, ivec4(rel, 0, 0));
|
||||
#endif
|
||||
|
||||
#ifdef MODE_STORE
|
||||
|
||||
ivec2 rel = imageLoad(src_process, pos).xy;
|
||||
float d = length(vec2(rel - pos));
|
||||
if (d > 0.01) {
|
||||
d += 1.0; //make it signed
|
||||
}
|
||||
d /= SDF_MAX_LENGTH;
|
||||
d = clamp(d, 0.0, 1.0);
|
||||
imageStore(dst_sdf, pos, vec4(d));
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef MODE_STORE_SHRINK
|
||||
|
||||
ivec2 base = pos << params.shift;
|
||||
ivec2 center = base + ivec2(params.shift);
|
||||
|
||||
ivec2 rel = imageLoad(src_process, pos).xy;
|
||||
float d = length(vec2(rel - center));
|
||||
|
||||
if (d > 0.01) {
|
||||
d += 1.0; //make it signed
|
||||
}
|
||||
d /= SDF_MAX_LENGTH;
|
||||
d = clamp(d, 0.0, 1.0);
|
||||
imageStore(dst_sdf, pos, vec4(d));
|
||||
|
||||
#endif
|
||||
}
|
@ -3,6 +3,8 @@
|
||||
|
||||
#define M_PI 3.14159265359
|
||||
|
||||
#define SDF_MAX_LENGTH 16384.0
|
||||
|
||||
#define FLAGS_INSTANCING_STRIDE_MASK 0xF
|
||||
#define FLAGS_INSTANCING_ENABLED (1 << 4)
|
||||
#define FLAGS_INSTANCING_HAS_COLORS (1 << 5)
|
||||
@ -24,6 +26,19 @@
|
||||
#define FLAGS_DEFAULT_NORMAL_MAP_USED (1 << 26)
|
||||
#define FLAGS_DEFAULT_SPECULAR_MAP_USED (1 << 27)
|
||||
|
||||
#define SAMPLER_NEAREST_CLAMP 0
|
||||
#define SAMPLER_LINEAR_CLAMP 1
|
||||
#define SAMPLER_NEAREST_WITH_MIPMAPS_CLAMP 2
|
||||
#define SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP 3
|
||||
#define SAMPLER_NEAREST_WITH_MIPMAPS_ANISOTROPIC_CLAMP 4
|
||||
#define SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_CLAMP 5
|
||||
#define SAMPLER_NEAREST_REPEAT 6
|
||||
#define SAMPLER_LINEAR_REPEAT 7
|
||||
#define SAMPLER_NEAREST_WITH_MIPMAPS_REPEAT 8
|
||||
#define SAMPLER_LINEAR_WITH_MIPMAPS_REPEAT 9
|
||||
#define SAMPLER_NEAREST_WITH_MIPMAPS_ANISOTROPIC_REPEAT 10
|
||||
#define SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_REPEAT 11
|
||||
|
||||
// Push Constant
|
||||
|
||||
layout(push_constant, binding = 0, std430) uniform DrawData {
|
||||
@ -68,8 +83,12 @@ layout(set = 0, binding = 1, std140) uniform CanvasData {
|
||||
float time;
|
||||
bool use_pixel_snap;
|
||||
|
||||
vec4 sdf_to_tex;
|
||||
vec2 screen_to_sdf;
|
||||
vec2 sdf_to_screen;
|
||||
|
||||
uint directional_light_count;
|
||||
uint pad0;
|
||||
float tex_to_sdf;
|
||||
uint pad1;
|
||||
uint pad2;
|
||||
}
|
||||
@ -115,10 +134,11 @@ layout(set = 0, binding = 4) uniform texture2D shadow_atlas_texture;
|
||||
layout(set = 0, binding = 5) uniform sampler shadow_sampler;
|
||||
|
||||
layout(set = 0, binding = 6) uniform texture2D screen_texture;
|
||||
layout(set = 0, binding = 7) uniform texture2D sdf_texture;
|
||||
|
||||
layout(set = 0, binding = 7) uniform sampler material_samplers[12];
|
||||
layout(set = 0, binding = 8) uniform sampler material_samplers[12];
|
||||
|
||||
layout(set = 0, binding = 8, std430) restrict readonly buffer GlobalVariableData {
|
||||
layout(set = 0, binding = 9, std430) restrict readonly buffer GlobalVariableData {
|
||||
vec4 data[];
|
||||
}
|
||||
global_variables;
|
||||
|
@ -68,7 +68,11 @@ 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_directional_lights, p_transform, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel);
|
||||
bool sdf_flag;
|
||||
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, sdf_flag);
|
||||
if (sdf_flag) {
|
||||
sdf_used = true;
|
||||
}
|
||||
}
|
||||
|
||||
void _collect_ysort_children(RenderingServerCanvas::Item *p_canvas_item, Transform2D p_transform, RenderingServerCanvas::Item *p_material_owner, RenderingServerCanvas::Item **r_items, int &r_index) {
|
||||
@ -301,6 +305,7 @@ void RenderingServerCanvas::_cull_canvas_item(Item *p_canvas_item, const Transfo
|
||||
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");
|
||||
|
||||
sdf_used = false;
|
||||
snapping_2d_transforms_to_pixel = p_snap_2d_transforms_to_pixel;
|
||||
|
||||
if (p_canvas->children_order_dirty) {
|
||||
@ -347,6 +352,10 @@ void RenderingServerCanvas::render_canvas(RID p_render_target, Canvas *p_canvas,
|
||||
RENDER_TIMESTAMP("<End Render Canvas");
|
||||
}
|
||||
|
||||
bool RenderingServerCanvas::was_sdf_used() {
|
||||
return sdf_used;
|
||||
}
|
||||
|
||||
RID RenderingServerCanvas::canvas_create() {
|
||||
Canvas *canvas = memnew(Canvas);
|
||||
ERR_FAIL_COND_V(!canvas, RID());
|
||||
@ -1266,6 +1275,11 @@ void RenderingServerCanvas::canvas_light_occluder_set_polygon(RID p_occluder, RI
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingServerCanvas::canvas_light_occluder_set_as_sdf_collision(RID p_occluder, bool p_enable) {
|
||||
RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_occluder);
|
||||
ERR_FAIL_COND(!occluder);
|
||||
}
|
||||
|
||||
void RenderingServerCanvas::canvas_light_occluder_set_transform(RID p_occluder, const Transform2D &p_xform) {
|
||||
RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_occluder);
|
||||
ERR_FAIL_COND(!occluder);
|
||||
@ -1287,53 +1301,24 @@ RID RenderingServerCanvas::canvas_occluder_polygon_create() {
|
||||
}
|
||||
|
||||
void RenderingServerCanvas::canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const Vector<Vector2> &p_shape, bool p_closed) {
|
||||
if (p_shape.size() < 3) {
|
||||
canvas_occluder_polygon_set_shape_as_lines(p_occluder_polygon, p_shape);
|
||||
return;
|
||||
}
|
||||
|
||||
Vector<Vector2> lines;
|
||||
int lc = p_shape.size() * 2;
|
||||
|
||||
lines.resize(lc - (p_closed ? 0 : 2));
|
||||
{
|
||||
Vector2 *w = lines.ptrw();
|
||||
const Vector2 *r = p_shape.ptr();
|
||||
|
||||
int max = lc / 2;
|
||||
if (!p_closed) {
|
||||
max--;
|
||||
}
|
||||
for (int i = 0; i < max; i++) {
|
||||
Vector2 a = r[i];
|
||||
Vector2 b = r[(i + 1) % (lc / 2)];
|
||||
w[i * 2 + 0] = a;
|
||||
w[i * 2 + 1] = b;
|
||||
}
|
||||
}
|
||||
|
||||
canvas_occluder_polygon_set_shape_as_lines(p_occluder_polygon, lines);
|
||||
}
|
||||
|
||||
void RenderingServerCanvas::canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon, const Vector<Vector2> &p_shape) {
|
||||
LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.getornull(p_occluder_polygon);
|
||||
ERR_FAIL_COND(!occluder_poly);
|
||||
ERR_FAIL_COND(p_shape.size() & 1);
|
||||
|
||||
int lc = p_shape.size();
|
||||
uint32_t pc = p_shape.size();
|
||||
ERR_FAIL_COND(pc < 2);
|
||||
|
||||
occluder_poly->aabb = Rect2();
|
||||
{
|
||||
const Vector2 *r = p_shape.ptr();
|
||||
for (int i = 0; i < lc; i++) {
|
||||
if (i == 0) {
|
||||
occluder_poly->aabb.position = r[i];
|
||||
} else {
|
||||
occluder_poly->aabb.expand_to(r[i]);
|
||||
}
|
||||
const Vector2 *r = p_shape.ptr();
|
||||
for (uint32_t i = 0; i < pc; i++) {
|
||||
if (i == 0) {
|
||||
occluder_poly->aabb.position = r[i];
|
||||
} else {
|
||||
occluder_poly->aabb.expand_to(r[i]);
|
||||
}
|
||||
}
|
||||
|
||||
RSG::canvas_render->occluder_polygon_set_shape_as_lines(occluder_poly->occluder, p_shape);
|
||||
RSG::canvas_render->occluder_polygon_set_shape(occluder_poly->occluder, p_shape, p_closed);
|
||||
|
||||
for (Set<RasterizerCanvas::LightOccluderInstance *>::Element *E = occluder_poly->owners.front(); E; E = E->next()) {
|
||||
E->get()->aabb_cache = occluder_poly->aabb;
|
||||
}
|
||||
|
@ -153,6 +153,7 @@ public:
|
||||
RID_PtrOwner<RasterizerCanvas::Light> canvas_light_owner;
|
||||
|
||||
bool disable_scale;
|
||||
bool sdf_used = false;
|
||||
bool snapping_2d_transforms_to_pixel = false;
|
||||
|
||||
private:
|
||||
@ -165,6 +166,8 @@ private:
|
||||
public:
|
||||
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);
|
||||
|
||||
bool was_sdf_used();
|
||||
|
||||
RID canvas_create();
|
||||
void canvas_set_item_mirroring(RID p_canvas, RID p_item, const Point2 &p_mirroring);
|
||||
void canvas_set_modulate(RID p_canvas, const Color &p_color);
|
||||
@ -247,12 +250,12 @@ public:
|
||||
void canvas_light_occluder_attach_to_canvas(RID p_occluder, RID p_canvas);
|
||||
void canvas_light_occluder_set_enabled(RID p_occluder, bool p_enabled);
|
||||
void canvas_light_occluder_set_polygon(RID p_occluder, RID p_polygon);
|
||||
void canvas_light_occluder_set_as_sdf_collision(RID p_occluder, bool p_enable);
|
||||
void canvas_light_occluder_set_transform(RID p_occluder, const Transform2D &p_xform);
|
||||
void canvas_light_occluder_set_light_mask(RID p_occluder, int p_mask);
|
||||
|
||||
RID canvas_occluder_polygon_create();
|
||||
void canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const Vector<Vector2> &p_shape, bool p_closed);
|
||||
void canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon, const Vector<Vector2> &p_shape);
|
||||
|
||||
void canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon, RS::CanvasOccluderPolygonCullMode p_mode);
|
||||
|
||||
|
@ -536,6 +536,7 @@ public:
|
||||
BIND2(viewport_set_global_canvas_transform, RID, const Transform2D &)
|
||||
BIND4(viewport_set_canvas_stacking, RID, RID, int, int)
|
||||
BIND2(viewport_set_shadow_atlas_size, RID, int)
|
||||
BIND3(viewport_set_sdf_oversize_and_scale, RID, ViewportSDFOversize, ViewportSDFScale)
|
||||
BIND3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int)
|
||||
BIND2(viewport_set_msaa, RID, ViewportMSAA)
|
||||
BIND2(viewport_set_screen_space_aa, RID, ViewportScreenSpaceAA)
|
||||
@ -776,12 +777,12 @@ public:
|
||||
BIND2(canvas_light_occluder_attach_to_canvas, RID, RID)
|
||||
BIND2(canvas_light_occluder_set_enabled, RID, bool)
|
||||
BIND2(canvas_light_occluder_set_polygon, RID, RID)
|
||||
BIND2(canvas_light_occluder_set_as_sdf_collision, RID, bool)
|
||||
BIND2(canvas_light_occluder_set_transform, RID, const Transform2D &)
|
||||
BIND2(canvas_light_occluder_set_light_mask, RID, int)
|
||||
|
||||
BIND0R(RID, canvas_occluder_polygon_create)
|
||||
BIND3(canvas_occluder_polygon_set_shape, RID, const Vector<Vector2> &, bool)
|
||||
BIND2(canvas_occluder_polygon_set_shape_as_lines, RID, const Vector<Vector2> &)
|
||||
|
||||
BIND2(canvas_occluder_polygon_set_cull_mode, RID, CanvasOccluderPolygonCullMode)
|
||||
|
||||
|
@ -146,6 +146,36 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface::
|
||||
RasterizerCanvas::Light *directional_lights = nullptr;
|
||||
RasterizerCanvas::Light *directional_lights_with_shadow = nullptr;
|
||||
|
||||
if (p_viewport->sdf_active) {
|
||||
//process SDF
|
||||
|
||||
Rect2 sdf_rect = RSG::storage->render_target_get_sdf_rect(p_viewport->render_target);
|
||||
|
||||
RasterizerCanvas::LightOccluderInstance *occluders = nullptr;
|
||||
|
||||
//make list of occluders
|
||||
for (Map<RID, Viewport::CanvasData>::Element *E = p_viewport->canvas_map.front(); E; E = E->next()) {
|
||||
RenderingServerCanvas::Canvas *canvas = static_cast<RenderingServerCanvas::Canvas *>(E->get().canvas);
|
||||
Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E->get(), clip_rect.size);
|
||||
|
||||
for (Set<RasterizerCanvas::LightOccluderInstance *>::Element *F = canvas->occluders.front(); F; F = F->next()) {
|
||||
if (!F->get()->enabled) {
|
||||
continue;
|
||||
}
|
||||
F->get()->xform_cache = xf * F->get()->xform;
|
||||
|
||||
if (sdf_rect.intersects_transformed(F->get()->xform_cache, F->get()->aabb_cache)) {
|
||||
F->get()->next = occluders;
|
||||
occluders = F->get();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RSG::canvas_render->render_sdf(p_viewport->render_target, occluders);
|
||||
|
||||
p_viewport->sdf_active = false; // if used, gets set active again
|
||||
}
|
||||
|
||||
Rect2 shadow_rect;
|
||||
|
||||
int light_count = 0;
|
||||
@ -195,7 +225,6 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface::
|
||||
}
|
||||
|
||||
//guess this is not needed, but keeping because it may be
|
||||
//RSG::canvas_render->light_internal_update(cl->light_internal, cl);
|
||||
}
|
||||
}
|
||||
|
||||
@ -256,7 +285,6 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface::
|
||||
light = light->shadows_next_ptr;
|
||||
}
|
||||
|
||||
//RSG::canvas_render->reset_canvas();
|
||||
RENDER_TIMESTAMP("<End rendering 2D Shadows");
|
||||
}
|
||||
|
||||
@ -340,7 +368,6 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface::
|
||||
light = light->shadows_next_ptr;
|
||||
}
|
||||
|
||||
//RSG::canvas_render->reset_canvas();
|
||||
RENDER_TIMESTAMP("<Render Directional 2D Shadows");
|
||||
}
|
||||
|
||||
@ -380,6 +407,9 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface::
|
||||
}
|
||||
|
||||
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);
|
||||
if (RSG::canvas->was_sdf_used()) {
|
||||
p_viewport->sdf_active = true;
|
||||
}
|
||||
i++;
|
||||
|
||||
if (scenario_draw_canvas_bg && E->key().get_layer() >= scenario_canvas_max_layer) {
|
||||
@ -400,8 +430,6 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface::
|
||||
_draw_3d(p_viewport, p_eye);
|
||||
}
|
||||
}
|
||||
|
||||
//RSG::canvas_render->canvas_debug_viewport_shadows(lights_with_shadow);
|
||||
}
|
||||
|
||||
if (RSG::storage->render_target_is_clear_requested(p_viewport->render_target)) {
|
||||
@ -925,6 +953,13 @@ void RenderingServerViewport::viewport_set_default_canvas_item_texture_repeat(RI
|
||||
viewport->texture_repeat = p_repeat;
|
||||
}
|
||||
|
||||
void RenderingServerViewport::viewport_set_sdf_oversize_and_scale(RID p_viewport, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) {
|
||||
Viewport *viewport = viewport_owner.getornull(p_viewport);
|
||||
ERR_FAIL_COND(!viewport);
|
||||
|
||||
RSG::storage->render_target_set_sdf_size_and_scale(viewport->render_target, p_size, p_scale);
|
||||
}
|
||||
|
||||
bool RenderingServerViewport::free(RID p_rid) {
|
||||
if (viewport_owner.owns(p_rid)) {
|
||||
Viewport *viewport = viewport_owner.getornull(p_rid);
|
||||
|
@ -82,6 +82,8 @@ public:
|
||||
RID shadow_atlas;
|
||||
int shadow_atlas_size;
|
||||
|
||||
bool sdf_active;
|
||||
|
||||
uint64_t last_pass = 0;
|
||||
|
||||
int render_info[RS::VIEWPORT_RENDER_INFO_MAX];
|
||||
@ -146,6 +148,7 @@ public:
|
||||
render_info[i] = 0;
|
||||
}
|
||||
use_xr = false;
|
||||
sdf_active = false;
|
||||
|
||||
time_cpu_begin = 0;
|
||||
time_cpu_end = 0;
|
||||
@ -232,6 +235,8 @@ public:
|
||||
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);
|
||||
|
||||
void viewport_set_sdf_oversize_and_scale(RID p_viewport, RS::ViewportSDFOversize p_over_size, RS::ViewportSDFScale p_scale);
|
||||
|
||||
void handle_timestamp(String p_timestamp, uint64_t p_cpu_time, uint64_t p_gpu_time);
|
||||
|
||||
void set_default_clear_color(const Color &p_color);
|
||||
|
@ -440,6 +440,8 @@ public:
|
||||
FUNC2(viewport_set_global_canvas_transform, RID, const Transform2D &)
|
||||
FUNC4(viewport_set_canvas_stacking, RID, RID, int, int)
|
||||
FUNC2(viewport_set_shadow_atlas_size, RID, int)
|
||||
FUNC3(viewport_set_sdf_oversize_and_scale, RID, ViewportSDFOversize, ViewportSDFScale)
|
||||
|
||||
FUNC3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int)
|
||||
FUNC2(viewport_set_msaa, RID, ViewportMSAA)
|
||||
FUNC2(viewport_set_screen_space_aa, RID, ViewportScreenSpaceAA)
|
||||
@ -676,12 +678,12 @@ public:
|
||||
FUNC2(canvas_light_occluder_attach_to_canvas, RID, RID)
|
||||
FUNC2(canvas_light_occluder_set_enabled, RID, bool)
|
||||
FUNC2(canvas_light_occluder_set_polygon, RID, RID)
|
||||
FUNC2(canvas_light_occluder_set_as_sdf_collision, RID, bool)
|
||||
FUNC2(canvas_light_occluder_set_transform, RID, const Transform2D &)
|
||||
FUNC2(canvas_light_occluder_set_light_mask, RID, int)
|
||||
|
||||
FUNCRID(canvas_occluder_polygon)
|
||||
FUNC3(canvas_occluder_polygon_set_shape, RID, const Vector<Vector2> &, bool)
|
||||
FUNC2(canvas_occluder_polygon_set_shape_as_lines, RID, const Vector<Vector2> &)
|
||||
|
||||
FUNC2(canvas_occluder_polygon_set_cull_mode, RID, CanvasOccluderPolygonCullMode)
|
||||
|
||||
|
@ -252,6 +252,27 @@ ShaderTypes::ShaderTypes() {
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SCREEN_TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D);
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].can_discard = true;
|
||||
|
||||
{
|
||||
ShaderLanguage::StageFunctionInfo func;
|
||||
func.arguments.push_back(ShaderLanguage::StageFunctionInfo::Argument("sdf_pos", ShaderLanguage::TYPE_VEC2));
|
||||
func.return_type = ShaderLanguage::TYPE_FLOAT; //whether it could emit
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].stage_functions["texture_sdf"] = func;
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].stage_functions["texture_sdf"] = func;
|
||||
func.return_type = ShaderLanguage::TYPE_VEC2; //whether it could emit
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].stage_functions["sdf_to_screen_uv"] = func;
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].stage_functions["sdf_to_screen_uv"] = func;
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].stage_functions["texture_sdf_normal"] = func;
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].stage_functions["texture_sdf_normal"] = func;
|
||||
}
|
||||
|
||||
{
|
||||
ShaderLanguage::StageFunctionInfo func;
|
||||
func.arguments.push_back(ShaderLanguage::StageFunctionInfo::Argument("uv", ShaderLanguage::TYPE_VEC2));
|
||||
func.return_type = ShaderLanguage::TYPE_VEC2; //whether it could emit
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].stage_functions["screen_uv_to_sdf"] = func;
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].stage_functions["screen_uv_to_sdf"] = func;
|
||||
}
|
||||
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["FRAGCOORD"] = constt(ShaderLanguage::TYPE_VEC4);
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["NORMAL"] = constt(ShaderLanguage::TYPE_VEC3);
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["COLOR"] = constt(ShaderLanguage::TYPE_VEC4);
|
||||
|
@ -1858,7 +1858,6 @@ void RenderingServer::_bind_methods() {
|
||||
|
||||
ClassDB::bind_method(D_METHOD("canvas_occluder_polygon_create"), &RenderingServer::canvas_occluder_polygon_create);
|
||||
ClassDB::bind_method(D_METHOD("canvas_occluder_polygon_set_shape", "occluder_polygon", "shape", "closed"), &RenderingServer::canvas_occluder_polygon_set_shape);
|
||||
ClassDB::bind_method(D_METHOD("canvas_occluder_polygon_set_shape_as_lines", "occluder_polygon", "shape"), &RenderingServer::canvas_occluder_polygon_set_shape_as_lines);
|
||||
ClassDB::bind_method(D_METHOD("canvas_occluder_polygon_set_cull_mode", "occluder_polygon", "mode"), &RenderingServer::canvas_occluder_polygon_set_cull_mode);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("global_variable_add", "name", "type", "default_value"), &RenderingServer::global_variable_add);
|
||||
|
@ -730,6 +730,23 @@ public:
|
||||
virtual void viewport_set_global_canvas_transform(RID p_viewport, const Transform2D &p_transform) = 0;
|
||||
virtual void viewport_set_canvas_stacking(RID p_viewport, RID p_canvas, int p_layer, int p_sublayer) = 0;
|
||||
|
||||
enum ViewportSDFOversize {
|
||||
VIEWPORT_SDF_OVERSIZE_100_PERCENT,
|
||||
VIEWPORT_SDF_OVERSIZE_120_PERCENT,
|
||||
VIEWPORT_SDF_OVERSIZE_150_PERCENT,
|
||||
VIEWPORT_SDF_OVERSIZE_200_PERCENT,
|
||||
VIEWPORT_SDF_OVERSIZE_MAX
|
||||
};
|
||||
|
||||
enum ViewportSDFScale {
|
||||
VIEWPORT_SDF_SCALE_100_PERCENT,
|
||||
VIEWPORT_SDF_SCALE_50_PERCENT,
|
||||
VIEWPORT_SDF_SCALE_25_PERCENT,
|
||||
VIEWPORT_SDF_SCALE_MAX
|
||||
};
|
||||
|
||||
virtual void viewport_set_sdf_oversize_and_scale(RID p_viewport, ViewportSDFOversize p_oversize, ViewportSDFScale p_scale) = 0;
|
||||
|
||||
virtual void viewport_set_shadow_atlas_size(RID p_viewport, int p_size) = 0;
|
||||
virtual void viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv) = 0;
|
||||
|
||||
@ -1245,12 +1262,12 @@ public:
|
||||
virtual void canvas_light_occluder_attach_to_canvas(RID p_occluder, RID p_canvas) = 0;
|
||||
virtual void canvas_light_occluder_set_enabled(RID p_occluder, bool p_enabled) = 0;
|
||||
virtual void canvas_light_occluder_set_polygon(RID p_occluder, RID p_polygon) = 0;
|
||||
virtual void canvas_light_occluder_set_as_sdf_collision(RID p_occluder, bool p_enable) = 0;
|
||||
virtual void canvas_light_occluder_set_transform(RID p_occluder, const Transform2D &p_xform) = 0;
|
||||
virtual void canvas_light_occluder_set_light_mask(RID p_occluder, int p_mask) = 0;
|
||||
|
||||
virtual RID canvas_occluder_polygon_create() = 0;
|
||||
virtual void canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const Vector<Vector2> &p_shape, bool p_closed) = 0;
|
||||
virtual void canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon, const Vector<Vector2> &p_shape) = 0;
|
||||
|
||||
enum CanvasOccluderPolygonCullMode {
|
||||
CANVAS_OCCLUDER_POLYGON_CULL_DISABLED,
|
||||
|
Loading…
Reference in New Issue
Block a user