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