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