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