blob: 2cf4a953d800b78c0577a57f48daa020168ee698 [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"
9
dvonbeck5b794fa2016-07-06 13:58:36 -070010#include "SkBitmapProcShader.h"
robertphillips5f865b92015-07-29 12:28:04 -070011#include "SkLightingShader.h"
dvonbeck5b794fa2016-07-06 13:58:36 -070012#include "SkNormalSource.h"
robertphillipsea4529d2015-08-17 15:04:47 -070013#include "SkPoint3.h"
14#include "SkShader.h"
robertphillips5f865b92015-07-29 12:28:04 -070015
robertphillips5f865b92015-07-29 12:28:04 -070016// Create a hemispherical normal map
robertphillips640898f2015-07-30 05:09:17 -070017static SkBitmap make_hemi_normalmap(int texSize) {
robertphillips5f865b92015-07-29 12:28:04 -070018 SkBitmap hemi;
19 hemi.allocN32Pixels(texSize, texSize);
20
robertphillipsea4529d2015-08-17 15:04:47 -070021 sk_tool_utils::create_hemi_normal_map(&hemi, SkIRect::MakeWH(texSize, texSize));
robertphillips5f865b92015-07-29 12:28:04 -070022 return hemi;
23}
24
robertphillips640898f2015-07-30 05:09:17 -070025// Create a truncated pyramid normal map
26static SkBitmap make_frustum_normalmap(int texSize) {
27 SkBitmap frustum;
28 frustum.allocN32Pixels(texSize, texSize);
29
robertphillipsea4529d2015-08-17 15:04:47 -070030 sk_tool_utils::create_frustum_normal_map(&frustum, SkIRect::MakeWH(texSize, texSize));
robertphillips640898f2015-07-30 05:09:17 -070031 return frustum;
32}
robertphillips5f865b92015-07-29 12:28:04 -070033
robertphillipsea4529d2015-08-17 15:04:47 -070034// Create a tetrahedral normal map
35static SkBitmap make_tetra_normalmap(int texSize) {
36 SkBitmap tetra;
37 tetra.allocN32Pixels(texSize, texSize);
38
39 sk_tool_utils::create_tetra_normal_map(&tetra, SkIRect::MakeWH(texSize, texSize));
40 return tetra;
41}
42
robertphillips5f865b92015-07-29 12:28:04 -070043namespace skiagm {
44
45// This GM exercises lighting shaders.
46class LightingShaderGM : public GM {
47public:
48 LightingShaderGM() {
49 this->setBGColor(sk_tool_utils::color_to_565(0xFFCCCCCC));
robertphillips640898f2015-07-30 05:09:17 -070050
robertphillips71e05522016-05-31 12:08:25 -070051 SkLights::Builder builder;
robertphillips640898f2015-07-30 05:09:17 -070052
robertphillips71e05522016-05-31 12:08:25 -070053 builder.add(SkLights::Light(SkColor3f::Make(1.0f, 1.0f, 1.0f),
dvonbeck5b794fa2016-07-06 13:58:36 -070054 SkVector3::Make(SK_ScalarRoot2Over2,
55 0.0f,
56 SK_ScalarRoot2Over2)));
robertphillips71e05522016-05-31 12:08:25 -070057 builder.add(SkLights::Light(SkColor3f::Make(0.2f, 0.2f, 0.2f)));
robertphillips2f0dbc72015-08-20 05:15:06 -070058
robertphillips71e05522016-05-31 12:08:25 -070059 fLights = builder.finish();
robertphillips5f865b92015-07-29 12:28:04 -070060 }
61
62protected:
robertphillipsea4529d2015-08-17 15:04:47 -070063 enum NormalMap {
64 kHemi_NormalMap,
65 kFrustum_NormalMap,
66 kTetra_NormalMap,
67
68 kLast_NormalMap = kTetra_NormalMap
69 };
70
71 static const int kNormalMapCount = kLast_NormalMap+1;
robertphillips5f865b92015-07-29 12:28:04 -070072
73 SkString onShortName() override {
74 return SkString("lightingshader");
75 }
76
77 SkISize onISize() override {
robertphillips640898f2015-07-30 05:09:17 -070078 return SkISize::Make(kGMSize, kGMSize);
robertphillips5f865b92015-07-29 12:28:04 -070079 }
80
81 void onOnceBeforeDraw() override {
robertphillips943a4622015-09-03 13:32:33 -070082 fDiffuse = sk_tool_utils::create_checkerboard_bitmap(
83 kTexSize, kTexSize,
84 sk_tool_utils::color_to_565(0x0),
85 sk_tool_utils::color_to_565(0xFF804020),
86 8);
robertphillipsea4529d2015-08-17 15:04:47 -070087
88 fNormalMaps[kHemi_NormalMap] = make_hemi_normalmap(kTexSize);
89 fNormalMaps[kFrustum_NormalMap] = make_frustum_normalmap(kTexSize);
90 fNormalMaps[kTetra_NormalMap] = make_tetra_normalmap(kTexSize);
robertphillips5f865b92015-07-29 12:28:04 -070091 }
92
robertphillipsea4529d2015-08-17 15:04:47 -070093 void drawRect(SkCanvas* canvas, const SkRect& r, NormalMap mapType) {
robertphillips5f865b92015-07-29 12:28:04 -070094
robertphillips640898f2015-07-30 05:09:17 -070095 SkRect bitmapBounds = SkRect::MakeIWH(fDiffuse.width(), fDiffuse.height());
robertphillips5f865b92015-07-29 12:28:04 -070096
robertphillips640898f2015-07-30 05:09:17 -070097 SkMatrix matrix;
98 matrix.setRectToRect(bitmapBounds, r, SkMatrix::kFill_ScaleToFit);
halcanary9d524f22016-03-29 09:03:52 -070099
robertphillips2f0dbc72015-08-20 05:15:06 -0700100 const SkMatrix& ctm = canvas->getTotalMatrix();
101
robertphillips5f865b92015-07-29 12:28:04 -0700102 SkPaint paint;
dvonbeck6af677f2016-07-10 18:38:33 -0700103 sk_sp<SkShader> diffuseShader = SkMakeBitmapShader(fDiffuse,
104 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, &matrix, nullptr);
dvonbeck5b794fa2016-07-06 13:58:36 -0700105 sk_sp<SkShader> normalMap = SkMakeBitmapShader(fNormalMaps[mapType],
106 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, &matrix, nullptr);
107 sk_sp<SkNormalSource> normalSource = SkNormalSource::MakeFromNormalMap(std::move(normalMap),
108 ctm);
dvonbeck6af677f2016-07-10 18:38:33 -0700109 paint.setShader(SkLightingShader::Make(std::move(diffuseShader), std::move(normalSource),
110 fLights));
robertphillips5f865b92015-07-29 12:28:04 -0700111
robertphillips5f865b92015-07-29 12:28:04 -0700112 canvas->drawRect(r, paint);
113 }
114
robertphillips640898f2015-07-30 05:09:17 -0700115 void onDraw(SkCanvas* canvas) override {
robertphillips2f0dbc72015-08-20 05:15:06 -0700116 SkMatrix m;
117 SkRect r;
robertphillips640898f2015-07-30 05:09:17 -0700118
robertphillips2f0dbc72015-08-20 05:15:06 -0700119 {
120 r = SkRect::MakeWH(SkIntToScalar(kTexSize), SkIntToScalar(kTexSize));
121 this->drawRect(canvas, r, kHemi_NormalMap);
robertphillips640898f2015-07-30 05:09:17 -0700122
robertphillips2f0dbc72015-08-20 05:15:06 -0700123 canvas->save();
124 m.setRotate(45.0f, r.centerX(), r.centerY());
125 m.postTranslate(kGMSize/2.0f - kTexSize/2.0f, 0.0f);
126 canvas->setMatrix(m);
127 this->drawRect(canvas, r, kHemi_NormalMap);
128 canvas->restore();
129 }
robertphillips640898f2015-07-30 05:09:17 -0700130
robertphillips2f0dbc72015-08-20 05:15:06 -0700131 {
132 r.offset(kGMSize - kTexSize, 0);
133 this->drawRect(canvas, r, kFrustum_NormalMap);
134
135 canvas->save();
136 m.setRotate(45.0f, r.centerX(), r.centerY());
137 m.postTranslate(0.0f, kGMSize/2.0f - kTexSize/2.0f);
138 canvas->setMatrix(m);
139 this->drawRect(canvas, r, kFrustum_NormalMap);
140 canvas->restore();
141 }
142
143 {
144 r.offset(0, kGMSize - kTexSize);
145 this->drawRect(canvas, r, kTetra_NormalMap);
146
147 canvas->save();
148 m.setRotate(45.0f, r.centerX(), r.centerY());
149 m.postTranslate(-kGMSize/2.0f + kTexSize/2.0f, 0.0f);
150 canvas->setMatrix(m);
151 this->drawRect(canvas, r, kTetra_NormalMap);
152 canvas->restore();
153 }
154
155 {
156 r.offset(kTexSize - kGMSize, 0);
157 this->drawRect(canvas, r, kHemi_NormalMap);
158
159 canvas->save();
160 m.setRotate(45.0f, r.centerX(), r.centerY());
161 m.postTranslate(0.0f, -kGMSize/2.0f + kTexSize/2.0f);
162 canvas->setMatrix(m);
163 this->drawRect(canvas, r, kHemi_NormalMap);
164 canvas->restore();
165 }
robertphillips640898f2015-07-30 05:09:17 -0700166 }
167
robertphillips5f865b92015-07-29 12:28:04 -0700168private:
169 static const int kTexSize = 128;
robertphillips640898f2015-07-30 05:09:17 -0700170 static const int kGMSize = 512;
robertphillips5f865b92015-07-29 12:28:04 -0700171
robertphillips71e05522016-05-31 12:08:25 -0700172 SkBitmap fDiffuse;
173 SkBitmap fNormalMaps[kNormalMapCount];
robertphillips640898f2015-07-30 05:09:17 -0700174
robertphillips71e05522016-05-31 12:08:25 -0700175 sk_sp<SkLights> fLights;
robertphillips5f865b92015-07-29 12:28:04 -0700176
177 typedef GM INHERITED;
178};
179
180//////////////////////////////////////////////////////////////////////////////
181
halcanary385fe4d2015-08-26 13:07:48 -0700182DEF_GM(return new LightingShaderGM;)
robertphillips5f865b92015-07-29 12:28:04 -0700183}