1 
2 /*
3  * Copyright 2015 Google Inc.
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 
9 #ifndef SkLights_DEFINED
10 #define SkLights_DEFINED
11 
12 #include "SkPoint3.h"
13 #include "SkRefCnt.h"
14 #include "../private/SkTArray.h"
15 
16 class SkColorSpaceXformer;
17 class SkReadBuffer;
18 class SkWriteBuffer;
19 
20 /** \class SkLights
21     SkLights encapsulates a set of directional, point and ambient lights for use with the
22     SkLightingShader.
23 */
24 class SK_API SkLights  : public SkRefCnt {
25 public:
26     class Light {
27     public:
28         enum LightType {
29             kDirectional_LightType,
30             kPoint_LightType
31         };
32 
Light(const Light & other)33         Light(const Light& other)
34                 : fType(other.fType)
35                 , fColor(other.fColor)
36                 , fDirOrPos(other.fDirOrPos)
37                 , fIntensity(other.fIntensity) {}
38 
Light(Light && other)39         Light(Light&& other)
40                 : fType(other.fType)
41                 , fColor(other.fColor)
42                 , fDirOrPos(other.fDirOrPos)
43                 , fIntensity(other.fIntensity) {}
44 
MakeDirectional(const SkColor3f & color,const SkVector3 & dir)45         static Light MakeDirectional(const SkColor3f& color, const SkVector3& dir) {
46             Light light(kDirectional_LightType, color, dir, 0.0f);
47             if (!light.fDirOrPos.normalize()) {
48                 light.fDirOrPos.set(0.0f, 0.0f, 1.0f);
49             }
50             return light;
51         }
52 
MakePoint(const SkColor3f & color,const SkPoint3 & pos,SkScalar intensity)53         static Light MakePoint(const SkColor3f& color, const SkPoint3& pos, SkScalar intensity) {
54             return Light(kPoint_LightType, color, pos, intensity);
55         }
56 
type()57         LightType type() const { return fType; }
color()58         const SkColor3f& color() const { return fColor; }
dir()59         const SkVector3& dir() const {
60             SkASSERT(kDirectional_LightType == fType);
61             return fDirOrPos;
62         }
pos()63         const SkPoint3& pos() const {
64             SkASSERT(kPoint_LightType == fType);
65             return fDirOrPos;
66         }
intensity()67         SkScalar intensity() const {
68             SkASSERT(kPoint_LightType == fType);
69             return fIntensity;
70         }
71 
72         Light& operator=(const Light& other) {
73             if (this == &other) {
74                 return *this;
75             }
76 
77             fType = other.fType;
78             fColor = other.fColor;
79             fDirOrPos = other.fDirOrPos;
80             fIntensity = other.fIntensity;
81             return *this;
82         }
83 
84         bool operator==(const Light& other) {
85             return (fType      == other.fType) &&
86                    (fColor     == other.fColor) &&
87                    (fDirOrPos  == other.fDirOrPos) &&
88                    (fIntensity == other.fIntensity);
89         }
90 
91         bool operator!=(const Light& other) { return !(this->operator==(other)); }
92 
93     private:
94         friend class SkLights;
95 
Light(LightType type,const SkColor3f & color,const SkVector3 & dirOrPos,SkScalar intensity)96         Light(LightType type, const SkColor3f& color, const SkVector3& dirOrPos,
97               SkScalar intensity)
98                 : fType(type)
99                 , fColor(color)
100                 , fDirOrPos(dirOrPos)
101                 , fIntensity(intensity) {}
102 
103         LightType   fType;
104         SkColor3f   fColor;           // linear (unpremul) color. Range is 0..1 in each channel.
105 
106         SkVector3   fDirOrPos;        // For directional lights, holds the direction towards the
107                                       // light (+Z is out of the screen).
108                                       // If degenerate, it will be replaced with (0, 0, 1).
109                                       // For point lights, holds location of point light
110 
111         SkScalar    fIntensity;       // For point lights, dictates the light intensity.
112                                       // Simply a multiplier to the final light output value.
113     };
114 
115     class Builder {
116     public:
Builder()117         Builder() : fLights(new SkLights) {}
118 
add(const Light & light)119         void add(const Light& light) {
120             if (fLights) {
121                 fLights->fLights.push_back(light);
122             }
123         }
124 
add(Light && light)125         void add(Light&& light) {
126             if (fLights) {
127                 fLights->fLights.push_back(std::move(light));
128             }
129         }
130 
setAmbientLightColor(const SkColor3f & color)131         void setAmbientLightColor(const SkColor3f& color) {
132             if (fLights) {
133                 fLights->fAmbientLightColor = color;
134             }
135         }
136 
finish()137         sk_sp<SkLights> finish() {
138             return std::move(fLights);
139         }
140 
141     private:
142         sk_sp<SkLights> fLights;
143     };
144 
145     /** Returns number of lights not including the ambient light.
146 
147         @return number of lights not including the ambient light
148     */
numLights()149     int numLights() const { return fLights.count(); }
150 
151     /** Returns the index-th light.
152 
153         @param index  the index of the desired light
154         @return       the index-th light
155     */
light(int index)156     const Light& light(int index) const { return fLights[index]; }
157 
158     /** Returns the ambient light.
159 
160         @return the ambient light
161     */
ambientLightColor()162     const SkColor3f& ambientLightColor() const {
163         return fAmbientLightColor;
164     }
165 
166     /**
167      *  Recreate an SkLights object that was serialized into a buffer.
168      *
169      *  @param  SkReadBuffer Serialized blob data.
170      *  @return A new SkLights representing the serialized data, or NULL if the buffer is
171      *          invalid.
172      */
173     static sk_sp<SkLights> MakeFromBuffer(SkReadBuffer& buf);
174 
175     /**
176      *  Serialize to a buffer.
177      *
178      *  @param  buffer the write buffer to write out to
179      */
180     void flatten(SkWriteBuffer& buf) const;
181 
182 private:
183     friend class SkLightingShaderImpl;
184 
SkLights()185     SkLights() : fAmbientLightColor(SkColor3f::Make(0.0f, 0.0f, 0.0f)) {}
186 
187     sk_sp<SkLights> makeColorSpace(SkColorSpaceXformer* xformer) const;
188 
189     SkTArray<Light> fLights;
190     SkColor3f       fAmbientLightColor;
191 
192     typedef SkRefCnt INHERITED;
193 };
194 
195 #endif
196