From a8a1f2e2a864e6b58d5bcf1c7e53a43cdb6d95d9 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Tue, 13 Jun 2017 01:23:04 -0300 Subject: [PATCH] -Fixed occluder rendering, closes #8560 -Ability to smooth out 2D shadow filters --- drivers/gles3/rasterizer_canvas_gles3.cpp | 11 +++-------- drivers/gles3/rasterizer_storage_gles3.cpp | 13 +++++++++++-- drivers/gles3/rasterizer_storage_gles3.h | 1 + drivers/gles3/shaders/canvas.glsl | 2 +- scene/2d/light_2d.cpp | 16 ++++++++++++++++ scene/2d/light_2d.h | 4 ++++ servers/visual/rasterizer.h | 2 ++ servers/visual/visual_server_canvas.cpp | 7 +++++++ servers/visual/visual_server_canvas.h | 1 + servers/visual/visual_server_raster.h | 1 + servers/visual/visual_server_wrap_mt.h | 1 + servers/visual_server.h | 1 + 12 files changed, 49 insertions(+), 11 deletions(-) diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index 55c8346c37..8123feccdc 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -113,7 +113,7 @@ void RasterizerCanvasGLES3::light_internal_update(RID p_rid, Light *p_light) { li->ubo_data.light_pos[0] = p_light->light_shader_pos.x; li->ubo_data.light_pos[1] = p_light->light_shader_pos.y; - li->ubo_data.shadowpixel_size = 1.0 / p_light->shadow_buffer_size; + li->ubo_data.shadowpixel_size = (1.0 / p_light->shadow_buffer_size) * (1.0 + p_light->shadow_smooth); li->ubo_data.light_outside_alpha = p_light->mode == VS::CANVAS_LIGHT_MODE_MASK ? 1.0 : 0.0; li->ubo_data.light_height = p_light->height; if (p_light->radius_cache == 0) @@ -1111,7 +1111,6 @@ void RasterizerCanvasGLES3::canvas_light_shadow_buffer_update(RID p_buffer, cons glBindFramebuffer(GL_FRAMEBUFFER, cls->fbo); - glEnableVertexAttribArray(VS::ARRAY_VERTEX); state.canvas_shadow_shader.bind(); glViewport(0, 0, cls->size, cls->height); @@ -1210,18 +1209,14 @@ void RasterizerCanvasGLES3::canvas_light_shadow_buffer_update(RID p_buffer, cons } } */ - glBindBuffer(GL_ARRAY_BUFFER, cc->vertex_id); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cc->index_id); - glVertexAttribPointer(VS::ARRAY_VERTEX, 3, GL_FLOAT, false, 0, 0); + glBindVertexArray(cc->array_id); glDrawElements(GL_TRIANGLES, cc->len * 3, GL_UNSIGNED_SHORT, 0); instance = instance->next; } } - glDisableVertexAttribArray(VS::ARRAY_VERTEX); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindVertexArray(0); } void RasterizerCanvasGLES3::reset_canvas() { diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 858c543785..cf540c1577 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -6110,6 +6110,7 @@ RID RasterizerStorageGLES3::canvas_light_occluder_create() { co->index_id = 0; co->vertex_id = 0; co->len = 0; + glGenVertexArrays(1, &co->array_id); return canvas_occluder_owner.make_rid(co); } @@ -6181,7 +6182,7 @@ void RasterizerStorageGLES3::canvas_light_occluder_set_polylines(RID p_occluder, if (!co->vertex_id) { glGenBuffers(1, &co->vertex_id); glBindBuffer(GL_ARRAY_BUFFER, co->vertex_id); - glBufferData(GL_ARRAY_BUFFER, lc * 6 * sizeof(real_t), vw.ptr(), GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, lc * 6 * sizeof(real_t), vw.ptr(), GL_DYNAMIC_DRAW); } else { glBindBuffer(GL_ARRAY_BUFFER, co->vertex_id); @@ -6194,7 +6195,7 @@ void RasterizerStorageGLES3::canvas_light_occluder_set_polylines(RID p_occluder, glGenBuffers(1, &co->index_id); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, co->index_id); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, lc * 3 * sizeof(uint16_t), iw.ptr(), GL_STATIC_DRAW); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, lc * 3 * sizeof(uint16_t), iw.ptr(), GL_DYNAMIC_DRAW); } else { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, co->index_id); @@ -6204,6 +6205,12 @@ void RasterizerStorageGLES3::canvas_light_occluder_set_polylines(RID p_occluder, glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); //unbind co->len = lc; + glBindVertexArray(co->array_id); + glBindBuffer(GL_ARRAY_BUFFER, co->vertex_id); + glEnableVertexAttribArray(VS::ARRAY_VERTEX); + glVertexAttribPointer(VS::ARRAY_VERTEX, 3, GL_FLOAT, false, 0, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, co->index_id); + glBindVertexArray(0); } } @@ -6432,6 +6439,8 @@ bool RasterizerStorageGLES3::free(RID p_rid) { if (co->vertex_id) glDeleteBuffers(1, &co->vertex_id); + glDeleteVertexArrays(1, &co->array_id); + canvas_occluder_owner.free(p_rid); memdelete(co); diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index 1357206bfa..1f101b8b61 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -1285,6 +1285,7 @@ public: struct CanvasOccluder : public RID_Data { + GLuint array_id; // 0 means, unconfigured GLuint vertex_id; // 0 means, unconfigured GLuint index_id; // 0 means, unconfigured PoolVector lines; diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl index 017009015e..d6850b535e 100644 --- a/drivers/gles3/shaders/canvas.glsl +++ b/drivers/gles3/shaders/canvas.glsl @@ -381,7 +381,7 @@ FRAGMENT_SHADER_CODE #ifdef SHADOW_FILTER_NEAREST - SHADOW_TEST(su+shadowpixel_size); + SHADOW_TEST(su); #endif diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp index 34413074c1..e8c2122bd1 100644 --- a/scene/2d/light_2d.cpp +++ b/scene/2d/light_2d.cpp @@ -336,6 +336,17 @@ String Light2D::get_configuration_warning() const { return String(); } +void Light2D::set_shadow_smooth(float p_amount) { + + shadow_smooth = p_amount; + VS::get_singleton()->canvas_light_set_shadow_smooth(canvas_light, shadow_smooth); +} + +float Light2D::get_shadow_smooth() const { + + return shadow_smooth; +} + void Light2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &Light2D::set_enabled); @@ -389,6 +400,9 @@ void Light2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_shadow_buffer_size", "size"), &Light2D::set_shadow_buffer_size); ClassDB::bind_method(D_METHOD("get_shadow_buffer_size"), &Light2D::get_shadow_buffer_size); + ClassDB::bind_method(D_METHOD("set_shadow_smooth", "smooth"), &Light2D::set_shadow_smooth); + ClassDB::bind_method(D_METHOD("get_shadow_smooth"), &Light2D::get_shadow_smooth); + ClassDB::bind_method(D_METHOD("set_shadow_gradient_length", "multiplier"), &Light2D::set_shadow_gradient_length); ClassDB::bind_method(D_METHOD("get_shadow_gradient_length"), &Light2D::get_shadow_gradient_length); @@ -420,6 +434,7 @@ void Light2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_buffer_size", PROPERTY_HINT_RANGE, "32,16384,1"), "set_shadow_buffer_size", "get_shadow_buffer_size"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "shadow_gradient_length", PROPERTY_HINT_RANGE, "1,4096,0.1"), "set_shadow_gradient_length", "get_shadow_gradient_length"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "shadow_filter", PROPERTY_HINT_ENUM, "None,PCF3,PCF5,PCF9,PCF13"), "set_shadow_filter", "get_shadow_filter"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "shadow_filter_smooth", PROPERTY_HINT_RANGE, "0,64,0.1"), "set_shadow_smooth", "get_shadow_smooth"); ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_item_cull_mask", PROPERTY_HINT_LAYERS_2D_RENDER), "set_item_shadow_cull_mask", "get_item_shadow_cull_mask"); BIND_CONSTANT(MODE_ADD); @@ -449,6 +464,7 @@ Light2D::Light2D() { energy = 1.0; shadow_color = Color(0, 0, 0, 0); shadow_filter = SHADOW_FILTER_NONE; + shadow_smooth = 0; set_notify_transform(true); } diff --git a/scene/2d/light_2d.h b/scene/2d/light_2d.h index 9b09d54dd8..90e55aeda4 100644 --- a/scene/2d/light_2d.h +++ b/scene/2d/light_2d.h @@ -69,6 +69,7 @@ private: int item_mask; int item_shadow_mask; int shadow_buffer_size; + float shadow_smooth; float shadow_gradient_length; Mode mode; Ref texture; @@ -146,6 +147,9 @@ public: void set_shadow_color(const Color &p_shadow_color); Color get_shadow_color() const; + void set_shadow_smooth(float p_amount); + float get_shadow_smooth() const; + virtual Rect2 get_item_rect() const; String get_configuration_warning() const; diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index eb06c64c40..c5fc2fe8af 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -546,6 +546,7 @@ public: float shadow_gradient_length; VS::CanvasLightShadowFilter shadow_filter; Color shadow_color; + float shadow_smooth; void *texture_cache; // implementation dependent Rect2 rect_cache; @@ -584,6 +585,7 @@ public: shadow_buffer_size = 256; shadow_gradient_length = 0; shadow_filter = VS::CANVAS_LIGHT_FILTER_NONE; + shadow_smooth = 0.0; } }; diff --git a/servers/visual/visual_server_canvas.cpp b/servers/visual/visual_server_canvas.cpp index 14a7af3e6e..48e6a3d006 100644 --- a/servers/visual/visual_server_canvas.cpp +++ b/servers/visual/visual_server_canvas.cpp @@ -916,6 +916,13 @@ void VisualServerCanvas::canvas_light_set_shadow_color(RID p_light, const Color clight->shadow_color = p_color; } +void VisualServerCanvas::canvas_light_set_shadow_smooth(RID p_light, float p_smooth) { + + RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + clight->shadow_smooth = p_smooth; +} + RID VisualServerCanvas::canvas_light_occluder_create() { RasterizerCanvas::LightOccluderInstance *occluder = memnew(RasterizerCanvas::LightOccluderInstance); diff --git a/servers/visual/visual_server_canvas.h b/servers/visual/visual_server_canvas.h index 47b057f96a..b4ddf2dc8e 100644 --- a/servers/visual/visual_server_canvas.h +++ b/servers/visual/visual_server_canvas.h @@ -209,6 +209,7 @@ public: void canvas_light_set_shadow_gradient_length(RID p_light, float p_length); void canvas_light_set_shadow_filter(RID p_light, VS::CanvasLightShadowFilter p_filter); void canvas_light_set_shadow_color(RID p_light, const Color &p_color); + void canvas_light_set_shadow_smooth(RID p_light, float p_smooth); RID canvas_light_occluder_create(); void canvas_light_occluder_attach_to_canvas(RID p_occluder, RID p_canvas); diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index b4b43a31be..dc44755726 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -1082,6 +1082,7 @@ public: BIND2(canvas_light_set_shadow_gradient_length, RID, float) BIND2(canvas_light_set_shadow_filter, RID, CanvasLightShadowFilter) BIND2(canvas_light_set_shadow_color, RID, const Color &) + BIND2(canvas_light_set_shadow_smooth, RID, float) BIND0R(RID, canvas_light_occluder_create) BIND2(canvas_light_occluder_attach_to_canvas, RID, RID) diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index 6d65999df1..05d8fb3dcd 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -511,6 +511,7 @@ public: FUNC2(canvas_light_set_shadow_gradient_length, RID, float) FUNC2(canvas_light_set_shadow_filter, RID, CanvasLightShadowFilter) FUNC2(canvas_light_set_shadow_color, RID, const Color &) + FUNC2(canvas_light_set_shadow_smooth, RID, float) FUNC0R(RID, canvas_light_occluder_create) FUNC2(canvas_light_occluder_attach_to_canvas, RID, RID) diff --git a/servers/visual_server.h b/servers/visual_server.h index 3290a460a1..4f2f9d30fa 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -844,6 +844,7 @@ public: virtual void canvas_light_set_shadow_gradient_length(RID p_light, float p_length) = 0; virtual void canvas_light_set_shadow_filter(RID p_light, CanvasLightShadowFilter p_filter) = 0; virtual void canvas_light_set_shadow_color(RID p_light, const Color &p_color) = 0; + virtual void canvas_light_set_shadow_smooth(RID p_light, float p_smooth) = 0; virtual RID canvas_light_occluder_create() = 0; virtual void canvas_light_occluder_attach_to_canvas(RID p_occluder, RID p_canvas) = 0;