949ceb249f
and improve perspective handling in rest of quad pipeline This function produces 0, 1, or 2 quads clipped to w > 0, with proper local coords. To make its signature a little easier to reason about, I added a simple 'DrawQuad' struct that represents the combination of device and local coordinates, and edge AA flags. I am open to suggestions for the name. GrQuad::bounds() remains perspective aware so that it is always correct. I updated CropToRect to check for w < 0 and not attempt to crop in that scenario. Theoretically, we could clip to w = 0 first and then go through the CropToRect optimization path. However, with the current state of the GrFillRectOp and GrTextureOp, that made it more annoying to have the bulk APIs handle the w clipping as well. So for now, the w plane clipping is entirely the responsibility of the ops. A benefit of this approach is that GrRenderTargetContext doesn't need to be modified, and in the case where the clipping produces 2 quads they are automatically put in the same op w/o going through any batching code. However, it is becoming clear to me that managing 4 effective code paths (fill + texture X simple + bulk API) is more maintenance than it's worth. I added skbug:9869 to work out how to simplify these op creation APIs further, and if we succeed there, I think it will make applying the W plane clipping more convenient as well. For now, since this affects SkiaRenderer on Linux stable, I am pushing for correctness. Bug: skia:9779, chromium:224618 Change-Id: I4218a956cbe0bbc2b5c9cf133a069d54c93848e8 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/268686 Commit-Queue: Michael Ludwig <michaelludwig@google.com> Reviewed-by: Brian Salomon <bsalomon@google.com>
132 lines
4.8 KiB
C++
132 lines
4.8 KiB
C++
/*
|
|
* Copyright 2020 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/SkColor.h"
|
|
#include "include/core/SkImage.h"
|
|
#include "include/core/SkMatrix.h"
|
|
#include "include/core/SkMatrix44.h"
|
|
#include "include/core/SkSurface.h"
|
|
#include "include/effects/SkGradientShader.h"
|
|
#include "include/private/SkM44.h"
|
|
#include "tools/timer/TimeUtils.h"
|
|
|
|
static SkM44 rotate_axis_angle(SkScalar x, SkScalar y, SkScalar z, SkScalar radians) {
|
|
// SkM44 doesn't expose any rotation factories yet
|
|
SkMatrix44 m;
|
|
m.setRotateAboutUnit(x, y, z, radians);
|
|
|
|
float a[16];
|
|
m.asColMajorf(a);
|
|
SkM44 m4;
|
|
m4.setColMajor(a);
|
|
return m4;
|
|
}
|
|
|
|
// Adapted from https://codepen.io/adamdupuis/pen/qLYzqB
|
|
class CrBug224618GM : public skiagm::GM {
|
|
public:
|
|
CrBug224618GM() : fTime(0.f) {}
|
|
|
|
protected:
|
|
SkString onShortName() override {
|
|
return SkString("crbug_224618");
|
|
}
|
|
|
|
SkISize onISize() override {
|
|
return SkISize::Make(kMaxVW, kMaxVW);
|
|
}
|
|
|
|
// This animates the FOV in viewer, to ensure the panorama covering rects are stable across
|
|
// a variety of perspective matrices
|
|
bool onAnimate(double nanos) override {
|
|
fTime = TimeUtils::Scaled(1e-9f * nanos, 0.5f);
|
|
return true;
|
|
}
|
|
|
|
void onOnceBeforeDraw() override {
|
|
static const SkColor kColors[2] = {SK_ColorTRANSPARENT, SkColorSetARGB(128, 255, 255, 255)};
|
|
sk_sp<SkShader> gradient = SkGradientShader::MakeRadial(
|
|
{200.f, 200.f}, 25.f, kColors, nullptr, 2, SkTileMode::kMirror,
|
|
SkGradientShader::kInterpolateColorsInPremul_Flag, nullptr);
|
|
|
|
sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(400, 400);
|
|
|
|
SkPaint bgPaint;
|
|
bgPaint.setShader(gradient);
|
|
surface->getCanvas()->drawPaint(bgPaint);
|
|
|
|
fCubeImage = surface->makeImageSnapshot();
|
|
}
|
|
|
|
void onDraw(SkCanvas* canvas) override {
|
|
SkScalar viewportWidth = SkScalarMod(fTime, 10.f) / 10.f * (kMaxVW - kMinVW) + kMinVW;
|
|
SkScalar radius = viewportWidth / 2.f; // round?
|
|
// See https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/perspective
|
|
SkM44 proj{1.f, 0.f, 0.f, 0.f,
|
|
0.f, 1.f, 0.f, 0.f,
|
|
0.f, 0.f, 1.f, 0.f,
|
|
0.f, 0.f, -1.f / radius, 1.f};
|
|
SkM44 zoom = SkM44::Translate(0.f, 0.f, radius);
|
|
SkM44 postZoom = SkM44::Translate(0.f, 0.f, -radius - 1.f);
|
|
SkM44 rotateHorizontal = rotate_axis_angle(0.f, 1.f, 0.f, 2.356194490192345f);
|
|
|
|
// w in degrees will need to be converted to radians
|
|
SkV4 axisAngles[6] = {
|
|
{0.f, 1.f, 0.f, -90.f}, // rotateY(-90deg)
|
|
{1.f, 0.f, 0.f, 0.f}, // <none>
|
|
{0.f, 1.f, 0.f, 90.f}, // rotateY(90deg)
|
|
{0.f, 1.f, 0.f, 180.f}, // rotateY(180deg)
|
|
{1.f, 0.f, 0.f, -90.f}, // rotateX(-90deg)
|
|
{1.f, 0.f, 0.f, 90.f}, // rotateX(90deg)
|
|
};
|
|
SkColor faceColors[6] = {
|
|
SK_ColorRED,
|
|
SK_ColorGREEN,
|
|
SK_ColorBLUE,
|
|
SK_ColorYELLOW,
|
|
SkColorSetARGB(0xFF, 0xFF, 0xA5, 0x00), // orange css
|
|
SkColorSetARGB(0xFF, 0x80, 0x00, 0x80) // purple css
|
|
};
|
|
|
|
for (int i = 0; i < 6; ++i) {
|
|
SkM44 model = rotate_axis_angle(axisAngles[i].x, axisAngles[i].y, axisAngles[i].z,
|
|
SkDegreesToRadians(axisAngles[i].w));
|
|
model = SkM44::Translate(radius, radius) * proj * // project and place content
|
|
zoom * rotateHorizontal * model * postZoom * // main model matrix
|
|
SkM44::Translate(-radius, -radius); // center content
|
|
|
|
canvas->save();
|
|
canvas->experimental_concat44(model);
|
|
|
|
SkPaint fillPaint;
|
|
fillPaint.setAntiAlias(true);
|
|
fillPaint.setFilterQuality(kLow_SkFilterQuality);
|
|
fillPaint.setColor(faceColors[i]);
|
|
|
|
// Leverages GrFillRectOp on GPU backend
|
|
canvas->drawRect(SkRect::MakeWH(viewportWidth, viewportWidth), fillPaint);
|
|
|
|
// Leverages GrTextureOp on GPU backend, to ensure sure both quad paths handle clipping
|
|
canvas->drawImageRect(fCubeImage.get(),
|
|
SkRect::MakeWH(fCubeImage->width(), fCubeImage->height()),
|
|
SkRect::MakeWH(viewportWidth, viewportWidth), &fillPaint,
|
|
SkCanvas::kFast_SrcRectConstraint);
|
|
|
|
canvas->restore();
|
|
}
|
|
}
|
|
private:
|
|
static const int kMaxVW = 800;
|
|
static const int kMinVW = 300;
|
|
|
|
SkScalar fTime;
|
|
sk_sp<SkImage> fCubeImage;
|
|
};
|
|
|
|
DEF_GM(return new CrBug224618GM();)
|