Home | History | Annotate | Download | only in core
      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