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