diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index e034878aaf2d7..36079fa1b8430 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -570,7 +570,17 @@ FILE: ../../../flutter/impeller/entity/entity_unittests.cc FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend.glsl FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend.vert FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_colorburn.frag +FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_colordodge.frag +FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_darken.frag +FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_difference.frag +FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_exclusion.frag +FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_hardlight.frag +FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_lighten.frag +FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_multiply.frag +FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_overlay.frag FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_screen.frag +FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_softlight.frag +FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_utils.glsl FILE: ../../../flutter/impeller/entity/shaders/blending/blend.frag FILE: ../../../flutter/impeller/entity/shaders/blending/blend.vert FILE: ../../../flutter/impeller/entity/shaders/border_mask_blur.frag diff --git a/impeller/aiks/aiks_unittests.cc b/impeller/aiks/aiks_unittests.cc index 7a1acabc8408f..1adcd168faa62 100644 --- a/impeller/aiks/aiks_unittests.cc +++ b/impeller/aiks/aiks_unittests.cc @@ -534,7 +534,16 @@ TEST_P(AiksTest, ColorWheel) { {"Modulate", Entity::BlendMode::kModulate}, // Advanced blends (color component blends) {"Screen", Entity::BlendMode::kScreen}, + {"Overlay", Entity::BlendMode::kOverlay}, + {"Darken", Entity::BlendMode::kDarken}, + {"Lighten", Entity::BlendMode::kLighten}, + {"ColorDodge", Entity::BlendMode::kColorDodge}, {"ColorBurn", Entity::BlendMode::kColorBurn}, + {"HardLight", Entity::BlendMode::kHardLight}, + {"SoftLight", Entity::BlendMode::kSoftLight}, + {"Difference", Entity::BlendMode::kDifference}, + {"Exclusion", Entity::BlendMode::kExclusion}, + {"Multiply", Entity::BlendMode::kMultiply}, }; assert(blends.size() == static_cast(Entity::BlendMode::kLastAdvancedBlendMode) + 1); diff --git a/impeller/display_list/display_list_dispatcher.cc b/impeller/display_list/display_list_dispatcher.cc index ec25ec44ebfcf..02b3414b8e0a3 100644 --- a/impeller/display_list/display_list_dispatcher.cc +++ b/impeller/display_list/display_list_dispatcher.cc @@ -66,17 +66,26 @@ static std::optional ToBlendMode(flutter::DlBlendMode mode) { return Entity::BlendMode::kModulate; case flutter::DlBlendMode::kScreen: return Entity::BlendMode::kScreen; - case flutter::DlBlendMode::kColorBurn: - return Entity::BlendMode::kColorBurn; case flutter::DlBlendMode::kOverlay: + return Entity::BlendMode::kOverlay; case flutter::DlBlendMode::kDarken: + return Entity::BlendMode::kDarken; case flutter::DlBlendMode::kLighten: + return Entity::BlendMode::kLighten; case flutter::DlBlendMode::kColorDodge: + return Entity::BlendMode::kColorDodge; + case flutter::DlBlendMode::kColorBurn: + return Entity::BlendMode::kColorBurn; case flutter::DlBlendMode::kHardLight: + return Entity::BlendMode::kHardLight; case flutter::DlBlendMode::kSoftLight: + return Entity::BlendMode::kSoftLight; case flutter::DlBlendMode::kDifference: + return Entity::BlendMode::kDifference; case flutter::DlBlendMode::kExclusion: + return Entity::BlendMode::kExclusion; case flutter::DlBlendMode::kMultiply: + return Entity::BlendMode::kMultiply; case flutter::DlBlendMode::kHue: case flutter::DlBlendMode::kSaturation: case flutter::DlBlendMode::kColor: diff --git a/impeller/entity/BUILD.gn b/impeller/entity/BUILD.gn index 3de1d3f68363c..b15c495aa2214 100644 --- a/impeller/entity/BUILD.gn +++ b/impeller/entity/BUILD.gn @@ -10,7 +10,16 @@ impeller_shaders("entity_shaders") { shaders = [ "shaders/blending/advanced_blend.vert", "shaders/blending/advanced_blend_colorburn.frag", + "shaders/blending/advanced_blend_colordodge.frag", + "shaders/blending/advanced_blend_darken.frag", + "shaders/blending/advanced_blend_difference.frag", + "shaders/blending/advanced_blend_exclusion.frag", + "shaders/blending/advanced_blend_hardlight.frag", + "shaders/blending/advanced_blend_lighten.frag", + "shaders/blending/advanced_blend_multiply.frag", + "shaders/blending/advanced_blend_overlay.frag", "shaders/blending/advanced_blend_screen.frag", + "shaders/blending/advanced_blend_softlight.frag", "shaders/blending/blend.frag", "shaders/blending/blend.vert", "shaders/border_mask_blur.frag", diff --git a/impeller/entity/contents/content_context.cc b/impeller/entity/contents/content_context.cc index 2ccd0232f69e7..318ed476d8260 100644 --- a/impeller/entity/contents/content_context.cc +++ b/impeller/entity/contents/content_context.cc @@ -155,10 +155,28 @@ ContentContext::ContentContext(std::shared_ptr context) CreateDefaultPipeline(*context_); texture_blend_pipelines_[{}] = CreateDefaultPipeline(*context_); + blend_colorburn_pipelines_[{}] = + CreateDefaultPipeline(*context_); + blend_colordodge_pipelines_[{}] = + CreateDefaultPipeline(*context_); + blend_darken_pipelines_[{}] = + CreateDefaultPipeline(*context_); + blend_difference_pipelines_[{}] = + CreateDefaultPipeline(*context_); + blend_exclusion_pipelines_[{}] = + CreateDefaultPipeline(*context_); + blend_hardlight_pipelines_[{}] = + CreateDefaultPipeline(*context_); + blend_lighten_pipelines_[{}] = + CreateDefaultPipeline(*context_); + blend_multiply_pipelines_[{}] = + CreateDefaultPipeline(*context_); + blend_overlay_pipelines_[{}] = + CreateDefaultPipeline(*context_); blend_screen_pipelines_[{}] = CreateDefaultPipeline(*context_); - blend_colorburn_pipelines_[{}] = - CreateDefaultPipeline(*context_); + blend_softlight_pipelines_[{}] = + CreateDefaultPipeline(*context_); texture_pipelines_[{}] = CreateDefaultPipeline(*context_); gaussian_blur_pipelines_[{}] = CreateDefaultPipeline(*context_); diff --git a/impeller/entity/contents/content_context.h b/impeller/entity/contents/content_context.h index 91c6bdbd9c253..3c26d738c8800 100644 --- a/impeller/entity/contents/content_context.h +++ b/impeller/entity/contents/content_context.h @@ -13,7 +13,16 @@ #include "impeller/base/validation.h" #include "impeller/entity/advanced_blend.vert.h" #include "impeller/entity/advanced_blend_colorburn.frag.h" +#include "impeller/entity/advanced_blend_colordodge.frag.h" +#include "impeller/entity/advanced_blend_darken.frag.h" +#include "impeller/entity/advanced_blend_difference.frag.h" +#include "impeller/entity/advanced_blend_exclusion.frag.h" +#include "impeller/entity/advanced_blend_hardlight.frag.h" +#include "impeller/entity/advanced_blend_lighten.frag.h" +#include "impeller/entity/advanced_blend_multiply.frag.h" +#include "impeller/entity/advanced_blend_overlay.frag.h" #include "impeller/entity/advanced_blend_screen.frag.h" +#include "impeller/entity/advanced_blend_softlight.frag.h" #include "impeller/entity/blend.frag.h" #include "impeller/entity/blend.vert.h" #include "impeller/entity/border_mask_blur.frag.h" @@ -42,10 +51,28 @@ using GradientFillPipeline = using SolidFillPipeline = PipelineT; using BlendPipeline = PipelineT; +using BlendColorBurnPipeline = + PipelineT; +using BlendColorDodgePipeline = + PipelineT; +using BlendDarkenPipeline = + PipelineT; +using BlendDifferencePipeline = + PipelineT; +using BlendExclusionPipeline = + PipelineT; +using BlendHardLightPipeline = + PipelineT; +using BlendLightenPipeline = + PipelineT; +using BlendMultiplyPipeline = + PipelineT; +using BlendOverlayPipeline = + PipelineT; using BlendScreenPipeline = PipelineT; -using BlendColorburnPipeline = - PipelineT; +using BlendSoftLightPipeline = + PipelineT; using TexturePipeline = PipelineT; using GaussianBlurPipeline = @@ -110,16 +137,6 @@ class ContentContext { return GetPipeline(texture_blend_pipelines_, opts); } - std::shared_ptr GetBlendScreenPipeline( - ContentContextOptions opts) const { - return GetPipeline(blend_screen_pipelines_, opts); - } - - std::shared_ptr GetBlendColorburnPipeline( - ContentContextOptions opts) const { - return GetPipeline(blend_colorburn_pipelines_, opts); - } - std::shared_ptr GetTexturePipeline( ContentContextOptions opts) const { return GetPipeline(texture_pipelines_, opts); @@ -154,6 +171,63 @@ class ContentContext { return GetPipeline(vertices_pipelines_, opts); } + // Advanced blends. + + std::shared_ptr GetBlendColorBurnPipeline( + ContentContextOptions opts) const { + return GetPipeline(blend_colorburn_pipelines_, opts); + } + + std::shared_ptr GetBlendColorDodgePipeline( + ContentContextOptions opts) const { + return GetPipeline(blend_colordodge_pipelines_, opts); + } + + std::shared_ptr GetBlendDarkenPipeline( + ContentContextOptions opts) const { + return GetPipeline(blend_darken_pipelines_, opts); + } + + std::shared_ptr GetBlendDifferencePipeline( + ContentContextOptions opts) const { + return GetPipeline(blend_difference_pipelines_, opts); + } + + std::shared_ptr GetBlendExclusionPipeline( + ContentContextOptions opts) const { + return GetPipeline(blend_exclusion_pipelines_, opts); + } + + std::shared_ptr GetBlendHardLightPipeline( + ContentContextOptions opts) const { + return GetPipeline(blend_hardlight_pipelines_, opts); + } + + std::shared_ptr GetBlendLightenPipeline( + ContentContextOptions opts) const { + return GetPipeline(blend_lighten_pipelines_, opts); + } + + std::shared_ptr GetBlendMultiplyPipeline( + ContentContextOptions opts) const { + return GetPipeline(blend_multiply_pipelines_, opts); + } + + std::shared_ptr GetBlendOverlayPipeline( + ContentContextOptions opts) const { + return GetPipeline(blend_overlay_pipelines_, opts); + } + + std::shared_ptr GetBlendScreenPipeline( + ContentContextOptions opts) const { + return GetPipeline(blend_screen_pipelines_, opts); + } + + std::shared_ptr GetBlendSoftLightPipeline( + ContentContextOptions opts) const { + return GetPipeline(blend_softlight_pipelines_, opts); + } + std::shared_ptr GetContext() const; using SubpassCallback = @@ -179,8 +253,6 @@ class ContentContext { mutable Variants gradient_fill_pipelines_; mutable Variants solid_fill_pipelines_; mutable Variants texture_blend_pipelines_; - mutable Variants blend_screen_pipelines_; - mutable Variants blend_colorburn_pipelines_; mutable Variants texture_pipelines_; mutable Variants gaussian_blur_pipelines_; mutable Variants border_mask_blur_pipelines_; @@ -188,6 +260,18 @@ class ContentContext { mutable Variants clip_pipelines_; mutable Variants glyph_atlas_pipelines_; mutable Variants vertices_pipelines_; + // Advanced blends. + mutable Variants blend_colorburn_pipelines_; + mutable Variants blend_colordodge_pipelines_; + mutable Variants blend_darken_pipelines_; + mutable Variants blend_difference_pipelines_; + mutable Variants blend_exclusion_pipelines_; + mutable Variants blend_hardlight_pipelines_; + mutable Variants blend_lighten_pipelines_; + mutable Variants blend_multiply_pipelines_; + mutable Variants blend_overlay_pipelines_; + mutable Variants blend_screen_pipelines_; + mutable Variants blend_softlight_pipelines_; template std::shared_ptr GetPipeline(Variants& container, diff --git a/impeller/entity/contents/filters/blend_filter_contents.cc b/impeller/entity/contents/filters/blend_filter_contents.cc index d108b65abde49..1c0988c8969e2 100644 --- a/impeller/entity/contents/filters/blend_filter_contents.cc +++ b/impeller/entity/contents/filters/blend_filter_contents.cc @@ -216,6 +216,18 @@ static bool PipelineBlend(const FilterInput::Vector& inputs, return true; } +#define BLEND_CASE(mode) \ + case Entity::BlendMode::k##mode: \ + advanced_blend_proc_ = \ + [](const FilterInput::Vector& inputs, const ContentContext& renderer, \ + const Entity& entity, RenderPass& pass, const Rect& coverage, \ + std::optional fg_color) { \ + PipelineProc p = &ContentContext::GetBlend##mode##Pipeline; \ + return AdvancedBlend( \ + inputs, renderer, entity, pass, coverage, fg_color, p); \ + }; \ + break; + void BlendFilterContents::SetBlendMode(Entity::BlendMode blend_mode) { if (blend_mode > Entity::BlendMode::kLastAdvancedBlendMode) { VALIDATION_LOG << "Invalid blend mode " << static_cast(blend_mode) @@ -226,31 +238,20 @@ void BlendFilterContents::SetBlendMode(Entity::BlendMode blend_mode) { if (blend_mode > Entity::BlendMode::kLastPipelineBlendMode) { static_assert(Entity::BlendMode::kLastAdvancedBlendMode == - Entity::BlendMode::kColorBurn); + Entity::BlendMode::kMultiply); switch (blend_mode) { - case Entity::BlendMode::kScreen: - advanced_blend_proc_ = [](const FilterInput::Vector& inputs, - const ContentContext& renderer, - const Entity& entity, RenderPass& pass, - const Rect& coverage, - std::optional fg_color) { - PipelineProc p = &ContentContext::GetBlendScreenPipeline; - return AdvancedBlend( - inputs, renderer, entity, pass, coverage, fg_color, p); - }; - break; - case Entity::BlendMode::kColorBurn: - advanced_blend_proc_ = [](const FilterInput::Vector& inputs, - const ContentContext& renderer, - const Entity& entity, RenderPass& pass, - const Rect& coverage, - std::optional fg_color) { - PipelineProc p = &ContentContext::GetBlendColorburnPipeline; - return AdvancedBlend( - inputs, renderer, entity, pass, coverage, fg_color, p); - }; - break; + BLEND_CASE(Screen) + BLEND_CASE(Overlay) + BLEND_CASE(Darken) + BLEND_CASE(Lighten) + BLEND_CASE(ColorDodge) + BLEND_CASE(ColorBurn) + BLEND_CASE(HardLight) + BLEND_CASE(SoftLight) + BLEND_CASE(Difference) + BLEND_CASE(Exclusion) + BLEND_CASE(Multiply) default: FML_UNREACHABLE(); } diff --git a/impeller/entity/entity.h b/impeller/entity/entity.h index f1fea96b3e7b6..dec0c15605dd8 100644 --- a/impeller/entity/entity.h +++ b/impeller/entity/entity.h @@ -43,10 +43,19 @@ class Entity { // pipelines on most graphics devices without extensions, and so they are // only able to be used via `BlendFilterContents`. kScreen, + kOverlay, + kDarken, + kLighten, + kColorDodge, kColorBurn, + kHardLight, + kSoftLight, + kDifference, + kExclusion, + kMultiply, kLastPipelineBlendMode = kModulate, - kLastAdvancedBlendMode = kColorBurn, + kLastAdvancedBlendMode = kMultiply, }; enum class ClipOperation { diff --git a/impeller/entity/shaders/blending/advanced_blend_colorburn.frag b/impeller/entity/shaders/blending/advanced_blend_colorburn.frag index 57e962da533f1..3449f5d6e9c49 100644 --- a/impeller/entity/shaders/blending/advanced_blend_colorburn.frag +++ b/impeller/entity/shaders/blending/advanced_blend_colorburn.frag @@ -2,11 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -vec3 ComponentIsValue(vec3 n, float value) { - return vec3(n.r == value, n.g == value, n.b == value); -} +#include "advanced_blend_utils.glsl" vec3 Blend(vec3 dst, vec3 src) { + // https://www.w3.org/TR/compositing-1/#blendingcolorburn vec3 color = 1 - min(vec3(1), (1 - dst) / src); color = mix(color, vec3(1), ComponentIsValue(dst, 1.0)); color = mix(color, vec3(0), ComponentIsValue(src, 0.0)); diff --git a/impeller/entity/shaders/blending/advanced_blend_colordodge.frag b/impeller/entity/shaders/blending/advanced_blend_colordodge.frag new file mode 100644 index 0000000000000..6fca72bea7990 --- /dev/null +++ b/impeller/entity/shaders/blending/advanced_blend_colordodge.frag @@ -0,0 +1,15 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "advanced_blend_utils.glsl" + +vec3 Blend(vec3 dst, vec3 src) { + // https://www.w3.org/TR/compositing-1/#blendingcolordodge + vec3 color = min(vec3(1), dst / (1 - src)); + color = mix(color, vec3(0), ComponentIsValue(dst, 0.0)); + color = mix(color, vec3(1), ComponentIsValue(src, 1.0)); + return color; +} + +#include "advanced_blend.glsl" diff --git a/impeller/entity/shaders/blending/advanced_blend_darken.frag b/impeller/entity/shaders/blending/advanced_blend_darken.frag new file mode 100644 index 0000000000000..bfc8cb20e22b9 --- /dev/null +++ b/impeller/entity/shaders/blending/advanced_blend_darken.frag @@ -0,0 +1,10 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +vec3 Blend(vec3 dst, vec3 src) { + // https://www.w3.org/TR/compositing-1/#blendingdarken + return min(dst, src); +} + +#include "advanced_blend.glsl" diff --git a/impeller/entity/shaders/blending/advanced_blend_difference.frag b/impeller/entity/shaders/blending/advanced_blend_difference.frag new file mode 100644 index 0000000000000..7545bc08b55cd --- /dev/null +++ b/impeller/entity/shaders/blending/advanced_blend_difference.frag @@ -0,0 +1,10 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +vec3 Blend(vec3 dst, vec3 src) { + // https://www.w3.org/TR/compositing-1/#blendingdifference + return abs(dst - src); +} + +#include "advanced_blend.glsl" diff --git a/impeller/entity/shaders/blending/advanced_blend_exclusion.frag b/impeller/entity/shaders/blending/advanced_blend_exclusion.frag new file mode 100644 index 0000000000000..a12e47e3d043b --- /dev/null +++ b/impeller/entity/shaders/blending/advanced_blend_exclusion.frag @@ -0,0 +1,10 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +vec3 Blend(vec3 dst, vec3 src) { + // https://www.w3.org/TR/compositing-1/#blendingexclusion + return dst + src - 2 * dst * src; +} + +#include "advanced_blend.glsl" diff --git a/impeller/entity/shaders/blending/advanced_blend_hardlight.frag b/impeller/entity/shaders/blending/advanced_blend_hardlight.frag new file mode 100644 index 0000000000000..186f5ecbcdef8 --- /dev/null +++ b/impeller/entity/shaders/blending/advanced_blend_hardlight.frag @@ -0,0 +1,11 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "advanced_blend_utils.glsl" + +vec3 Blend(vec3 dst, vec3 src) { + return BlendHardLight(dst, src); +} + +#include "advanced_blend.glsl" diff --git a/impeller/entity/shaders/blending/advanced_blend_lighten.frag b/impeller/entity/shaders/blending/advanced_blend_lighten.frag new file mode 100644 index 0000000000000..1aca8cc4b7fcd --- /dev/null +++ b/impeller/entity/shaders/blending/advanced_blend_lighten.frag @@ -0,0 +1,10 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +vec3 Blend(vec3 dst, vec3 src) { + // https://www.w3.org/TR/compositing-1/#blendinglighten + return max(dst, src); +} + +#include "advanced_blend.glsl" diff --git a/impeller/entity/shaders/blending/advanced_blend_multiply.frag b/impeller/entity/shaders/blending/advanced_blend_multiply.frag new file mode 100644 index 0000000000000..92656d23fa0a7 --- /dev/null +++ b/impeller/entity/shaders/blending/advanced_blend_multiply.frag @@ -0,0 +1,10 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +vec3 Blend(vec3 dst, vec3 src) { + // https://www.w3.org/TR/compositing-1/#blendingmultiply + return dst * src; +} + +#include "advanced_blend.glsl" diff --git a/impeller/entity/shaders/blending/advanced_blend_overlay.frag b/impeller/entity/shaders/blending/advanced_blend_overlay.frag new file mode 100644 index 0000000000000..d6197f1103147 --- /dev/null +++ b/impeller/entity/shaders/blending/advanced_blend_overlay.frag @@ -0,0 +1,13 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "advanced_blend_utils.glsl" + +vec3 Blend(vec3 dst, vec3 src) { + // https://www.w3.org/TR/compositing-1/#blendinghardlight + // HardLight, but with reversed parameters. + return BlendHardLight(src, dst); +} + +#include "advanced_blend.glsl" diff --git a/impeller/entity/shaders/blending/advanced_blend_screen.frag b/impeller/entity/shaders/blending/advanced_blend_screen.frag index 09988e27be9dd..7f059766abcf7 100644 --- a/impeller/entity/shaders/blending/advanced_blend_screen.frag +++ b/impeller/entity/shaders/blending/advanced_blend_screen.frag @@ -2,8 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "advanced_blend_utils.glsl" + vec3 Blend(vec3 dst, vec3 src) { - return dst + src - (dst * src); + // https://www.w3.org/TR/compositing-1/#blendingscreen + return BlendScreen(dst, src); } #include "advanced_blend.glsl" diff --git a/impeller/entity/shaders/blending/advanced_blend_softlight.frag b/impeller/entity/shaders/blending/advanced_blend_softlight.frag new file mode 100644 index 0000000000000..e646a304054d9 --- /dev/null +++ b/impeller/entity/shaders/blending/advanced_blend_softlight.frag @@ -0,0 +1,20 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "advanced_blend_utils.glsl" + +vec3 Blend(vec3 dst, vec3 src) { + // https://www.w3.org/TR/compositing-1/#blendingsoftlight + + vec3 D = MixComponents(((16 * dst - 12) * dst + 4) * dst, // + sqrt(dst), // + dst, // + 0.25); + + return MixHalf(dst - (1 - 2 * src) * dst * (1 - dst), // + dst + (2 * src - 1) * (D - dst), // + src); +} + +#include "advanced_blend.glsl" diff --git a/impeller/entity/shaders/blending/advanced_blend_utils.glsl b/impeller/entity/shaders/blending/advanced_blend_utils.glsl new file mode 100644 index 0000000000000..94ec9b6e03e66 --- /dev/null +++ b/impeller/entity/shaders/blending/advanced_blend_utils.glsl @@ -0,0 +1,26 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +vec3 ComponentIsValue(vec3 n, float value) { + vec3 diff = abs(n - value); + return vec3(diff.r < 0.0001, diff.g < 0.0001, diff.b < 0.0001); +} + +vec3 MixComponents(vec3 a, vec3 b, vec3 weight, float cutoff) { + return vec3(mix(a.x, b.x, weight.x > cutoff), // + mix(a.y, b.y, weight.y > cutoff), // + mix(a.z, b.z, weight.z > cutoff)); +} + +vec3 MixHalf(vec3 a, vec3 b, vec3 weight) { + return MixComponents(a, b, weight, 0.5); +} + +vec3 BlendScreen(vec3 dst, vec3 src) { + return dst + src - (dst * src); +} + +vec3 BlendHardLight(vec3 dst, vec3 src) { + return MixHalf(dst * (2 * src), BlendScreen(dst, 2 * src - 1), src); +}