1*c8dee2aaSAndroid Build Coastguard Worker /* 2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2020 Google LLC 3*c8dee2aaSAndroid Build Coastguard Worker * 4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be 5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file. 6*c8dee2aaSAndroid Build Coastguard Worker */ 7*c8dee2aaSAndroid Build Coastguard Worker #include "gm/gm.h" 8*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h" 9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColor.h" 10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImage.h" 11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkM44.h" 12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkMatrix.h" 13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSurface.h" 14*c8dee2aaSAndroid Build Coastguard Worker #include "include/effects/SkGradientShader.h" 15*c8dee2aaSAndroid Build Coastguard Worker #include "tools/timer/TimeUtils.h" 16*c8dee2aaSAndroid Build Coastguard Worker 17*c8dee2aaSAndroid Build Coastguard Worker // Adapted from https://codepen.io/adamdupuis/pen/qLYzqB 18*c8dee2aaSAndroid Build Coastguard Worker class CrBug224618GM : public skiagm::GM { 19*c8dee2aaSAndroid Build Coastguard Worker public: CrBug224618GM()20*c8dee2aaSAndroid Build Coastguard Worker CrBug224618GM() : fTime(0.f) {} 21*c8dee2aaSAndroid Build Coastguard Worker 22*c8dee2aaSAndroid Build Coastguard Worker protected: getName() const23*c8dee2aaSAndroid Build Coastguard Worker SkString getName() const override { return SkString("crbug_224618"); } 24*c8dee2aaSAndroid Build Coastguard Worker getISize()25*c8dee2aaSAndroid Build Coastguard Worker SkISize getISize() override { return SkISize::Make(kMaxVW, kMaxVW); } 26*c8dee2aaSAndroid Build Coastguard Worker 27*c8dee2aaSAndroid Build Coastguard Worker // This animates the FOV in viewer, to ensure the panorama covering rects are stable across 28*c8dee2aaSAndroid Build Coastguard Worker // a variety of perspective matrices onAnimate(double nanos)29*c8dee2aaSAndroid Build Coastguard Worker bool onAnimate(double nanos) override { 30*c8dee2aaSAndroid Build Coastguard Worker fTime = TimeUtils::Scaled(1e-9f * nanos, 0.5f); 31*c8dee2aaSAndroid Build Coastguard Worker return true; 32*c8dee2aaSAndroid Build Coastguard Worker } 33*c8dee2aaSAndroid Build Coastguard Worker onOnceBeforeDraw()34*c8dee2aaSAndroid Build Coastguard Worker void onOnceBeforeDraw() override { 35*c8dee2aaSAndroid Build Coastguard Worker static const SkColor kColors[2] = {SK_ColorTRANSPARENT, SkColorSetARGB(128, 255, 255, 255)}; 36*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkShader> gradient = SkGradientShader::MakeRadial( 37*c8dee2aaSAndroid Build Coastguard Worker {200.f, 200.f}, 25.f, kColors, nullptr, 2, SkTileMode::kMirror, 38*c8dee2aaSAndroid Build Coastguard Worker SkGradientShader::kInterpolateColorsInPremul_Flag, nullptr); 39*c8dee2aaSAndroid Build Coastguard Worker 40*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkSurface> surface = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(400, 400)); 41*c8dee2aaSAndroid Build Coastguard Worker 42*c8dee2aaSAndroid Build Coastguard Worker SkPaint bgPaint; 43*c8dee2aaSAndroid Build Coastguard Worker bgPaint.setShader(gradient); 44*c8dee2aaSAndroid Build Coastguard Worker surface->getCanvas()->drawPaint(bgPaint); 45*c8dee2aaSAndroid Build Coastguard Worker 46*c8dee2aaSAndroid Build Coastguard Worker fCubeImage = surface->makeImageSnapshot(); 47*c8dee2aaSAndroid Build Coastguard Worker } 48*c8dee2aaSAndroid Build Coastguard Worker onDraw(SkCanvas * canvas)49*c8dee2aaSAndroid Build Coastguard Worker void onDraw(SkCanvas* canvas) override { 50*c8dee2aaSAndroid Build Coastguard Worker SkScalar viewportWidth = SkScalarMod(fTime, 10.f) / 10.f * (kMaxVW - kMinVW) + kMinVW; 51*c8dee2aaSAndroid Build Coastguard Worker SkScalar radius = viewportWidth / 2.f; // round? 52*c8dee2aaSAndroid Build Coastguard Worker // See https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/perspective 53*c8dee2aaSAndroid Build Coastguard Worker SkM44 proj{1.f, 0.f, 0.f, 0.f, 54*c8dee2aaSAndroid Build Coastguard Worker 0.f, 1.f, 0.f, 0.f, 55*c8dee2aaSAndroid Build Coastguard Worker 0.f, 0.f, 1.f, 0.f, 56*c8dee2aaSAndroid Build Coastguard Worker 0.f, 0.f, -1.f / radius, 1.f}; 57*c8dee2aaSAndroid Build Coastguard Worker SkM44 zoom = SkM44::Translate(0.f, 0.f, radius); 58*c8dee2aaSAndroid Build Coastguard Worker SkM44 postZoom = SkM44::Translate(0.f, 0.f, -radius - 1.f); 59*c8dee2aaSAndroid Build Coastguard Worker SkM44 rotateHorizontal = SkM44::Rotate({0, 1, 0}, 2.356194490192345f); 60*c8dee2aaSAndroid Build Coastguard Worker 61*c8dee2aaSAndroid Build Coastguard Worker // w in degrees will need to be converted to radians 62*c8dee2aaSAndroid Build Coastguard Worker SkV4 axisAngles[6] = { 63*c8dee2aaSAndroid Build Coastguard Worker {0.f, 1.f, 0.f, -90.f}, // rotateY(-90deg) 64*c8dee2aaSAndroid Build Coastguard Worker {1.f, 0.f, 0.f, 0.f}, // <none> 65*c8dee2aaSAndroid Build Coastguard Worker {0.f, 1.f, 0.f, 90.f}, // rotateY(90deg) 66*c8dee2aaSAndroid Build Coastguard Worker {0.f, 1.f, 0.f, 180.f}, // rotateY(180deg) 67*c8dee2aaSAndroid Build Coastguard Worker {1.f, 0.f, 0.f, -90.f}, // rotateX(-90deg) 68*c8dee2aaSAndroid Build Coastguard Worker {1.f, 0.f, 0.f, 90.f}, // rotateX(90deg) 69*c8dee2aaSAndroid Build Coastguard Worker }; 70*c8dee2aaSAndroid Build Coastguard Worker SkColor faceColors[6] = { 71*c8dee2aaSAndroid Build Coastguard Worker SK_ColorRED, 72*c8dee2aaSAndroid Build Coastguard Worker SK_ColorGREEN, 73*c8dee2aaSAndroid Build Coastguard Worker SK_ColorBLUE, 74*c8dee2aaSAndroid Build Coastguard Worker SK_ColorYELLOW, 75*c8dee2aaSAndroid Build Coastguard Worker SkColorSetARGB(0xFF, 0xFF, 0xA5, 0x00), // orange css 76*c8dee2aaSAndroid Build Coastguard Worker SkColorSetARGB(0xFF, 0x80, 0x00, 0x80) // purple css 77*c8dee2aaSAndroid Build Coastguard Worker }; 78*c8dee2aaSAndroid Build Coastguard Worker 79*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < 6; ++i) { 80*c8dee2aaSAndroid Build Coastguard Worker SkM44 model = SkM44::Rotate({axisAngles[i].x, axisAngles[i].y, axisAngles[i].z}, 81*c8dee2aaSAndroid Build Coastguard Worker SkDegreesToRadians(axisAngles[i].w)); 82*c8dee2aaSAndroid Build Coastguard Worker model = SkM44::Translate(radius, radius) * proj * // project and place content 83*c8dee2aaSAndroid Build Coastguard Worker zoom * rotateHorizontal * model * postZoom * // main model matrix 84*c8dee2aaSAndroid Build Coastguard Worker SkM44::Translate(-radius, -radius); // center content 85*c8dee2aaSAndroid Build Coastguard Worker 86*c8dee2aaSAndroid Build Coastguard Worker canvas->save(); 87*c8dee2aaSAndroid Build Coastguard Worker canvas->concat(model); 88*c8dee2aaSAndroid Build Coastguard Worker 89*c8dee2aaSAndroid Build Coastguard Worker SkPaint fillPaint; 90*c8dee2aaSAndroid Build Coastguard Worker fillPaint.setAntiAlias(true); 91*c8dee2aaSAndroid Build Coastguard Worker fillPaint.setColor(faceColors[i]); 92*c8dee2aaSAndroid Build Coastguard Worker 93*c8dee2aaSAndroid Build Coastguard Worker // Leverages FillRectOp on GPU backend 94*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(SkRect::MakeWH(viewportWidth, viewportWidth), fillPaint); 95*c8dee2aaSAndroid Build Coastguard Worker 96*c8dee2aaSAndroid Build Coastguard Worker // Leverages TextureOp on GPU backend, to ensure sure both quad paths handle clipping 97*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImageRect(fCubeImage.get(), 98*c8dee2aaSAndroid Build Coastguard Worker SkRect::MakeWH(fCubeImage->width(), fCubeImage->height()), 99*c8dee2aaSAndroid Build Coastguard Worker SkRect::MakeWH(viewportWidth, viewportWidth), 100*c8dee2aaSAndroid Build Coastguard Worker SkSamplingOptions(SkFilterMode::kLinear), &fillPaint, 101*c8dee2aaSAndroid Build Coastguard Worker SkCanvas::kFast_SrcRectConstraint); 102*c8dee2aaSAndroid Build Coastguard Worker 103*c8dee2aaSAndroid Build Coastguard Worker canvas->restore(); 104*c8dee2aaSAndroid Build Coastguard Worker } 105*c8dee2aaSAndroid Build Coastguard Worker } 106*c8dee2aaSAndroid Build Coastguard Worker private: 107*c8dee2aaSAndroid Build Coastguard Worker static const int kMaxVW = 800; 108*c8dee2aaSAndroid Build Coastguard Worker static const int kMinVW = 300; 109*c8dee2aaSAndroid Build Coastguard Worker 110*c8dee2aaSAndroid Build Coastguard Worker SkScalar fTime; 111*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> fCubeImage; 112*c8dee2aaSAndroid Build Coastguard Worker }; 113*c8dee2aaSAndroid Build Coastguard Worker 114*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new CrBug224618GM();) 115