Particles: SkImageBinding to allow sampling an image from script

Provides functionality similar to AE property maps

Change-Id: I1705706a6b7e25fbab55465f2e20d0b145330b0b
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/255977
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
This commit is contained in:
Brian Osman 2019-12-03 09:49:12 -05:00 committed by Skia Commit-Bot
parent 9dac0d8216
commit db2e7641be
2 changed files with 109 additions and 0 deletions

View File

@ -7,7 +7,9 @@
#include "modules/particles/include/SkParticleBinding.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkContourMeasure.h"
#include "include/core/SkImage.h"
#include "include/core/SkPath.h"
#include "include/utils/SkParsePath.h"
#include "include/utils/SkRandom.h"
@ -193,6 +195,74 @@ private:
SkPathContours fContours;
};
// Exposes an SkBitmap as an external, callable value. p(xy) returns a float4
class SkBitmapExternalValue : public SkParticleExternalValue {
public:
SkBitmapExternalValue(const char* name, SkSL::Compiler& compiler, const SkBitmap& bitmap)
: SkParticleExternalValue(name, compiler, *compiler.context().fFloat4_Type)
, fBitmap(bitmap) {
SkASSERT(bitmap.colorType() == kRGBA_F32_SkColorType);
}
bool canCall() const override { return true; }
int callParameterCount() const override { return 1; }
void getCallParameterTypes(const SkSL::Type** outTypes) const override {
outTypes[0] = fCompiler.context().fFloat2_Type.get();
}
void call(int index, float* arguments, float* outReturn) override {
int x = SkTPin(static_cast<int>(arguments[0] * fBitmap.width()), 0, fBitmap.width() - 1);
int y = SkTPin(static_cast<int>(arguments[1] * fBitmap.height()), 0, fBitmap.height() - 1);
float* p = static_cast<float*>(fBitmap.getAddr(x, y));
memcpy(outReturn, p, 4 * sizeof(float));
}
private:
SkBitmap fBitmap;
};
class SkImageBinding : public SkParticleBinding {
public:
SkImageBinding(const char* name = "", const char* imagePath = "", const char* imageName = "")
: SkParticleBinding(name)
, fImagePath(imagePath)
, fImageName(imageName) {}
REFLECTED(SkImageBinding, SkParticleBinding)
void visitFields(SkFieldVisitor* v) override {
SkParticleBinding::visitFields(v);
v->visit("ImagePath", fImagePath);
v->visit("ImageName", fImageName);
}
std::unique_ptr<SkParticleExternalValue> toValue(SkSL::Compiler& compiler) override {
return std::unique_ptr<SkParticleExternalValue>(
new SkBitmapExternalValue(fName.c_str(), compiler, fBitmap));
}
void prepare(const skresources::ResourceProvider* resourceProvider) override {
if (auto asset = resourceProvider->loadImageAsset(fImagePath.c_str(), fImageName.c_str(),
nullptr)) {
if (auto image = asset->getFrame(0)) {
fBitmap.allocPixels(image->imageInfo().makeColorType(kRGBA_F32_SkColorType));
image->readPixels(fBitmap.pixmap(), 0, 0);
return;
}
}
fBitmap.allocPixels(SkImageInfo::Make(1, 1, kRGBA_F32_SkColorType, kPremul_SkAlphaType));
fBitmap.eraseColor(SK_ColorWHITE);
}
private:
SkString fImagePath;
SkString fImageName;
// Cached
SkBitmap fBitmap;
};
sk_sp<SkParticleBinding> SkParticleBinding::MakeEffectBinding(
const char* name, sk_sp<SkParticleEffectParams> params) {
return sk_sp<SkParticleBinding>(new SkEffectBinding(name, params));
@ -205,6 +275,7 @@ sk_sp<SkParticleBinding> SkParticleBinding::MakePathBinding(const char* name, co
void SkParticleBinding::RegisterBindingTypes() {
REGISTER_REFLECTED(SkParticleBinding);
REGISTER_REFLECTED(SkEffectBinding);
REGISTER_REFLECTED(SkImageBinding);
REGISTER_REFLECTED(SkPathBinding);
REGISTER_REFLECTED(SkTextBinding);
}

View File

@ -0,0 +1,38 @@
{
"MaxCount": 4000,
"Drawable": {
"Type": "SkCircleDrawable",
"Radius": 3
},
"EffectCode": [
"void effectSpawn(inout Effect effect) {",
" effect.rate = 4000;",
"}",
"",
"void effectUpdate(inout Effect effect) {",
"}",
""
],
"Code": [
"void spawn(inout Particle p) {",
" p.lifetime = 1;",
" p.pos = float2(rand, rand) * 200;",
" p.vel = float2(rand, rand) * 2 - 1;",
" p.vel *= 20;",
" p.scale = mix(0.25, 1, rand);",
"}",
"",
"void update(inout Particle p) {",
" p.color = img(p.pos / 200);",
"}",
""
],
"Bindings": [
{
"Type": "SkImageBinding",
"Name": "img",
"ImagePath": "images",
"ImageName": "mandrill_128.png"
}
]
}