Add support to render grayscale sprites with ShaderRenderer

This commit is contained in:
David Capello 2023-03-17 17:25:58 -03:00
parent 9e08386a28
commit 7781ff69a1
2 changed files with 35 additions and 0 deletions

View File

@ -43,6 +43,15 @@ half4 main(vec2 fragcoord) {
}
)";
const char* kGrayscaleShaderCode = R"(
uniform shader iImg;
half4 main(vec2 fragcoord) {
half4 c = iImg.eval(fragcoord);
return half4(c.rrr * c.g, c.g);
}
)";
inline SkBlendMode to_skia(const doc::BlendMode bm) {
switch (bm) {
case doc::BlendMode::NORMAL: return SkBlendMode::kSrcOver;
@ -87,6 +96,7 @@ ShaderRenderer::ShaderRenderer()
m_bgEffect = makeShader(kBgShaderCode).effect;
m_indexedEffect = makeShader(kIndexedShaderCode).effect;
m_grayscaleEffect = makeShader(kGrayscaleShaderCode).effect;
}
ShaderRenderer::~ShaderRenderer() = default;
@ -431,6 +441,30 @@ void ShaderRenderer::drawImage(SkCanvas* canvas,
}
case doc::ColorMode::GRAYSCALE: {
// We use kR8G8_unorm_SkColorType to access gray and alpha
auto skImg = SkImage::MakeRasterData(
SkImageInfo::Make(srcImage->width(),
srcImage->height(),
kR8G8_unorm_SkColorType,
kOpaque_SkAlphaType),
skData,
srcImage->getRowStrideSize());
SkRuntimeShaderBuilder builder(m_grayscaleEffect);
builder.child("iImg") = skImg->makeRawShader(SkSamplingOptions(SkFilterMode::kNearest));
SkPaint p;
p.setAlpha(opacity);
p.setBlendMode(to_skia(blendMode));
p.setStyle(SkPaint::kFill_Style);
p.setShader(builder.makeShader());
canvas->save();
canvas->translate(
SkIntToScalar(x),
SkIntToScalar(y));
canvas->drawRect(SkRect::MakeXYWH(0, 0, srcImage->width(), srcImage->height()), p);
canvas->restore();
break;
}

View File

@ -89,6 +89,7 @@ namespace app {
render::Projection m_proj;
sk_sp<SkRuntimeEffect> m_bgEffect;
sk_sp<SkRuntimeEffect> m_indexedEffect;
sk_sp<SkRuntimeEffect> m_grayscaleEffect;
const doc::Sprite* m_sprite = nullptr;
const doc::LayerImage* m_bgLayer = nullptr;
// TODO these members are the same as in render::Render, we should