blob: 95e30acda4966c57321ca618fe859e7e52891296 [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"
Mike Klein33d20552017-03-22 13:47:51 -04009#include "sk_tool_utils.h"
robertphillips5f865b92015-07-29 12:28:04 -070010#include "SkLightingShader.h"
dvonbeck5b794fa2016-07-06 13:58:36 -070011#include "SkNormalSource.h"
robertphillipsea4529d2015-08-17 15:04:47 -070012#include "SkPoint3.h"
13#include "SkShader.h"
robertphillips5f865b92015-07-29 12:28:04 -070014
robertphillips5f865b92015-07-29 12:28:04 -070015// Create a hemispherical normal map
robertphillips640898f2015-07-30 05:09:17 -070016static SkBitmap make_hemi_normalmap(int texSize) {
robertphillips5f865b92015-07-29 12:28:04 -070017 SkBitmap hemi;
18 hemi.allocN32Pixels(texSize, texSize);
19
robertphillipsea4529d2015-08-17 15:04:47 -070020 sk_tool_utils::create_hemi_normal_map(&hemi, SkIRect::MakeWH(texSize, texSize));
robertphillips5f865b92015-07-29 12:28:04 -070021 return hemi;
22}
23
robertphillips640898f2015-07-30 05:09:17 -070024// Create a truncated pyramid normal map
25static SkBitmap make_frustum_normalmap(int texSize) {
26 SkBitmap frustum;
27 frustum.allocN32Pixels(texSize, texSize);
28
robertphillipsea4529d2015-08-17 15:04:47 -070029 sk_tool_utils::create_frustum_normal_map(&frustum, SkIRect::MakeWH(texSize, texSize));
robertphillips640898f2015-07-30 05:09:17 -070030 return frustum;
31}
robertphillips5f865b92015-07-29 12:28:04 -070032
robertphillipsea4529d2015-08-17 15:04:47 -070033// Create a tetrahedral normal map
34static SkBitmap make_tetra_normalmap(int texSize) {
35 SkBitmap tetra;
36 tetra.allocN32Pixels(texSize, texSize);
37
38 sk_tool_utils::create_tetra_normal_map(&tetra, SkIRect::MakeWH(texSize, texSize));
39 return tetra;
40}
41
robertphillips5f865b92015-07-29 12:28:04 -070042namespace skiagm {
43
44// This GM exercises lighting shaders.
45class LightingShaderGM : public GM {
46public:
47 LightingShaderGM() {
48 this->setBGColor(sk_tool_utils::color_to_565(0xFFCCCCCC));
robertphillips640898f2015-07-30 05:09:17 -070049
robertphillips71e05522016-05-31 12:08:25 -070050 SkLights::Builder builder;
robertphillips640898f2015-07-30 05:09:17 -070051
vjiaoblack772b5ee2016-08-12 11:38:47 -070052 builder.add(SkLights::Light::MakeDirectional(SkColor3f::Make(1.0f, 1.0f, 1.0f),
53 SkVector3::Make(SK_ScalarRoot2Over2,
54 0.0f,
55 SK_ScalarRoot2Over2)));
vjiaoblacka8eabc42016-08-29 10:22:09 -070056 builder.setAmbientLightColor(SkColor3f::Make(0.2f, 0.2f, 0.2f));
robertphillips2f0dbc72015-08-20 05:15:06 -070057
robertphillips71e05522016-05-31 12:08:25 -070058 fLights = builder.finish();
robertphillips5f865b92015-07-29 12:28:04 -070059 }
60
61protected:
robertphillipsea4529d2015-08-17 15:04:47 -070062 enum NormalMap {
63 kHemi_NormalMap,
64 kFrustum_NormalMap,
65 kTetra_NormalMap,
66
67 kLast_NormalMap = kTetra_NormalMap
68 };
69
mtkleindbfd7ab2016-09-01 11:24:54 -070070 static constexpr int kNormalMapCount = kLast_NormalMap+1;
robertphillips5f865b92015-07-29 12:28:04 -070071
72 SkString onShortName() override {
73 return SkString("lightingshader");
74 }
75
76 SkISize onISize() override {
robertphillips640898f2015-07-30 05:09:17 -070077 return SkISize::Make(kGMSize, kGMSize);
robertphillips5f865b92015-07-29 12:28:04 -070078 }
79
80 void onOnceBeforeDraw() override {
robertphillips943a4622015-09-03 13:32:33 -070081 fDiffuse = sk_tool_utils::create_checkerboard_bitmap(
82 kTexSize, kTexSize,
83 sk_tool_utils::color_to_565(0x0),
84 sk_tool_utils::color_to_565(0xFF804020),
85 8);
robertphillipsea4529d2015-08-17 15:04:47 -070086
87 fNormalMaps[kHemi_NormalMap] = make_hemi_normalmap(kTexSize);
88 fNormalMaps[kFrustum_NormalMap] = make_frustum_normalmap(kTexSize);
89 fNormalMaps[kTetra_NormalMap] = make_tetra_normalmap(kTexSize);
robertphillips5f865b92015-07-29 12:28:04 -070090 }
91
robertphillipsea4529d2015-08-17 15:04:47 -070092 void drawRect(SkCanvas* canvas, const SkRect& r, NormalMap mapType) {
robertphillips5f865b92015-07-29 12:28:04 -070093
robertphillips640898f2015-07-30 05:09:17 -070094 SkRect bitmapBounds = SkRect::MakeIWH(fDiffuse.width(), fDiffuse.height());
robertphillips5f865b92015-07-29 12:28:04 -070095
robertphillips640898f2015-07-30 05:09:17 -070096 SkMatrix matrix;
97 matrix.setRectToRect(bitmapBounds, r, SkMatrix::kFill_ScaleToFit);
halcanary9d524f22016-03-29 09:03:52 -070098
robertphillips2f0dbc72015-08-20 05:15:06 -070099 const SkMatrix& ctm = canvas->getTotalMatrix();
100
robertphillips5f865b92015-07-29 12:28:04 -0700101 SkPaint paint;
reed1ec04d92016-08-05 12:07:41 -0700102 sk_sp<SkShader> diffuseShader = SkShader::MakeBitmapShader(fDiffuse,
103 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, &matrix);
104 sk_sp<SkShader> normalMap = SkShader::MakeBitmapShader(fNormalMaps[mapType],
105 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, &matrix);
dvonbeck5b794fa2016-07-06 13:58:36 -0700106 sk_sp<SkNormalSource> normalSource = SkNormalSource::MakeFromNormalMap(std::move(normalMap),
107 ctm);
dvonbeck6af677f2016-07-10 18:38:33 -0700108 paint.setShader(SkLightingShader::Make(std::move(diffuseShader), std::move(normalSource),
109 fLights));
robertphillips5f865b92015-07-29 12:28:04 -0700110
robertphillips5f865b92015-07-29 12:28:04 -0700111 canvas->drawRect(r, paint);
112 }
113
robertphillips640898f2015-07-30 05:09:17 -0700114 void onDraw(SkCanvas* canvas) override {
robertphillips2f0dbc72015-08-20 05:15:06 -0700115 SkMatrix m;
116 SkRect r;
robertphillips640898f2015-07-30 05:09:17 -0700117
robertphillips2f0dbc72015-08-20 05:15:06 -0700118 {
119 r = SkRect::MakeWH(SkIntToScalar(kTexSize), SkIntToScalar(kTexSize));
120 this->drawRect(canvas, r, kHemi_NormalMap);
robertphillips640898f2015-07-30 05:09:17 -0700121
robertphillips2f0dbc72015-08-20 05:15:06 -0700122 canvas->save();
123 m.setRotate(45.0f, r.centerX(), r.centerY());
124 m.postTranslate(kGMSize/2.0f - kTexSize/2.0f, 0.0f);
125 canvas->setMatrix(m);
126 this->drawRect(canvas, r, kHemi_NormalMap);
127 canvas->restore();
128 }
robertphillips640898f2015-07-30 05:09:17 -0700129
robertphillips2f0dbc72015-08-20 05:15:06 -0700130 {
131 r.offset(kGMSize - kTexSize, 0);
132 this->drawRect(canvas, r, kFrustum_NormalMap);
133
134 canvas->save();
135 m.setRotate(45.0f, r.centerX(), r.centerY());
136 m.postTranslate(0.0f, kGMSize/2.0f - kTexSize/2.0f);
137 canvas->setMatrix(m);
138 this->drawRect(canvas, r, kFrustum_NormalMap);
139 canvas->restore();
140 }
141
142 {
143 r.offset(0, kGMSize - kTexSize);
144 this->drawRect(canvas, r, kTetra_NormalMap);
145
146 canvas->save();
147 m.setRotate(45.0f, r.centerX(), r.centerY());
148 m.postTranslate(-kGMSize/2.0f + kTexSize/2.0f, 0.0f);
149 canvas->setMatrix(m);
150 this->drawRect(canvas, r, kTetra_NormalMap);
151 canvas->restore();
152 }
153
154 {
155 r.offset(kTexSize - kGMSize, 0);
156 this->drawRect(canvas, r, kHemi_NormalMap);
157
158 canvas->save();
159 m.setRotate(45.0f, r.centerX(), r.centerY());
160 m.postTranslate(0.0f, -kGMSize/2.0f + kTexSize/2.0f);
161 canvas->setMatrix(m);
162 this->drawRect(canvas, r, kHemi_NormalMap);
163 canvas->restore();
164 }
robertphillips640898f2015-07-30 05:09:17 -0700165 }
166
robertphillips5f865b92015-07-29 12:28:04 -0700167private:
mtkleindbfd7ab2016-09-01 11:24:54 -0700168 static constexpr int kTexSize = 128;
169 static constexpr int kGMSize = 512;
robertphillips5f865b92015-07-29 12:28:04 -0700170
robertphillips71e05522016-05-31 12:08:25 -0700171 SkBitmap fDiffuse;
172 SkBitmap fNormalMaps[kNormalMapCount];
robertphillips640898f2015-07-30 05:09:17 -0700173
robertphillips71e05522016-05-31 12:08:25 -0700174 sk_sp<SkLights> fLights;
robertphillips5f865b92015-07-29 12:28:04 -0700175
176 typedef GM INHERITED;
177};
178
179//////////////////////////////////////////////////////////////////////////////
180
halcanary385fe4d2015-08-26 13:07:48 -0700181DEF_GM(return new LightingShaderGM;)
robertphillips5f865b92015-07-29 12:28:04 -0700182}