• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 #include "sk_tool_utils.h"
10 #include "SkLightingShader.h"
11 #include "SkNormalSource.h"
12 #include "SkPoint3.h"
13 #include "SkShader.h"
14 
15 // Create a hemispherical normal map
make_hemi_normalmap(int texSize)16 static SkBitmap make_hemi_normalmap(int texSize) {
17     SkBitmap hemi;
18     hemi.allocN32Pixels(texSize, texSize);
19 
20     sk_tool_utils::create_hemi_normal_map(&hemi, SkIRect::MakeWH(texSize, texSize));
21     return hemi;
22 }
23 
24 // Create a truncated pyramid normal map
make_frustum_normalmap(int texSize)25 static SkBitmap make_frustum_normalmap(int texSize) {
26     SkBitmap frustum;
27     frustum.allocN32Pixels(texSize, texSize);
28 
29     sk_tool_utils::create_frustum_normal_map(&frustum, SkIRect::MakeWH(texSize, texSize));
30     return frustum;
31 }
32 
33 // Create a tetrahedral normal map
make_tetra_normalmap(int texSize)34 static 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 
42 namespace skiagm {
43 
44 // This GM exercises lighting shaders by drawing rotated and non-rotated normal mapped rects with
45 // a directional light off to the viewers right.
46 class LightingShaderGM : public GM {
47 public:
LightingShaderGM()48     LightingShaderGM() {
49         this->setBGColor(0xFFCCCCCC);
50     }
51 
52 protected:
53     enum NormalMap {
54         kHemi_NormalMap,
55         kFrustum_NormalMap,
56         kTetra_NormalMap,
57 
58         kLast_NormalMap = kTetra_NormalMap
59     };
60 
61     static constexpr int kNormalMapCount = kLast_NormalMap+1;
62 
onShortName()63     SkString onShortName() override { return SkString("lightingshader"); }
64 
onISize()65     SkISize onISize() override { return SkISize::Make(kGMSize, kGMSize); }
66 
onOnceBeforeDraw()67     void onOnceBeforeDraw() override {
68         {
69             SkLights::Builder builder;
70 
71             // The direction vector is towards the light w/ +Z coming out of the screen
72             builder.add(SkLights::Light::MakeDirectional(SkColor3f::Make(1.0f, 1.0f, 1.0f),
73                                                          SkVector3::Make(SK_ScalarRoot2Over2,
74                                                                          0.0f,
75                                                                          SK_ScalarRoot2Over2)));
76             builder.setAmbientLightColor(SkColor3f::Make(0.2f, 0.2f, 0.2f));
77 
78             fLights = builder.finish();
79         }
80 
81         fDiffuse = sk_tool_utils::create_checkerboard_bitmap(
82                                                         kTexSize, kTexSize,
83                                                         0x00000000,
84                                                         sk_tool_utils::color_to_565(0xFF804020),
85                                                         8);
86 
87         fNormalMaps[kHemi_NormalMap]    = make_hemi_normalmap(kTexSize);
88         fNormalMaps[kFrustum_NormalMap] = make_frustum_normalmap(kTexSize);
89         fNormalMaps[kTetra_NormalMap]   = make_tetra_normalmap(kTexSize);
90     }
91 
drawRect(SkCanvas * canvas,const SkRect & r,NormalMap mapType)92     void drawRect(SkCanvas* canvas, const SkRect& r, NormalMap mapType) {
93 
94         SkRect bitmapBounds = SkRect::MakeIWH(fDiffuse.width(), fDiffuse.height());
95 
96         SkMatrix matrix;
97         matrix.setRectToRect(bitmapBounds, r, SkMatrix::kFill_ScaleToFit);
98 
99         const SkMatrix& ctm = canvas->getTotalMatrix();
100 
101         SkPaint paint;
102         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);
106         sk_sp<SkNormalSource> normalSource = SkNormalSource::MakeFromNormalMap(std::move(normalMap),
107                                                                                ctm);
108         paint.setShader(SkLightingShader::Make(std::move(diffuseShader), std::move(normalSource),
109                                                fLights));
110 
111         canvas->drawRect(r, paint);
112     }
113 
114     // Draw an axis-aligned and rotated version of the normal mapped rect
drawPair(SkCanvas * canvas,const SkRect & r,NormalMap mapType,const SkVector & v)115     void drawPair(SkCanvas* canvas, const SkRect& r, NormalMap mapType, const SkVector& v) {
116         SkMatrix m;
117         m.setRotate(45.0f, r.centerX(), r.centerY());
118         m.postTranslate(kScale * v.fX, kScale * v.fY);
119 
120         this->drawRect(canvas, r, mapType);
121 
122         canvas->save();
123             canvas->setMatrix(m);
124             this->drawRect(canvas, r, mapType);
125         canvas->restore();
126     }
127 
onDraw(SkCanvas * canvas)128     void onDraw(SkCanvas* canvas) override {
129         SkRect r;
130 
131         r = SkRect::MakeWH(SkIntToScalar(kTexSize), SkIntToScalar(kTexSize));
132         this->drawPair(canvas, r, kHemi_NormalMap, SkVector::Make(1.0f, 0.0f));
133 
134         r.offset(kGMSize - kTexSize, 0);
135         this->drawPair(canvas, r, kFrustum_NormalMap, SkVector::Make(0.0f, 1.0f));
136 
137         r.offset(0, kGMSize - kTexSize);
138         this->drawPair(canvas, r, kTetra_NormalMap, SkVector::Make(-1.0, 0.0f));
139 
140         r.offset(kTexSize - kGMSize, 0);
141         this->drawPair(canvas, r, kHemi_NormalMap, SkVector::Make(0.0f, -1));
142     }
143 
144 private:
145     static constexpr int kTexSize = 128;
146     static constexpr int kGMSize  = 512;
147     static constexpr SkScalar kScale = kGMSize/2.0f - kTexSize/2.0f;
148 
149     SkBitmap        fDiffuse;
150     SkBitmap        fNormalMaps[kNormalMapCount];
151 
152     sk_sp<SkLights> fLights;
153 
154     typedef GM INHERITED;
155 };
156 
157 //////////////////////////////////////////////////////////////////////////////
158 
159 DEF_GM(return new LightingShaderGM;)
160 }
161