Skip to content

Commit

Permalink
Merge pull request #43886 from reduz/sdf-2d
Browse files Browse the repository at this point in the history
Implement Signed Distance Fields for 2D shaders
  • Loading branch information
akien-mga authored Nov 26, 2020
2 parents 4e5625c + 1bcf3c3 commit 0a54dcb
Show file tree
Hide file tree
Showing 26 changed files with 1,028 additions and 89 deletions.
5 changes: 5 additions & 0 deletions editor/editor_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
14 changes: 14 additions & 0 deletions scene/2d/light_occluder_2d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -265,21 +265,35 @@ 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);

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() {
Expand Down
5 changes: 4 additions & 1 deletion scene/2d/light_occluder_2d.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ class LightOccluder2D : public Node2D {
bool enabled;
int mask;
Ref<OccluderPolygon2D> occluder_polygon;

bool sdf_collision;
void _poly_changed();

protected:
Expand All @@ -103,6 +103,9 @@ class LightOccluder2D : public Node2D {
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();
Expand Down
8 changes: 8 additions & 0 deletions scene/main/scene_tree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
42 changes: 42 additions & 0 deletions scene/main/viewport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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");
Expand All @@ -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);
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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() {
Expand Down
26 changes: 26 additions & 0 deletions scene/main/viewport.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,21 @@ class Viewport : public Node {
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
};
Expand Down Expand Up @@ -285,6 +300,9 @@ class Viewport : public Node {
Ref<ViewportTexture> default_texture;
Set<ViewportTexture *> viewport_textures;

SDFOversize sdf_oversize;
SDFScale sdf_scale;

enum SubWindowDrag {
SUB_WINDOW_DRAG_DISABLED,
SUB_WINDOW_DRAG_MOVE,
Expand Down Expand Up @@ -572,6 +590,12 @@ class Viewport : public Node {

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;

Expand Down Expand Up @@ -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);
Expand Down
11 changes: 9 additions & 2 deletions servers/rendering/rasterizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -752,6 +752,9 @@ class RasterizerStorage {
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;

Expand Down Expand Up @@ -1324,7 +1327,7 @@ class RasterizerCanvas {
}
};

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 {
Expand All @@ -1336,12 +1339,14 @@ class RasterizerCanvas {
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;
Expand All @@ -1354,8 +1359,10 @@ class RasterizerCanvas {
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;

Expand Down
Loading

0 comments on commit 0a54dcb

Please sign in to comment.