blob: 54f698a75323cbf2abbd2fb989d15ef97f1f90fb [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
robertphillips5f865b92015-07-29 12:28:04 -070010#include "SkLightingShader.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
robertphillips2f0dbc72015-08-20 05:15:06 -070049 SkLightingShader::Lights::Builder builder;
robertphillips640898f2015-07-30 05:09:17 -070050
robertphillips2f0dbc72015-08-20 05:15:06 -070051 builder.add(SkLight(SkColor3f::Make(1.0f, 1.0f, 1.0f),
52 SkVector3::Make(1.0f, 0.0f, 0.0f)));
53 builder.add(SkLight(SkColor3f::Make(0.2f, 0.2f, 0.2f)));
54
55 fLights.reset(builder.finish());
robertphillips5f865b92015-07-29 12:28:04 -070056 }
57
58protected:
robertphillipsea4529d2015-08-17 15:04:47 -070059 enum NormalMap {
60 kHemi_NormalMap,
61 kFrustum_NormalMap,
62 kTetra_NormalMap,
63
64 kLast_NormalMap = kTetra_NormalMap
65 };
66
67 static const int kNormalMapCount = kLast_NormalMap+1;
robertphillips5f865b92015-07-29 12:28:04 -070068
69 SkString onShortName() override {
70 return SkString("lightingshader");
71 }
72
73 SkISize onISize() override {
robertphillips640898f2015-07-30 05:09:17 -070074 return SkISize::Make(kGMSize, kGMSize);
robertphillips5f865b92015-07-29 12:28:04 -070075 }
76
77 void onOnceBeforeDraw() override {
robertphillips943a4622015-09-03 13:32:33 -070078 fDiffuse = sk_tool_utils::create_checkerboard_bitmap(
79 kTexSize, kTexSize,
80 sk_tool_utils::color_to_565(0x0),
81 sk_tool_utils::color_to_565(0xFF804020),
82 8);
robertphillipsea4529d2015-08-17 15:04:47 -070083
84 fNormalMaps[kHemi_NormalMap] = make_hemi_normalmap(kTexSize);
85 fNormalMaps[kFrustum_NormalMap] = make_frustum_normalmap(kTexSize);
86 fNormalMaps[kTetra_NormalMap] = make_tetra_normalmap(kTexSize);
robertphillips5f865b92015-07-29 12:28:04 -070087 }
88
robertphillipsea4529d2015-08-17 15:04:47 -070089 void drawRect(SkCanvas* canvas, const SkRect& r, NormalMap mapType) {
robertphillips5f865b92015-07-29 12:28:04 -070090
robertphillips640898f2015-07-30 05:09:17 -070091 SkRect bitmapBounds = SkRect::MakeIWH(fDiffuse.width(), fDiffuse.height());
robertphillips5f865b92015-07-29 12:28:04 -070092
robertphillips640898f2015-07-30 05:09:17 -070093 SkMatrix matrix;
94 matrix.setRectToRect(bitmapBounds, r, SkMatrix::kFill_ScaleToFit);
halcanary9d524f22016-03-29 09:03:52 -070095
robertphillips2f0dbc72015-08-20 05:15:06 -070096 const SkMatrix& ctm = canvas->getTotalMatrix();
97
98 // TODO: correctly pull out the pure rotation
99 SkVector invNormRotation = { ctm[SkMatrix::kMScaleX], ctm[SkMatrix::kMSkewY] };
100
robertphillips5f865b92015-07-29 12:28:04 -0700101 SkPaint paint;
reedfe630452016-03-25 09:08:00 -0700102 paint.setShader(SkLightingShader::Make(fDiffuse, fNormalMaps[mapType], fLights,
103 invNormRotation, &matrix, &matrix));
robertphillips5f865b92015-07-29 12:28:04 -0700104
robertphillips5f865b92015-07-29 12:28:04 -0700105 canvas->drawRect(r, paint);
106 }
107
robertphillips640898f2015-07-30 05:09:17 -0700108 void onDraw(SkCanvas* canvas) override {
robertphillips2f0dbc72015-08-20 05:15:06 -0700109 SkMatrix m;
110 SkRect r;
robertphillips640898f2015-07-30 05:09:17 -0700111
robertphillips2f0dbc72015-08-20 05:15:06 -0700112 {
113 r = SkRect::MakeWH(SkIntToScalar(kTexSize), SkIntToScalar(kTexSize));
114 this->drawRect(canvas, r, kHemi_NormalMap);
robertphillips640898f2015-07-30 05:09:17 -0700115
robertphillips2f0dbc72015-08-20 05:15:06 -0700116 canvas->save();
117 m.setRotate(45.0f, r.centerX(), r.centerY());
118 m.postTranslate(kGMSize/2.0f - kTexSize/2.0f, 0.0f);
119 canvas->setMatrix(m);
120 this->drawRect(canvas, r, kHemi_NormalMap);
121 canvas->restore();
122 }
robertphillips640898f2015-07-30 05:09:17 -0700123
robertphillips2f0dbc72015-08-20 05:15:06 -0700124 {
125 r.offset(kGMSize - kTexSize, 0);
126 this->drawRect(canvas, r, kFrustum_NormalMap);
127
128 canvas->save();
129 m.setRotate(45.0f, r.centerX(), r.centerY());
130 m.postTranslate(0.0f, kGMSize/2.0f - kTexSize/2.0f);
131 canvas->setMatrix(m);
132 this->drawRect(canvas, r, kFrustum_NormalMap);
133 canvas->restore();
134 }
135
136 {
137 r.offset(0, kGMSize - kTexSize);
138 this->drawRect(canvas, r, kTetra_NormalMap);
139
140 canvas->save();
141 m.setRotate(45.0f, r.centerX(), r.centerY());
142 m.postTranslate(-kGMSize/2.0f + kTexSize/2.0f, 0.0f);
143 canvas->setMatrix(m);
144 this->drawRect(canvas, r, kTetra_NormalMap);
145 canvas->restore();
146 }
147
148 {
149 r.offset(kTexSize - kGMSize, 0);
150 this->drawRect(canvas, r, kHemi_NormalMap);
151
152 canvas->save();
153 m.setRotate(45.0f, r.centerX(), r.centerY());
154 m.postTranslate(0.0f, -kGMSize/2.0f + kTexSize/2.0f);
155 canvas->setMatrix(m);
156 this->drawRect(canvas, r, kHemi_NormalMap);
157 canvas->restore();
158 }
robertphillips640898f2015-07-30 05:09:17 -0700159 }
160
robertphillips5f865b92015-07-29 12:28:04 -0700161private:
162 static const int kTexSize = 128;
robertphillips640898f2015-07-30 05:09:17 -0700163 static const int kGMSize = 512;
robertphillips5f865b92015-07-29 12:28:04 -0700164
robertphillips640898f2015-07-30 05:09:17 -0700165 SkBitmap fDiffuse;
robertphillipsea4529d2015-08-17 15:04:47 -0700166 SkBitmap fNormalMaps[kNormalMapCount];
robertphillips640898f2015-07-30 05:09:17 -0700167
robertphillips2f0dbc72015-08-20 05:15:06 -0700168 SkAutoTUnref<const SkLightingShader::Lights> fLights;
robertphillips5f865b92015-07-29 12:28:04 -0700169
170 typedef GM INHERITED;
171};
172
173//////////////////////////////////////////////////////////////////////////////
174
halcanary385fe4d2015-08-26 13:07:48 -0700175DEF_GM(return new LightingShaderGM;)
robertphillips5f865b92015-07-29 12:28:04 -0700176}