Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit a3ff568

Browse files
committed
Fix alpha issues
1 parent 44f856a commit a3ff568

File tree

7 files changed

+77
-63
lines changed

7 files changed

+77
-63
lines changed

impeller/aiks/aiks_unittests.cc

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,7 @@ TEST_P(AiksTest, CanDrawWithAdvancedBlend) {
521521
};
522522

523523
Paint paint;
524+
paint.blend_mode = Entity::BlendMode::kSourceOver;
524525

525526
// Draw a fancy color wheel for the backdrop.
526527
// https://www.desmos.com/calculator/xw7kafthwd
@@ -547,10 +548,16 @@ TEST_P(AiksTest, CanDrawWithAdvancedBlend) {
547548
ImGui::SetNextWindowPos({325, 550});
548549
}
549550

550-
ImGui::Begin("Controls");
551+
// UI state.
551552
static int current_blend_index = 3;
552-
ImGui::ListBox("Blending mode", &current_blend_index,
553-
blend_mode_names.data(), blend_mode_names.size());
553+
static float alpha = 1;
554+
555+
ImGui::Begin("Controls");
556+
{
557+
ImGui::ListBox("Blending mode", &current_blend_index,
558+
blend_mode_names.data(), blend_mode_names.size());
559+
ImGui::SliderFloat("Alpha", &alpha, 0, 1);
560+
}
554561
ImGui::End();
555562

556563
Canvas canvas;
@@ -570,11 +577,11 @@ TEST_P(AiksTest, CanDrawWithAdvancedBlend) {
570577
paint.blend_mode = Entity::BlendMode::kPlus;
571578
const Scalar x = std::sin(k2Pi / 3);
572579
const Scalar y = -std::cos(k2Pi / 3);
573-
paint.color = Color::Red();
580+
paint.color = Color::Red().WithAlpha(alpha);
574581
canvas.DrawCircle(Point(-x, y) * 45, 65, paint);
575-
paint.color = Color::Green();
582+
paint.color = Color::Green().WithAlpha(alpha);
576583
canvas.DrawCircle(Point(0, -1) * 45, 65, paint);
577-
paint.color = Color::Blue();
584+
paint.color = Color::Blue().WithAlpha(alpha);
578585
canvas.DrawCircle(Point(x, y) * 45, 65, paint);
579586
}
580587
canvas.Restore();

impeller/entity/contents/content_context.cc

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,29 +13,35 @@
1313

1414
namespace impeller {
1515

16+
template <typename PipelineT>
17+
static std::unique_ptr<PipelineT> CreateDefault(const Context& context) {
18+
auto desc = PipelineT::Builder::MakeDefaultPipelineDescriptor(context);
19+
if (!desc.has_value()) {
20+
return nullptr;
21+
}
22+
// Apply pipeline options for the
23+
ContentContext::ApplyOptionsToDescriptor(*desc, {});
24+
return std::make_unique<PipelineT>(context, desc);
25+
}
26+
1627
ContentContext::ContentContext(std::shared_ptr<Context> context)
1728
: context_(std::move(context)) {
1829
if (!context_ || !context_->IsValid()) {
1930
return;
2031
}
2132

22-
// Pipelines whose default descriptors work fine for the entity framework.
23-
gradient_fill_pipelines_[{}] =
24-
std::make_unique<GradientFillPipeline>(*context_);
25-
solid_fill_pipelines_[{}] = std::make_unique<SolidFillPipeline>(*context_);
26-
texture_blend_pipelines_[{}] = std::make_unique<BlendPipeline>(*context_);
27-
blend_screen_pipelines_[{}] =
28-
std::make_unique<BlendScreenPipeline>(*context_);
33+
gradient_fill_pipelines_[{}] = CreateDefault<GradientFillPipeline>(*context_);
34+
solid_fill_pipelines_[{}] = CreateDefault<SolidFillPipeline>(*context_);
35+
texture_blend_pipelines_[{}] = CreateDefault<BlendPipeline>(*context_);
36+
blend_screen_pipelines_[{}] = CreateDefault<BlendScreenPipeline>(*context_);
2937
blend_colorburn_pipelines_[{}] =
30-
std::make_unique<BlendColorburnPipeline>(*context_);
31-
texture_pipelines_[{}] = std::make_unique<TexturePipeline>(*context_);
32-
gaussian_blur_pipelines_[{}] =
33-
std::make_unique<GaussianBlurPipeline>(*context_);
38+
CreateDefault<BlendColorburnPipeline>(*context_);
39+
texture_pipelines_[{}] = CreateDefault<TexturePipeline>(*context_);
40+
gaussian_blur_pipelines_[{}] = CreateDefault<GaussianBlurPipeline>(*context_);
3441
border_mask_blur_pipelines_[{}] =
35-
std::make_unique<BorderMaskBlurPipeline>(*context_);
36-
solid_stroke_pipelines_[{}] =
37-
std::make_unique<SolidStrokePipeline>(*context_);
38-
glyph_atlas_pipelines_[{}] = std::make_unique<GlyphAtlasPipeline>(*context_);
42+
CreateDefault<BorderMaskBlurPipeline>(*context_);
43+
solid_stroke_pipelines_[{}] = CreateDefault<SolidStrokePipeline>(*context_);
44+
glyph_atlas_pipelines_[{}] = CreateDefault<GlyphAtlasPipeline>(*context_);
3945

4046
// Pipelines that are variants of the base pipelines with custom descriptors.
4147
// TODO(98684): Rework this API to allow fetching the descriptor without

impeller/entity/contents/content_context.h

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -153,30 +153,6 @@ class ContentContext {
153153
std::shared_ptr<Texture> MakeSubpass(ISize texture_size,
154154
SubpassCallback subpass_callback) const;
155155

156-
private:
157-
std::shared_ptr<Context> context_;
158-
159-
template <class T>
160-
using Variants = std::unordered_map<ContentContextOptions,
161-
std::unique_ptr<T>,
162-
ContentContextOptions::Hash,
163-
ContentContextOptions::Equal>;
164-
165-
// These are mutable because while the prototypes are created eagerly, any
166-
// variants requested from that are lazily created and cached in the variants
167-
// map.
168-
mutable Variants<GradientFillPipeline> gradient_fill_pipelines_;
169-
mutable Variants<SolidFillPipeline> solid_fill_pipelines_;
170-
mutable Variants<BlendPipeline> texture_blend_pipelines_;
171-
mutable Variants<BlendScreenPipeline> blend_screen_pipelines_;
172-
mutable Variants<BlendColorburnPipeline> blend_colorburn_pipelines_;
173-
mutable Variants<TexturePipeline> texture_pipelines_;
174-
mutable Variants<GaussianBlurPipeline> gaussian_blur_pipelines_;
175-
mutable Variants<BorderMaskBlurPipeline> border_mask_blur_pipelines_;
176-
mutable Variants<SolidStrokePipeline> solid_stroke_pipelines_;
177-
mutable Variants<ClipPipeline> clip_pipelines_;
178-
mutable Variants<GlyphAtlasPipeline> glyph_atlas_pipelines_;
179-
180156
static void ApplyOptionsToDescriptor(PipelineDescriptor& desc,
181157
const ContentContextOptions& options) {
182158
auto blend_mode = options.blend_mode;
@@ -218,7 +194,7 @@ class ContentContext {
218194
case Entity::BlendMode::kSourceOver:
219195
color0.dst_alpha_blend_factor = BlendFactor::kOneMinusSourceAlpha;
220196
color0.dst_color_blend_factor = BlendFactor::kOneMinusSourceAlpha;
221-
color0.src_alpha_blend_factor = BlendFactor::kSourceAlpha;
197+
color0.src_alpha_blend_factor = BlendFactor::kOne;
222198
color0.src_color_blend_factor = BlendFactor::kOne;
223199
break;
224200
case Entity::BlendMode::kDestinationOver:
@@ -296,6 +272,30 @@ class ContentContext {
296272
}
297273
}
298274

275+
private:
276+
std::shared_ptr<Context> context_;
277+
278+
template <class T>
279+
using Variants = std::unordered_map<ContentContextOptions,
280+
std::unique_ptr<T>,
281+
ContentContextOptions::Hash,
282+
ContentContextOptions::Equal>;
283+
284+
// These are mutable because while the prototypes are created eagerly, any
285+
// variants requested from that are lazily created and cached in the variants
286+
// map.
287+
mutable Variants<GradientFillPipeline> gradient_fill_pipelines_;
288+
mutable Variants<SolidFillPipeline> solid_fill_pipelines_;
289+
mutable Variants<BlendPipeline> texture_blend_pipelines_;
290+
mutable Variants<BlendScreenPipeline> blend_screen_pipelines_;
291+
mutable Variants<BlendColorburnPipeline> blend_colorburn_pipelines_;
292+
mutable Variants<TexturePipeline> texture_pipelines_;
293+
mutable Variants<GaussianBlurPipeline> gaussian_blur_pipelines_;
294+
mutable Variants<BorderMaskBlurPipeline> border_mask_blur_pipelines_;
295+
mutable Variants<SolidStrokePipeline> solid_stroke_pipelines_;
296+
mutable Variants<ClipPipeline> clip_pipelines_;
297+
mutable Variants<GlyphAtlasPipeline> glyph_atlas_pipelines_;
298+
299299
template <class TypedPipeline>
300300
std::shared_ptr<Pipeline> GetPipeline(Variants<TypedPipeline>& container,
301301
ContentContextOptions opts) const {

impeller/entity/contents/filters/blend_filter_contents.cc

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "impeller/entity/contents/filters/blend_filter_contents.h"
66

77
#include "impeller/entity/contents/content_context.h"
8+
#include "impeller/entity/contents/contents.h"
89
#include "impeller/entity/contents/filters/inputs/filter_input.h"
910
#include "impeller/renderer/render_pass.h"
1011
#include "impeller/renderer/sampler_library.h"
@@ -20,13 +21,16 @@ BlendFilterContents::~BlendFilterContents() = default;
2021
using PipelineProc =
2122
std::shared_ptr<Pipeline> (ContentContext::*)(ContentContextOptions) const;
2223

23-
template <typename VS, typename FS>
24+
template <typename TPipeline>
2425
static bool AdvancedBlend(const FilterInput::Vector& inputs,
2526
const ContentContext& renderer,
2627
const Entity& entity,
2728
RenderPass& pass,
2829
const Rect& coverage,
2930
PipelineProc pipeline_proc) {
31+
using VS = typename TPipeline::VertexShader;
32+
using FS = typename TPipeline::FragmentShader;
33+
3034
if (inputs.size() < 2) {
3135
return false;
3236
}
@@ -65,8 +69,7 @@ static bool AdvancedBlend(const FilterInput::Vector& inputs,
6569
});
6670
auto vtx_buffer = vtx_builder.CreateVertexBuffer(host_buffer);
6771

68-
auto options = OptionsFromPass(pass);
69-
options.blend_mode = Entity::BlendMode::kSource;
72+
auto options = OptionsFromPassAndEntity(pass, entity);
7073
std::shared_ptr<Pipeline> pipeline =
7174
std::invoke(pipeline_proc, renderer, options);
7275

@@ -108,9 +111,8 @@ void BlendFilterContents::SetBlendMode(Entity::BlendMode blend_mode) {
108111
const Entity& entity, RenderPass& pass,
109112
const Rect& coverage) {
110113
PipelineProc p = &ContentContext::GetBlendScreenPipeline;
111-
return AdvancedBlend<BlendScreenPipeline::VertexShader,
112-
BlendScreenPipeline::FragmentShader>(
113-
inputs, renderer, entity, pass, coverage, p);
114+
return AdvancedBlend<BlendScreenPipeline>(inputs, renderer, entity,
115+
pass, coverage, p);
114116
};
115117
break;
116118
case Entity::BlendMode::kColorBurn:
@@ -119,9 +121,8 @@ void BlendFilterContents::SetBlendMode(Entity::BlendMode blend_mode) {
119121
const Entity& entity, RenderPass& pass,
120122
const Rect& coverage) {
121123
PipelineProc p = &ContentContext::GetBlendColorburnPipeline;
122-
return AdvancedBlend<BlendColorburnPipeline::VertexShader,
123-
BlendColorburnPipeline::FragmentShader>(
124-
inputs, renderer, entity, pass, coverage, p);
124+
return AdvancedBlend<BlendColorburnPipeline>(inputs, renderer, entity,
125+
pass, coverage, p);
125126
};
126127
break;
127128
default:

impeller/entity/entity_pass.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ bool EntityPass::Render(ContentContext& renderer,
153153

154154
Entity entity;
155155
entity.SetContents(contents);
156-
entity.SetBlendMode(Entity::BlendMode::kSource);
156+
entity.SetBlendMode(Entity::BlendMode::kSourceOver);
157157

158158
entity.Render(renderer, *render_pass);
159159
}
@@ -322,7 +322,7 @@ bool EntityPass::RenderInternal(ContentContext& renderer,
322322
element_entity.GetTransformation().Invert())};
323323
element_entity.SetContents(
324324
FilterContents::MakeBlend(element_entity.GetBlendMode(), inputs));
325-
element_entity.SetBlendMode(Entity::BlendMode::kSource);
325+
element_entity.SetBlendMode(Entity::BlendMode::kSourceOver);
326326
}
327327

328328
// Create a new render pass to render the element if one isn't active.

impeller/entity/shaders/advanced_blend_colorburn.frag

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ vec3 ComponentIsValue(vec3 n, float value) {
1717
}
1818

1919
void main() {
20-
const vec4 dst =
21-
SampleWithBorder(texture_sampler_dst, v_dst_texture_coords);
22-
const vec4 src =
23-
SampleWithBorder(texture_sampler_src, v_src_texture_coords);
20+
const vec4 dst = Unpremultiply(
21+
SampleWithBorder(texture_sampler_dst, v_dst_texture_coords));
22+
const vec4 src = Unpremultiply(
23+
SampleWithBorder(texture_sampler_src, v_src_texture_coords));
2424

2525
vec3 color = 1 - min(vec3(1), (1 - dst.rgb) / src.rgb);
2626
color = mix(color, vec3(1), ComponentIsValue(dst.rgb, 1.0));
2727
color = mix(color, vec3(0), ComponentIsValue(src.rgb, 0.0));
2828

29-
frag_color = vec4(color, dst.a - src.a + src.a);
29+
frag_color = vec4(color * src.a, src.a);
3030
}

impeller/entity/shaders/advanced_blend_screen.frag

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,5 @@ void main() {
1919
SampleWithBorder(texture_sampler_src, v_src_texture_coords));
2020

2121
vec3 color = dst.rgb + src.rgb - (dst.rgb * src.rgb);
22-
frag_color = vec4(color, dst.a - src.a + src.a);
22+
frag_color = vec4(color * src.a, src.a);
2323
}

0 commit comments

Comments
 (0)