aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar robertphillips <robertphillips@google.com>2015-08-17 15:04:47 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-08-17 15:04:47 -0700
commitea4529d09a6ad50582e348eee1c275a9ffb59278 (patch)
tree3688b0482de18a8ef6f676cdf3ad0dc936e06bd9
parentdf5b7603d2d2bb3ec75cfbf235a672ee80cf8d3a (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.cpp107
-rw-r--r--tools/sk_tool_utils.cpp108
-rw-r--r--tools/sk_tool_utils.h6
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