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 
     10 #ifndef SkLightingShader_DEFINED
     11 #define SkLightingShader_DEFINED
     12 
     13 #include "SkFlattenable.h"
     14 #include "SkLight.h"
     15 #include "SkShader.h"
     16 #include "SkTDArray.h"
     17 
     18 class SkBitmap;
     19 class SkMatrix;
     20 
     21 class SK_API SkLightingShader {
     22 public:
     23     class Lights  : public SkRefCnt {
     24     public:
     25         class Builder {
     26         public:
     27             Builder(const SkLight lights[], int numLights)
     28                 : fLights(new Lights(lights, numLights)) {}
     29 
     30             Builder() : fLights(new Lights) {}
     31 
     32             // TODO: limit the number of lights here or just ignore those
     33             // above some maximum?
     34             void add(const SkLight& light) {
     35                 if (fLights) {
     36                     *fLights->fLights.push() = light;
     37                 }
     38             }
     39 
     40             const Lights* finish() {
     41                 return fLights.detach();
     42             }
     43 
     44         private:
     45             SkAutoTUnref<Lights> fLights;
     46         };
     47 
     48         int numLights() const {
     49             return fLights.count();
     50         }
     51 
     52         const SkLight& light(int index) const {
     53             return fLights[index];
     54         }
     55 
     56     private:
     57         Lights() {}
     58         Lights(const SkLight lights[], int numLights) : fLights(lights, numLights) {}
     59 
     60         SkTDArray<SkLight> fLights;
     61 
     62         typedef SkRefCnt INHERITED;
     63     };
     64 
     65     /** Returns a shader that lights the diffuse and normal maps with a single light.
     66 
     67         It returns a shader with a reference count of 1.
     68         The caller should decrement the shader's reference count when done with the shader.
     69         It is an error for count to be < 2.
     70         @param  diffuse     the diffuse bitmap
     71         @param  normal      the normal map
     72         @param  light       the light applied to the normal map
     73         @param  ambient     the linear (unpremul) ambient light color. Range is 0..1/channel.
     74         @param  localMatrix the matrix mapping the textures to the dest rect
     75 
     76         nullptr will be returned if:
     77             either 'diffuse' or 'normal' are empty
     78             either 'diffuse' or 'normal' are too big (> 65535 on a side)
     79             'diffuse' and 'normal' aren't the same size
     80 
     81         The lighting equation is currently:
     82             result = LightColor * DiffuseColor * (Normal * LightDir) + AmbientColor
     83 
     84         The normal map is currently assumed to be an 8888 image where the normal at a texel
     85         is retrieved by:
     86             N.x = R-127;
     87             N.y = G-127;
     88             N.z = B-127;
     89             N.normalize();
     90         The +Z axis is thus encoded in RGB as (127, 127, 255) while the -Z axis is
     91         (127, 127, 0).
     92     */
     93     static SkShader* Create(const SkBitmap& diffuse, const SkBitmap& normal,
     94                             const Lights* lights, const SkVector& invNormRotation,
     95                             const SkMatrix* diffLocalMatrix, const SkMatrix* normLocalMatrix);
     96 
     97     SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP()
     98 };
     99 
    100 #endif
    101