193966d88efb090f77f6109f0e19cc982b83d5da9robertphillips
293966d88efb090f77f6109f0e19cc982b83d5da9robertphillips/*
393966d88efb090f77f6109f0e19cc982b83d5da9robertphillips * Copyright 2015 Google Inc.
493966d88efb090f77f6109f0e19cc982b83d5da9robertphillips *
593966d88efb090f77f6109f0e19cc982b83d5da9robertphillips * Use of this source code is governed by a BSD-style license that can be
693966d88efb090f77f6109f0e19cc982b83d5da9robertphillips * found in the LICENSE file.
793966d88efb090f77f6109f0e19cc982b83d5da9robertphillips */
893966d88efb090f77f6109f0e19cc982b83d5da9robertphillips
993966d88efb090f77f6109f0e19cc982b83d5da9robertphillips#ifndef SkLights_DEFINED
1093966d88efb090f77f6109f0e19cc982b83d5da9robertphillips#define SkLights_DEFINED
1193966d88efb090f77f6109f0e19cc982b83d5da9robertphillips
12772b5ee446d7545eec4ca7d6dc9d75461e2a9c38vjiaoblack#include "../private/SkTArray.h"
136b20a559968e1ed0d3aa4ecbd6ddda9e681b4f86Hal Canary#include "SkImage.h"
1493966d88efb090f77f6109f0e19cc982b83d5da9robertphillips#include "SkPoint3.h"
1593966d88efb090f77f6109f0e19cc982b83d5da9robertphillips#include "SkRefCnt.h"
16772b5ee446d7545eec4ca7d6dc9d75461e2a9c38vjiaoblack
17772b5ee446d7545eec4ca7d6dc9d75461e2a9c38vjiaoblackclass SkReadBuffer;
18772b5ee446d7545eec4ca7d6dc9d75461e2a9c38vjiaoblackclass SkWriteBuffer;
1993966d88efb090f77f6109f0e19cc982b83d5da9robertphillips
2093966d88efb090f77f6109f0e19cc982b83d5da9robertphillipsclass SK_API SkLights  : public SkRefCnt {
2193966d88efb090f77f6109f0e19cc982b83d5da9robertphillipspublic:
2293966d88efb090f77f6109f0e19cc982b83d5da9robertphillips    class Light {
2393966d88efb090f77f6109f0e19cc982b83d5da9robertphillips    public:
2493966d88efb090f77f6109f0e19cc982b83d5da9robertphillips        enum LightType {
25772b5ee446d7545eec4ca7d6dc9d75461e2a9c38vjiaoblack            kDirectional_LightType,
26772b5ee446d7545eec4ca7d6dc9d75461e2a9c38vjiaoblack            kPoint_LightType
2793966d88efb090f77f6109f0e19cc982b83d5da9robertphillips        };
2893966d88efb090f77f6109f0e19cc982b83d5da9robertphillips
29a746f7894ae96558abd0775aef68d895f99dd53brobertphillips        Light(const Light& other)
30a746f7894ae96558abd0775aef68d895f99dd53brobertphillips            : fType(other.fType)
31a746f7894ae96558abd0775aef68d895f99dd53brobertphillips            , fColor(other.fColor)
3256f33ea2acb39ebb041340a8ab7564facb95afcevjiaoblack            , fDirOrPos(other.fDirOrPos)
3356f33ea2acb39ebb041340a8ab7564facb95afcevjiaoblack            , fIntensity(other.fIntensity)
34c1a50e1b735bd717eed1fc72a8f093a1b399cb07vjiaoblack            , fShadowMap(other.fShadowMap)
35c1a50e1b735bd717eed1fc72a8f093a1b399cb07vjiaoblack            , fIsRadial(other.fIsRadial) {
36a746f7894ae96558abd0775aef68d895f99dd53brobertphillips        }
37a746f7894ae96558abd0775aef68d895f99dd53brobertphillips
38a746f7894ae96558abd0775aef68d895f99dd53brobertphillips        Light(Light&& other)
39a746f7894ae96558abd0775aef68d895f99dd53brobertphillips            : fType(other.fType)
40a746f7894ae96558abd0775aef68d895f99dd53brobertphillips            , fColor(other.fColor)
4156f33ea2acb39ebb041340a8ab7564facb95afcevjiaoblack            , fDirOrPos(other.fDirOrPos)
4256f33ea2acb39ebb041340a8ab7564facb95afcevjiaoblack            , fIntensity(other.fIntensity)
43c1a50e1b735bd717eed1fc72a8f093a1b399cb07vjiaoblack            , fShadowMap(std::move(other.fShadowMap))
44c1a50e1b735bd717eed1fc72a8f093a1b399cb07vjiaoblack            , fIsRadial(other.fIsRadial)  {
45a746f7894ae96558abd0775aef68d895f99dd53brobertphillips        }
46a746f7894ae96558abd0775aef68d895f99dd53brobertphillips
47c1a50e1b735bd717eed1fc72a8f093a1b399cb07vjiaoblack        static Light MakeDirectional(const SkColor3f& color, const SkVector3& dir,
48c1a50e1b735bd717eed1fc72a8f093a1b399cb07vjiaoblack                                     bool isRadial = false) {
49c1a50e1b735bd717eed1fc72a8f093a1b399cb07vjiaoblack            Light light(kDirectional_LightType, color, dir, isRadial);
5056f33ea2acb39ebb041340a8ab7564facb95afcevjiaoblack            if (!light.fDirOrPos.normalize()) {
5156f33ea2acb39ebb041340a8ab7564facb95afcevjiaoblack                light.fDirOrPos.set(0.0f, 0.0f, 1.0f);
5293966d88efb090f77f6109f0e19cc982b83d5da9robertphillips            }
53772b5ee446d7545eec4ca7d6dc9d75461e2a9c38vjiaoblack            return light;
54772b5ee446d7545eec4ca7d6dc9d75461e2a9c38vjiaoblack        }
55772b5ee446d7545eec4ca7d6dc9d75461e2a9c38vjiaoblack
56c1a50e1b735bd717eed1fc72a8f093a1b399cb07vjiaoblack        static Light MakePoint(const SkColor3f& color, const SkPoint3& pos, SkScalar intensity,
57c1a50e1b735bd717eed1fc72a8f093a1b399cb07vjiaoblack                               bool isRadial = false) {
58c1a50e1b735bd717eed1fc72a8f093a1b399cb07vjiaoblack            return Light(kPoint_LightType, color, pos, intensity, isRadial);
5993966d88efb090f77f6109f0e19cc982b83d5da9robertphillips        }
6093966d88efb090f77f6109f0e19cc982b83d5da9robertphillips
6193966d88efb090f77f6109f0e19cc982b83d5da9robertphillips        LightType type() const { return fType; }
6293966d88efb090f77f6109f0e19cc982b83d5da9robertphillips        const SkColor3f& color() const { return fColor; }
63772b5ee446d7545eec4ca7d6dc9d75461e2a9c38vjiaoblack        const SkVector3& dir() const {
64772b5ee446d7545eec4ca7d6dc9d75461e2a9c38vjiaoblack            SkASSERT(kDirectional_LightType == fType);
6556f33ea2acb39ebb041340a8ab7564facb95afcevjiaoblack            return fDirOrPos;
66772b5ee446d7545eec4ca7d6dc9d75461e2a9c38vjiaoblack        }
67772b5ee446d7545eec4ca7d6dc9d75461e2a9c38vjiaoblack        const SkPoint3& pos() const {
68772b5ee446d7545eec4ca7d6dc9d75461e2a9c38vjiaoblack            SkASSERT(kPoint_LightType == fType);
6956f33ea2acb39ebb041340a8ab7564facb95afcevjiaoblack            return fDirOrPos;
7056f33ea2acb39ebb041340a8ab7564facb95afcevjiaoblack        }
7156f33ea2acb39ebb041340a8ab7564facb95afcevjiaoblack        SkScalar intensity() const {
7256f33ea2acb39ebb041340a8ab7564facb95afcevjiaoblack            SkASSERT(kPoint_LightType == fType);
7356f33ea2acb39ebb041340a8ab7564facb95afcevjiaoblack            return fIntensity;
7493966d88efb090f77f6109f0e19cc982b83d5da9robertphillips        }
7593966d88efb090f77f6109f0e19cc982b83d5da9robertphillips
7695302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack        void setShadowMap(sk_sp<SkImage> shadowMap) {
7795302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack            fShadowMap = std::move(shadowMap);
7895302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack        }
7995302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack
80a746f7894ae96558abd0775aef68d895f99dd53brobertphillips        SkImage* getShadowMap() const {
81a746f7894ae96558abd0775aef68d895f99dd53brobertphillips            return fShadowMap.get();
8295302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack        }
8395302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack
84c1a50e1b735bd717eed1fc72a8f093a1b399cb07vjiaoblack        bool isRadial() const { return fIsRadial; }
85c1a50e1b735bd717eed1fc72a8f093a1b399cb07vjiaoblack
8695302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack        Light& operator= (const Light& b) {
87a746f7894ae96558abd0775aef68d895f99dd53brobertphillips            if (this == &b) {
8895302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack                return *this;
8995302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack            }
9095302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack
91a746f7894ae96558abd0775aef68d895f99dd53brobertphillips            fColor = b.fColor;
92a746f7894ae96558abd0775aef68d895f99dd53brobertphillips            fType = b.fType;
9356f33ea2acb39ebb041340a8ab7564facb95afcevjiaoblack            fDirOrPos = b.fDirOrPos;
9456f33ea2acb39ebb041340a8ab7564facb95afcevjiaoblack            fIntensity = b.fIntensity;
95a746f7894ae96558abd0775aef68d895f99dd53brobertphillips            fShadowMap = b.fShadowMap;
96c1a50e1b735bd717eed1fc72a8f093a1b399cb07vjiaoblack            fIsRadial = b.fIsRadial;
9795302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack            return *this;
9895302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack        }
996ad75d10eb2462e614f2b7cba293144a7e91a842dvonbeck
1006ad75d10eb2462e614f2b7cba293144a7e91a842dvonbeck        bool operator== (const Light& b) {
1016ad75d10eb2462e614f2b7cba293144a7e91a842dvonbeck            if (this == &b) {
1026ad75d10eb2462e614f2b7cba293144a7e91a842dvonbeck                return true;
1036ad75d10eb2462e614f2b7cba293144a7e91a842dvonbeck            }
1046ad75d10eb2462e614f2b7cba293144a7e91a842dvonbeck
1056ad75d10eb2462e614f2b7cba293144a7e91a842dvonbeck            return (fColor     == b.fColor) &&
1066ad75d10eb2462e614f2b7cba293144a7e91a842dvonbeck                   (fType      == b.fType) &&
10756f33ea2acb39ebb041340a8ab7564facb95afcevjiaoblack                   (fDirOrPos  == b.fDirOrPos) &&
10856f33ea2acb39ebb041340a8ab7564facb95afcevjiaoblack                   (fShadowMap == b.fShadowMap) &&
109c1a50e1b735bd717eed1fc72a8f093a1b399cb07vjiaoblack                   (fIntensity == b.fIntensity) &&
110c1a50e1b735bd717eed1fc72a8f093a1b399cb07vjiaoblack                   (fIsRadial  == b.fIsRadial);
1116ad75d10eb2462e614f2b7cba293144a7e91a842dvonbeck        }
1126ad75d10eb2462e614f2b7cba293144a7e91a842dvonbeck
1136ad75d10eb2462e614f2b7cba293144a7e91a842dvonbeck        bool operator!= (const Light& b) { return !(this->operator==(b)); }
1146ad75d10eb2462e614f2b7cba293144a7e91a842dvonbeck
11593966d88efb090f77f6109f0e19cc982b83d5da9robertphillips    private:
11693966d88efb090f77f6109f0e19cc982b83d5da9robertphillips        LightType   fType;
11793966d88efb090f77f6109f0e19cc982b83d5da9robertphillips        SkColor3f   fColor;           // linear (unpremul) color. Range is 0..1 in each channel.
11856f33ea2acb39ebb041340a8ab7564facb95afcevjiaoblack
11956f33ea2acb39ebb041340a8ab7564facb95afcevjiaoblack        SkVector3   fDirOrPos;        // For directional lights, holds the direction towards the
120772b5ee446d7545eec4ca7d6dc9d75461e2a9c38vjiaoblack                                      // light (+Z is out of the screen).
12193966d88efb090f77f6109f0e19cc982b83d5da9robertphillips                                      // If degenerate, it will be replaced with (0, 0, 1).
122772b5ee446d7545eec4ca7d6dc9d75461e2a9c38vjiaoblack                                      // For point lights, holds location of point light
12356f33ea2acb39ebb041340a8ab7564facb95afcevjiaoblack
12456f33ea2acb39ebb041340a8ab7564facb95afcevjiaoblack        SkScalar    fIntensity;       // For point lights, dictates the light intensity.
12556f33ea2acb39ebb041340a8ab7564facb95afcevjiaoblack                                      // Simply a multiplier to the final light output value.
12695302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack        sk_sp<SkImage> fShadowMap;
127c1a50e1b735bd717eed1fc72a8f093a1b399cb07vjiaoblack        bool        fIsRadial;        // Whether the light is radial or not. Radial lights will
128c1a50e1b735bd717eed1fc72a8f093a1b399cb07vjiaoblack                                      // cast shadows and lights radially outwards.
129772b5ee446d7545eec4ca7d6dc9d75461e2a9c38vjiaoblack
130c1a50e1b735bd717eed1fc72a8f093a1b399cb07vjiaoblack        Light(LightType type, const SkColor3f& color, const SkVector3& dirOrPos,
131c1a50e1b735bd717eed1fc72a8f093a1b399cb07vjiaoblack              SkScalar intensity = 0.0f, bool isRadial = false) {
132772b5ee446d7545eec4ca7d6dc9d75461e2a9c38vjiaoblack            fType = type;
133772b5ee446d7545eec4ca7d6dc9d75461e2a9c38vjiaoblack            fColor = color;
134a8eabc4a2a5559a1410fdbb348f967cd1554b325vjiaoblack            fDirOrPos = dirOrPos;
13556f33ea2acb39ebb041340a8ab7564facb95afcevjiaoblack            fIntensity = intensity;
136c1a50e1b735bd717eed1fc72a8f093a1b399cb07vjiaoblack            fIsRadial = isRadial;
137772b5ee446d7545eec4ca7d6dc9d75461e2a9c38vjiaoblack        }
13893966d88efb090f77f6109f0e19cc982b83d5da9robertphillips    };
13993966d88efb090f77f6109f0e19cc982b83d5da9robertphillips
14093966d88efb090f77f6109f0e19cc982b83d5da9robertphillips    class Builder {
14193966d88efb090f77f6109f0e19cc982b83d5da9robertphillips    public:
142a8eabc4a2a5559a1410fdbb348f967cd1554b325vjiaoblack        Builder() : fLights(new SkLights) {}
143772b5ee446d7545eec4ca7d6dc9d75461e2a9c38vjiaoblack
14493966d88efb090f77f6109f0e19cc982b83d5da9robertphillips        void add(const Light& light) {
14593966d88efb090f77f6109f0e19cc982b83d5da9robertphillips            if (fLights) {
146a746f7894ae96558abd0775aef68d895f99dd53brobertphillips                fLights->fLights.push_back(light);
147a746f7894ae96558abd0775aef68d895f99dd53brobertphillips            }
148a746f7894ae96558abd0775aef68d895f99dd53brobertphillips        }
149a746f7894ae96558abd0775aef68d895f99dd53brobertphillips
150a746f7894ae96558abd0775aef68d895f99dd53brobertphillips        void add(Light&& light) {
151a746f7894ae96558abd0775aef68d895f99dd53brobertphillips            if (fLights) {
152a746f7894ae96558abd0775aef68d895f99dd53brobertphillips                fLights->fLights.push_back(std::move(light));
15393966d88efb090f77f6109f0e19cc982b83d5da9robertphillips            }
15493966d88efb090f77f6109f0e19cc982b83d5da9robertphillips        }
15593966d88efb090f77f6109f0e19cc982b83d5da9robertphillips
156a8eabc4a2a5559a1410fdbb348f967cd1554b325vjiaoblack        void setAmbientLightColor(const SkColor3f& color) {
157a8eabc4a2a5559a1410fdbb348f967cd1554b325vjiaoblack            if (fLights) {
158a8eabc4a2a5559a1410fdbb348f967cd1554b325vjiaoblack                fLights->fAmbientLightColor = color;
159a8eabc4a2a5559a1410fdbb348f967cd1554b325vjiaoblack            }
160a8eabc4a2a5559a1410fdbb348f967cd1554b325vjiaoblack        }
161a8eabc4a2a5559a1410fdbb348f967cd1554b325vjiaoblack
162adf5afa628adb62a0ad451d07ef1442381a0ee20robertphillips        sk_sp<SkLights> finish() {
163a746f7894ae96558abd0775aef68d895f99dd53brobertphillips            return std::move(fLights);
16493966d88efb090f77f6109f0e19cc982b83d5da9robertphillips        }
16593966d88efb090f77f6109f0e19cc982b83d5da9robertphillips
16693966d88efb090f77f6109f0e19cc982b83d5da9robertphillips    private:
16793966d88efb090f77f6109f0e19cc982b83d5da9robertphillips        sk_sp<SkLights> fLights;
16893966d88efb090f77f6109f0e19cc982b83d5da9robertphillips    };
16993966d88efb090f77f6109f0e19cc982b83d5da9robertphillips
17093966d88efb090f77f6109f0e19cc982b83d5da9robertphillips    int numLights() const {
17193966d88efb090f77f6109f0e19cc982b83d5da9robertphillips        return fLights.count();
17293966d88efb090f77f6109f0e19cc982b83d5da9robertphillips    }
17393966d88efb090f77f6109f0e19cc982b83d5da9robertphillips
17493966d88efb090f77f6109f0e19cc982b83d5da9robertphillips    const Light& light(int index) const {
17593966d88efb090f77f6109f0e19cc982b83d5da9robertphillips        return fLights[index];
17693966d88efb090f77f6109f0e19cc982b83d5da9robertphillips    }
17793966d88efb090f77f6109f0e19cc982b83d5da9robertphillips
17895302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack    Light& light(int index) {
17995302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack        return fLights[index];
18095302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack    }
18195302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack
182a8eabc4a2a5559a1410fdbb348f967cd1554b325vjiaoblack    const SkColor3f& ambientLightColor() const {
183a8eabc4a2a5559a1410fdbb348f967cd1554b325vjiaoblack        return fAmbientLightColor;
184a8eabc4a2a5559a1410fdbb348f967cd1554b325vjiaoblack    }
185a8eabc4a2a5559a1410fdbb348f967cd1554b325vjiaoblack
186772b5ee446d7545eec4ca7d6dc9d75461e2a9c38vjiaoblack    static sk_sp<SkLights> MakeFromBuffer(SkReadBuffer& buf);
187772b5ee446d7545eec4ca7d6dc9d75461e2a9c38vjiaoblack
188772b5ee446d7545eec4ca7d6dc9d75461e2a9c38vjiaoblack    void flatten(SkWriteBuffer& buf) const;
189772b5ee446d7545eec4ca7d6dc9d75461e2a9c38vjiaoblack
19093966d88efb090f77f6109f0e19cc982b83d5da9robertphillipsprivate:
191a8eabc4a2a5559a1410fdbb348f967cd1554b325vjiaoblack    SkLights() {
192a8eabc4a2a5559a1410fdbb348f967cd1554b325vjiaoblack        fAmbientLightColor.set(0.0f, 0.0f, 0.0f);
193a8eabc4a2a5559a1410fdbb348f967cd1554b325vjiaoblack    }
194a746f7894ae96558abd0775aef68d895f99dd53brobertphillips    SkTArray<Light> fLights;
195a8eabc4a2a5559a1410fdbb348f967cd1554b325vjiaoblack    SkColor3f fAmbientLightColor;
196a746f7894ae96558abd0775aef68d895f99dd53brobertphillips    typedef SkRefCnt INHERITED;
19793966d88efb090f77f6109f0e19cc982b83d5da9robertphillips};
19893966d88efb090f77f6109f0e19cc982b83d5da9robertphillips
19993966d88efb090f77f6109f0e19cc982b83d5da9robertphillips#endif
200