1*c8dee2aaSAndroid Build Coastguard Worker // Copyright 2024 Google LLC.
2*c8dee2aaSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
3*c8dee2aaSAndroid Build Coastguard Worker #include "tools/fiddle/examples.h"
4*c8dee2aaSAndroid Build Coastguard Worker REG_FIDDLE(SkSL_RawImageShaders, 384, 128, false, 0) {
make_image(sk_sp<SkRuntimeEffect> effect,const SkImageInfo & info)5*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkImage> make_image(sk_sp<SkRuntimeEffect> effect,
6*c8dee2aaSAndroid Build Coastguard Worker const SkImageInfo& info) {
7*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkSurface> surface = SkSurfaces::Raster(info);
8*c8dee2aaSAndroid Build Coastguard Worker SkCanvas* canvas = surface->getCanvas();
9*c8dee2aaSAndroid Build Coastguard Worker auto shader = effect->makeShader(/*uniforms=*/ nullptr, /*children=*/ {});
10*c8dee2aaSAndroid Build Coastguard Worker if (!shader) {
11*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
12*c8dee2aaSAndroid Build Coastguard Worker }
13*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
14*c8dee2aaSAndroid Build Coastguard Worker paint.setShader(std::move(shader));
15*c8dee2aaSAndroid Build Coastguard Worker paint.setBlendMode(SkBlendMode::kSrc);
16*c8dee2aaSAndroid Build Coastguard Worker canvas->drawPaint(paint);
17*c8dee2aaSAndroid Build Coastguard Worker return surface->makeImageSnapshot();
18*c8dee2aaSAndroid Build Coastguard Worker }
19*c8dee2aaSAndroid Build Coastguard Worker
draw(SkCanvas * canvas)20*c8dee2aaSAndroid Build Coastguard Worker void draw(SkCanvas* canvas) {
21*c8dee2aaSAndroid Build Coastguard Worker // Make a hemispherical normal map image:
22*c8dee2aaSAndroid Build Coastguard Worker auto imageInfo = SkImageInfo::MakeN32Premul(128, 128);
23*c8dee2aaSAndroid Build Coastguard Worker auto imageShader = SkRuntimeEffect::MakeForShader(SkString(R"(
24*c8dee2aaSAndroid Build Coastguard Worker vec4 main(vec2 p) {
25*c8dee2aaSAndroid Build Coastguard Worker p = (p / 128) * 2 - 1;
26*c8dee2aaSAndroid Build Coastguard Worker float len2 = dot(p, p);
27*c8dee2aaSAndroid Build Coastguard Worker vec3 v = (len2 > 1) ? vec3(0, 0, 1) : vec3(p, sqrt(1 - len2));
28*c8dee2aaSAndroid Build Coastguard Worker return (v * 0.5 + 0.5).xyz1;
29*c8dee2aaSAndroid Build Coastguard Worker })")).effect;
30*c8dee2aaSAndroid Build Coastguard Worker auto normalImage = make_image(imageShader, imageInfo);
31*c8dee2aaSAndroid Build Coastguard Worker
32*c8dee2aaSAndroid Build Coastguard Worker // Make a simple lighting effect:
33*c8dee2aaSAndroid Build Coastguard Worker auto litEffect = SkRuntimeEffect::MakeForShader(SkString(R"(
34*c8dee2aaSAndroid Build Coastguard Worker uniform shader normals;
35*c8dee2aaSAndroid Build Coastguard Worker vec4 main(vec2 p) {
36*c8dee2aaSAndroid Build Coastguard Worker vec3 n = normalize(normals.eval(p).xyz * 2 - 1);
37*c8dee2aaSAndroid Build Coastguard Worker vec3 l = normalize(vec3(-1, -1, 0.5));
38*c8dee2aaSAndroid Build Coastguard Worker return saturate(dot(n, l)).xxx1;
39*c8dee2aaSAndroid Build Coastguard Worker })")).effect;
40*c8dee2aaSAndroid Build Coastguard Worker SkRuntimeShaderBuilder builder(litEffect);
41*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
42*c8dee2aaSAndroid Build Coastguard Worker
43*c8dee2aaSAndroid Build Coastguard Worker // FIRST: Draw the lighting to our (not color managed) canvas.
44*c8dee2aaSAndroid Build Coastguard Worker // This is our CORRECT, reference result:
45*c8dee2aaSAndroid Build Coastguard Worker builder.child("normals") = normalImage->makeShader(SkSamplingOptions{});
46*c8dee2aaSAndroid Build Coastguard Worker paint.setShader(builder.makeShader());
47*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect({0,0,128,128}, paint);
48*c8dee2aaSAndroid Build Coastguard Worker
49*c8dee2aaSAndroid Build Coastguard Worker // Make an offscreen surface with a wide gamut:
50*c8dee2aaSAndroid Build Coastguard Worker auto rec2020 = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB,
51*c8dee2aaSAndroid Build Coastguard Worker SkNamedGamut::kRec2020);
52*c8dee2aaSAndroid Build Coastguard Worker auto info = SkImageInfo::Make(128, 128, kRGBA_F16_SkColorType,
53*c8dee2aaSAndroid Build Coastguard Worker kPremul_SkAlphaType, rec2020);
54*c8dee2aaSAndroid Build Coastguard Worker auto surface = SkSurfaces::Raster(info);
55*c8dee2aaSAndroid Build Coastguard Worker
56*c8dee2aaSAndroid Build Coastguard Worker // SECOND: Draw the lighting to the offscreen surface. Color management
57*c8dee2aaSAndroid Build Coastguard Worker // changes the normals, producing INCORRECT (wrong direction) lighting:
58*c8dee2aaSAndroid Build Coastguard Worker surface->getCanvas()->drawPaint(paint);
59*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(surface->makeImageSnapshot(), 128, 0);
60*c8dee2aaSAndroid Build Coastguard Worker
61*c8dee2aaSAndroid Build Coastguard Worker // THIRD: Convert the normals to a raw image shader. This ignores color
62*c8dee2aaSAndroid Build Coastguard Worker // management for that image, so we get CORRECT lighting again:
63*c8dee2aaSAndroid Build Coastguard Worker builder.child("normals") = normalImage->makeRawShader(SkSamplingOptions{});
64*c8dee2aaSAndroid Build Coastguard Worker paint.setShader(builder.makeShader());
65*c8dee2aaSAndroid Build Coastguard Worker surface->getCanvas()->drawPaint(paint);
66*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(surface->makeImageSnapshot(), 256, 0);
67*c8dee2aaSAndroid Build Coastguard Worker }
68*c8dee2aaSAndroid Build Coastguard Worker } // END FIDDLE
69