From bcc3643989762a6814f1f0c5a4b63a0e66d6286c Mon Sep 17 00:00:00 2001 From: bruvzg <7645683+bruvzg@users.noreply.github.com> Date: Fri, 12 Aug 2022 14:03:28 +0300 Subject: Add font LCD sub-pixel anti-aliasing support. --- .../renderer_rd/renderer_canvas_render_rd.cpp | 74 ++++++++++++++++++---- .../renderer_rd/renderer_canvas_render_rd.h | 2 + servers/rendering/renderer_rd/shaders/canvas.glsl | 8 ++- .../renderer_rd/shaders/canvas_uniforms_inc.glsl | 1 + 4 files changed, 73 insertions(+), 12 deletions(-) (limited to 'servers/rendering/renderer_rd') diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index 38a2340d40..937585c98b 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -494,7 +494,11 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend } //bind pipeline - { + if (rect->flags & CANVAS_RECT_LCD) { + RID pipeline = pipeline_variants->variants[light_mode][PIPELINE_VARIANT_QUAD_LCD_BLEND].get_render_pipeline(RD::INVALID_ID, p_framebuffer_format); + RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline); + RD::get_singleton()->draw_list_set_blend_constants(p_draw_list, rect->modulate); + } else { RID pipeline = pipeline_variants->variants[light_mode][PIPELINE_VARIANT_QUAD].get_render_pipeline(RD::INVALID_ID, p_framebuffer_format); RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline); } @@ -556,6 +560,8 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend push_constant.msdf[1] = rect->outline; // Outline size. push_constant.msdf[2] = 0.f; // Reserved. push_constant.msdf[3] = 0.f; // Reserved. + } else if (rect->flags & CANVAS_RECT_LCD) { + push_constant.flags |= FLAGS_USE_LCD; } push_constant.modulation[0] = rect->modulate.r * base_color.r; @@ -2113,6 +2119,18 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) { RD::PipelineColorBlendState blend_state; blend_state.attachments.push_back(attachment); + RD::PipelineColorBlendState::Attachment attachment_lcd; + attachment_lcd.enable_blend = true; + attachment_lcd.alpha_blend_op = RD::BLEND_OP_ADD; + attachment_lcd.color_blend_op = RD::BLEND_OP_ADD; + attachment_lcd.src_color_blend_factor = RD::BLEND_FACTOR_CONSTANT_COLOR; + attachment_lcd.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_COLOR; + attachment_lcd.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE; + attachment_lcd.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + + RD::PipelineColorBlendState blend_state_lcd; + blend_state_lcd.attachments.push_back(attachment_lcd); + //update pipelines for (int i = 0; i < PIPELINE_LIGHT_MODE_MAX; i++) { @@ -2128,10 +2146,12 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) { RD::RENDER_PRIMITIVE_LINES, RD::RENDER_PRIMITIVE_LINESTRIPS, RD::RENDER_PRIMITIVE_POINTS, + RD::RENDER_PRIMITIVE_TRIANGLES, }; ShaderVariant shader_variants[PIPELINE_LIGHT_MODE_MAX][PIPELINE_VARIANT_MAX] = { - { //non lit + { + //non lit SHADER_VARIANT_QUAD, SHADER_VARIANT_NINEPATCH, SHADER_VARIANT_PRIMITIVE, @@ -2141,8 +2161,11 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) { SHADER_VARIANT_ATTRIBUTES, SHADER_VARIANT_ATTRIBUTES, SHADER_VARIANT_ATTRIBUTES, - SHADER_VARIANT_ATTRIBUTES_POINTS }, - { //lit + SHADER_VARIANT_ATTRIBUTES_POINTS, + SHADER_VARIANT_QUAD, + }, + { + //lit SHADER_VARIANT_QUAD_LIGHT, SHADER_VARIANT_NINEPATCH_LIGHT, SHADER_VARIANT_PRIMITIVE_LIGHT, @@ -2152,11 +2175,17 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) { SHADER_VARIANT_ATTRIBUTES_LIGHT, SHADER_VARIANT_ATTRIBUTES_LIGHT, SHADER_VARIANT_ATTRIBUTES_LIGHT, - SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT }, + SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT, + SHADER_VARIANT_QUAD_LIGHT, + }, }; RID shader_variant = canvas_singleton->shader.canvas_shader.version_get_shader(version, shader_variants[i][j]); - pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0); + if (j == PIPELINE_VARIANT_QUAD_LCD_BLEND) { + pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state_lcd, RD::DYNAMIC_STATE_BLEND_CONSTANTS); + } else { + pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0); + } } } @@ -2363,6 +2392,18 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() { blend_state.attachments.push_back(blend_attachment); + RD::PipelineColorBlendState::Attachment attachment_lcd; + attachment_lcd.enable_blend = true; + attachment_lcd.alpha_blend_op = RD::BLEND_OP_ADD; + attachment_lcd.color_blend_op = RD::BLEND_OP_ADD; + attachment_lcd.src_color_blend_factor = RD::BLEND_FACTOR_CONSTANT_COLOR; + attachment_lcd.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_COLOR; + attachment_lcd.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE; + attachment_lcd.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + + RD::PipelineColorBlendState blend_state_lcd; + blend_state_lcd.attachments.push_back(attachment_lcd); + for (int i = 0; i < PIPELINE_LIGHT_MODE_MAX; i++) { for (int j = 0; j < PIPELINE_VARIANT_MAX; j++) { RD::RenderPrimitive primitive[PIPELINE_VARIANT_MAX] = { @@ -2376,10 +2417,12 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() { RD::RENDER_PRIMITIVE_LINES, RD::RENDER_PRIMITIVE_LINESTRIPS, RD::RENDER_PRIMITIVE_POINTS, + RD::RENDER_PRIMITIVE_TRIANGLES, }; ShaderVariant shader_variants[PIPELINE_LIGHT_MODE_MAX][PIPELINE_VARIANT_MAX] = { - { //non lit + { + //non lit SHADER_VARIANT_QUAD, SHADER_VARIANT_NINEPATCH, SHADER_VARIANT_PRIMITIVE, @@ -2389,8 +2432,11 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() { SHADER_VARIANT_ATTRIBUTES, SHADER_VARIANT_ATTRIBUTES, SHADER_VARIANT_ATTRIBUTES, - SHADER_VARIANT_ATTRIBUTES_POINTS }, - { //lit + SHADER_VARIANT_ATTRIBUTES_POINTS, + SHADER_VARIANT_QUAD, + }, + { + //lit SHADER_VARIANT_QUAD_LIGHT, SHADER_VARIANT_NINEPATCH_LIGHT, SHADER_VARIANT_PRIMITIVE_LIGHT, @@ -2400,11 +2446,17 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() { SHADER_VARIANT_ATTRIBUTES_LIGHT, SHADER_VARIANT_ATTRIBUTES_LIGHT, SHADER_VARIANT_ATTRIBUTES_LIGHT, - SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT }, + SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT, + SHADER_VARIANT_QUAD_LIGHT, + }, }; RID shader_variant = shader.canvas_shader.version_get_shader(shader.default_version, shader_variants[i][j]); - shader.pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0); + if (j == PIPELINE_VARIANT_QUAD_LCD_BLEND) { + shader.pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state_lcd, RD::DYNAMIC_STATE_BLEND_CONSTANTS); + } else { + shader.pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0); + } } } } diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h index bcbbbaa1a0..54077a5b9a 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h @@ -85,6 +85,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender { FLAGS_DEFAULT_SPECULAR_MAP_USED = (1 << 27), FLAGS_USE_MSDF = (1 << 28), + FLAGS_USE_LCD = (1 << 29), }; enum { @@ -122,6 +123,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender { PIPELINE_VARIANT_ATTRIBUTE_LINES, PIPELINE_VARIANT_ATTRIBUTE_LINES_STRIP, PIPELINE_VARIANT_ATTRIBUTE_POINTS, + PIPELINE_VARIANT_QUAD_LCD_BLEND, PIPELINE_VARIANT_MAX }; enum PipelineLightMode { diff --git a/servers/rendering/renderer_rd/shaders/canvas.glsl b/servers/rendering/renderer_rd/shaders/canvas.glsl index f8e9020f9f..459d798a80 100644 --- a/servers/rendering/renderer_rd/shaders/canvas.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas.glsl @@ -509,7 +509,13 @@ void main() { float a = clamp(d * px_size + 0.5, 0.0, 1.0); color.a = a * color.a; } - + } else if (bool(draw_data.flags & FLAGS_USE_LCD)) { + vec4 lcd_sample = texture(sampler2D(color_texture, texture_sampler), uv); + if (lcd_sample.a == 1.0) { + color.rgb = lcd_sample.rgb * color.a; + } else { + color = vec4(0.0, 0.0, 0.0, 0.0); + } } else { #else { diff --git a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl index 2ea6965c09..1b627a3e81 100644 --- a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl @@ -25,6 +25,7 @@ #define FLAGS_DEFAULT_SPECULAR_MAP_USED (1 << 27) #define FLAGS_USE_MSDF (1 << 28) +#define FLAGS_USE_LCD (1 << 29) #define SAMPLER_NEAREST_CLAMP 0 #define SAMPLER_LINEAR_CLAMP 1 -- cgit v1.2.3