2015-07-29 19:28:04 +00:00
|
|
|
/*
|
|
|
|
* 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 "gm.h"
|
|
|
|
#include "SkLightingShader.h"
|
2016-07-06 20:58:36 +00:00
|
|
|
#include "SkNormalSource.h"
|
2015-08-17 22:04:47 +00:00
|
|
|
#include "SkPoint3.h"
|
|
|
|
#include "SkShader.h"
|
2015-07-29 19:28:04 +00:00
|
|
|
|
|
|
|
// Create a hemispherical normal map
|
2015-07-30 12:09:17 +00:00
|
|
|
static SkBitmap make_hemi_normalmap(int texSize) {
|
2015-07-29 19:28:04 +00:00
|
|
|
SkBitmap hemi;
|
|
|
|
hemi.allocN32Pixels(texSize, texSize);
|
|
|
|
|
2015-08-17 22:04:47 +00:00
|
|
|
sk_tool_utils::create_hemi_normal_map(&hemi, SkIRect::MakeWH(texSize, texSize));
|
2015-07-29 19:28:04 +00:00
|
|
|
return hemi;
|
|
|
|
}
|
|
|
|
|
2015-07-30 12:09:17 +00:00
|
|
|
// Create a truncated pyramid normal map
|
|
|
|
static SkBitmap make_frustum_normalmap(int texSize) {
|
|
|
|
SkBitmap frustum;
|
|
|
|
frustum.allocN32Pixels(texSize, texSize);
|
|
|
|
|
2015-08-17 22:04:47 +00:00
|
|
|
sk_tool_utils::create_frustum_normal_map(&frustum, SkIRect::MakeWH(texSize, texSize));
|
2015-07-30 12:09:17 +00:00
|
|
|
return frustum;
|
|
|
|
}
|
2015-07-29 19:28:04 +00:00
|
|
|
|
2015-08-17 22:04:47 +00:00
|
|
|
// Create a tetrahedral normal map
|
|
|
|
static SkBitmap make_tetra_normalmap(int texSize) {
|
|
|
|
SkBitmap tetra;
|
|
|
|
tetra.allocN32Pixels(texSize, texSize);
|
|
|
|
|
|
|
|
sk_tool_utils::create_tetra_normal_map(&tetra, SkIRect::MakeWH(texSize, texSize));
|
|
|
|
return tetra;
|
|
|
|
}
|
|
|
|
|
2015-07-29 19:28:04 +00:00
|
|
|
namespace skiagm {
|
|
|
|
|
|
|
|
// This GM exercises lighting shaders.
|
|
|
|
class LightingShaderGM : public GM {
|
|
|
|
public:
|
|
|
|
LightingShaderGM() {
|
|
|
|
this->setBGColor(sk_tool_utils::color_to_565(0xFFCCCCCC));
|
2015-07-30 12:09:17 +00:00
|
|
|
|
2016-05-31 19:08:25 +00:00
|
|
|
SkLights::Builder builder;
|
2015-07-30 12:09:17 +00:00
|
|
|
|
2016-05-31 19:08:25 +00:00
|
|
|
builder.add(SkLights::Light(SkColor3f::Make(1.0f, 1.0f, 1.0f),
|
2016-07-06 20:58:36 +00:00
|
|
|
SkVector3::Make(SK_ScalarRoot2Over2,
|
|
|
|
0.0f,
|
|
|
|
SK_ScalarRoot2Over2)));
|
2016-05-31 19:08:25 +00:00
|
|
|
builder.add(SkLights::Light(SkColor3f::Make(0.2f, 0.2f, 0.2f)));
|
2015-08-20 12:15:06 +00:00
|
|
|
|
2016-05-31 19:08:25 +00:00
|
|
|
fLights = builder.finish();
|
2015-07-29 19:28:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
2015-08-17 22:04:47 +00:00
|
|
|
enum NormalMap {
|
|
|
|
kHemi_NormalMap,
|
|
|
|
kFrustum_NormalMap,
|
|
|
|
kTetra_NormalMap,
|
|
|
|
|
|
|
|
kLast_NormalMap = kTetra_NormalMap
|
|
|
|
};
|
|
|
|
|
|
|
|
static const int kNormalMapCount = kLast_NormalMap+1;
|
2015-07-29 19:28:04 +00:00
|
|
|
|
|
|
|
SkString onShortName() override {
|
|
|
|
return SkString("lightingshader");
|
|
|
|
}
|
|
|
|
|
|
|
|
SkISize onISize() override {
|
2015-07-30 12:09:17 +00:00
|
|
|
return SkISize::Make(kGMSize, kGMSize);
|
2015-07-29 19:28:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void onOnceBeforeDraw() override {
|
2015-09-03 20:32:33 +00:00
|
|
|
fDiffuse = sk_tool_utils::create_checkerboard_bitmap(
|
|
|
|
kTexSize, kTexSize,
|
|
|
|
sk_tool_utils::color_to_565(0x0),
|
|
|
|
sk_tool_utils::color_to_565(0xFF804020),
|
|
|
|
8);
|
2015-08-17 22:04:47 +00:00
|
|
|
|
|
|
|
fNormalMaps[kHemi_NormalMap] = make_hemi_normalmap(kTexSize);
|
|
|
|
fNormalMaps[kFrustum_NormalMap] = make_frustum_normalmap(kTexSize);
|
|
|
|
fNormalMaps[kTetra_NormalMap] = make_tetra_normalmap(kTexSize);
|
2015-07-29 19:28:04 +00:00
|
|
|
}
|
|
|
|
|
2015-08-17 22:04:47 +00:00
|
|
|
void drawRect(SkCanvas* canvas, const SkRect& r, NormalMap mapType) {
|
2015-07-29 19:28:04 +00:00
|
|
|
|
2015-07-30 12:09:17 +00:00
|
|
|
SkRect bitmapBounds = SkRect::MakeIWH(fDiffuse.width(), fDiffuse.height());
|
2015-07-29 19:28:04 +00:00
|
|
|
|
2015-07-30 12:09:17 +00:00
|
|
|
SkMatrix matrix;
|
|
|
|
matrix.setRectToRect(bitmapBounds, r, SkMatrix::kFill_ScaleToFit);
|
2016-03-29 16:03:52 +00:00
|
|
|
|
2015-08-20 12:15:06 +00:00
|
|
|
const SkMatrix& ctm = canvas->getTotalMatrix();
|
|
|
|
|
2015-07-29 19:28:04 +00:00
|
|
|
SkPaint paint;
|
2016-08-05 19:07:41 +00:00
|
|
|
sk_sp<SkShader> diffuseShader = SkShader::MakeBitmapShader(fDiffuse,
|
|
|
|
SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, &matrix);
|
|
|
|
sk_sp<SkShader> normalMap = SkShader::MakeBitmapShader(fNormalMaps[mapType],
|
|
|
|
SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, &matrix);
|
2016-07-06 20:58:36 +00:00
|
|
|
sk_sp<SkNormalSource> normalSource = SkNormalSource::MakeFromNormalMap(std::move(normalMap),
|
|
|
|
ctm);
|
2016-07-11 01:38:33 +00:00
|
|
|
paint.setShader(SkLightingShader::Make(std::move(diffuseShader), std::move(normalSource),
|
|
|
|
fLights));
|
2015-07-29 19:28:04 +00:00
|
|
|
|
2015-07-30 12:09:17 +00:00
|
|
|
canvas->drawRect(r, paint);
|
|
|
|
}
|
|
|
|
|
|
|
|
void onDraw(SkCanvas* canvas) override {
|
2015-08-20 12:15:06 +00:00
|
|
|
SkMatrix m;
|
|
|
|
SkRect r;
|
|
|
|
|
|
|
|
{
|
|
|
|
r = SkRect::MakeWH(SkIntToScalar(kTexSize), SkIntToScalar(kTexSize));
|
|
|
|
this->drawRect(canvas, r, kHemi_NormalMap);
|
|
|
|
|
|
|
|
canvas->save();
|
|
|
|
m.setRotate(45.0f, r.centerX(), r.centerY());
|
|
|
|
m.postTranslate(kGMSize/2.0f - kTexSize/2.0f, 0.0f);
|
|
|
|
canvas->setMatrix(m);
|
|
|
|
this->drawRect(canvas, r, kHemi_NormalMap);
|
|
|
|
canvas->restore();
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
r.offset(kGMSize - kTexSize, 0);
|
|
|
|
this->drawRect(canvas, r, kFrustum_NormalMap);
|
|
|
|
|
|
|
|
canvas->save();
|
|
|
|
m.setRotate(45.0f, r.centerX(), r.centerY());
|
|
|
|
m.postTranslate(0.0f, kGMSize/2.0f - kTexSize/2.0f);
|
|
|
|
canvas->setMatrix(m);
|
|
|
|
this->drawRect(canvas, r, kFrustum_NormalMap);
|
|
|
|
canvas->restore();
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
r.offset(0, kGMSize - kTexSize);
|
|
|
|
this->drawRect(canvas, r, kTetra_NormalMap);
|
|
|
|
|
|
|
|
canvas->save();
|
|
|
|
m.setRotate(45.0f, r.centerX(), r.centerY());
|
|
|
|
m.postTranslate(-kGMSize/2.0f + kTexSize/2.0f, 0.0f);
|
|
|
|
canvas->setMatrix(m);
|
|
|
|
this->drawRect(canvas, r, kTetra_NormalMap);
|
|
|
|
canvas->restore();
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
r.offset(kTexSize - kGMSize, 0);
|
|
|
|
this->drawRect(canvas, r, kHemi_NormalMap);
|
|
|
|
|
|
|
|
canvas->save();
|
|
|
|
m.setRotate(45.0f, r.centerX(), r.centerY());
|
|
|
|
m.postTranslate(0.0f, -kGMSize/2.0f + kTexSize/2.0f);
|
|
|
|
canvas->setMatrix(m);
|
|
|
|
this->drawRect(canvas, r, kHemi_NormalMap);
|
|
|
|
canvas->restore();
|
|
|
|
}
|
2015-07-29 19:28:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
static const int kTexSize = 128;
|
2015-07-30 12:09:17 +00:00
|
|
|
static const int kGMSize = 512;
|
|
|
|
|
2016-05-31 19:08:25 +00:00
|
|
|
SkBitmap fDiffuse;
|
|
|
|
SkBitmap fNormalMaps[kNormalMapCount];
|
2015-07-29 19:28:04 +00:00
|
|
|
|
2016-05-31 19:08:25 +00:00
|
|
|
sk_sp<SkLights> fLights;
|
2015-07-29 19:28:04 +00:00
|
|
|
|
|
|
|
typedef GM INHERITED;
|
|
|
|
};
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2015-08-26 20:07:48 +00:00
|
|
|
DEF_GM(return new LightingShaderGM;)
|
2015-07-29 19:28:04 +00:00
|
|
|
}
|