Can't fold ctm and color matrix when in perspective
Will work on clipping in follow-up CL Change-Id: I1e4cc485555a435c740a4e5b50445f21e9ec20c7 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/260404 Reviewed-by: Mike Klein <mtklein@google.com> Commit-Queue: Mike Reed <reed@google.com>
This commit is contained in:
parent
fdb2b7d530
commit
cbeabd969b
@ -460,7 +460,7 @@ static SkHalfPlane half_plane_w0(const SkMatrix& m) {
|
||||
return { m[SkMatrix::kMPersp0], m[SkMatrix::kMPersp1], m[SkMatrix::kMPersp2] - 0.05f };
|
||||
}
|
||||
|
||||
class HalfPlaneView3 : public Sample {
|
||||
class SampleCameraView : public Sample {
|
||||
float fNear = 0.05f;
|
||||
float fFar = 4;
|
||||
float fAngle = SK_ScalarPI / 4;
|
||||
@ -472,18 +472,6 @@ class HalfPlaneView3 : public Sample {
|
||||
SkMatrix44 fRot;
|
||||
SkPoint3 fTrans;
|
||||
|
||||
SkPath fPath;
|
||||
sk_sp<SkShader> fShader;
|
||||
bool fShowUnclipped = false;
|
||||
|
||||
SkString name() override { return SkString("halfplane3"); }
|
||||
|
||||
void onOnceBeforeDraw() override {
|
||||
fPath = make_path();
|
||||
fShader = GetResourceAsImage("images/mandrill_128.png")
|
||||
->makeShader(SkMatrix::MakeScale(3, 3));
|
||||
}
|
||||
|
||||
void rotate(float x, float y, float z) {
|
||||
SkMatrix44 r;
|
||||
if (x) {
|
||||
@ -496,22 +484,70 @@ class HalfPlaneView3 : public Sample {
|
||||
fRot.postConcat(r);
|
||||
}
|
||||
|
||||
SkMatrix44 get44() const {
|
||||
public:
|
||||
SkMatrix44 get44(const SkRect& r) const {
|
||||
SkMatrix44 camera,
|
||||
perspective,
|
||||
translate,
|
||||
viewport;
|
||||
|
||||
SkScalar w = r.width();
|
||||
SkScalar h = r.height();
|
||||
|
||||
Sk3Perspective(&perspective, fNear, fFar, fAngle);
|
||||
Sk3LookAt(&camera, fEye, fCOA, fUp);
|
||||
translate.setTranslate(fTrans.fX, fTrans.fY, fTrans.fZ);
|
||||
viewport.setScale(200, 200, 1).postTranslate( 200, 200, 0);
|
||||
viewport.setScale(w*0.5f, h*0.5f, 1).postTranslate(r.centerX(), r.centerY(), 0);
|
||||
|
||||
return viewport * perspective * camera * translate * fRot * inv(viewport);
|
||||
}
|
||||
|
||||
bool onChar(SkUnichar uni) override {
|
||||
float delta = SK_ScalarPI / 30;
|
||||
switch (uni) {
|
||||
case '8': this->rotate( delta, 0, 0); return true;
|
||||
case '2': this->rotate(-delta, 0, 0); return true;
|
||||
case '4': this->rotate(0, delta, 0); return true;
|
||||
case '6': this->rotate(0, -delta, 0); return true;
|
||||
case '-': this->rotate(0, 0, delta); return true;
|
||||
case '+': this->rotate(0, 0, -delta); return true;
|
||||
|
||||
case 'i': fTrans.fZ += 0.1f; SkDebugf("z %g\n", fTrans.fZ); return true;
|
||||
case 'k': fTrans.fZ -= 0.1f; SkDebugf("z %g\n", fTrans.fZ); return true;
|
||||
|
||||
case 'n': fNear += 0.1f; SkDebugf("near %g\n", fNear); return true;
|
||||
case 'N': fNear -= 0.1f; SkDebugf("near %g\n", fNear); return true;
|
||||
case 'f': fFar += 0.1f; SkDebugf("far %g\n", fFar); return true;
|
||||
case 'F': fFar -= 0.1f; SkDebugf("far %g\n", fFar); return true;
|
||||
default: break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class HalfPlaneView3 : public SampleCameraView {
|
||||
SkPath fPath;
|
||||
sk_sp<SkShader> fShader;
|
||||
bool fShowUnclipped = false;
|
||||
|
||||
SkString name() override { return SkString("halfplane3"); }
|
||||
|
||||
void onOnceBeforeDraw() override {
|
||||
fPath = make_path();
|
||||
fShader = GetResourceAsImage("images/mandrill_128.png")
|
||||
->makeShader(SkMatrix::MakeScale(3, 3));
|
||||
}
|
||||
|
||||
bool onChar(SkUnichar uni) override {
|
||||
switch (uni) {
|
||||
case 'u': fShowUnclipped = !fShowUnclipped; return true;
|
||||
default: break;
|
||||
}
|
||||
return this->SampleCameraView::onChar(uni);
|
||||
}
|
||||
|
||||
void onDrawContent(SkCanvas* canvas) override {
|
||||
SkMatrix mx = this->get44();
|
||||
SkMatrix mx = this->get44({0, 0, 400, 400});
|
||||
|
||||
SkPaint paint;
|
||||
paint.setColor({0.75, 0.75, 0.75, 1});
|
||||
@ -543,36 +579,39 @@ class HalfPlaneView3 : public Sample {
|
||||
SkHalfPlane hpw = half_plane_w0(mx);
|
||||
draw_halfplane(canvas, hpw, planeColor);
|
||||
}
|
||||
|
||||
bool onChar(SkUnichar uni) override {
|
||||
float delta = SK_ScalarPI / 30;
|
||||
switch (uni) {
|
||||
case '8': this->rotate( delta, 0, 0); return true;
|
||||
case '2': this->rotate(-delta, 0, 0); return true;
|
||||
case '4': this->rotate(0, delta, 0); return true;
|
||||
case '6': this->rotate(0, -delta, 0); return true;
|
||||
case '-': this->rotate(0, 0, delta); return true;
|
||||
case '+': this->rotate(0, 0, -delta); return true;
|
||||
|
||||
case 'i': fTrans.fZ += 0.1f; SkDebugf("z %g\n", fTrans.fZ); return true;
|
||||
case 'k': fTrans.fZ -= 0.1f; SkDebugf("z %g\n", fTrans.fZ); return true;
|
||||
|
||||
case 'n': fNear += 0.1f; SkDebugf("near %g\n", fNear); return true;
|
||||
case 'N': fNear -= 0.1f; SkDebugf("near %g\n", fNear); return true;
|
||||
case 'f': fFar += 0.1f; SkDebugf("far %g\n", fFar); return true;
|
||||
case 'F': fFar -= 0.1f; SkDebugf("far %g\n", fFar); return true;
|
||||
|
||||
case 'u': fShowUnclipped = !fShowUnclipped; return true;
|
||||
default: break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Click* onFindClickHandler(SkScalar x, SkScalar y, skui::ModifierKey modi) override {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool onClick(Click* click) override {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
DEF_SAMPLE( return new HalfPlaneView3(); )
|
||||
|
||||
class HalfPlaneCoons : public SampleCameraView {
|
||||
SkPoint fPatch[12];
|
||||
SkColor fColors[4] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorBLACK };
|
||||
|
||||
SkString name() override { return SkString("halfplane-coons"); }
|
||||
|
||||
void onOnceBeforeDraw() override {
|
||||
fPatch[0] = { 0, 0 };
|
||||
fPatch[1] = { 100, 0 };
|
||||
fPatch[2] = { 200, 0 };
|
||||
fPatch[3] = { 300, 0 };
|
||||
fPatch[4] = { 300, 100 };
|
||||
fPatch[5] = { 300, 200 };
|
||||
fPatch[6] = { 300, 300 };
|
||||
fPatch[7] = { 200, 300 };
|
||||
fPatch[8] = { 100, 300 };
|
||||
fPatch[9] = { 0, 300 };
|
||||
fPatch[10] = { 0, 200 };
|
||||
fPatch[11] = { 0, 100 };
|
||||
}
|
||||
|
||||
void onDrawContent(SkCanvas* canvas) override {
|
||||
SkMatrix mx = this->get44({0, 0, 300, 300});
|
||||
|
||||
SkPaint paint;
|
||||
|
||||
canvas->save();
|
||||
canvas->concat(mx);
|
||||
canvas->drawPatch(fPatch, fColors, nullptr, SkBlendMode::kSrc, paint);
|
||||
canvas->restore();
|
||||
}
|
||||
};
|
||||
DEF_SAMPLE( return new HalfPlaneCoons(); )
|
||||
|
@ -26,7 +26,10 @@ struct Matrix43 {
|
||||
return Sk4f::Load(&fMat[0]) * x + Sk4f::Load(&fMat[4]) * y + Sk4f::Load(&fMat[8]);
|
||||
}
|
||||
|
||||
void setConcat(const Matrix43& a, const SkMatrix& b) {
|
||||
// Pass a by value, so we don't have to worry about aliasing with this
|
||||
void setConcat(const Matrix43 a, const SkMatrix& b) {
|
||||
SkASSERT(!b.hasPerspective());
|
||||
|
||||
fMat[ 0] = a.dot(0, b.getScaleX(), b.getSkewY());
|
||||
fMat[ 1] = a.dot(1, b.getScaleX(), b.getSkewY());
|
||||
fMat[ 2] = a.dot(2, b.getScaleX(), b.getSkewY());
|
||||
@ -71,6 +74,7 @@ class SkTriColorShader : public SkShaderBase {
|
||||
public:
|
||||
SkTriColorShader(bool isOpaque) : fIsOpaque(isOpaque) {}
|
||||
|
||||
// This gets called for each triangle, without re-calling onAppendStages.
|
||||
bool update(const SkMatrix& ctmInv, const SkPoint pts[], const SkPMColor4f colors[],
|
||||
int index0, int index1, int index2);
|
||||
|
||||
@ -82,6 +86,9 @@ protected:
|
||||
#endif
|
||||
bool onAppendStages(const SkStageRec& rec) const override {
|
||||
rec.fPipeline->append(SkRasterPipeline::seed_shader);
|
||||
if (rec.fCTM.hasPerspective()) {
|
||||
rec.fPipeline->append(SkRasterPipeline::matrix_perspective, &fM33);
|
||||
}
|
||||
rec.fPipeline->append(SkRasterPipeline::matrix_4x3, &fM43);
|
||||
return true;
|
||||
}
|
||||
@ -92,7 +99,11 @@ private:
|
||||
Factory getFactory() const override { return nullptr; }
|
||||
const char* getTypeName() const override { return nullptr; }
|
||||
|
||||
Matrix43 fM43; // we overwrite this for each triangle
|
||||
// If ctm has perspective, we need both of these matrices,
|
||||
// otherwise we can combine them, and only use fM43
|
||||
|
||||
Matrix43 fM43;
|
||||
SkMatrix fM33;
|
||||
const bool fIsOpaque;
|
||||
|
||||
typedef SkShaderBase INHERITED;
|
||||
@ -112,18 +123,19 @@ bool SkTriColorShader::update(const SkMatrix& ctmInv, const SkPoint pts[],
|
||||
return false;
|
||||
}
|
||||
|
||||
SkMatrix dstToUnit;
|
||||
dstToUnit.setConcat(im, ctmInv);
|
||||
fM33.setConcat(im, ctmInv);
|
||||
|
||||
Sk4f c0 = Sk4f::Load(colors[index0].vec()),
|
||||
c1 = Sk4f::Load(colors[index1].vec()),
|
||||
c2 = Sk4f::Load(colors[index2].vec());
|
||||
|
||||
Matrix43 colorm;
|
||||
(c1 - c0).store(&colorm.fMat[0]);
|
||||
(c2 - c0).store(&colorm.fMat[4]);
|
||||
c0.store(&colorm.fMat[8]);
|
||||
fM43.setConcat(colorm, dstToUnit);
|
||||
(c1 - c0).store(&fM43.fMat[0]);
|
||||
(c2 - c0).store(&fM43.fMat[4]);
|
||||
c0.store(&fM43.fMat[8]);
|
||||
|
||||
if (!fM33.hasPerspective()) {
|
||||
fM43.setConcat(fM43, fM33);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user