/*
 * Copyright 2015 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 "sk_tool_utils.h"
#include "SkLightingShader.h"
#include "SkNormalSource.h"
#include "SkPoint3.h"
#include "SkShader.h"

// Create a hemispherical normal map
static SkBitmap make_hemi_normalmap(int texSize) {
    SkBitmap hemi;
    hemi.allocN32Pixels(texSize, texSize);

    sk_tool_utils::create_hemi_normal_map(&hemi, SkIRect::MakeWH(texSize, texSize));
    return hemi;
}

// Create a truncated pyramid normal map
static SkBitmap make_frustum_normalmap(int texSize) {
    SkBitmap frustum;
    frustum.allocN32Pixels(texSize, texSize);

    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 by drawing rotated and non-rotated normal mapped rects with
// a directional light off to the viewers right.
class LightingShaderGM : public GM {
public:
    LightingShaderGM() {
        this->setBGColor(sk_tool_utils::color_to_565(0xFFCCCCCC));
    }

protected:
    enum NormalMap {
        kHemi_NormalMap,
        kFrustum_NormalMap,
        kTetra_NormalMap,

        kLast_NormalMap = kTetra_NormalMap
    };

    static constexpr int kNormalMapCount = kLast_NormalMap+1;

    SkString onShortName() override { return SkString("lightingshader"); }

    SkISize onISize() override { return SkISize::Make(kGMSize, kGMSize); }

    void onOnceBeforeDraw() override {
        {
            SkLights::Builder builder;

            // The direction vector is towards the light w/ +Z coming out of the screen
            builder.add(SkLights::Light::MakeDirectional(SkColor3f::Make(1.0f, 1.0f, 1.0f),
                                                         SkVector3::Make(SK_ScalarRoot2Over2,
                                                                         0.0f,
                                                                         SK_ScalarRoot2Over2)));
            builder.setAmbientLightColor(SkColor3f::Make(0.2f, 0.2f, 0.2f));

            fLights = builder.finish();
        }

        fDiffuse = sk_tool_utils::create_checkerboard_bitmap(
                                                        kTexSize, kTexSize,
                                                        sk_tool_utils::color_to_565(0x0),
                                                        sk_tool_utils::color_to_565(0xFF804020),
                                                        8);

        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, NormalMap mapType) {

        SkRect bitmapBounds = SkRect::MakeIWH(fDiffuse.width(), fDiffuse.height());

        SkMatrix matrix;
        matrix.setRectToRect(bitmapBounds, r, SkMatrix::kFill_ScaleToFit);

        const SkMatrix& ctm = canvas->getTotalMatrix();

        SkPaint paint;
        sk_sp<SkShader> diffuseShader = SkShader::MakeBitmapShader(fDiffuse,
                SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, &matrix);
        sk_sp<SkShader> normalMap = SkShader::MakeBitmapShader(fNormalMaps[mapType],
                SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, &matrix);
        sk_sp<SkNormalSource> normalSource = SkNormalSource::MakeFromNormalMap(std::move(normalMap),
                                                                               ctm);
        paint.setShader(SkLightingShader::Make(std::move(diffuseShader), std::move(normalSource),
                                               fLights));

        canvas->drawRect(r, paint);
    }

    // Draw an axis-aligned and rotated version of the normal mapped rect
    void drawPair(SkCanvas* canvas, const SkRect& r, NormalMap mapType, const SkVector& v) {
        SkMatrix m;
        m.setRotate(45.0f, r.centerX(), r.centerY());
        m.postTranslate(kScale * v.fX, kScale * v.fY);

        this->drawRect(canvas, r, mapType);

        canvas->save();
            canvas->setMatrix(m);
            this->drawRect(canvas, r, mapType);
        canvas->restore();
    }

    void onDraw(SkCanvas* canvas) override {
        SkRect r;

        r = SkRect::MakeWH(SkIntToScalar(kTexSize), SkIntToScalar(kTexSize));
        this->drawPair(canvas, r, kHemi_NormalMap, SkVector::Make(1.0f, 0.0f));

        r.offset(kGMSize - kTexSize, 0);
        this->drawPair(canvas, r, kFrustum_NormalMap, SkVector::Make(0.0f, 1.0f));

        r.offset(0, kGMSize - kTexSize);
        this->drawPair(canvas, r, kTetra_NormalMap, SkVector::Make(-1.0, 0.0f));

        r.offset(kTexSize - kGMSize, 0);
        this->drawPair(canvas, r, kHemi_NormalMap, SkVector::Make(0.0f, -1));
    }

private:
    static constexpr int kTexSize = 128;
    static constexpr int kGMSize  = 512;
    static constexpr SkScalar kScale = kGMSize/2.0f - kTexSize/2.0f;

    SkBitmap        fDiffuse;
    SkBitmap        fNormalMaps[kNormalMapCount];

    sk_sp<SkLights> fLights;

    typedef GM INHERITED;
};

//////////////////////////////////////////////////////////////////////////////

DEF_GM(return new LightingShaderGM;)
}
