blob: 8576dd72d57a1d4debd8480549ab72728ac8f1d6 [file] [log] [blame]
robertphillips5f865b92015-07-29 12:28:04 -07001/*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "gm.h"
robertphillips5f865b92015-07-29 12:28:04 -07009#include "SkLightingShader.h"
dvonbeck5b794fa2016-07-06 13:58:36 -070010#include "SkNormalSource.h"
robertphillipsea4529d2015-08-17 15:04:47 -070011#include "SkPoint3.h"
12#include "SkShader.h"
robertphillips5f865b92015-07-29 12:28:04 -070013
robertphillips5f865b92015-07-29 12:28:04 -070014// Create a hemispherical normal map
robertphillips640898f2015-07-30 05:09:17 -070015static SkBitmap make_hemi_normalmap(int texSize) {
robertphillips5f865b92015-07-29 12:28:04 -070016 SkBitmap hemi;
17 hemi.allocN32Pixels(texSize, texSize);
18
robertphillipsea4529d2015-08-17 15:04:47 -070019 sk_tool_utils::create_hemi_normal_map(&hemi, SkIRect::MakeWH(texSize, texSize));
robertphillips5f865b92015-07-29 12:28:04 -070020 return hemi;
21}
22
robertphillips640898f2015-07-30 05:09:17 -070023// Create a truncated pyramid normal map
24static SkBitmap make_frustum_normalmap(int texSize) {
25 SkBitmap frustum;
26 frustum.allocN32Pixels(texSize, texSize);
27
robertphillipsea4529d2015-08-17 15:04:47 -070028 sk_tool_utils::create_frustum_normal_map(&frustum, SkIRect::MakeWH(texSize, texSize));
robertphillips640898f2015-07-30 05:09:17 -070029 return frustum;
30}
robertphillips5f865b92015-07-29 12:28:04 -070031
robertphillipsea4529d2015-08-17 15:04:47 -070032// Create a tetrahedral normal map
33static SkBitmap make_tetra_normalmap(int texSize) {
34 SkBitmap tetra;
35 tetra.allocN32Pixels(texSize, texSize);
36
37 sk_tool_utils::create_tetra_normal_map(&tetra, SkIRect::MakeWH(texSize, texSize));
38 return tetra;
39}
40
robertphillips5f865b92015-07-29 12:28:04 -070041namespace skiagm {
42
43// This GM exercises lighting shaders.
44class LightingShaderGM : public GM {
45public:
46 LightingShaderGM() {
47 this->setBGColor(sk_tool_utils::color_to_565(0xFFCCCCCC));
robertphillips640898f2015-07-30 05:09:17 -070048
robertphillips71e05522016-05-31 12:08:25 -070049 SkLights::Builder builder;
robertphillips640898f2015-07-30 05:09:17 -070050
vjiaoblack772b5ee2016-08-12 11:38:47 -070051 builder.add(SkLights::Light::MakeDirectional(SkColor3f::Make(1.0f, 1.0f, 1.0f),
52 SkVector3::Make(SK_ScalarRoot2Over2,
53 0.0f,
54 SK_ScalarRoot2Over2)));
vjiaoblacka8eabc42016-08-29 10:22:09 -070055 builder.setAmbientLightColor(SkColor3f::Make(0.2f, 0.2f, 0.2f));
robertphillips2f0dbc72015-08-20 05:15:06 -070056
robertphillips71e05522016-05-31 12:08:25 -070057 fLights = builder.finish();
robertphillips5f865b92015-07-29 12:28:04 -070058 }
59
60protected:
robertphillipsea4529d2015-08-17 15:04:47 -070061 enum NormalMap {
62 kHemi_NormalMap,
63 kFrustum_NormalMap,
64 kTetra_NormalMap,
65
66 kLast_NormalMap = kTetra_NormalMap
67 };
68
mtkleindbfd7ab2016-09-01 11:24:54 -070069 static constexpr int kNormalMapCount = kLast_NormalMap+1;
robertphillips5f865b92015-07-29 12:28:04 -070070
71 SkString onShortName() override {
72 return SkString("lightingshader");
73 }
74
75 SkISize onISize() override {
robertphillips640898f2015-07-30 05:09:17 -070076 return SkISize::Make(kGMSize, kGMSize);
robertphillips5f865b92015-07-29 12:28:04 -070077 }
78
79 void onOnceBeforeDraw() override {
robertphillips943a4622015-09-03 13:32:33 -070080 fDiffuse = sk_tool_utils::create_checkerboard_bitmap(
81 kTexSize, kTexSize,
82 sk_tool_utils::color_to_565(0x0),
83 sk_tool_utils::color_to_565(0xFF804020),
84 8);
robertphillipsea4529d2015-08-17 15:04:47 -070085
86 fNormalMaps[kHemi_NormalMap] = make_hemi_normalmap(kTexSize);
87 fNormalMaps[kFrustum_NormalMap] = make_frustum_normalmap(kTexSize);
88 fNormalMaps[kTetra_NormalMap] = make_tetra_normalmap(kTexSize);
robertphillips5f865b92015-07-29 12:28:04 -070089 }
90
robertphillipsea4529d2015-08-17 15:04:47 -070091 void drawRect(SkCanvas* canvas, const SkRect& r, NormalMap mapType) {
robertphillips5f865b92015-07-29 12:28:04 -070092
robertphillips640898f2015-07-30 05:09:17 -070093 SkRect bitmapBounds = SkRect::MakeIWH(fDiffuse.width(), fDiffuse.height());
robertphillips5f865b92015-07-29 12:28:04 -070094
robertphillips640898f2015-07-30 05:09:17 -070095 SkMatrix matrix;
96 matrix.setRectToRect(bitmapBounds, r, SkMatrix::kFill_ScaleToFit);
halcanary9d524f22016-03-29 09:03:52 -070097
robertphillips2f0dbc72015-08-20 05:15:06 -070098 const SkMatrix& ctm = canvas->getTotalMatrix();
99
robertphillips5f865b92015-07-29 12:28:04 -0700100 SkPaint paint;
reed1ec04d92016-08-05 12:07:41 -0700101 sk_sp<SkShader> diffuseShader = SkShader::MakeBitmapShader(fDiffuse,
102 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, &matrix);
103 sk_sp<SkShader> normalMap = SkShader::MakeBitmapShader(fNormalMaps[mapType],
104 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, &matrix);
dvonbeck5b794fa2016-07-06 13:58:36 -0700105 sk_sp<SkNormalSource> normalSource = SkNormalSource::MakeFromNormalMap(std::move(normalMap),
106 ctm);
dvonbeck6af677f2016-07-10 18:38:33 -0700107 paint.setShader(SkLightingShader::Make(std::move(diffuseShader), std::move(normalSource),
108 fLights));
robertphillips5f865b92015-07-29 12:28:04 -0700109
robertphillips5f865b92015-07-29 12:28:04 -0700110 canvas->drawRect(r, paint);
111 }
112
robertphillips640898f2015-07-30 05:09:17 -0700113 void onDraw(SkCanvas* canvas) override {
robertphillips2f0dbc72015-08-20 05:15:06 -0700114 SkMatrix m;
115 SkRect r;
robertphillips640898f2015-07-30 05:09:17 -0700116
robertphillips2f0dbc72015-08-20 05:15:06 -0700117 {
118 r = SkRect::MakeWH(SkIntToScalar(kTexSize), SkIntToScalar(kTexSize));
119 this->drawRect(canvas, r, kHemi_NormalMap);
robertphillips640898f2015-07-30 05:09:17 -0700120
robertphillips2f0dbc72015-08-20 05:15:06 -0700121 canvas->save();
122 m.setRotate(45.0f, r.centerX(), r.centerY());
123 m.postTranslate(kGMSize/2.0f - kTexSize/2.0f, 0.0f);
124 canvas->setMatrix(m);
125 this->drawRect(canvas, r, kHemi_NormalMap);
126 canvas->restore();
127 }
robertphillips640898f2015-07-30 05:09:17 -0700128
robertphillips2f0dbc72015-08-20 05:15:06 -0700129 {
130 r.offset(kGMSize - kTexSize, 0);
131 this->drawRect(canvas, r, kFrustum_NormalMap);
132
133 canvas->save();
134 m.setRotate(45.0f, r.centerX(), r.centerY());
135 m.postTranslate(0.0f, kGMSize/2.0f - kTexSize/2.0f);
136 canvas->setMatrix(m);
137 this->drawRect(canvas, r, kFrustum_NormalMap);
138 canvas->restore();
139 }
140
141 {
142 r.offset(0, kGMSize - kTexSize);
143 this->drawRect(canvas, r, kTetra_NormalMap);
144
145 canvas->save();
146 m.setRotate(45.0f, r.centerX(), r.centerY());
147 m.postTranslate(-kGMSize/2.0f + kTexSize/2.0f, 0.0f);
148 canvas->setMatrix(m);
149 this->drawRect(canvas, r, kTetra_NormalMap);
150 canvas->restore();
151 }
152
153 {
154 r.offset(kTexSize - kGMSize, 0);
155 this->drawRect(canvas, r, kHemi_NormalMap);
156
157 canvas->save();
158 m.setRotate(45.0f, r.centerX(), r.centerY());
159 m.postTranslate(0.0f, -kGMSize/2.0f + kTexSize/2.0f);
160 canvas->setMatrix(m);
161 this->drawRect(canvas, r, kHemi_NormalMap);
162 canvas->restore();
163 }
robertphillips640898f2015-07-30 05:09:17 -0700164 }
165
robertphillips5f865b92015-07-29 12:28:04 -0700166private:
mtkleindbfd7ab2016-09-01 11:24:54 -0700167 static constexpr int kTexSize = 128;
168 static constexpr int kGMSize = 512;
robertphillips5f865b92015-07-29 12:28:04 -0700169
robertphillips71e05522016-05-31 12:08:25 -0700170 SkBitmap fDiffuse;
171 SkBitmap fNormalMaps[kNormalMapCount];
robertphillips640898f2015-07-30 05:09:17 -0700172
robertphillips71e05522016-05-31 12:08:25 -0700173 sk_sp<SkLights> fLights;
robertphillips5f865b92015-07-29 12:28:04 -0700174
175 typedef GM INHERITED;
176};
177
178//////////////////////////////////////////////////////////////////////////////
179
halcanary385fe4d2015-08-26 13:07:48 -0700180DEF_GM(return new LightingShaderGM;)
robertphillips5f865b92015-07-29 12:28:04 -0700181}