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 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 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 61 LightType type() const { return fType; } 62 const SkColor3f& color() const { return fColor; } 63 const SkVector3& dir() const { 64 SkASSERT(kDirectional_LightType == fType); 65 return fDirOrPos; 66 } 67 const SkPoint3& pos() const { 68 SkASSERT(kPoint_LightType == fType); 69 return fDirOrPos; 70 } 71 SkScalar intensity() const { 72 SkASSERT(kPoint_LightType == fType); 73 return fIntensity; 74 } 75 76 void setShadowMap(sk_sp<SkImage> shadowMap) { 77 fShadowMap = std::move(shadowMap); 78 } 79 80 SkImage* getShadowMap() const { 81 return fShadowMap.get(); 82 } 83 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 friend class SkLights; 117 118 LightType fType; 119 SkColor3f fColor; // linear (unpremul) color. Range is 0..1 in each channel. 120 121 SkVector3 fDirOrPos; // For directional lights, holds the direction towards the 122 // light (+Z is out of the screen). 123 // If degenerate, it will be replaced with (0, 0, 1). 124 // For point lights, holds location of point light 125 126 SkScalar fIntensity; // For point lights, dictates the light intensity. 127 // Simply a multiplier to the final light output value. 128 sk_sp<SkImage> fShadowMap; 129 bool fIsRadial; // Whether the light is radial or not. Radial lights will 130 // cast shadows and lights radially outwards. 131 132 Light(LightType type, const SkColor3f& color, const SkVector3& dirOrPos, 133 SkScalar intensity = 0.0f, bool isRadial = false) { 134 fType = type; 135 fColor = color; 136 fDirOrPos = dirOrPos; 137 fIntensity = intensity; 138 fIsRadial = isRadial; 139 } 140 }; 141 142 class Builder { 143 public: 144 Builder() : fLights(new SkLights) {} 145 146 void add(const Light& light) { 147 if (fLights) { 148 fLights->fLights.push_back(light); 149 } 150 } 151 152 void add(Light&& light) { 153 if (fLights) { 154 fLights->fLights.push_back(std::move(light)); 155 } 156 } 157 158 void setAmbientLightColor(const SkColor3f& color) { 159 if (fLights) { 160 fLights->fAmbientLightColor = color; 161 } 162 } 163 164 sk_sp<SkLights> finish() { 165 return std::move(fLights); 166 } 167 168 private: 169 sk_sp<SkLights> fLights; 170 }; 171 172 int numLights() const { 173 return fLights.count(); 174 } 175 176 const Light& light(int index) const { 177 return fLights[index]; 178 } 179 180 Light& light(int index) { 181 return fLights[index]; 182 } 183 184 const SkColor3f& ambientLightColor() const { 185 return fAmbientLightColor; 186 } 187 188 static sk_sp<SkLights> MakeFromBuffer(SkReadBuffer& buf); 189 190 void flatten(SkWriteBuffer& buf) const; 191 192 private: 193 SkLights() { 194 fAmbientLightColor.set(0.0f, 0.0f, 0.0f); 195 } 196 197 friend class SkLightingShaderImpl; 198 sk_sp<SkLights> makeColorSpace(SkColorSpaceXformer* xformer) const; 199 200 SkTArray<Light> fLights; 201 SkColor3f fAmbientLightColor; 202 typedef SkRefCnt INHERITED; 203 }; 204 205 #endif 206