diff options
author | robertphillips <robertphillips@google.com> | 2015-08-17 15:04:47 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-08-17 15:04:47 -0700 |
commit | ea4529d09a6ad50582e348eee1c275a9ffb59278 (patch) | |
tree | 3688b0482de18a8ef6f676cdf3ad0dc936e06bd9 | |
parent | df5b7603d2d2bb3ec75cfbf235a672ee80cf8d3a (diff) |
Move normal map creation methods to sk_tools
Split off of https://codereview.chromium.org/1261433009/ (Add SkCanvas::drawLitAtlas call)
Review URL: https://codereview.chromium.org/1298763002
-rw-r--r-- | gm/lightingshader.cpp | 107 | ||||
-rw-r--r-- | tools/sk_tool_utils.cpp | 108 | ||||
-rw-r--r-- | tools/sk_tool_utils.h | 6 |
3 files changed, 148 insertions, 73 deletions
diff --git a/gm/lightingshader.cpp b/gm/lightingshader.cpp index 771c0bc2e3..7e33504477 100644 --- a/gm/lightingshader.cpp +++ b/gm/lightingshader.cpp @@ -7,8 +7,9 @@ #include "gm.h" -#include "SkColorPriv.h" #include "SkLightingShader.h" +#include "SkPoint3.h" +#include "SkShader.h" static SkBitmap make_checkerboard(int texSize) { SkBitmap bitmap; @@ -27,25 +28,7 @@ static SkBitmap make_hemi_normalmap(int texSize) { SkBitmap hemi; hemi.allocN32Pixels(texSize, texSize); - for (int y = 0; y < texSize; ++y) { - for (int x = 0; x < texSize; ++x) { - SkScalar locX = (x + 0.5f - texSize/2.0f) / (texSize/2.0f); - SkScalar locY = (y + 0.5f - texSize/2.0f) / (texSize/2.0f); - - SkScalar locZ = locX * locX + locY * locY; - if (locZ >= 1.0f) { - locX = 0.0f; - locY = 0.0f; - locZ = 0.0f; - } - locZ = sqrtf(1.0f - locZ); - unsigned char r = static_cast<unsigned char>((0.5f * locX + 0.5f) * 255); - unsigned char g = static_cast<unsigned char>((-0.5f * locY + 0.5f) * 255); - unsigned char b = static_cast<unsigned char>((0.5f * locZ + 0.5f) * 255); - *hemi.getAddr32(x, y) = SkPackARGB32(0xFF, r, g, b); - } - } - + sk_tool_utils::create_hemi_normal_map(&hemi, SkIRect::MakeWH(texSize, texSize)); return hemi; } @@ -54,49 +37,19 @@ static SkBitmap make_frustum_normalmap(int texSize) { SkBitmap frustum; frustum.allocN32Pixels(texSize, texSize); - SkIRect inner = SkIRect::MakeWH(texSize, texSize); - inner.inset(texSize/4, texSize/4); - - SkPoint3 norm; - const SkPoint3 left = SkPoint3::Make(-SK_ScalarRoot2Over2, 0.0f, SK_ScalarRoot2Over2); - const SkPoint3 up = SkPoint3::Make(0.0f, -SK_ScalarRoot2Over2, SK_ScalarRoot2Over2); - const SkPoint3 right = SkPoint3::Make(SK_ScalarRoot2Over2, 0.0f, SK_ScalarRoot2Over2); - const SkPoint3 down = SkPoint3::Make(0.0f, SK_ScalarRoot2Over2, SK_ScalarRoot2Over2); - - for (int y = 0; y < texSize; ++y) { - for (int x = 0; x < texSize; ++x) { - if (inner.contains(x, y)) { - norm.set(0.0f, 0.0f, 1.0f); - } else { - SkScalar locX = x + 0.5f - texSize/2.0f; - SkScalar locY = y + 0.5f - texSize/2.0f; - - if (locX >= 0.0f) { - if (locY > 0.0f) { - norm = locX >= locY ? right : down; // LR corner - } else { - norm = locX > -locY ? right : up; // UR corner - } - } else { - if (locY > 0.0f) { - norm = -locX > locY ? left : down; // LL corner - } else { - norm = locX > locY ? up : left; // UL corner - } - } - } - - SkASSERT(SkScalarNearlyEqual(norm.length(), 1.0f)); - unsigned char r = static_cast<unsigned char>((0.5f * norm.fX + 0.5f) * 255); - unsigned char g = static_cast<unsigned char>((-0.5f * norm.fY + 0.5f) * 255); - unsigned char b = static_cast<unsigned char>((0.5f * norm.fZ + 0.5f) * 255); - *frustum.getAddr32(x, y) = SkPackARGB32(0xFF, r, g, b); - } - } - + sk_tool_utils::create_frustum_normal_map(&frustum, SkIRect::MakeWH(texSize, texSize)); return frustum; } +// Create a tetrahedral normal map +static SkBitmap make_tetra_normalmap(int texSize) { + SkBitmap tetra; + tetra.allocN32Pixels(texSize, texSize); + + sk_tool_utils::create_tetra_normal_map(&tetra, SkIRect::MakeWH(texSize, texSize)); + return tetra; +} + namespace skiagm { // This GM exercises lighting shaders. @@ -106,14 +59,21 @@ public: this->setBGColor(sk_tool_utils::color_to_565(0xFFCCCCCC)); fLight.fColor = SkColor3f::Make(1.0f, 1.0f, 1.0f); - fLight.fDirection.fX = 0.0f; - fLight.fDirection.fY = 0.0f; - fLight.fDirection.fZ = 1.0f; + fLight.fDirection = SkVector3::Make(0.0f, 0.0f, 1.0f); fAmbient = SkColor3f::Make(0.1f, 0.1f, 0.1f); } protected: + enum NormalMap { + kHemi_NormalMap, + kFrustum_NormalMap, + kTetra_NormalMap, + + kLast_NormalMap = kTetra_NormalMap + }; + + static const int kNormalMapCount = kLast_NormalMap+1; SkString onShortName() override { return SkString("lightingshader"); @@ -125,11 +85,13 @@ protected: void onOnceBeforeDraw() override { fDiffuse = make_checkerboard(kTexSize); - fHemiNormalMap = make_hemi_normalmap(kTexSize); - fFrustumNormalMap = make_frustum_normalmap(kTexSize); + + fNormalMaps[kHemi_NormalMap] = make_hemi_normalmap(kTexSize); + fNormalMaps[kFrustum_NormalMap] = make_frustum_normalmap(kTexSize); + fNormalMaps[kTetra_NormalMap] = make_tetra_normalmap(kTexSize); } - void drawRect(SkCanvas* canvas, const SkRect& r, bool hemi) { + void drawRect(SkCanvas* canvas, const SkRect& r, NormalMap mapType) { SkRect bitmapBounds = SkRect::MakeIWH(fDiffuse.width(), fDiffuse.height()); @@ -138,7 +100,7 @@ protected: SkAutoTUnref<SkShader> fShader(SkLightingShader::Create( fDiffuse, - hemi ? fHemiNormalMap : fFrustumNormalMap, + fNormalMaps[mapType], fLight, fAmbient, &matrix)); @@ -150,16 +112,16 @@ protected: void onDraw(SkCanvas* canvas) override { SkRect r = SkRect::MakeWH(SkIntToScalar(kTexSize), SkIntToScalar(kTexSize)); - this->drawRect(canvas, r, true); + this->drawRect(canvas, r, kHemi_NormalMap); r.offset(kGMSize - kTexSize, 0); - this->drawRect(canvas, r, false); + this->drawRect(canvas, r, kFrustum_NormalMap); r.offset(0, kGMSize - kTexSize); - this->drawRect(canvas, r, true); + this->drawRect(canvas, r, kTetra_NormalMap); r.offset(kTexSize - kGMSize, 0); - this->drawRect(canvas, r, false); + this->drawRect(canvas, r, kHemi_NormalMap); } private: @@ -167,8 +129,7 @@ private: static const int kGMSize = 512; SkBitmap fDiffuse; - SkBitmap fHemiNormalMap; - SkBitmap fFrustumNormalMap; + SkBitmap fNormalMaps[kNormalMapCount]; SkLightingShader::Light fLight; SkColor3f fAmbient; diff --git a/tools/sk_tool_utils.cpp b/tools/sk_tool_utils.cpp index a6d381e2cf..6e76fc14c2 100644 --- a/tools/sk_tool_utils.cpp +++ b/tools/sk_tool_utils.cpp @@ -12,6 +12,7 @@ #include "SkBitmap.h" #include "SkCanvas.h" #include "SkCommonFlags.h" +#include "SkPoint3.h" #include "SkShader.h" #include "SkTestScalerContext.h" #include "SkTextBlob.h" @@ -209,5 +210,112 @@ void add_to_text_blob(SkTextBlobBuilder* builder, const char* text, const SkPain memcpy(run.glyphs, glyphs.begin(), glyphs.count() * sizeof(uint16_t)); } +static inline void norm_to_rgb(SkBitmap* bm, int x, int y, const SkVector3& norm) { + SkASSERT(SkScalarNearlyEqual(norm.length(), 1.0f)); + unsigned char r = static_cast<unsigned char>((0.5f * norm.fX + 0.5f) * 255); + unsigned char g = static_cast<unsigned char>((-0.5f * norm.fY + 0.5f) * 255); + unsigned char b = static_cast<unsigned char>((0.5f * norm.fZ + 0.5f) * 255); + *bm->getAddr32(x, y) = SkPackARGB32(0xFF, r, g, b); +} + +void create_hemi_normal_map(SkBitmap* bm, const SkIRect& dst) { + const SkPoint center = SkPoint::Make(dst.fLeft + (dst.width() / 2.0f), + dst.fTop + (dst.height() / 2.0f)); + const SkPoint halfSize = SkPoint::Make(dst.width() / 2.0f, dst.height() / 2.0f); + + SkVector3 norm; + + for (int y = dst.fTop; y < dst.fBottom; ++y) { + for (int x = dst.fLeft; x < dst.fRight; ++x) { + norm.fX = (x + 0.5f - center.fX) / halfSize.fX; + norm.fY = (y + 0.5f - center.fY) / halfSize.fY; + + SkScalar tmp = norm.fX * norm.fX + norm.fY * norm.fY; + if (tmp >= 1.0f) { + norm.set(0.0f, 0.0f, 1.0f); + } else { + norm.fZ = sqrt(1.0f - tmp); + } + + norm_to_rgb(bm, x, y, norm); + } + } +} + +void create_frustum_normal_map(SkBitmap* bm, const SkIRect& dst) { + const SkPoint center = SkPoint::Make(dst.fLeft + (dst.width() / 2.0f), + dst.fTop + (dst.height() / 2.0f)); + + SkIRect inner = dst; + inner.inset(dst.width()/4, dst.height()/4); + + SkPoint3 norm; + const SkPoint3 left = SkPoint3::Make(-SK_ScalarRoot2Over2, 0.0f, SK_ScalarRoot2Over2); + const SkPoint3 up = SkPoint3::Make(0.0f, -SK_ScalarRoot2Over2, SK_ScalarRoot2Over2); + const SkPoint3 right = SkPoint3::Make(SK_ScalarRoot2Over2, 0.0f, SK_ScalarRoot2Over2); + const SkPoint3 down = SkPoint3::Make(0.0f, SK_ScalarRoot2Over2, SK_ScalarRoot2Over2); + + for (int y = dst.fTop; y < dst.fBottom; ++y) { + for (int x = dst.fLeft; x < dst.fRight; ++x) { + if (inner.contains(x, y)) { + norm.set(0.0f, 0.0f, 1.0f); + } else { + SkScalar locX = x + 0.5f - center.fX; + SkScalar locY = y + 0.5f - center.fY; + + if (locX >= 0.0f) { + if (locY > 0.0f) { + norm = locX >= locY ? right : down; // LR corner + } else { + norm = locX > -locY ? right : up; // UR corner + } + } else { + if (locY > 0.0f) { + norm = -locX > locY ? left : down; // LL corner + } else { + norm = locX > locY ? up : left; // UL corner + } + } + } + + norm_to_rgb(bm, x, y, norm); + } + } +} + +void create_tetra_normal_map(SkBitmap* bm, const SkIRect& dst) { + const SkPoint center = SkPoint::Make(dst.fLeft + (dst.width() / 2.0f), + dst.fTop + (dst.height() / 2.0f)); + + static const SkScalar k1OverRoot3 = 0.5773502692f; + + SkPoint3 norm; + const SkPoint3 leftUp = SkPoint3::Make(-k1OverRoot3, -k1OverRoot3, k1OverRoot3); + const SkPoint3 rightUp = SkPoint3::Make(k1OverRoot3, -k1OverRoot3, k1OverRoot3); + const SkPoint3 down = SkPoint3::Make(0.0f, SK_ScalarRoot2Over2, SK_ScalarRoot2Over2); + + for (int y = dst.fTop; y < dst.fBottom; ++y) { + for (int x = dst.fLeft; x < dst.fRight; ++x) { + SkScalar locX = x + 0.5f - center.fX; + SkScalar locY = y + 0.5f - center.fY; + + if (locX >= 0.0f) { + if (locY > 0.0f) { + norm = locX >= locY ? rightUp : down; // LR corner + } else { + norm = rightUp; + } + } else { + if (locY > 0.0f) { + norm = -locX > locY ? leftUp : down; // LL corner + } else { + norm = leftUp; + } + } + + norm_to_rgb(bm, x, y, norm); + } + } +} } // namespace sk_tool_utils diff --git a/tools/sk_tool_utils.h b/tools/sk_tool_utils.h index 1d1d365285..b7a5dd78d0 100644 --- a/tools/sk_tool_utils.h +++ b/tools/sk_tool_utils.h @@ -119,6 +119,12 @@ namespace sk_tool_utils { void add_to_text_blob(SkTextBlobBuilder* builder, const char* text, const SkPaint& origPaint, SkScalar x, SkScalar y); + void create_hemi_normal_map(SkBitmap* bm, const SkIRect& dst); + + void create_frustum_normal_map(SkBitmap* bm, const SkIRect& dst); + + void create_tetra_normal_map(SkBitmap* bm, const SkIRect& dst); + } // namespace sk_tool_utils #endif // sk_tool_utils_DEFINED |