Hello all, this is my implementation of Skia shader that can be used as overlays or normal controls for fully vectorial UI
class NoiseShaderControl : public iplug::igraphics::IControl
{
public:
NoiseShaderControl(const iplug::igraphics::IRECT& bounds, bool isOverlay = false,
float opacity = 1.0F)
: IControl(bounds), mIsOverlay_(isOverlay), mOpacity_(opacity)
{
// Create the Perlin Noise shader
mNoiseShader_ = SkShaders::MakeTurbulence(0.5F, // Base frequency X
0.5f, // Base frequency Y
SK_ScalarPI, // Number of octaves
rand() // Seed value for randomness
);
// Configure paint object
mPaint_.setShader(mNoiseShader_);
if (mIsOverlay_)
{
mPaint_.setAlphaf(mOpacity_); // Adjust transparency for overlay
mPaint_.setBlendMode(SkBlendMode::kOverlay); // Overlay blending mode
}
}
void Draw(iplug::igraphics::IGraphics& g) override
{
if (g.GetDrawContext()) // Ensure Skia backend
{
SkCanvas* canvas = static_cast<SkCanvas*>(g.GetDrawContext());
SkRect skRect = SkRect::MakeLTRB(mRECT.L, mRECT.T, mRECT.R, mRECT.B);
// Draw the noise shader over the specified rectangle
canvas->drawRect(skRect, mPaint_);
}
}
private:
SkPaint mPaint_; // Skia paint object to configure drawing
sk_sp<SkShader> mNoiseShader_; // Perlin noise shader
bool mIsOverlay_; // Flag for overlay mode
float mOpacity_; // Opacity for transparency control
};
for now I have only made a noise shader however with this as a template yall can make other shaders that are included in Skia, Cheers
This is some scratches, however the Opacity is not being used. This version uses 400 scratches
class StaticScratchesControl : public iplug::igraphics::IControl
{
public:
StaticScratchesControl(const iplug::igraphics::IRECT& bounds, bool isOverlay = false,
float opacity = 1.0F)
: IControl(bounds), mIsOverlay_(isOverlay), mOpacity_(opacity)
{
// Define image dimensions
int width = static_cast<int>(bounds.W());
int height = static_cast<int>(bounds.H());
// Create SkSurface with no alpha blending issues
auto surface = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(width, height));
if (surface)
{
SkCanvas* canvas = surface->getCanvas();
// Clear the canvas to fully transparent
canvas->clear (SK_ColorTRANSPARENT);
// Configure scratch paint (force fully opaque white)
mScratchPaint_.setColor(SkColorSetARGB(255, 255, 255, 255)); // Solid white
mScratchPaint_.setStrokeWidth(0.05F);
mScratchPaint_.setAntiAlias(true);
// Draw scratches
DrawScratches(canvas, width, height, 400); // 400 scratches
// Save the result as an immutable SkImage
mScratchImage_ = surface->makeImageSnapshot();
}
// Configure paint for rendering cached scratches
mPaint_.setBlendMode(SkBlendMode::kSrcOver); // Force normal paint mode
}
void Draw(iplug::igraphics::IGraphics& g) override
{
if (g.GetDrawContext() && mScratchImage_) // Ensure Skia backend and image exists
{
SkCanvas* canvas = static_cast<SkCanvas*>(g.GetDrawContext());
SkRect skRect = SkRect::MakeLTRB(mRECT.L, mRECT.T, mRECT.R, mRECT.B);
// Draw the cached scratches image (directly without blending issues)
canvas->drawImageRect(mScratchImage_, skRect, SkSamplingOptions(), &mPaint_);
}
}
private:
void DrawScratches(SkCanvas* canvas, float width, float height, int numScratches)
{
for (int i = 0; i < numScratches; ++i)
{
// Random starting point
float x1 = static_cast<float>(rand() % static_cast<int>(width));
float y1 = static_cast<float>(rand() % static_cast<int>(height));
// Random scratch length
float length = 10.0F + static_cast<float>(rand() % 40);
// Random angle (0° to 360°)
float angle = static_cast<float>(rand() % 360);
float radian = angle * (M_PI / 180.0F);
// Calculate end points
float x2 = x1 + length * cos(radian);
float y2 = y1 + length * sin(radian);
// Draw scratch
canvas->drawLine(x1, y1, x2, y2, mScratchPaint_);
}
}
SkPaint mPaint_; // Paint object for final drawing of cached image
sk_sp<SkImage> mScratchImage_; // Cached scratches image
SkPaint mScratchPaint_; // Paint object for rendering scratches
bool mIsOverlay_; // Flag for overlay mode
float mOpacity_; // Opacity for transparency control
};
Example with both scratches and noise
1 Like