320a40d773
Lessons learned 1. ImageShader (correctly) always compresses (typically via PNG) during serialization. This has the surprise results of - if the image was marked opaque, but has some non-opaque pixels (i.e. bug in blitter or caller), then compressing may "fix" those pixels, making the deserialized version draw differently. bug filed. - 565 compressess/decompresses to 8888 (at least on Mac), which draws differently (esp. under some filters). bug filed. 2. BitmapShader did not enforce a copy for mutable bitmaps, but ImageShader does (since it creates an Image). Thus the former would see subsequent changes to the pixels after shader creation, while the latter does not, hence the change to the BlitRow test to avoid this modify-after-create pattern. I sure hope this prev. behavior was a bug/undefined-behavior, since this CL changes that. BUG=skia:5595 GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2195893002 Review-Url: https://codereview.chromium.org/2195893002
100 lines
3.3 KiB
C++
Executable File
100 lines
3.3 KiB
C++
Executable File
/*
|
|
* Copyright 2015 Google Inc.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*/
|
|
#include "DecodeFile.h"
|
|
#include "SampleCode.h"
|
|
#include "Resources.h"
|
|
|
|
#include "SkBitmapProcShader.h"
|
|
#include "SkCanvas.h"
|
|
#include "SkLightingShader.h"
|
|
#include "SkNormalSource.h"
|
|
#include "SkPoint3.h"
|
|
|
|
static sk_sp<SkLights> create_lights(SkScalar angle, SkScalar blue) {
|
|
|
|
const SkVector3 dir = SkVector3::Make(SkScalarSin(angle)*SkScalarSin(SK_ScalarPI*0.25f),
|
|
SkScalarCos(angle)*SkScalarSin(SK_ScalarPI*0.25f),
|
|
SkScalarCos(SK_ScalarPI*0.25f));
|
|
|
|
SkLights::Builder builder;
|
|
|
|
builder.add(SkLights::Light(SkColor3f::Make(1.0f, 1.0f, blue), dir));
|
|
builder.add(SkLights::Light(SkColor3f::Make(0.1f, 0.1f, 0.1f)));
|
|
|
|
return builder.finish();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
class LightingView : public SampleView {
|
|
public:
|
|
SkBitmap fDiffuseBitmap;
|
|
SkBitmap fNormalBitmap;
|
|
SkScalar fLightAngle;
|
|
SkScalar fColorFactor;
|
|
|
|
LightingView() {
|
|
SkString diffusePath = GetResourcePath("brickwork-texture.jpg");
|
|
decode_file(diffusePath.c_str(), &fDiffuseBitmap);
|
|
SkString normalPath = GetResourcePath("brickwork_normal-map.jpg");
|
|
decode_file(normalPath.c_str(), &fNormalBitmap);
|
|
|
|
fLightAngle = 0.0f;
|
|
fColorFactor = 0.0f;
|
|
}
|
|
|
|
protected:
|
|
// overrides from SkEventSink
|
|
bool onQuery(SkEvent* evt) override {
|
|
if (SampleCode::TitleQ(*evt)) {
|
|
SampleCode::TitleR(evt, "Lighting");
|
|
return true;
|
|
}
|
|
return this->INHERITED::onQuery(evt);
|
|
}
|
|
|
|
void onDrawContent(SkCanvas* canvas) override {
|
|
fLightAngle += 0.015f;
|
|
fColorFactor += 0.01f;
|
|
if (fColorFactor > 1.0f) {
|
|
fColorFactor = 0.0f;
|
|
}
|
|
|
|
sk_sp<SkLights> lights(create_lights(fLightAngle, fColorFactor));
|
|
SkPaint paint;
|
|
sk_sp<SkShader> normalMap = SkMakeBitmapShader(fNormalBitmap,
|
|
SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, nullptr, nullptr);
|
|
sk_sp<SkNormalSource> normalSource = SkNormalSource::MakeFromNormalMap(
|
|
std::move(normalMap), SkMatrix::I());
|
|
sk_sp<SkShader> diffuseShader = SkShader::MakeBitmapShader(fDiffuseBitmap,
|
|
SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, nullptr);
|
|
paint.setShader(SkLightingShader::Make(std::move(diffuseShader), std::move(normalSource),
|
|
std::move(lights)));
|
|
paint.setColor(SK_ColorBLACK);
|
|
|
|
SkRect r = SkRect::MakeWH((SkScalar)fDiffuseBitmap.width(),
|
|
(SkScalar)fDiffuseBitmap.height());
|
|
canvas->drawRect(r, paint);
|
|
|
|
// so we're constantly updating
|
|
this->inval(nullptr);
|
|
}
|
|
|
|
SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
|
|
this->inval(nullptr);
|
|
return this->INHERITED::onFindClickHandler(x, y, modi);
|
|
}
|
|
|
|
private:
|
|
typedef SampleView INHERITED;
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
static SkView* MyFactory() { return new LightingView; }
|
|
static SkViewRegister reg(MyFactory);
|