2019-06-20 16:40:30 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2019 Google LLC
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "gm/gm.h"
|
|
|
|
#include "include/core/SkCanvas.h"
|
|
|
|
#include "include/core/SkData.h"
|
|
|
|
#include "include/core/SkPaint.h"
|
|
|
|
#include "include/core/SkSize.h"
|
|
|
|
#include "include/core/SkString.h"
|
2020-07-15 14:52:37 +00:00
|
|
|
#include "include/core/SkSurface.h"
|
|
|
|
#include "include/effects/SkGradientShader.h"
|
2020-02-13 17:36:28 +00:00
|
|
|
#include "include/effects/SkImageFilters.h"
|
2020-01-02 16:55:24 +00:00
|
|
|
#include "include/effects/SkRuntimeEffect.h"
|
2020-07-15 14:52:37 +00:00
|
|
|
#include "include/utils/SkRandom.h"
|
2020-02-13 17:36:28 +00:00
|
|
|
#include "tools/Resources.h"
|
2019-06-20 16:40:30 +00:00
|
|
|
|
2020-07-15 14:52:37 +00:00
|
|
|
enum RT_Flags {
|
|
|
|
kAnimate_RTFlag = 0x1,
|
|
|
|
kBench_RTFlag = 0x2,
|
|
|
|
};
|
|
|
|
|
|
|
|
class RuntimeShaderGM : public skiagm::GM {
|
|
|
|
public:
|
|
|
|
RuntimeShaderGM(const char* name, SkISize size, const char* sksl, uint32_t flags = 0)
|
|
|
|
: fName(name), fSize(size), fFlags(flags), fSkSL(sksl) {}
|
2019-06-20 16:40:30 +00:00
|
|
|
|
2020-07-15 14:52:37 +00:00
|
|
|
void onOnceBeforeDraw() override {
|
|
|
|
auto [effect, error] = SkRuntimeEffect::Make(fSkSL);
|
|
|
|
if (!effect) {
|
|
|
|
SkDebugf("RuntimeShader error: %s\n", error.c_str());
|
|
|
|
}
|
|
|
|
fEffect = std::move(effect);
|
2019-06-20 16:40:30 +00:00
|
|
|
}
|
|
|
|
|
2020-07-15 14:52:37 +00:00
|
|
|
bool runAsBench() const override { return SkToBool(fFlags & kBench_RTFlag); }
|
|
|
|
SkString onShortName() override { return fName; }
|
|
|
|
SkISize onISize() override { return fSize; }
|
2019-06-20 16:40:30 +00:00
|
|
|
|
2020-07-15 14:52:37 +00:00
|
|
|
bool onAnimate(double nanos) override {
|
|
|
|
fSecs = nanos / (1000 * 1000 * 1000);
|
|
|
|
return SkToBool(fFlags & kAnimate_RTFlag);
|
|
|
|
}
|
2019-06-20 16:40:30 +00:00
|
|
|
|
2020-07-15 14:52:37 +00:00
|
|
|
protected:
|
|
|
|
SkString fName;
|
|
|
|
SkISize fSize;
|
|
|
|
uint32_t fFlags;
|
|
|
|
float fSecs = 0.0f;
|
|
|
|
|
|
|
|
SkString fSkSL;
|
|
|
|
sk_sp<SkRuntimeEffect> fEffect;
|
|
|
|
};
|
|
|
|
|
|
|
|
class SimpleRT : public RuntimeShaderGM {
|
|
|
|
public:
|
|
|
|
SimpleRT() : RuntimeShaderGM("runtime_shader", {512, 256}, R"(
|
|
|
|
uniform half4 gColor;
|
|
|
|
|
2020-08-13 20:59:48 +00:00
|
|
|
half4 main(float2 p) {
|
2020-09-14 18:44:42 +00:00
|
|
|
return half4(p*(1.0/255), gColor.b, 1);
|
2020-07-15 14:52:37 +00:00
|
|
|
}
|
|
|
|
)", kBench_RTFlag) {}
|
2019-06-20 16:40:30 +00:00
|
|
|
|
|
|
|
void onDraw(SkCanvas* canvas) override {
|
2020-07-15 14:52:37 +00:00
|
|
|
SkRuntimeShaderBuilder builder(fEffect);
|
2019-12-26 13:43:05 +00:00
|
|
|
|
|
|
|
SkMatrix localM;
|
|
|
|
localM.setRotate(90, 128, 128);
|
Remove 'in' variables from SkRuntimeEffect
Runtime effects previously allowed two kinds of global input variables:
'in' variables could be bool, int, or float. 'uniform' could be float,
vector, or matrix. Uniform variables worked like you'd expect, but 'in'
variables were baked into the program statically. There was a large
amount of machinery to make this work, and it meant that 'in' variables
needed to have values before we could make decisions about program
caching, and before we could catch some errors. It was also essentially
syntactic sugar over the client just inserting the value into their SkSL
as a string. Finally: No one was using the feature.
To simplify the mental model, and make the API much more predictable,
this CL removes 'in' variables entirely. We no longer need to
"specialize" runtime effect programs, which means we can catch more
errors up front (those not detected until optimization). All of the API
that referred to "inputs" (the previous term that unified 'in' and
'uniform') now just refers to "uniforms".
Bug: skia:10593
Change-Id: I971f620d868b259e652b3114f0b497c2620f4b0c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/309050
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
Reviewed-by: John Stiles <johnstiles@google.com>
2020-08-10 18:26:16 +00:00
|
|
|
builder.uniform("gColor") = SkColor4f{1, 0, 0, 1};
|
2019-12-26 13:43:05 +00:00
|
|
|
|
2019-06-20 16:40:30 +00:00
|
|
|
SkPaint p;
|
2020-07-15 14:52:37 +00:00
|
|
|
p.setShader(builder.makeShader(&localM, true));
|
2019-06-20 16:40:30 +00:00
|
|
|
canvas->drawRect({0, 0, 256, 256}, p);
|
|
|
|
}
|
|
|
|
};
|
2020-07-15 14:52:37 +00:00
|
|
|
DEF_GM(return new SimpleRT;)
|
2020-02-13 17:36:28 +00:00
|
|
|
|
|
|
|
static sk_sp<SkShader> make_shader(sk_sp<SkImage> img, SkISize size) {
|
2020-05-21 16:11:27 +00:00
|
|
|
SkMatrix scale = SkMatrix::Scale(size.width() / (float)img->width(),
|
|
|
|
size.height() / (float)img->height());
|
2020-12-10 02:48:52 +00:00
|
|
|
return img->makeShader(SkSamplingOptions(), scale);
|
2020-02-13 17:36:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static sk_sp<SkShader> make_threshold(SkISize size) {
|
|
|
|
auto info = SkImageInfo::Make(size.width(), size.height(), kAlpha_8_SkColorType,
|
|
|
|
kPremul_SkAlphaType);
|
|
|
|
auto surf = SkSurface::MakeRaster(info);
|
|
|
|
auto canvas = surf->getCanvas();
|
|
|
|
|
|
|
|
const SkScalar rad = 50;
|
|
|
|
SkColor colors[] = {SK_ColorBLACK, 0};
|
|
|
|
SkPaint paint;
|
|
|
|
paint.setAntiAlias(true);
|
|
|
|
paint.setShader(SkGradientShader::MakeRadial({0,0}, rad, colors, nullptr, 2, SkTileMode::kClamp));
|
|
|
|
|
|
|
|
SkPaint layerPaint;
|
|
|
|
const SkScalar sigma = 16.0f;
|
|
|
|
layerPaint.setImageFilter(SkImageFilters::Blur(sigma, sigma, nullptr));
|
|
|
|
canvas->saveLayer(nullptr, &layerPaint);
|
|
|
|
|
|
|
|
SkRandom rand;
|
|
|
|
for (int i = 0; i < 25; ++i) {
|
|
|
|
SkScalar x = rand.nextF() * size.width();
|
|
|
|
SkScalar y = rand.nextF() * size.height();
|
|
|
|
canvas->save();
|
|
|
|
canvas->translate(x, y);
|
|
|
|
canvas->drawCircle(0, 0, rad, paint);
|
|
|
|
canvas->restore();
|
|
|
|
}
|
|
|
|
|
|
|
|
canvas->restore(); // apply the blur
|
|
|
|
|
2020-12-10 02:48:52 +00:00
|
|
|
return surf->makeImageSnapshot()->makeShader(SkSamplingOptions());
|
2020-02-13 17:36:28 +00:00
|
|
|
}
|
|
|
|
|
2020-07-15 14:52:37 +00:00
|
|
|
class ThresholdRT : public RuntimeShaderGM {
|
|
|
|
public:
|
|
|
|
ThresholdRT() : RuntimeShaderGM("threshold_rt", {256, 256}, R"(
|
2020-11-04 20:40:50 +00:00
|
|
|
uniform shader before_map;
|
|
|
|
uniform shader after_map;
|
|
|
|
uniform shader threshold_map;
|
2020-07-15 14:52:37 +00:00
|
|
|
|
|
|
|
uniform float cutoff;
|
|
|
|
uniform float slope;
|
|
|
|
|
|
|
|
float smooth_cutoff(float x) {
|
|
|
|
x = x * slope + (0.5 - slope * cutoff);
|
|
|
|
return clamp(x, 0, 1);
|
|
|
|
}
|
|
|
|
|
2020-08-13 20:59:48 +00:00
|
|
|
half4 main(float2 xy) {
|
2020-07-15 14:52:37 +00:00
|
|
|
half4 before = sample(before_map);
|
|
|
|
half4 after = sample(after_map);
|
|
|
|
|
|
|
|
float m = smooth_cutoff(sample(threshold_map).a);
|
2020-09-14 18:44:42 +00:00
|
|
|
return mix(before, after, m);
|
2020-07-15 14:52:37 +00:00
|
|
|
}
|
|
|
|
)", kAnimate_RTFlag | kBench_RTFlag) {}
|
2020-02-13 17:36:28 +00:00
|
|
|
|
2020-07-15 14:52:37 +00:00
|
|
|
sk_sp<SkShader> fBefore, fAfter, fThreshold;
|
2020-02-13 17:36:28 +00:00
|
|
|
|
|
|
|
void onOnceBeforeDraw() override {
|
|
|
|
const SkISize size = {256, 256};
|
|
|
|
fThreshold = make_threshold(size);
|
|
|
|
fBefore = make_shader(GetResourceAsImage("images/mandrill_256.png"), size);
|
|
|
|
fAfter = make_shader(GetResourceAsImage("images/dog.jpg"), size);
|
|
|
|
|
2020-07-15 14:52:37 +00:00
|
|
|
this->RuntimeShaderGM::onOnceBeforeDraw();
|
2020-02-13 17:36:28 +00:00
|
|
|
}
|
|
|
|
|
2020-07-15 14:52:37 +00:00
|
|
|
void onDraw(SkCanvas* canvas) override {
|
|
|
|
SkRuntimeShaderBuilder builder(fEffect);
|
2020-02-13 17:36:28 +00:00
|
|
|
|
Remove 'in' variables from SkRuntimeEffect
Runtime effects previously allowed two kinds of global input variables:
'in' variables could be bool, int, or float. 'uniform' could be float,
vector, or matrix. Uniform variables worked like you'd expect, but 'in'
variables were baked into the program statically. There was a large
amount of machinery to make this work, and it meant that 'in' variables
needed to have values before we could make decisions about program
caching, and before we could catch some errors. It was also essentially
syntactic sugar over the client just inserting the value into their SkSL
as a string. Finally: No one was using the feature.
To simplify the mental model, and make the API much more predictable,
this CL removes 'in' variables entirely. We no longer need to
"specialize" runtime effect programs, which means we can catch more
errors up front (those not detected until optimization). All of the API
that referred to "inputs" (the previous term that unified 'in' and
'uniform') now just refers to "uniforms".
Bug: skia:10593
Change-Id: I971f620d868b259e652b3114f0b497c2620f4b0c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/309050
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
Reviewed-by: John Stiles <johnstiles@google.com>
2020-08-10 18:26:16 +00:00
|
|
|
builder.uniform("cutoff") = sin(fSecs) * 0.55f + 0.5f;
|
|
|
|
builder.uniform("slope") = 10.0f;
|
2020-02-13 17:36:28 +00:00
|
|
|
|
2020-07-15 14:52:37 +00:00
|
|
|
builder.child("before_map") = fBefore;
|
|
|
|
builder.child("after_map") = fAfter;
|
|
|
|
builder.child("threshold_map") = fThreshold;
|
2020-02-13 17:36:28 +00:00
|
|
|
|
|
|
|
SkPaint paint;
|
2020-07-15 14:52:37 +00:00
|
|
|
paint.setShader(builder.makeShader(nullptr, true));
|
2020-02-13 17:36:28 +00:00
|
|
|
canvas->drawRect({0, 0, 256, 256}, paint);
|
|
|
|
|
|
|
|
auto draw = [&](SkScalar x, SkScalar y, sk_sp<SkShader> shader) {
|
|
|
|
paint.setShader(shader);
|
|
|
|
canvas->save();
|
|
|
|
canvas->translate(x, y);
|
|
|
|
canvas->drawRect({0, 0, 256, 256}, paint);
|
|
|
|
canvas->restore();
|
|
|
|
};
|
|
|
|
draw(256, 0, fThreshold);
|
|
|
|
draw( 0, 256, fBefore);
|
|
|
|
draw(256, 256, fAfter);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
DEF_GM(return new ThresholdRT;)
|
2020-04-30 16:06:23 +00:00
|
|
|
|
2020-07-15 14:52:37 +00:00
|
|
|
class SpiralRT : public RuntimeShaderGM {
|
|
|
|
public:
|
|
|
|
SpiralRT() : RuntimeShaderGM("spiral_rt", {512, 512}, R"(
|
|
|
|
uniform float rad_scale;
|
|
|
|
uniform float2 in_center;
|
|
|
|
layout(srgb_unpremul) uniform float4 in_colors0;
|
|
|
|
layout(srgb_unpremul) uniform float4 in_colors1;
|
|
|
|
|
2020-08-13 20:59:48 +00:00
|
|
|
half4 main(float2 p) {
|
2020-07-15 14:52:37 +00:00
|
|
|
float2 pp = p - in_center;
|
|
|
|
float radius = length(pp);
|
|
|
|
radius = sqrt(radius);
|
|
|
|
float angle = atan(pp.y / pp.x);
|
|
|
|
float t = (angle + 3.1415926/2) / (3.1415926);
|
|
|
|
t += radius * rad_scale;
|
|
|
|
t = fract(t);
|
2020-09-14 18:44:42 +00:00
|
|
|
return in_colors0 * (1-t) + in_colors1 * t;
|
2020-04-30 16:06:23 +00:00
|
|
|
}
|
2020-07-15 14:52:37 +00:00
|
|
|
)", kAnimate_RTFlag | kBench_RTFlag) {}
|
2020-04-30 16:06:23 +00:00
|
|
|
|
|
|
|
void onDraw(SkCanvas* canvas) override {
|
2020-07-15 14:52:37 +00:00
|
|
|
SkRuntimeShaderBuilder builder(fEffect);
|
|
|
|
|
Remove 'in' variables from SkRuntimeEffect
Runtime effects previously allowed two kinds of global input variables:
'in' variables could be bool, int, or float. 'uniform' could be float,
vector, or matrix. Uniform variables worked like you'd expect, but 'in'
variables were baked into the program statically. There was a large
amount of machinery to make this work, and it meant that 'in' variables
needed to have values before we could make decisions about program
caching, and before we could catch some errors. It was also essentially
syntactic sugar over the client just inserting the value into their SkSL
as a string. Finally: No one was using the feature.
To simplify the mental model, and make the API much more predictable,
this CL removes 'in' variables entirely. We no longer need to
"specialize" runtime effect programs, which means we can catch more
errors up front (those not detected until optimization). All of the API
that referred to "inputs" (the previous term that unified 'in' and
'uniform') now just refers to "uniforms".
Bug: skia:10593
Change-Id: I971f620d868b259e652b3114f0b497c2620f4b0c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/309050
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
Reviewed-by: John Stiles <johnstiles@google.com>
2020-08-10 18:26:16 +00:00
|
|
|
builder.uniform("rad_scale") = std::sin(fSecs * 0.5f + 2.0f) / 5;
|
|
|
|
builder.uniform("in_center") = SkV2{256, 256};
|
|
|
|
builder.uniform("in_colors0") = SkV4{1, 0, 0, 1};
|
|
|
|
builder.uniform("in_colors1") = SkV4{0, 1, 0, 1};
|
2020-04-30 16:06:23 +00:00
|
|
|
|
|
|
|
SkPaint paint;
|
2020-07-15 14:52:37 +00:00
|
|
|
paint.setShader(builder.makeShader(nullptr, true));
|
2020-04-30 16:06:23 +00:00
|
|
|
canvas->drawRect({0, 0, 512, 512}, paint);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
DEF_GM(return new SpiralRT;)
|
2020-05-21 20:41:43 +00:00
|
|
|
|
2020-07-15 14:52:37 +00:00
|
|
|
class ColorCubeRT : public RuntimeShaderGM {
|
|
|
|
public:
|
|
|
|
ColorCubeRT() : RuntimeShaderGM("color_cube_rt", {512, 512}, R"(
|
2020-11-04 20:40:50 +00:00
|
|
|
uniform shader input;
|
|
|
|
uniform shader color_cube;
|
2020-05-21 20:41:43 +00:00
|
|
|
|
2020-07-15 14:52:37 +00:00
|
|
|
uniform float rg_scale;
|
|
|
|
uniform float rg_bias;
|
|
|
|
uniform float b_scale;
|
|
|
|
uniform float inv_size;
|
2020-05-21 20:41:43 +00:00
|
|
|
|
2020-08-13 20:59:48 +00:00
|
|
|
half4 main(float2 xy) {
|
2020-09-14 18:44:42 +00:00
|
|
|
float4 c = unpremul(sample(input));
|
2020-05-21 20:41:43 +00:00
|
|
|
|
2020-07-15 14:52:37 +00:00
|
|
|
// Map to cube coords:
|
|
|
|
float3 cubeCoords = float3(c.rg * rg_scale + rg_bias, c.b * b_scale);
|
2020-05-21 20:41:43 +00:00
|
|
|
|
2020-07-15 14:52:37 +00:00
|
|
|
// Compute slice coordinate
|
|
|
|
float2 coords1 = float2((floor(cubeCoords.b) + cubeCoords.r) * inv_size, cubeCoords.g);
|
|
|
|
float2 coords2 = float2(( ceil(cubeCoords.b) + cubeCoords.r) * inv_size, cubeCoords.g);
|
2020-05-21 20:41:43 +00:00
|
|
|
|
2020-07-15 14:52:37 +00:00
|
|
|
// Two bilinear fetches, plus a manual lerp for the third axis:
|
2020-08-13 20:59:48 +00:00
|
|
|
half4 color = mix(sample(color_cube, coords1), sample(color_cube, coords2),
|
2020-09-14 18:44:42 +00:00
|
|
|
fract(cubeCoords.b));
|
2020-05-21 20:41:43 +00:00
|
|
|
|
2020-07-15 14:52:37 +00:00
|
|
|
// Premul again
|
|
|
|
color.rgb *= color.a;
|
2020-08-13 20:59:48 +00:00
|
|
|
|
|
|
|
return color;
|
2020-05-21 20:41:43 +00:00
|
|
|
}
|
2020-07-15 14:52:37 +00:00
|
|
|
)") {}
|
|
|
|
|
|
|
|
sk_sp<SkImage> fMandrill, fMandrillSepia, fIdentityCube, fSepiaCube;
|
2020-05-21 20:41:43 +00:00
|
|
|
|
2020-07-15 14:52:37 +00:00
|
|
|
void onOnceBeforeDraw() override {
|
|
|
|
fMandrill = GetResourceAsImage("images/mandrill_256.png");
|
|
|
|
fMandrillSepia = GetResourceAsImage("images/mandrill_sepia.png");
|
|
|
|
fIdentityCube = GetResourceAsImage("images/lut_identity.png");
|
|
|
|
fSepiaCube = GetResourceAsImage("images/lut_sepia.png");
|
2020-05-21 20:41:43 +00:00
|
|
|
|
2020-07-15 14:52:37 +00:00
|
|
|
this->RuntimeShaderGM::onOnceBeforeDraw();
|
|
|
|
}
|
2020-05-21 20:41:43 +00:00
|
|
|
|
2020-06-18 21:11:16 +00:00
|
|
|
void onDraw(SkCanvas* canvas) override {
|
2020-07-15 14:52:37 +00:00
|
|
|
SkRuntimeShaderBuilder builder(fEffect);
|
|
|
|
|
2020-05-21 20:41:43 +00:00
|
|
|
// First we draw the unmodified image, and a copy that was sepia-toned in Photoshop:
|
|
|
|
canvas->drawImage(fMandrill, 0, 0);
|
|
|
|
canvas->drawImage(fMandrillSepia, 0, 256);
|
|
|
|
|
|
|
|
// LUT dimensions should be (kSize^2, kSize)
|
|
|
|
constexpr float kSize = 16.0f;
|
|
|
|
|
2021-01-15 02:59:01 +00:00
|
|
|
const SkSamplingOptions sampling(SkFilterMode::kLinear);
|
2020-12-10 02:48:52 +00:00
|
|
|
|
Remove 'in' variables from SkRuntimeEffect
Runtime effects previously allowed two kinds of global input variables:
'in' variables could be bool, int, or float. 'uniform' could be float,
vector, or matrix. Uniform variables worked like you'd expect, but 'in'
variables were baked into the program statically. There was a large
amount of machinery to make this work, and it meant that 'in' variables
needed to have values before we could make decisions about program
caching, and before we could catch some errors. It was also essentially
syntactic sugar over the client just inserting the value into their SkSL
as a string. Finally: No one was using the feature.
To simplify the mental model, and make the API much more predictable,
this CL removes 'in' variables entirely. We no longer need to
"specialize" runtime effect programs, which means we can catch more
errors up front (those not detected until optimization). All of the API
that referred to "inputs" (the previous term that unified 'in' and
'uniform') now just refers to "uniforms".
Bug: skia:10593
Change-Id: I971f620d868b259e652b3114f0b497c2620f4b0c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/309050
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
Reviewed-by: John Stiles <johnstiles@google.com>
2020-08-10 18:26:16 +00:00
|
|
|
builder.uniform("rg_scale") = (kSize - 1) / kSize;
|
|
|
|
builder.uniform("rg_bias") = 0.5f / kSize;
|
|
|
|
builder.uniform("b_scale") = kSize - 1;
|
|
|
|
builder.uniform("inv_size") = 1.0f / kSize;
|
2020-05-28 17:38:24 +00:00
|
|
|
|
2020-12-10 02:48:52 +00:00
|
|
|
builder.child("input") = fMandrill->makeShader(sampling);
|
2020-05-21 20:41:43 +00:00
|
|
|
|
|
|
|
SkPaint paint;
|
|
|
|
|
2020-05-28 17:38:24 +00:00
|
|
|
// TODO: Should we add SkImage::makeNormalizedShader() to handle this automatically?
|
|
|
|
SkMatrix normalize = SkMatrix::Scale(1.0f / (kSize * kSize), 1.0f / kSize);
|
|
|
|
|
2020-05-21 20:41:43 +00:00
|
|
|
// Now draw the image with an identity color cube - it should look like the original
|
2020-12-10 02:48:52 +00:00
|
|
|
builder.child("color_cube") = fIdentityCube->makeShader(sampling, normalize);
|
2020-05-21 20:41:43 +00:00
|
|
|
paint.setShader(builder.makeShader(nullptr, true));
|
|
|
|
canvas->translate(256, 0);
|
|
|
|
canvas->drawRect({ 0, 0, 256, 256 }, paint);
|
|
|
|
|
|
|
|
// ... and with a sepia-tone color cube. This should match the sepia-toned image.
|
2020-12-10 02:48:52 +00:00
|
|
|
builder.child("color_cube") = fSepiaCube->makeShader(sampling, normalize);
|
2020-05-21 20:41:43 +00:00
|
|
|
paint.setShader(builder.makeShader(nullptr, true));
|
|
|
|
canvas->translate(0, 256);
|
|
|
|
canvas->drawRect({ 0, 0, 256, 256 }, paint);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
DEF_GM(return new ColorCubeRT;)
|
2020-07-10 18:08:56 +00:00
|
|
|
|
2020-07-15 14:52:37 +00:00
|
|
|
class DefaultColorRT : public RuntimeShaderGM {
|
|
|
|
public:
|
2020-08-12 14:22:34 +00:00
|
|
|
// This test also *explicitly* doesn't include coords in main's parameter list, to test that
|
|
|
|
// runtime shaders work without them being declared (when they're not used).
|
2020-07-15 14:52:37 +00:00
|
|
|
DefaultColorRT() : RuntimeShaderGM("default_color_rt", {512, 256}, R"(
|
2020-11-04 20:40:50 +00:00
|
|
|
uniform shader input;
|
2020-08-13 20:59:48 +00:00
|
|
|
half4 main() {
|
|
|
|
return sample(input);
|
2020-07-15 14:52:37 +00:00
|
|
|
}
|
|
|
|
)") {}
|
|
|
|
|
2020-07-10 18:08:56 +00:00
|
|
|
sk_sp<SkImage> fMandrill;
|
|
|
|
|
|
|
|
void onOnceBeforeDraw() override {
|
|
|
|
fMandrill = GetResourceAsImage("images/mandrill_256.png");
|
2020-07-15 14:52:37 +00:00
|
|
|
this->RuntimeShaderGM::onOnceBeforeDraw();
|
2020-07-10 18:08:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void onDraw(SkCanvas* canvas) override {
|
|
|
|
SkRuntimeShaderBuilder builder(fEffect);
|
|
|
|
|
|
|
|
// First, we leave the child as null, so sampling it returns the default (paint) color
|
|
|
|
SkPaint paint;
|
|
|
|
paint.setColor4f({ 0.25f, 0.75f, 0.75f, 1.0f });
|
|
|
|
paint.setShader(builder.makeShader(nullptr, false));
|
|
|
|
canvas->drawRect({ 0, 0, 256, 256 }, paint);
|
|
|
|
|
|
|
|
// Now we bind an image shader as the child. This (by convention) scales by the paint alpha
|
2020-12-10 02:48:52 +00:00
|
|
|
builder.child("input") = fMandrill->makeShader(SkSamplingOptions());
|
2020-07-10 18:08:56 +00:00
|
|
|
paint.setColor4f({ 1.0f, 1.0f, 1.0f, 0.5f });
|
|
|
|
paint.setShader(builder.makeShader(nullptr, false));
|
|
|
|
canvas->translate(256, 0);
|
|
|
|
canvas->drawRect({ 0, 0, 256, 256 }, paint);
|
|
|
|
|
|
|
|
}
|
|
|
|
};
|
|
|
|
DEF_GM(return new DefaultColorRT;)
|
2021-02-03 15:54:07 +00:00
|
|
|
|
|
|
|
|
|
|
|
DEF_SIMPLE_GM(child_sampling_rt, canvas, 256,256) {
|
|
|
|
static constexpr char scale[] =
|
|
|
|
"uniform shader child;"
|
|
|
|
"half4 main(float2 xy) {"
|
|
|
|
" return sample(child, xy*0.1);"
|
|
|
|
"}";
|
|
|
|
|
|
|
|
SkPaint p;
|
|
|
|
p.setColor(SK_ColorRED);
|
|
|
|
p.setAntiAlias(true);
|
|
|
|
p.setStyle(SkPaint::kStroke_Style);
|
|
|
|
p.setStrokeWidth(1);
|
|
|
|
|
|
|
|
auto surf = SkSurface::MakeRasterN32Premul(100,100);
|
|
|
|
surf->getCanvas()->drawLine(0, 0, 100, 100, p);
|
|
|
|
auto shader = surf->makeImageSnapshot()->makeShader(SkSamplingOptions(SkFilterMode::kLinear));
|
|
|
|
|
2021-02-11 22:40:03 +00:00
|
|
|
SkRuntimeShaderBuilder builder(SkRuntimeEffect::Make(SkString(scale)).effect);
|
2021-02-03 15:54:07 +00:00
|
|
|
builder.child("child") = shader;
|
|
|
|
p.setShader(builder.makeShader(nullptr, false));
|
|
|
|
|
|
|
|
canvas->drawPaint(p);
|
|
|
|
}
|