Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
view_effect.hpp
Go to the documentation of this file.
1#pragma once
2
4#include <algorithm>
5#include <cmath>
6#include <memory>
7#include <string>
8#include <vector>
9
10namespace pulp::canvas {
11
17public:
18 virtual ~ViewEffect() = default;
19
28 virtual void configure_layer(Canvas& canvas, float x, float y, float w, float h) = 0;
29
32 virtual int layer_count() const { return 1; }
33
35 virtual bool needs_layer() const { return true; }
36
49 virtual void paint_overlay(Canvas& canvas, float x, float y,
50 float w, float h) {
51 (void)canvas; (void)x; (void)y; (void)w; (void)h;
52 }
53};
54
57 float radius_x = 4.0f;
58 float radius_y = 4.0f;
59
60 void configure_layer(Canvas& canvas, float x, float y, float w, float h) override {
61 canvas.save_layer(x, y, w, h, 1.0f, std::max(radius_x, radius_y));
62 }
63};
64
80 float threshold = 0.8f;
81 float intensity = 0.5f;
82 float radius = 8.0f;
83
84 void configure_layer(Canvas& canvas, float x, float y, float w, float h) override {
85 // Real bloom: SkiaCanvas thresholds + blurs + additively composites the
86 // glow; other backends degrade to a plain blurred layer (base default).
87 canvas.save_layer_with_bloom(x, y, w, h, intensity, threshold, radius);
88 }
89};
90
97 float offset = 2.0f;
98
99 void configure_layer(Canvas& canvas, float x, float y, float w, float h) override {
101 u.value = offset; // per-channel offset (px), passed via `value`
102 canvas.save_layer_with_sksl_post_effect(
103 x, y, w, h,
104 "uniform shader content;"
105 "uniform float value;"
106 "half4 main(float2 xy) {"
107 " return half4(content.eval(xy + float2(value, 0.0)).r,"
108 " content.eval(xy).g,"
109 " content.eval(xy - float2(value, 0.0)).b,"
110 " content.eval(xy).a);"
111 "}",
112 u, /*sample_radius=*/offset);
113 }
114};
115
123 float intensity = 0.5f;
124 float radius = 0.75f;
125 Color edge_color = Color::rgba(0.0f, 0.0f, 0.0f, 0.5f);
126
127 void configure_layer(Canvas& canvas, float x, float y, float w, float h) override {
128 // Plain compositing layer; the darkening happens in paint_overlay().
129 canvas.save_layer(x, y, w, h, 1.0f, 0.0f);
130 }
131
132 void paint_overlay(Canvas& canvas, float x, float y,
133 float w, float h) override {
134 if (intensity <= 0.0f || w <= 0.0f || h <= 0.0f) return;
135 const float cx = x + w * 0.5f;
136 const float cy = y + h * 0.5f;
137 const float outer = 0.5f * std::sqrt(w * w + h * h); // center→corner
138 const float inner = radius * std::min(w, h) * 0.5f; // darkening start
139 const float inner_frac =
140 outer > 0.0f ? std::min(inner / outer, 0.99f) : 0.0f;
141
142 const Color clear = Color::rgba(edge_color.r, edge_color.g,
143 edge_color.b, 0.0f);
144 const Color edge = Color::rgba(edge_color.r, edge_color.g, edge_color.b,
146 const Color colors[3] = {clear, clear, edge};
147 const float positions[3] = {0.0f, inner_frac, 1.0f};
148 canvas.set_fill_gradient_radial(cx, cy, outer, colors, positions, 3);
149 canvas.fill_rect(x, y, w, h);
150 canvas.clear_fill_gradient();
151 }
152};
153
161 std::string sksl;
162 float value = 0.0f;
163 float time = 0.0f;
166 std::vector<Canvas::NamedUniform> uniforms;
171 float sample_radius = 0.0f;
172
173 void configure_layer(Canvas& canvas, float x, float y, float w, float h) override {
175 u.value = value;
176 u.time = time;
177 canvas.save_layer_with_sksl_post_effect(x, y, w, h, sksl, u,
179 }
180};
181
182// A `CustomShaderEffect` (arbitrary SkSL as a view post-effect) used to live
183// here. It stored `sksl`, `value`, and `time` and then ignored all three —
184// `configure_layer()` pushed a plain layer, so setting one had no visual effect
185// whatsoever. Applying SkSL to already-rendered subtree content needs a
186// child-shader compositor (Skia's runtime-shader image filter), which now
187// exists as `Canvas::save_layer_with_sksl_post_effect` (the SkSL declares
188// `uniform shader content`). A view post-effect can be built on it; note that
189// this is distinct from `draw_with_sksl()`, which fills a fresh rect from a
190// generative shader and cannot post-process. Widget body shaders — which do
191// work — are `CustomShaderHost`.
192
194class EffectChain : public ViewEffect {
195public:
196 void add(std::shared_ptr<ViewEffect> effect) {
197 effects_.push_back(std::move(effect));
198 }
199
200 void configure_layer(Canvas& canvas, float x, float y, float w, float h) override {
201 // Apply effects in order — each wraps the previous in a layer
202 for (auto& effect : effects_) {
203 effect->configure_layer(canvas, x, y, w, h);
204 }
205 }
206
210 int layer_count() const override {
211 int total = 0;
212 for (const auto& effect : effects_) total += effect->layer_count();
213 return total;
214 }
215
216 bool needs_layer() const override {
217 return !effects_.empty();
218 }
219
222 void paint_overlay(Canvas& canvas, float x, float y,
223 float w, float h) override {
224 for (auto& effect : effects_)
225 effect->paint_overlay(canvas, x, y, w, h);
226 }
227
228 const std::vector<std::shared_ptr<ViewEffect>>& effects() const { return effects_; }
229
230private:
231 std::vector<std::shared_ptr<ViewEffect>> effects_;
232};
233
234} // namespace pulp::canvas
Definition canvas.hpp:240
BlendMode
Indices 0..15 match the existing W3C "advanced" composite ops and must stay stable — set_blend_mode i...
Definition canvas.hpp:527
@ normal
Definition canvas.hpp:529
Chains multiple effects in sequence.
Definition view_effect.hpp:194
bool needs_layer() const override
Whether this effect requires a compositing layer (most do).
Definition view_effect.hpp:216
const std::vector< std::shared_ptr< ViewEffect > > & effects() const
Definition view_effect.hpp:228
int layer_count() const override
One layer per child, summed — a chain pushes as many layers as it has effects.
Definition view_effect.hpp:210
void configure_layer(Canvas &canvas, float x, float y, float w, float h) override
Push the compositing layer(s) this effect needs, configured with its opacity, image filters,...
Definition view_effect.hpp:200
void add(std::shared_ptr< ViewEffect > effect)
Definition view_effect.hpp:196
void paint_overlay(Canvas &canvas, float x, float y, float w, float h) override
Forward the overlay to every child (in order).
Definition view_effect.hpp:222
Base class for GPU post-processing effects.
Definition view_effect.hpp:16
virtual void paint_overlay(Canvas &canvas, float x, float y, float w, float h)
Paint an overlay on TOP of the already-painted subtree, but still INSIDE the effect's compositing lay...
Definition view_effect.hpp:49
virtual int layer_count() const
How many layers configure_layer() pushes.
Definition view_effect.hpp:32
virtual bool needs_layer() const
Whether this effect requires a compositing layer (most do).
Definition view_effect.hpp:35
virtual ~ViewEffect()=default
virtual void configure_layer(Canvas &canvas, float x, float y, float w, float h)=0
Push the compositing layer(s) this effect needs, configured with its opacity, image filters,...
Definition affine_transform.hpp:24
Uniforms passed to custom widget shaders.
Definition canvas.hpp:1635
Chromatic aberration — real per-channel RGB offset for a glitch/lens effect.
Definition view_effect.hpp:96
void configure_layer(Canvas &canvas, float x, float y, float w, float h) override
Push the compositing layer(s) this effect needs, configured with its opacity, image filters,...
Definition view_effect.hpp:99
float offset
Pixel offset between channels.
Definition view_effect.hpp:97
Definition canvas.hpp:52
static constexpr Color rgba(float r, float g, float b, float a=1.0f)
Construct from float channels [0,1] (>1.0 allowed for HDR).
Definition canvas.hpp:56
GPU bloom/glow — a real bright-pass + blur + additive composite.
Definition view_effect.hpp:79
float threshold
Brightness cutoff in [0,1]; below it, no glow.
Definition view_effect.hpp:80
float radius
Blur radius (px) of the glow.
Definition view_effect.hpp:82
float intensity
Glow gain applied to the thresholded highlights.
Definition view_effect.hpp:81
void configure_layer(Canvas &canvas, float x, float y, float w, float h) override
Push the compositing layer(s) this effect needs, configured with its opacity, image filters,...
Definition view_effect.hpp:84
GPU blur effect — multi-pass Gaussian blur via SkImageFilters.
Definition view_effect.hpp:56
float radius_x
Definition view_effect.hpp:57
void configure_layer(Canvas &canvas, float x, float y, float w, float h) override
Push the compositing layer(s) this effect needs, configured with its opacity, image filters,...
Definition view_effect.hpp:60
float radius_y
Definition view_effect.hpp:58
Arbitrary-SkSL view post-effect.
Definition view_effect.hpp:160
Canvas::BlendMode blend_mode
How the finished post-effect layer composites onto its parent.
Definition view_effect.hpp:169
std::vector< Canvas::NamedUniform > uniforms
Arbitrary named uniforms (name → float/vec) the shader declares — the real user-facing surface.
Definition view_effect.hpp:166
float sample_radius
Max neighbor-sampling distance (px) for content.eval offsets.
Definition view_effect.hpp:171
void configure_layer(Canvas &canvas, float x, float y, float w, float h) override
Push the compositing layer(s) this effect needs, configured with its opacity, image filters,...
Definition view_effect.hpp:173
std::string sksl
Definition view_effect.hpp:161
float time
bound to the shader's time uniform when present
Definition view_effect.hpp:163
float value
bound to the shader's value uniform when present
Definition view_effect.hpp:162
Vignette — darken the edges of the view by drawing a real radial-gradient overlay on top of the finis...
Definition view_effect.hpp:122
float radius
Fraction of view half-extent where darkening starts.
Definition view_effect.hpp:124
void paint_overlay(Canvas &canvas, float x, float y, float w, float h) override
Paint an overlay on TOP of the already-painted subtree, but still INSIDE the effect's compositing lay...
Definition view_effect.hpp:132
Color edge_color
Definition view_effect.hpp:125
float intensity
Darkening strength (0=none, 1=full edge_color).
Definition view_effect.hpp:123
void configure_layer(Canvas &canvas, float x, float y, float w, float h) override
Push the compositing layer(s) this effect needs, configured with its opacity, image filters,...
Definition view_effect.hpp:127