OLD | NEW |
---|---|
(Empty) | |
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 "SkPoint3.h" | |
14 #include "SkShader.h" | |
15 | |
16 //////////////////////////////////////////////////////////////////////////////// /////////// | |
17 | |
18 /* | |
19 SkLightingShader TODOs: | |
20 support other than clamp mode | |
21 allow 'diffuse' & 'normal' to be of different dimensions? | |
22 support different light types | |
23 support multiple lights | |
24 enforce normal map is 4 channel | |
jvanverth1
2015/07/23 17:40:14
use SkImages instead of SkBitmaps
robertphillips
2015/07/28 14:15:45
Done.
| |
25 | |
26 To Test: | |
27 non-opaque diffuse textures | |
28 A8 diffuse textures | |
29 down & upsampled draws | |
30 */ | |
31 | |
32 | |
33 | |
34 /** \class SkLightingShader | |
35 This subclass of shader applies lighting. | |
36 */ | |
37 class SK_API SkLightingShader : public SkShader { | |
38 public: | |
39 struct Light { | |
40 SkVector3 fDirection; // direction towards the light (+Z is out of the screen) | |
41 SkColor fColor; // linear (unpremul) color | |
42 }; | |
43 | |
44 /** Create a new lighting shader that use the provided normal map, light | |
45 and ambient color to light the diffuse bitmap. | |
46 @param diffuse the diffuse bitmap | |
47 @param normal the normal map | |
48 @param light the light applied to the normal map | |
49 @param ambient the linear (unpremul) ambient light color | |
50 */ | |
51 SkLightingShader(const SkBitmap& diffuse, const SkBitmap& normal, const Ligh t& light, | |
52 const SkColor ambient) | |
53 : fDiffuseMap(diffuse) | |
54 , fNormalMap(normal) | |
55 , fLight(light) | |
56 , fAmbientColor(ambient) { | |
57 if (!fLight.fDirection.normalize()) { | |
58 fLight.fDirection = SkPoint3::Make(0.0f, 0.0f, 1.0f); | |
59 } | |
60 SkColorSetA(fLight.fColor, 0xFF); | |
61 SkColorSetA(fAmbientColor, 0xFF); | |
62 } | |
63 | |
64 bool isOpaque() const override; | |
65 | |
66 void setLight(const Light& light) { | |
67 fLight = light; | |
68 if (!fLight.fDirection.normalize()) { | |
69 fLight.fDirection = SkPoint3::Make(0.0f, 0.0f, 1.0f); | |
70 } | |
71 SkColorSetA(fLight.fColor, 0xFF); | |
72 SkColorSetA(fAmbientColor, 0xFF); | |
73 } | |
74 | |
75 bool asFragmentProcessor(GrContext*, const SkPaint& paint, const SkMatrix& v iewM, | |
76 const SkMatrix* localMatrix, GrColor* color, | |
77 GrProcessorDataManager*, GrFragmentProcessor** fp) const override; | |
78 | |
79 size_t contextSize() const override; | |
80 | |
81 class LightingShaderContext : public SkShader::Context { | |
82 public: | |
83 // The context takes ownership of the states. It will call their destruc tors | |
84 // but will NOT free the memory. | |
85 LightingShaderContext(const SkLightingShader&, const ContextRec&, | |
86 SkBitmapProcState* diffuseState, SkBitmapProcState * normalState); | |
87 ~LightingShaderContext() override; | |
88 | |
89 void shadeSpan(int x, int y, SkPMColor[], int count) override; | |
90 | |
91 uint32_t getFlags() const override { return fFlags; } | |
92 | |
93 private: | |
94 SkBitmapProcState* fDiffuseState; | |
95 SkBitmapProcState* fNormalState; | |
96 uint32_t fFlags; | |
97 | |
98 typedef SkShader::Context INHERITED; | |
99 }; | |
100 | |
101 SK_TO_STRING_OVERRIDE() | |
102 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(LightingShader) | |
103 | |
104 protected: | |
105 void flatten(SkWriteBuffer&) const override; | |
106 Context* onCreateContext(const ContextRec&, void*) const override; | |
107 | |
108 private: | |
109 SkBitmap fDiffuseMap; | |
110 SkBitmap fNormalMap; | |
111 Light fLight; | |
112 SkColor fAmbientColor; // linear (unpremul) color | |
113 | |
114 typedef SkShader INHERITED; | |
115 }; | |
116 | |
117 // TODO: it would be nice to be able to call this from SkShader but this | |
118 // would need to reside in core. | |
119 #if 0 | |
120 // Commonly used allocator. It currently is only used to allocate up to 3 object s. The total | |
121 // bytes requested is calculated using one of our large shaders, its context siz e plus the size of | |
122 // an Sk3DBlitter in SkDraw.cpp | |
123 // Note that some contexts may contain other contexts (e.g. for compose shaders) , but we've not | |
124 // yet found a situation where the size below isn't big enough. | |
125 typedef SkSmallAllocator<3, 1024> SkTBlitterAllocator; | |
126 | |
127 // If alloc is non-NULL, it will be used to allocate the returned SkShader, and MUST outlive | |
128 // the SkShader. | |
129 SkShader* SkCreateLightingShader(const SkBitmap& diffuse, const SkBitmap& normal , | |
130 const SkLightingShader::Light& light, const SkC olor ambient, | |
131 SkTBlitterAllocator* alloc); | |
132 #endif | |
133 | |
134 #endif | |
OLD | NEW |