Index: gm/victor-shadows.cpp |
diff --git a/gm/victor-shadows.cpp b/gm/victor-shadows.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..835a24300ca3f0cdd09a6bf675a841441227714d |
--- /dev/null |
+++ b/gm/victor-shadows.cpp |
@@ -0,0 +1,182 @@ |
+/* |
+ * Copyright 2016 Google Inc. |
+ * |
+ * Use of this source code is governed by a BSD-style license that can be |
+ * found in the LICENSE file. |
+ */ |
+ |
+#include "gm.h" |
+#include "SkDrawFilter.h" |
+#include "SkLights.h" |
+#include "SkLightingShader.h" |
+#include "SkPictureRecorder.h" |
+#include "SkSurface.h" |
+ |
+ |
+sk_sp<SkShader> make_lighting_shader(const SkMatrix& ctm, sk_sp<SkLights> lights) { |
+ // TODO: Victor figures this out |
+#if 0 |
+ // TODO: correctly pull out the pure rotation |
+ SkVector invNormRotation = { ctm[SkMatrix::kMScaleX], ctm[SkMatrix::kMSkewY] }; |
+ |
+ return SkLightingShader::Make(nullptr, |
+ nullptr, |
+ std::move(lights), |
+ invNormRotation, |
+ nullptr, |
+ nullptr); |
+#else |
+ return nullptr; |
+#endif |
+} |
+ |
+sk_sp<SkPicture> make_picture(int width, int height, sk_sp<SkLights> lights) { |
+ SkPictureRecorder recorder; |
+ |
+ // eventually add SkBBHFactory (bounding box factory) |
+ SkCanvas* canvas = recorder.beginRecording(SkRect::MakeIWH(width, height)); |
+ |
+ SkASSERT(canvas->getTotalMatrix().isIdentity()); |
+ sk_sp<SkShader> identityLights(make_lighting_shader(canvas->getTotalMatrix(), lights)); |
+ SkPaint paint; |
+ paint.setShader(identityLights); |
+ paint.setColor(SK_ColorWHITE); |
+ |
+ // LONG RANGE TODO: tag occluders |
+ // LONG RANGE TODO: track number of IDs we need (hopefully less than 256) |
+ // and determinate the mapping from z to id |
+ |
+ // universal receiver, "ground" |
+ canvas->drawRect(SkRect::MakeIWH(width, height), paint); |
+ |
+ // Maybe add the ID here along with the depth |
robertphillips
2016/07/01 15:17:54
Note that you're also going to need to add a SkCan
|
+ // canvas->setZ(10); |
+ |
+ canvas->save(); |
+ canvas->translate(50, 50); |
+ canvas->clipRect(SkRect::MakeLTRB(475, 475, 525, 525)); |
+ |
+ // Add an assert that Z order matches painter's order |
+ /// |
+ // canvas->setZ(20); |
+ |
+ SkASSERT(!canvas->getTotalMatrix().isIdentity()); |
+ paint.setShader(make_lighting_shader(canvas->getTotalMatrix(), lights)); |
+ paint.setColor(SK_ColorBLUE); |
+ |
+ // use an IDE |
+ canvas->drawRect(SkRect::MakeLTRB(0, 0, 1000, 1000), paint); |
+ canvas->restore(); |
+ |
+ // TODO: think about if the Z-order always matching painting order is too strict |
+ SkASSERT(canvas->getTotalMatrix().isIdentity()); |
+ paint.setShader(identityLights); |
+ paint.setColor(SK_ColorRED); |
+ canvas->drawRect(SkRect::MakeLTRB(700, 700, 710, 710), paint); |
+ |
+ return recorder.finishRecordingAsPicture(); |
+} |
+ |
+namespace skiagm { |
+ |
robertphillips
2016/07/01 15:17:54
Thinking about this a bit more I think we should u
jvanverth1
2016/07/01 15:31:04
After talking to Robert about this, when we create
|
+class SkFoo : public SkDrawFilter { |
+public: |
+ SkFoo(/*SkTDynamicHash<int, int> *hash*/) { |
+ |
+ } |
+ |
+ bool filter(SkPaint* paint, Type) override { |
+ SkPaint newPaint; |
+ |
+ SkColor color = 0xFF000000; |
+ |
+ color |= 0x000000AA; // Put the index into the blue component |
+ newPaint.setColor(color); |
+ // Map the individual draw to a specific index |
+ *paint = newPaint; |
+ return true; |
+ } |
+}; |
+ |
+// This GM ... |
+class Shadows1GM : public GM { |
+public: |
+ Shadows1GM() { |
+ this->setBGColor(sk_tool_utils::color_to_565(0xFFCCCCCC)); |
+ |
+ SkLights::Builder builder; |
+ |
+ builder.add(SkLights::Light(SkColor3f::Make(1.0f, 1.0f, 1.0f), |
+ SkVector3::Make(1.0f, 0.0f, 0.0f))); |
+ builder.add(SkLights::Light(SkColor3f::Make(0.2f, 0.2f, 0.2f))); |
+ |
+ fLights = builder.finish(); |
+ } |
+ |
+protected: |
+ static const int kWidth = 1024; |
+ static const int kHeight = 1024; |
+ |
+ |
+ SkString onShortName() override { |
+ return SkString("victor-shadows"); |
+ } |
+ |
+ SkISize onISize() override { |
+ return SkISize::Make(kWidth, kHeight); |
+ } |
+ |
+ void onDraw(SkCanvas* canvas) override { |
+ |
+ sk_sp<SkPicture> pic(make_picture(kWidth, kHeight, fLights)); |
+ |
+ sk_sp<SkDrawFilter> filter(new SkFoo()); |
+ |
+ sk_sp<SkImage> img; |
+ for (int i = 0; i < fLights->numLights(); ++i) { |
+ if (SkLights::Light::kAmbient_LightType == fLights->light(i).type()) { |
+ continue; |
+ } |
+ |
+ // generate shadow map |
+ |
+ // TODO: compute the correct size of the shadow map from the light properties |
+ // TODO: maybe add a kDepth_8_SkColorType |
+ // TODO: change to kIndex_8_SkColorType |
robertphillips
2016/07/01 15:17:55
We could probably start off with this being kAlpha
|
+ SkImageInfo info = SkImageInfo::Make(256, 256, kBGRA_8888_SkColorType, kOpaque_SkAlphaType); |
+ |
+ sk_sp<SkSurface> surf(canvas->makeSurface(info)); |
+ SkCanvas* shadowMapCanvas = surf->getCanvas(); |
+ |
+ // TODO: add a matrix to map the scene to the viewpoint of the light |
+ fLights->light(i); |
+ |
+ SkMatrix mat; |
+ mat.setRectToRect(SkRect::MakeIWH(kWidth, kHeight), SkRect::MakeIWH(256, 256), |
+ SkMatrix::kFill_ScaleToFit); |
+ |
+ shadowMapCanvas->setMatrix(mat); |
+ shadowMapCanvas->setDrawFilter(filter.get()); |
+ shadowMapCanvas->drawPicture(pic); |
+ |
+ img = surf->makeImageSnapshot(); |
+ |
+ // TODO: Add something like this |
+ fLights->light(i).setShadowMap(img); |
+ } |
+ |
+ // perform final pass |
+ canvas->drawPicture(std::move(pic)); |
+ //canvas->drawImage(img, 0, 0); |
+ } |
+ |
+private: |
+ sk_sp<SkLights> fLights; |
+ |
+ typedef GM INHERITED; |
+}; |
+ |
+////////////////////////////////////////////////////////////////////////////// |
+ |
+DEF_GM(return new Shadows1GM;) |
+} |