Prototype interpreter particle affector

Change-Id: Ib440570ecbd46b5bc98d346592cbbb72f58ae85a
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/212500
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
This commit is contained in:
Brian Osman 2019-05-09 14:05:04 -04:00 committed by Skia Commit-Bot
parent 8610e9c9de
commit c04cadbb6e
3 changed files with 318 additions and 0 deletions

View File

@ -14,6 +14,8 @@
#include "include/utils/SkTextUtils.h"
#include "modules/particles/include/SkCurve.h"
#include "modules/particles/include/SkParticleData.h"
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLInterpreter.h"
void SkParticleAffector::apply(const SkParticleUpdateParams& params,
@ -433,6 +435,78 @@ private:
SkColorCurve fCurve;
};
static const char* kDefaultCode =
"layout(ctype=float) in uniform float dt;\n"
"layout(ctype=float) in uniform float effectAge;\n"
"\n"
"void main(in float age,\n"
" in float invLifetime,\n"
" inout float2 pos,\n"
" inout float2 dir,\n"
" inout float scale,\n"
" inout float2 vel,\n"
" inout float spin,\n"
" inout float4 color,\n"
" in float t) {\n"
"}\n";
class SkInterpreterAffector : public SkParticleAffector {
public:
SkInterpreterAffector() : fCode(kDefaultCode) {
this->rebuild();
}
REFLECTED(SkInterpreterAffector, SkParticleAffector)
void onApply(const SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
fInterpreter->setInputs((SkSL::Interpreter::Value*)&params);
for (int i = 0; i < count; ++i) {
fInterpreter->run(*fMain, (SkSL::Interpreter::Value*)&ps[i].fAge, nullptr);
}
}
void visitFields(SkFieldVisitor* v) override {
SkString oldCode = fCode;
SkParticleAffector::visitFields(v);
v->visit("Code", fCode);
if (fCode != oldCode) {
this->rebuild();
}
}
private:
SkString fCode;
// Cached
std::unique_ptr<SkSL::Interpreter> fInterpreter;
SkSL::ByteCodeFunction* fMain;
void rebuild() {
SkSL::Compiler compiler;
SkSL::Program::Settings settings;
auto program = compiler.convertProgram(SkSL::Program::kGeneric_Kind,
SkSL::String(fCode.c_str()), settings);
if (!program) {
SkDebugf("%s\n", compiler.errorText().c_str());
return;
}
auto byteCode = compiler.toByteCode(*program);
if (compiler.errorCount()) {
SkDebugf("%s\n", compiler.errorText().c_str());
return;
}
// These will be replaced with the real inputs in onApply, before running
SkParticleUpdateParams defaultInputs = { 0.0f, 0.0f, 0 };
fMain = byteCode->fFunctions[0].get();
fInterpreter.reset(new SkSL::Interpreter(std::move(program), std::move(byteCode),
(SkSL::Interpreter::Value*)&defaultInputs));
}
};
void SkParticleAffector::RegisterAffectorTypes() {
REGISTER_REFLECTED(SkParticleAffector);
REGISTER_REFLECTED(SkLinearVelocityAffector);
@ -445,6 +519,7 @@ void SkParticleAffector::RegisterAffectorTypes() {
REGISTER_REFLECTED(SkSizeAffector);
REGISTER_REFLECTED(SkFrameAffector);
REGISTER_REFLECTED(SkColorAffector);
REGISTER_REFLECTED(SkInterpreterAffector);
}
sk_sp<SkParticleAffector> SkParticleAffector::MakeLinearVelocity(const SkCurve& angle,

View File

@ -0,0 +1,63 @@
{
"MaxCount": 6000,
"Duration": 5,
"Rate": 2000,
"Life": {
"Input": {
"Source": "Age",
"TileMode": "Repeat",
"Left": 0,
"Right": 1
},
"XValues": [],
"Segments": [
{
"Type": "Constant",
"Ranged": true,
"Bidirectional": false,
"A0": 2,
"A1": 4
}
]
},
"Drawable": {
"Type": "SkCircleDrawable",
"Radius": 2
},
"Spawn": [
{
"Type": "SkFrameAffector",
"Enabled": true,
"Curve": {
"Input": {
"Source": "Random",
"TileMode": "Repeat",
"Left": 0,
"Right": 1
},
"XValues": [],
"Segments": [
{
"Type": "Linear",
"Ranged": false,
"Bidirectional": false,
"A0": 0,
"D0": 1
}
]
}
},
{
"Type": "SkInterpreterAffector",
"Enabled": true,
"Code": "layout(ctype=float) in uniform float dt;\nlayout(ctype=float) in uniform float effectAge;\n\nvoid main(in float age,\n in float invLifetime,\n inout float2 pos,\n inout float2 dir,\n inout float scale,\n inout float2 vel,\n inout float spin,\n inout float4 color,\n in float t) {\n float r = t;\n vel.x = 50 + (30 * r);\n r = (r * 7) % 1;\n vel.y = (r * 20) - 10;\n r = (r * 11) % 1;\n}\n"
}
],
"Update": [
{
"Type": "SkInterpreterAffector",
"Enabled": true,
"Code": "layout(ctype=float) in uniform float dt;\nlayout(ctype=float) in uniform float effectAge;\n\nvoid main(in float age,\n in float invLifetime,\n inout float2 pos,\n inout float2 dir,\n inout float scale,\n inout float2 vel,\n inout float spin,\n inout float4 color,\n in float t) {\n color.r = age;\n color.g = 1 - age;\n\n float x = age;\n float ix = 1 - age;\n\n scale = 0.5 * ix*ix*ix + 3*ix*ix*x + 2*3*ix*x*x + 0.5*x*x*x;\n\n vel.y += 20.0 * dt;\n}\n"
}
]
}

View File

@ -0,0 +1,180 @@
{
"MaxCount": 6000,
"Duration": 5,
"Rate": 2000,
"Life": {
"Input": {
"Source": "Age",
"TileMode": "Repeat",
"Left": 0,
"Right": 1
},
"XValues": [],
"Segments": [
{
"Type": "Constant",
"Ranged": true,
"Bidirectional": false,
"A0": 2,
"A1": 4
}
]
},
"Drawable": {
"Type": "SkCircleDrawable",
"Radius": 2
},
"Spawn": [
{
"Type": "SkFrameAffector",
"Enabled": true,
"Curve": {
"Input": {
"Source": "Random",
"TileMode": "Repeat",
"Left": 0,
"Right": 1
},
"XValues": [],
"Segments": [
{
"Type": "Linear",
"Ranged": false,
"Bidirectional": false,
"A0": 0,
"D0": 1
}
]
}
},
{
"Type": "SkLinearVelocityAffector",
"Enabled": true,
"Force": false,
"Frame": "World",
"Angle": {
"Input": {
"Source": "Age",
"TileMode": "Repeat",
"Left": 0,
"Right": 1
},
"XValues": [],
"Segments": [
{
"Type": "Constant",
"Ranged": true,
"Bidirectional": false,
"A0": 80,
"A1": 100
}
]
},
"Strength": {
"Input": {
"Source": "Age",
"TileMode": "Repeat",
"Left": 0,
"Right": 1
},
"XValues": [],
"Segments": [
{
"Type": "Constant",
"Ranged": true,
"Bidirectional": false,
"A0": 50,
"A1": 80
}
]
}
}
],
"Update": [
{
"Type": "SkColorAffector",
"Enabled": true,
"Curve": {
"Input": {
"Source": "Age",
"TileMode": "Repeat",
"Left": 0,
"Right": 1
},
"XValues": [],
"Segments": [
{
"Type": "Linear",
"Ranged": false,
"A0": [ 0, 1, 1, 1 ],
"D0": [ 1, 0, 1, 1 ]
}
]
}
},
{
"Type": "SkSizeAffector",
"Enabled": true,
"Curve": {
"Input": {
"Source": "Age",
"TileMode": "Repeat",
"Left": 0,
"Right": 1
},
"XValues": [],
"Segments": [
{
"Type": "Cubic",
"Ranged": false,
"Bidirectional": false,
"A0": 0.5,
"B0": 1,
"C0": 2,
"D0": 0.5
}
]
}
},
{
"Type": "SkLinearVelocityAffector",
"Enabled": true,
"Force": true,
"Frame": "World",
"Angle": {
"Input": {
"Source": "Age",
"TileMode": "Repeat",
"Left": 0,
"Right": 1
},
"XValues": [],
"Segments": [
{
"Type": "Constant",
"Ranged": false,
"Bidirectional": false,
"A0": 0
}
]
},
"Strength": {
"Input": {
"Source": "Age",
"TileMode": "Repeat",
"Left": 0,
"Right": 1
},
"XValues": [],
"Segments": [
{
"Type": "Constant",
"Ranged": false,
"Bidirectional": false,
"A0": -20
}
]
}
}
]
}