OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2015 Google Inc. | 3 * Copyright 2015 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 #include "SkBitmapProcState.h" | 9 #include "SkBitmapProcState.h" |
10 #include "SkColor.h" | 10 #include "SkColor.h" |
11 #include "SkEmptyShader.h" | 11 #include "SkEmptyShader.h" |
12 #include "SkErrorInternals.h" | 12 #include "SkErrorInternals.h" |
13 #include "SkLightingShader.h" | 13 #include "SkLightingShader.h" |
14 #include "SkMathPriv.h" | 14 #include "SkMathPriv.h" |
15 #include "SkReadBuffer.h" | 15 #include "SkReadBuffer.h" |
16 #include "SkWriteBuffer.h" | 16 #include "SkWriteBuffer.h" |
17 | 17 |
18 //////////////////////////////////////////////////////////////////////////// | 18 //////////////////////////////////////////////////////////////////////////// |
19 | 19 |
20 /* | 20 /* |
21 SkLightingShader TODOs: | 21 SkLightingShader TODOs: |
22 support other than clamp mode | 22 support other than clamp mode |
23 allow 'diffuse' & 'normal' to be of different dimensions? | 23 allow 'diffuse' & 'normal' to be of different dimensions? |
24 support different light types | 24 support different light types |
25 support multiple lights | 25 support multiple lights |
26 enforce normal map is 4 channel | 26 enforce normal map is 4 channel |
27 use SkImages instead if SkBitmaps | 27 use SkImages instead if SkBitmaps |
28 vec3 for ambient and light-color | |
29 add dox for both lighting equation, and how we compute normal from bitma
p | |
30 | 28 |
31 To Test: | 29 To Test: |
32 non-opaque diffuse textures | 30 non-opaque diffuse textures |
33 A8 diffuse textures | 31 A8 diffuse textures |
34 down & upsampled draws | 32 down & upsampled draws |
35 */ | 33 */ |
36 | 34 |
37 | 35 |
38 | 36 |
39 /** \class SkLightingShaderImpl | 37 /** \class SkLightingShaderImpl |
40 This subclass of shader applies lighting. | 38 This subclass of shader applies lighting. |
41 */ | 39 */ |
42 class SK_API SkLightingShaderImpl : public SkShader { | 40 class SK_API SkLightingShaderImpl : public SkShader { |
43 public: | 41 public: |
44 | 42 |
45 /** Create a new lighting shader that use the provided normal map, light | 43 /** Create a new lighting shader that use the provided normal map, light |
46 and ambient color to light the diffuse bitmap. | 44 and ambient color to light the diffuse bitmap. |
47 @param diffuse the diffuse bitmap | 45 @param diffuse the diffuse bitmap |
48 @param normal the normal map | 46 @param normal the normal map |
49 @param light the light applied to the normal map | 47 @param light the light applied to the normal map |
50 @param ambient the linear (unpremul) ambient light color | 48 @param ambient the linear (unpremul) ambient light color |
51 */ | 49 */ |
52 SkLightingShaderImpl(const SkBitmap& diffuse, const SkBitmap& normal, | 50 SkLightingShaderImpl(const SkBitmap& diffuse, const SkBitmap& normal, |
53 const SkLightingShader::Light& light, | 51 const SkLightingShader::Light& light, |
54 const SkColor ambient, const SkMatrix* localMatrix) | 52 const SkColor3f& ambient, const SkMatrix* localMatrix) |
55 : INHERITED(localMatrix) | 53 : INHERITED(localMatrix) |
56 , fDiffuseMap(diffuse) | 54 , fDiffuseMap(diffuse) |
57 , fNormalMap(normal) | 55 , fNormalMap(normal) |
58 , fLight(light) | 56 , fLight(light) |
59 , fAmbientColor(ambient) { | 57 , fAmbientColor(ambient) { |
60 if (!fLight.fDirection.normalize()) { | 58 if (!fLight.fDirection.normalize()) { |
61 fLight.fDirection = SkPoint3::Make(0.0f, 0.0f, 1.0f); | 59 fLight.fDirection = SkPoint3::Make(0.0f, 0.0f, 1.0f); |
62 } | 60 } |
63 SkColorSetA(fLight.fColor, 0xFF); | |
64 SkColorSetA(fAmbientColor, 0xFF); | |
65 } | 61 } |
66 | 62 |
67 bool isOpaque() const override; | 63 bool isOpaque() const override; |
68 | 64 |
69 bool asFragmentProcessor(GrContext*, const SkPaint& paint, const SkMatrix& v
iewM, | 65 bool asFragmentProcessor(GrContext*, const SkPaint& paint, const SkMatrix& v
iewM, |
70 const SkMatrix* localMatrix, GrColor* color, | 66 const SkMatrix* localMatrix, GrColor* color, |
71 GrProcessorDataManager*, GrFragmentProcessor** fp)
const override; | 67 GrProcessorDataManager*, GrFragmentProcessor** fp)
const override; |
72 | 68 |
73 size_t contextSize() const override; | 69 size_t contextSize() const override; |
74 | 70 |
(...skipping 21 matching lines...) Expand all Loading... |
96 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLightingShaderImpl) | 92 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLightingShaderImpl) |
97 | 93 |
98 protected: | 94 protected: |
99 void flatten(SkWriteBuffer&) const override; | 95 void flatten(SkWriteBuffer&) const override; |
100 Context* onCreateContext(const ContextRec&, void*) const override; | 96 Context* onCreateContext(const ContextRec&, void*) const override; |
101 | 97 |
102 private: | 98 private: |
103 SkBitmap fDiffuseMap; | 99 SkBitmap fDiffuseMap; |
104 SkBitmap fNormalMap; | 100 SkBitmap fNormalMap; |
105 SkLightingShader::Light fLight; | 101 SkLightingShader::Light fLight; |
106 SkColor fAmbientColor; // linear (unpremul) color | 102 SkColor3f fAmbientColor; // linear (unpremul) color. Range is
0..1/channel. |
107 | 103 |
108 friend class SkLightingShader; | 104 friend class SkLightingShader; |
109 | 105 |
110 typedef SkShader INHERITED; | 106 typedef SkShader INHERITED; |
111 }; | 107 }; |
112 | 108 |
113 //////////////////////////////////////////////////////////////////////////// | 109 //////////////////////////////////////////////////////////////////////////// |
114 | 110 |
115 #if SK_SUPPORT_GPU | 111 #if SK_SUPPORT_GPU |
116 | 112 |
117 #include "GrCoordTransform.h" | 113 #include "GrCoordTransform.h" |
118 #include "GrFragmentProcessor.h" | 114 #include "GrFragmentProcessor.h" |
119 #include "GrTextureAccess.h" | 115 #include "GrTextureAccess.h" |
120 #include "gl/GrGLProcessor.h" | 116 #include "gl/GrGLProcessor.h" |
121 #include "gl/builders/GrGLProgramBuilder.h" | 117 #include "gl/builders/GrGLProgramBuilder.h" |
122 #include "SkGr.h" | 118 #include "SkGr.h" |
123 | 119 |
124 class LightingFP : public GrFragmentProcessor { | 120 class LightingFP : public GrFragmentProcessor { |
125 public: | 121 public: |
126 LightingFP(GrTexture* diffuse, GrTexture* normal, const SkMatrix& matrix, | 122 LightingFP(GrTexture* diffuse, GrTexture* normal, const SkMatrix& matrix, |
127 SkVector3 lightDir, GrColor lightColor, GrColor ambientColor) | 123 const SkVector3& lightDir, const SkColor3f& lightColor, |
| 124 const SkColor3f& ambientColor) |
128 : fDeviceTransform(kDevice_GrCoordSet, matrix) | 125 : fDeviceTransform(kDevice_GrCoordSet, matrix) |
129 , fDiffuseTextureAccess(diffuse) | 126 , fDiffuseTextureAccess(diffuse) |
130 , fNormalTextureAccess(normal) | 127 , fNormalTextureAccess(normal) |
131 , fLightDir(lightDir) | 128 , fLightDir(lightDir) |
132 , fLightColor(lightColor) | 129 , fLightColor(lightColor) |
133 , fAmbientColor(ambientColor) { | 130 , fAmbientColor(ambientColor) { |
134 this->addCoordTransform(&fDeviceTransform); | 131 this->addCoordTransform(&fDeviceTransform); |
135 this->addTextureAccess(&fDiffuseTextureAccess); | 132 this->addTextureAccess(&fDiffuseTextureAccess); |
136 this->addTextureAccess(&fNormalTextureAccess); | 133 this->addTextureAccess(&fNormalTextureAccess); |
137 | 134 |
138 this->initClassID<LightingFP>(); | 135 this->initClassID<LightingFP>(); |
139 } | 136 } |
140 | 137 |
141 class LightingGLFP : public GrGLFragmentProcessor { | 138 class LightingGLFP : public GrGLFragmentProcessor { |
142 public: | 139 public: |
143 LightingGLFP() : fLightColor(GrColor_ILLEGAL), fAmbientColor(GrColor_ILL
EGAL) { | 140 LightingGLFP() { |
144 fLightDir.fX = 10000.0f; | 141 fLightDir.fX = 10000.0f; |
| 142 fLightColor.fX = 0.0f; |
| 143 fAmbientColor.fX = 0.0f; |
145 } | 144 } |
146 | 145 |
147 void emitCode(EmitArgs& args) override { | 146 void emitCode(EmitArgs& args) override { |
148 | 147 |
149 GrGLFragmentBuilder* fpb = args.fBuilder->getFragmentShaderBuilder()
; | 148 GrGLFragmentBuilder* fpb = args.fBuilder->getFragmentShaderBuilder()
; |
150 | 149 |
151 // add uniforms | 150 // add uniforms |
152 const char* lightDirUniName = NULL; | 151 const char* lightDirUniName = NULL; |
153 fLightDirUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragme
nt_Visibility, | 152 fLightDirUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragme
nt_Visibility, |
154 kVec3f_GrSLType, kDefault_G
rSLPrecision, | 153 kVec3f_GrSLType, kDefault_G
rSLPrecision, |
155 "LightDir", &lightDirUniNam
e); | 154 "LightDir", &lightDirUniNam
e); |
156 | 155 |
157 const char* lightColorUniName = NULL; | 156 const char* lightColorUniName = NULL; |
158 fLightColorUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFrag
ment_Visibility, | 157 fLightColorUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFrag
ment_Visibility, |
159 kVec4f_GrSLType, kDefault
_GrSLPrecision, | 158 kVec3f_GrSLType, kDefault
_GrSLPrecision, |
160 "LightColor", &lightColor
UniName); | 159 "LightColor", &lightColor
UniName); |
161 | 160 |
162 const char* ambientColorUniName = NULL; | 161 const char* ambientColorUniName = NULL; |
163 fAmbientColorUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFr
agment_Visibility, | 162 fAmbientColorUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFr
agment_Visibility, |
164 kVec4f_GrSLType, kDefau
lt_GrSLPrecision, | 163 kVec3f_GrSLType, kDefau
lt_GrSLPrecision, |
165 "AmbientColor", &ambien
tColorUniName); | 164 "AmbientColor", &ambien
tColorUniName); |
166 | 165 |
167 fpb->codeAppend("vec4 diffuseColor = "); | 166 fpb->codeAppend("vec4 diffuseColor = "); |
168 fpb->appendTextureLookupAndModulate(args.fInputColor, args.fSamplers
[0], | 167 fpb->appendTextureLookupAndModulate(args.fInputColor, args.fSamplers
[0], |
169 args.fCoords[0].c_str(), | 168 args.fCoords[0].c_str(), |
170 args.fCoords[0].getType()); | 169 args.fCoords[0].getType()); |
171 fpb->codeAppend(";"); | 170 fpb->codeAppend(";"); |
172 | 171 |
173 fpb->codeAppend("vec4 normalColor = "); | 172 fpb->codeAppend("vec4 normalColor = "); |
174 fpb->appendTextureLookup(args.fSamplers[1], | 173 fpb->appendTextureLookup(args.fSamplers[1], |
175 args.fCoords[0].c_str(), | 174 args.fCoords[0].c_str(), |
176 args.fCoords[0].getType()); | 175 args.fCoords[0].getType()); |
177 fpb->codeAppend(";"); | 176 fpb->codeAppend(";"); |
178 | 177 |
179 fpb->codeAppend("vec3 normal = normalize(normalColor.rgb - vec3(0.5)
);"); | 178 fpb->codeAppend("vec3 normal = normalize(normalColor.rgb - vec3(0.5)
);"); |
180 fpb->codeAppendf("vec3 lightDir = normalize(%s);", lightDirUniName); | 179 fpb->codeAppendf("vec3 lightDir = normalize(%s);", lightDirUniName); |
181 fpb->codeAppend("float NdotL = dot(normal, lightDir);"); | 180 fpb->codeAppend("float NdotL = dot(normal, lightDir);"); |
182 // diffuse light | 181 // diffuse light |
183 fpb->codeAppendf("vec3 result = %s.rgb*diffuseColor.rgb*NdotL;", lig
htColorUniName); | 182 fpb->codeAppendf("vec3 result = %s*diffuseColor.rgb*NdotL;", lightCo
lorUniName); |
184 // ambient light | 183 // ambient light |
185 fpb->codeAppendf("result += %s.rgb;", ambientColorUniName); | 184 fpb->codeAppendf("result += %s;", ambientColorUniName); |
186 fpb->codeAppendf("%s = vec4(result.rgb, diffuseColor.a);", args.fOut
putColor); | 185 fpb->codeAppendf("%s = vec4(result.rgb, diffuseColor.a);", args.fOut
putColor); |
187 } | 186 } |
188 | 187 |
189 void setData(const GrGLProgramDataManager& pdman, const GrProcessor& pro
c) override { | 188 void setData(const GrGLProgramDataManager& pdman, const GrProcessor& pro
c) override { |
190 const LightingFP& lightingFP = proc.cast<LightingFP>(); | 189 const LightingFP& lightingFP = proc.cast<LightingFP>(); |
191 | 190 |
192 SkVector3 lightDir = lightingFP.lightDir(); | 191 const SkVector3& lightDir = lightingFP.lightDir(); |
193 if (lightDir != fLightDir) { | 192 if (lightDir != fLightDir) { |
194 pdman.set3fv(fLightDirUni, 1, &lightDir.fX); | 193 pdman.set3fv(fLightDirUni, 1, &lightDir.fX); |
195 fLightDir = lightDir; | 194 fLightDir = lightDir; |
196 } | 195 } |
197 | 196 |
198 GrColor lightColor = lightingFP.lightColor(); | 197 const SkColor3f& lightColor = lightingFP.lightColor(); |
199 if (lightColor != fLightColor) { | 198 if (lightColor != fLightColor) { |
200 GrGLfloat c[4]; | 199 pdman.set3fv(fLightColorUni, 1, &lightColor.fX); |
201 GrColorToRGBAFloat(lightColor, c); | |
202 pdman.set4fv(fLightColorUni, 1, c); | |
203 fLightColor = lightColor; | 200 fLightColor = lightColor; |
204 } | 201 } |
205 | 202 |
206 GrColor ambientColor = lightingFP.ambientColor(); | 203 const SkColor3f& ambientColor = lightingFP.ambientColor(); |
207 if (ambientColor != fAmbientColor) { | 204 if (ambientColor != fAmbientColor) { |
208 GrGLfloat c[4]; | 205 pdman.set3fv(fAmbientColorUni, 1, &ambientColor.fX); |
209 GrColorToRGBAFloat(ambientColor, c); | |
210 pdman.set4fv(fAmbientColorUni, 1, c); | |
211 fAmbientColor = ambientColor; | 206 fAmbientColor = ambientColor; |
212 } | 207 } |
213 } | 208 } |
214 | 209 |
215 static void GenKey(const GrProcessor& proc, const GrGLSLCaps&, | 210 static void GenKey(const GrProcessor& proc, const GrGLSLCaps&, |
216 GrProcessorKeyBuilder* b) { | 211 GrProcessorKeyBuilder* b) { |
217 // const LightingFP& lightingFP = proc.cast<LightingFP>(); | 212 // const LightingFP& lightingFP = proc.cast<LightingFP>(); |
218 // only one shader generated currently | 213 // only one shader generated currently |
219 b->add32(0x0); | 214 b->add32(0x0); |
220 } | 215 } |
221 | 216 |
222 private: | 217 private: |
223 SkVector3 fLightDir; | 218 SkVector3 fLightDir; |
224 GrGLProgramDataManager::UniformHandle fLightDirUni; | 219 GrGLProgramDataManager::UniformHandle fLightDirUni; |
225 | 220 |
226 GrColor fLightColor; | 221 SkColor3f fLightColor; |
227 GrGLProgramDataManager::UniformHandle fLightColorUni; | 222 GrGLProgramDataManager::UniformHandle fLightColorUni; |
228 | 223 |
229 GrColor fAmbientColor; | 224 SkColor3f fAmbientColor; |
230 GrGLProgramDataManager::UniformHandle fAmbientColorUni; | 225 GrGLProgramDataManager::UniformHandle fAmbientColorUni; |
231 }; | 226 }; |
232 | 227 |
233 GrGLFragmentProcessor* createGLInstance() const override { return SkNEW(Ligh
tingGLFP); } | 228 GrGLFragmentProcessor* createGLInstance() const override { return SkNEW(Ligh
tingGLFP); } |
234 | 229 |
235 void getGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) con
st override { | 230 void getGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) con
st override { |
236 LightingGLFP::GenKey(*this, caps, b); | 231 LightingGLFP::GenKey(*this, caps, b); |
237 } | 232 } |
238 | 233 |
239 const char* name() const override { return "LightingFP"; } | 234 const char* name() const override { return "LightingFP"; } |
240 | 235 |
241 void onComputeInvariantOutput(GrInvariantOutput* inout) const override { | 236 void onComputeInvariantOutput(GrInvariantOutput* inout) const override { |
242 inout->mulByUnknownFourComponents(); | 237 inout->mulByUnknownFourComponents(); |
243 } | 238 } |
244 | 239 |
245 SkVector3 lightDir() const { return fLightDir; } | 240 const SkVector3& lightDir() const { return fLightDir; } |
246 GrColor lightColor() const { return fLightColor; } | 241 const SkColor3f& lightColor() const { return fLightColor; } |
247 GrColor ambientColor() const { return fAmbientColor; } | 242 const SkColor3f& ambientColor() const { return fAmbientColor; } |
248 | 243 |
249 private: | 244 private: |
250 bool onIsEqual(const GrFragmentProcessor& proc) const override { | 245 bool onIsEqual(const GrFragmentProcessor& proc) const override { |
251 const LightingFP& lightingFP = proc.cast<LightingFP>(); | 246 const LightingFP& lightingFP = proc.cast<LightingFP>(); |
252 return fDeviceTransform == lightingFP.fDeviceTransform && | 247 return fDeviceTransform == lightingFP.fDeviceTransform && |
253 fDiffuseTextureAccess == lightingFP.fDiffuseTextureAccess && | 248 fDiffuseTextureAccess == lightingFP.fDiffuseTextureAccess && |
254 fNormalTextureAccess == lightingFP.fNormalTextureAccess && | 249 fNormalTextureAccess == lightingFP.fNormalTextureAccess && |
255 fLightDir == lightingFP.fLightDir && | 250 fLightDir == lightingFP.fLightDir && |
256 fLightColor == lightingFP.fLightColor && | 251 fLightColor == lightingFP.fLightColor && |
257 fAmbientColor == lightingFP.fAmbientColor; | 252 fAmbientColor == lightingFP.fAmbientColor; |
258 } | 253 } |
259 | 254 |
260 GrCoordTransform fDeviceTransform; | 255 GrCoordTransform fDeviceTransform; |
261 GrTextureAccess fDiffuseTextureAccess; | 256 GrTextureAccess fDiffuseTextureAccess; |
262 GrTextureAccess fNormalTextureAccess; | 257 GrTextureAccess fNormalTextureAccess; |
263 SkVector3 fLightDir; | 258 SkVector3 fLightDir; |
264 GrColor fLightColor; | 259 SkColor3f fLightColor; |
265 GrColor fAmbientColor; | 260 SkColor3f fAmbientColor; |
266 }; | 261 }; |
267 | 262 |
268 //////////////////////////////////////////////////////////////////////////// | 263 //////////////////////////////////////////////////////////////////////////// |
269 | 264 |
270 bool SkLightingShaderImpl::asFragmentProcessor(GrContext* context, const SkPaint
& paint, | 265 bool SkLightingShaderImpl::asFragmentProcessor(GrContext* context, const SkPaint
& paint, |
271 const SkMatrix& viewM, const SkMa
trix* localMatrix, | 266 const SkMatrix& viewM, const SkMa
trix* localMatrix, |
272 GrColor* color, GrProcessorDataMa
nager*, | 267 GrColor* color, GrProcessorDataMa
nager*, |
273 GrFragmentProcessor** fp) const { | 268 GrFragmentProcessor** fp) const { |
274 // we assume diffuse and normal maps have same width and height | 269 // we assume diffuse and normal maps have same width and height |
275 // TODO: support different sizes | 270 // TODO: support different sizes |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
334 return false; | 329 return false; |
335 } | 330 } |
336 | 331 |
337 SkAutoTUnref<GrTexture> normalTexture(GrRefCachedBitmapTexture(context, fNor
malMap, ¶ms)); | 332 SkAutoTUnref<GrTexture> normalTexture(GrRefCachedBitmapTexture(context, fNor
malMap, ¶ms)); |
338 if (!normalTexture) { | 333 if (!normalTexture) { |
339 SkErrorInternals::SetError(kInternalError_SkError, | 334 SkErrorInternals::SetError(kInternalError_SkError, |
340 "Couldn't convert bitmap to texture."); | 335 "Couldn't convert bitmap to texture."); |
341 return false; | 336 return false; |
342 } | 337 } |
343 | 338 |
344 GrColor lightColor = GrColorPackRGBA(SkColorGetR(fLight.fColor), SkColorGetG
(fLight.fColor), | |
345 SkColorGetB(fLight.fColor), SkColorGetA
(fLight.fColor)); | |
346 GrColor ambientColor = GrColorPackRGBA(SkColorGetR(fAmbientColor), SkColorGe
tG(fAmbientColor), | |
347 SkColorGetB(fAmbientColor), SkColorGe
tA(fAmbientColor)); | |
348 | |
349 *fp = SkNEW_ARGS(LightingFP, (diffuseTexture, normalTexture, matrix, | 339 *fp = SkNEW_ARGS(LightingFP, (diffuseTexture, normalTexture, matrix, |
350 fLight.fDirection, lightColor, ambientColor)); | 340 fLight.fDirection, fLight.fColor, fAmbientColo
r)); |
351 *color = GrColorPackA4(paint.getAlpha()); | 341 *color = GrColorPackA4(paint.getAlpha()); |
352 return true; | 342 return true; |
353 } | 343 } |
354 #else | 344 #else |
355 | 345 |
356 bool SkLightingShaderImpl::asFragmentProcessor(GrContext* context, const SkPaint
& paint, | 346 bool SkLightingShaderImpl::asFragmentProcessor(GrContext* context, const SkPaint
& paint, |
357 const SkMatrix& viewM, const SkMa
trix* localMatrix, | 347 const SkMatrix& viewM, const SkMa
trix* localMatrix, |
358 GrColor* color, GrProcessorDataMa
nager*, | 348 GrColor* color, GrProcessorDataMa
nager*, |
359 GrFragmentProcessor** fp) const { | 349 GrFragmentProcessor** fp) const { |
360 SkDEBUGFAIL("Should not call in GPU-less build"); | 350 SkDEBUGFAIL("Should not call in GPU-less build"); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
393 fFlags = flags; | 383 fFlags = flags; |
394 } | 384 } |
395 | 385 |
396 SkLightingShaderImpl::LightingShaderContext::~LightingShaderContext() { | 386 SkLightingShaderImpl::LightingShaderContext::~LightingShaderContext() { |
397 // The bitmap proc states have been created outside of the context on memory
that will be freed | 387 // The bitmap proc states have been created outside of the context on memory
that will be freed |
398 // elsewhere. Call the destructors but leave the freeing of the memory to th
e caller. | 388 // elsewhere. Call the destructors but leave the freeing of the memory to th
e caller. |
399 fDiffuseState->~SkBitmapProcState(); | 389 fDiffuseState->~SkBitmapProcState(); |
400 fNormalState->~SkBitmapProcState(); | 390 fNormalState->~SkBitmapProcState(); |
401 } | 391 } |
402 | 392 |
403 static inline int light(int light, int diff, SkScalar NdotL, int ambient) { | 393 static inline int light(SkScalar light, int diff, SkScalar NdotL, SkScalar ambie
nt) { |
404 int color = int(light * diff * NdotL + 255 * ambient); | 394 SkScalar color = light * diff * NdotL + 255 * ambient; |
405 if (color <= 0) { | 395 if (color <= 0.0f) { |
406 return 0; | 396 return 0; |
407 } else if (color >= 255*255) { | 397 } else if (color >= 255.0f) { |
408 return 255; | 398 return 255; |
409 } else { | 399 } else { |
410 return SkDiv255Round(color); | 400 return (int) color; |
411 } | 401 } |
412 } | 402 } |
413 | 403 |
414 // larger is better (fewer times we have to loop), but we shouldn't | 404 // larger is better (fewer times we have to loop), but we shouldn't |
415 // take up too much stack-space (each could here costs 16 bytes) | 405 // take up too much stack-space (each could here costs 16 bytes) |
416 #define TMP_COUNT 16 | 406 #define TMP_COUNT 16 |
417 | 407 |
418 void SkLightingShaderImpl::LightingShaderContext::shadeSpan(int x, int y, | 408 void SkLightingShaderImpl::LightingShaderContext::shadeSpan(int x, int y, |
419 SkPMColor result[],
int count) { | 409 SkPMColor result[],
int count) { |
420 const SkLightingShaderImpl& lightShader = static_cast<const SkLightingShader
Impl&>(fShader); | 410 const SkLightingShaderImpl& lightShader = static_cast<const SkLightingShader
Impl&>(fShader); |
(...skipping 30 matching lines...) Expand all Loading... |
451 SkASSERT(0xFF == SkColorGetA(tmpNormal2[i])); // opaque -> unpremul | 441 SkASSERT(0xFF == SkColorGetA(tmpNormal2[i])); // opaque -> unpremul |
452 norm.set(SkIntToScalar(SkGetPackedR32(tmpNormal2[i]))-127.0f, | 442 norm.set(SkIntToScalar(SkGetPackedR32(tmpNormal2[i]))-127.0f, |
453 SkIntToScalar(SkGetPackedG32(tmpNormal2[i]))-127.0f, | 443 SkIntToScalar(SkGetPackedG32(tmpNormal2[i]))-127.0f, |
454 SkIntToScalar(SkGetPackedB32(tmpNormal2[i]))-127.0f); | 444 SkIntToScalar(SkGetPackedB32(tmpNormal2[i]))-127.0f); |
455 norm.normalize(); | 445 norm.normalize(); |
456 | 446 |
457 SkColor diffColor = SkUnPreMultiply::PMColorToColor(tmpColor2[i]); | 447 SkColor diffColor = SkUnPreMultiply::PMColorToColor(tmpColor2[i]); |
458 NdotL = norm.dot(lightShader.fLight.fDirection); | 448 NdotL = norm.dot(lightShader.fLight.fDirection); |
459 | 449 |
460 // This is all done in linear unpremul color space | 450 // This is all done in linear unpremul color space |
461 r = light(SkColorGetR(lightShader.fLight.fColor), SkColorGetR(diffCo
lor), NdotL, | 451 r = light(lightShader.fLight.fColor.fX, SkColorGetR(diffColor), Ndot
L, |
462 SkColorGetR(lightShader.fAmbientColor)); | 452 lightShader.fAmbientColor.fX); |
463 g = light(SkColorGetG(lightShader.fLight.fColor), SkColorGetG(diffCo
lor), NdotL, | 453 g = light(lightShader.fLight.fColor.fY, SkColorGetG(diffColor), Ndot
L, |
464 SkColorGetG(lightShader.fAmbientColor)); | 454 lightShader.fAmbientColor.fY); |
465 b = light(SkColorGetB(lightShader.fLight.fColor), SkColorGetB(diffCo
lor), NdotL, | 455 b = light(lightShader.fLight.fColor.fZ, SkColorGetB(diffColor), Ndot
L, |
466 SkColorGetB(lightShader.fAmbientColor)); | 456 lightShader.fAmbientColor.fZ); |
467 | 457 |
468 result[i] = SkPreMultiplyARGB(SkColorGetA(diffColor), r, g, b); | 458 result[i] = SkPreMultiplyARGB(SkColorGetA(diffColor), r, g, b); |
469 } | 459 } |
470 | 460 |
471 result += n; | 461 result += n; |
472 x += n; | 462 x += n; |
473 count -= n; | 463 count -= n; |
474 } while (count > 0); | 464 } while (count > 0); |
475 } | 465 } |
476 | 466 |
(...skipping 18 matching lines...) Expand all Loading... |
495 SkBitmap normal; | 485 SkBitmap normal; |
496 if (!buf.readBitmap(&normal)) { | 486 if (!buf.readBitmap(&normal)) { |
497 return NULL; | 487 return NULL; |
498 } | 488 } |
499 normal.setImmutable(); | 489 normal.setImmutable(); |
500 | 490 |
501 SkLightingShader::Light light; | 491 SkLightingShader::Light light; |
502 if (!buf.readScalarArray(&light.fDirection.fX, 3)) { | 492 if (!buf.readScalarArray(&light.fDirection.fX, 3)) { |
503 return NULL; | 493 return NULL; |
504 } | 494 } |
505 light.fColor = buf.readColor(); | 495 if (!buf.readScalarArray(&light.fColor.fX, 3)) { |
| 496 return NULL; |
| 497 } |
506 | 498 |
507 SkColor ambient = buf.readColor(); | 499 SkColor3f ambient; |
| 500 if (!buf.readScalarArray(&ambient.fX, 3)) { |
| 501 return NULL; |
| 502 } |
508 | 503 |
509 return SkNEW_ARGS(SkLightingShaderImpl, (diffuse, normal, light, ambient, &l
ocalMatrix)); | 504 return SkNEW_ARGS(SkLightingShaderImpl, (diffuse, normal, light, ambient, &l
ocalMatrix)); |
510 } | 505 } |
511 | 506 |
512 void SkLightingShaderImpl::flatten(SkWriteBuffer& buf) const { | 507 void SkLightingShaderImpl::flatten(SkWriteBuffer& buf) const { |
513 buf.writeMatrix(this->getLocalMatrix()); | 508 buf.writeMatrix(this->getLocalMatrix()); |
514 | 509 |
515 buf.writeBitmap(fDiffuseMap); | 510 buf.writeBitmap(fDiffuseMap); |
516 buf.writeBitmap(fNormalMap); | 511 buf.writeBitmap(fNormalMap); |
517 buf.writeScalarArray(&fLight.fDirection.fX, 3); | 512 buf.writeScalarArray(&fLight.fDirection.fX, 3); |
518 buf.writeColor(fLight.fColor); | 513 buf.writeScalarArray(&fLight.fColor.fX, 3); |
519 buf.writeColor(fAmbientColor); | 514 buf.writeScalarArray(&fAmbientColor.fX, 3); |
520 } | 515 } |
521 | 516 |
522 SkShader::Context* SkLightingShaderImpl::onCreateContext(const ContextRec& rec, | 517 SkShader::Context* SkLightingShaderImpl::onCreateContext(const ContextRec& rec, |
523 void* storage) const { | 518 void* storage) const { |
524 | 519 |
525 SkMatrix totalInverse; | 520 SkMatrix totalInverse; |
526 // Do this first, so we know the matrix can be inverted. | 521 // Do this first, so we know the matrix can be inverted. |
527 if (!this->computeTotalInverse(rec, &totalInverse)) { | 522 if (!this->computeTotalInverse(rec, &totalInverse)) { |
528 return NULL; | 523 return NULL; |
529 } | 524 } |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
564 // communicates between its matrix-proc and its sampler-proc. Until we can | 559 // communicates between its matrix-proc and its sampler-proc. Until we can |
565 // widen that, we have to reject bitmaps that are larger. | 560 // widen that, we have to reject bitmaps that are larger. |
566 // | 561 // |
567 static const int kMaxSize = 65535; | 562 static const int kMaxSize = 65535; |
568 | 563 |
569 return bm.width() > kMaxSize || bm.height() > kMaxSize; | 564 return bm.width() > kMaxSize || bm.height() > kMaxSize; |
570 } | 565 } |
571 | 566 |
572 SkShader* SkLightingShader::Create(const SkBitmap& diffuse, const SkBitmap& norm
al, | 567 SkShader* SkLightingShader::Create(const SkBitmap& diffuse, const SkBitmap& norm
al, |
573 const SkLightingShader::Light& light, | 568 const SkLightingShader::Light& light, |
574 const SkColor ambient, | 569 const SkColor3f& ambient, |
575 const SkMatrix* localMatrix) { | 570 const SkMatrix* localMatrix) { |
576 if (diffuse.isNull() || bitmap_is_too_big(diffuse) || | 571 if (diffuse.isNull() || bitmap_is_too_big(diffuse) || |
577 normal.isNull() || bitmap_is_too_big(normal) || | 572 normal.isNull() || bitmap_is_too_big(normal) || |
578 diffuse.width() != normal.width() || | 573 diffuse.width() != normal.width() || |
579 diffuse.height() != normal.height()) { | 574 diffuse.height() != normal.height()) { |
580 return nullptr; | 575 return nullptr; |
581 } | 576 } |
582 | 577 |
583 return SkNEW_ARGS(SkLightingShaderImpl, (diffuse, normal, light, ambient, lo
calMatrix)); | 578 return SkNEW_ARGS(SkLightingShaderImpl, (diffuse, normal, light, ambient, lo
calMatrix)); |
584 } | 579 } |
585 | 580 |
586 /////////////////////////////////////////////////////////////////////////////// | 581 /////////////////////////////////////////////////////////////////////////////// |
587 | 582 |
588 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkLightingShader) | 583 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkLightingShader) |
589 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLightingShaderImpl) | 584 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLightingShaderImpl) |
590 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END | 585 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END |
591 | 586 |
592 /////////////////////////////////////////////////////////////////////////////// | 587 /////////////////////////////////////////////////////////////////////////////// |
OLD | NEW |