OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
| 8 #include "SkBitmapProcShader.h" |
8 #include "SkBitmapProcState.h" | 9 #include "SkBitmapProcState.h" |
9 #include "SkColor.h" | 10 #include "SkColor.h" |
10 #include "SkEmptyShader.h" | 11 #include "SkEmptyShader.h" |
11 #include "SkErrorInternals.h" | 12 #include "SkErrorInternals.h" |
12 #include "SkLightingShader.h" | 13 #include "SkLightingShader.h" |
13 #include "SkMathPriv.h" | 14 #include "SkMathPriv.h" |
14 #include "SkPoint3.h" | 15 #include "SkPoint3.h" |
15 #include "SkReadBuffer.h" | 16 #include "SkReadBuffer.h" |
16 #include "SkWriteBuffer.h" | 17 #include "SkWriteBuffer.h" |
17 | 18 |
(...skipping 12 matching lines...) Expand all Loading... |
30 non-opaque diffuse textures | 31 non-opaque diffuse textures |
31 A8 diffuse textures | 32 A8 diffuse textures |
32 down & upsampled draws | 33 down & upsampled draws |
33 */ | 34 */ |
34 | 35 |
35 | 36 |
36 | 37 |
37 /** \class SkLightingShaderImpl | 38 /** \class SkLightingShaderImpl |
38 This subclass of shader applies lighting. | 39 This subclass of shader applies lighting. |
39 */ | 40 */ |
40 class SK_API SkLightingShaderImpl : public SkShader { | 41 class SkLightingShaderImpl : public SkShader { |
41 public: | 42 public: |
42 | 43 |
43 /** Create a new lighting shader that uses the provided normal map and | 44 /** Create a new lighting shader that uses the provided normal map and |
44 lights to light the diffuse bitmap. | 45 lights to light the diffuse bitmap. |
45 @param diffuse the diffuse bitmap | 46 @param diffuse the diffuse bitmap |
46 @param normal the normal map | 47 @param normal the normal map |
47 @param lights the lights applied to the normal map | 48 @param lights the lights applied to the normal map |
48 @param invNormRotation rotation applied to the normal map's normals | 49 @param invNormRotation rotation applied to the normal map's normals |
49 @param diffLocalM the local matrix for the diffuse coordinates | 50 @param diffLocalM the local matrix for the diffuse coordinates |
50 @param normLocalM the local matrix for the normal coordinates | 51 @param normLocalM the local matrix for the normal coordinates |
| 52 @param normalSource the normal source for GPU computations |
51 */ | 53 */ |
52 SkLightingShaderImpl(const SkBitmap& diffuse, const SkBitmap& normal, | 54 SkLightingShaderImpl(const SkBitmap& diffuse, const SkBitmap& normal, |
53 const sk_sp<SkLights> lights, | 55 const sk_sp<SkLights> lights, |
54 const SkVector& invNormRotation, | 56 const SkVector& invNormRotation, |
55 const SkMatrix* diffLocalM, const SkMatrix* normLocalM) | 57 const SkMatrix* diffLocalM, const SkMatrix* normLocalM, |
| 58 sk_sp<SkLightingShader::NormalSource> normalSource) |
56 : INHERITED(diffLocalM) | 59 : INHERITED(diffLocalM) |
57 , fDiffuseMap(diffuse) | 60 , fDiffuseMap(diffuse) |
58 , fNormalMap(normal) | 61 , fNormalMap(normal) |
59 , fLights(std::move(lights)) | 62 , fLights(std::move(lights)) |
60 , fInvNormRotation(invNormRotation) { | 63 , fInvNormRotation(invNormRotation) { |
61 | 64 |
62 if (normLocalM) { | 65 if (normLocalM) { |
63 fNormLocalMatrix = *normLocalM; | 66 fNormLocalMatrix = *normLocalM; |
64 } else { | 67 } else { |
65 fNormLocalMatrix.reset(); | 68 fNormLocalMatrix.reset(); |
66 } | 69 } |
67 // Pre-cache so future calls to fNormLocalMatrix.getType() are threadsaf
e. | 70 // Pre-cache so future calls to fNormLocalMatrix.getType() are threadsaf
e. |
68 (void)fNormLocalMatrix.getType(); | 71 (void)fNormLocalMatrix.getType(); |
69 | 72 |
| 73 fNormalSource = std::move(normalSource); |
70 } | 74 } |
71 | 75 |
72 bool isOpaque() const override; | 76 bool isOpaque() const override; |
73 | 77 |
74 #if SK_SUPPORT_GPU | 78 #if SK_SUPPORT_GPU |
75 sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*, | 79 sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*, |
76 const SkMatrix& viewM, | 80 const SkMatrix& viewM, |
77 const SkMatrix* localMatrix, | 81 const SkMatrix* localMatrix, |
78 SkFilterQuality, | 82 SkFilterQuality, |
79 SkSourceGammaTreatment) const
override; | 83 SkSourceGammaTreatment) const
override; |
(...skipping 30 matching lines...) Expand all Loading... |
110 | 114 |
111 private: | 115 private: |
112 SkBitmap fDiffuseMap; | 116 SkBitmap fDiffuseMap; |
113 SkBitmap fNormalMap; | 117 SkBitmap fNormalMap; |
114 | 118 |
115 sk_sp<SkLights> fLights; | 119 sk_sp<SkLights> fLights; |
116 | 120 |
117 SkMatrix fNormLocalMatrix; | 121 SkMatrix fNormLocalMatrix; |
118 SkVector fInvNormRotation; | 122 SkVector fInvNormRotation; |
119 | 123 |
| 124 sk_sp<SkLightingShader::NormalSource> fNormalSource; |
| 125 |
120 friend class SkLightingShader; | 126 friend class SkLightingShader; |
121 | 127 |
122 typedef SkShader INHERITED; | 128 typedef SkShader INHERITED; |
123 }; | 129 }; |
124 | 130 |
125 //////////////////////////////////////////////////////////////////////////// | 131 //////////////////////////////////////////////////////////////////////////// |
126 | 132 |
127 #if SK_SUPPORT_GPU | 133 #if SK_SUPPORT_GPU |
128 | 134 |
129 #include "GrCoordTransform.h" | 135 #include "GrCoordTransform.h" |
130 #include "GrFragmentProcessor.h" | 136 #include "GrFragmentProcessor.h" |
131 #include "GrInvariantOutput.h" | 137 #include "GrInvariantOutput.h" |
132 #include "GrTextureAccess.h" | 138 #include "GrTextureAccess.h" |
133 #include "glsl/GrGLSLFragmentProcessor.h" | 139 #include "glsl/GrGLSLFragmentProcessor.h" |
134 #include "glsl/GrGLSLFragmentShaderBuilder.h" | 140 #include "glsl/GrGLSLFragmentShaderBuilder.h" |
135 #include "glsl/GrGLSLProgramDataManager.h" | 141 #include "glsl/GrGLSLProgramDataManager.h" |
136 #include "glsl/GrGLSLUniformHandler.h" | 142 #include "glsl/GrGLSLUniformHandler.h" |
137 #include "SkGr.h" | 143 #include "SkGr.h" |
138 #include "SkGrPriv.h" | 144 #include "SkGrPriv.h" |
139 | 145 |
140 class LightingFP : public GrFragmentProcessor { | 146 class LightingFP : public GrFragmentProcessor { |
141 public: | 147 public: |
142 LightingFP(GrTexture* diffuse, GrTexture* normal, const SkMatrix& diffMatrix
, | 148 LightingFP(GrTexture* diffuse, const SkMatrix& diffMatrix, const GrTexturePa
rams& diffParams, |
143 const SkMatrix& normMatrix, const GrTextureParams& diffParams, | 149 sk_sp<SkLights> lights, sk_sp<GrFragmentProcessor> normalFP) |
144 const GrTextureParams& normParams, sk_sp<SkLights> lights, | |
145 const SkVector& invNormRotation) | |
146 : fDiffDeviceTransform(kLocal_GrCoordSet, diffMatrix, diffuse, diffParam
s.filterMode()) | 150 : fDiffDeviceTransform(kLocal_GrCoordSet, diffMatrix, diffuse, diffParam
s.filterMode()) |
147 , fNormDeviceTransform(kLocal_GrCoordSet, normMatrix, normal, normParams
.filterMode()) | 151 , fDiffuseTextureAccess(diffuse, diffParams) { |
148 , fDiffuseTextureAccess(diffuse, diffParams) | |
149 , fNormalTextureAccess(normal, normParams) | |
150 , fInvNormRotation(invNormRotation) { | |
151 this->addCoordTransform(&fDiffDeviceTransform); | 152 this->addCoordTransform(&fDiffDeviceTransform); |
152 this->addCoordTransform(&fNormDeviceTransform); | |
153 this->addTextureAccess(&fDiffuseTextureAccess); | 153 this->addTextureAccess(&fDiffuseTextureAccess); |
154 this->addTextureAccess(&fNormalTextureAccess); | |
155 | 154 |
156 // fuse all ambient lights into a single one | 155 // fuse all ambient lights into a single one |
157 fAmbientColor.set(0.0f, 0.0f, 0.0f); | 156 fAmbientColor.set(0.0f, 0.0f, 0.0f); |
158 for (int i = 0; i < lights->numLights(); ++i) { | 157 for (int i = 0; i < lights->numLights(); ++i) { |
159 if (SkLights::Light::kAmbient_LightType == lights->light(i).type())
{ | 158 if (SkLights::Light::kAmbient_LightType == lights->light(i).type())
{ |
160 fAmbientColor += lights->light(i).color(); | 159 fAmbientColor += lights->light(i).color(); |
161 } else { | 160 } else { |
162 // TODO: handle more than one of these | 161 // TODO: handle more than one of these |
163 fLightColor = lights->light(i).color(); | 162 fLightColor = lights->light(i).color(); |
164 fLightDir = lights->light(i).dir(); | 163 fLightDir = lights->light(i).dir(); |
165 } | 164 } |
166 } | 165 } |
167 | 166 |
| 167 this->registerChildProcessor(std::move(normalFP)); |
168 this->initClassID<LightingFP>(); | 168 this->initClassID<LightingFP>(); |
169 } | 169 } |
170 | 170 |
171 class LightingGLFP : public GrGLSLFragmentProcessor { | 171 class GLSLLightingFP : public GrGLSLFragmentProcessor { |
172 public: | 172 public: |
173 LightingGLFP() { | 173 GLSLLightingFP() { |
174 fLightDir.fX = 10000.0f; | 174 fLightDir.fX = 10000.0f; |
175 fLightColor.fX = 0.0f; | 175 fLightColor.fX = 0.0f; |
176 fAmbientColor.fX = 0.0f; | 176 fAmbientColor.fX = 0.0f; |
177 fInvNormRotation.set(0.0f, 0.0f); | |
178 } | 177 } |
179 | 178 |
180 void emitCode(EmitArgs& args) override { | 179 void emitCode(EmitArgs& args) override { |
181 | 180 |
182 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder; | 181 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder; |
183 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; | 182 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; |
184 | 183 |
185 // add uniforms | 184 // add uniforms |
186 const char* lightDirUniName = nullptr; | 185 const char* lightDirUniName = nullptr; |
187 fLightDirUni = uniformHandler->addUniform(kFragment_GrShaderFlag, | 186 fLightDirUni = uniformHandler->addUniform(kFragment_GrShaderFlag, |
188 kVec3f_GrSLType, kDefault_
GrSLPrecision, | 187 kVec3f_GrSLType, kDefault_
GrSLPrecision, |
189 "LightDir", &lightDirUniNa
me); | 188 "LightDir", &lightDirUniNa
me); |
190 | 189 |
191 const char* lightColorUniName = nullptr; | 190 const char* lightColorUniName = nullptr; |
192 fLightColorUni = uniformHandler->addUniform(kFragment_GrShaderFlag, | 191 fLightColorUni = uniformHandler->addUniform(kFragment_GrShaderFlag, |
193 kVec3f_GrSLType, kDefaul
t_GrSLPrecision, | 192 kVec3f_GrSLType, kDefaul
t_GrSLPrecision, |
194 "LightColor", &lightColo
rUniName); | 193 "LightColor", &lightColo
rUniName); |
195 | 194 |
196 const char* ambientColorUniName = nullptr; | 195 const char* ambientColorUniName = nullptr; |
197 fAmbientColorUni = uniformHandler->addUniform(kFragment_GrShaderFlag
, | 196 fAmbientColorUni = uniformHandler->addUniform(kFragment_GrShaderFlag
, |
198 kVec3f_GrSLType, kDefa
ult_GrSLPrecision, | 197 kVec3f_GrSLType, kDefa
ult_GrSLPrecision, |
199 "AmbientColor", &ambie
ntColorUniName); | 198 "AmbientColor", &ambie
ntColorUniName); |
200 | 199 |
201 const char* xformUniName = nullptr; | |
202 fXformUni = uniformHandler->addUniform(kFragment_GrShaderFlag, | |
203 kVec2f_GrSLType, kDefault_GrS
LPrecision, | |
204 "Xform", &xformUniName); | |
205 | |
206 fragBuilder->codeAppend("vec4 diffuseColor = "); | 200 fragBuilder->codeAppend("vec4 diffuseColor = "); |
207 fragBuilder->appendTextureLookupAndModulate(args.fInputColor, args.f
TexSamplers[0], | 201 fragBuilder->appendTextureLookupAndModulate(args.fInputColor, args.f
TexSamplers[0], |
208 args.fCoords[0].c_str(), | 202 args.fCoords[0].c_str(), |
209 args.fCoords[0].getType()); | 203 args.fCoords[0].getType()); |
210 fragBuilder->codeAppend(";"); | 204 fragBuilder->codeAppend(";"); |
211 | 205 |
212 fragBuilder->codeAppend("vec4 normalColor = "); | 206 SkString dstNormalName("dstNormal"); |
213 fragBuilder->appendTextureLookup(args.fTexSamplers[1], | 207 this->emitChild(0, nullptr, &dstNormalName, args); |
214 args.fCoords[1].c_str(), | |
215 args.fCoords[1].getType()); | |
216 fragBuilder->codeAppend(";"); | |
217 | 208 |
218 fragBuilder->codeAppend("vec3 normal = normalColor.rgb - vec3(0.5);"
); | 209 fragBuilder->codeAppendf("vec3 normal = %s.xyz;", dstNormalName.c_st
r()); |
219 | |
220 fragBuilder->codeAppendf( | |
221 "mat3 m = mat3(%s.x, -%s.y, 0.0, %s.y, %s.x, 0.
0, 0.0, 0.0, 1.0);", | |
222 xformUniName, xformUniName, xformUniName, xform
UniName); | |
223 | |
224 // TODO: inverse map the light direction vectors in the vertex shade
r rather than | |
225 // transforming all the normals here! | |
226 fragBuilder->codeAppend("normal = normalize(m*normal);"); | |
227 | |
228 fragBuilder->codeAppendf("float NdotL = clamp(dot(normal, %s), 0.0,
1.0);", | 210 fragBuilder->codeAppendf("float NdotL = clamp(dot(normal, %s), 0.0,
1.0);", |
229 lightDirUniName); | 211 lightDirUniName); |
230 // diffuse light | 212 // diffuse light |
231 fragBuilder->codeAppendf("vec3 result = %s*diffuseColor.rgb*NdotL;",
lightColorUniName); | 213 fragBuilder->codeAppendf("vec3 result = %s*diffuseColor.rgb*NdotL;",
lightColorUniName); |
232 // ambient light | 214 // ambient light |
233 fragBuilder->codeAppendf("result += %s;", ambientColorUniName); | 215 fragBuilder->codeAppendf("result += %s;", ambientColorUniName); |
234 fragBuilder->codeAppendf("%s = vec4(result.rgb, diffuseColor.a);", a
rgs.fOutputColor); | 216 fragBuilder->codeAppendf("%s = vec4(result.rgb, diffuseColor.a);", a
rgs.fOutputColor); |
235 } | 217 } |
236 | 218 |
237 static void GenKey(const GrProcessor& proc, const GrGLSLCaps&, | 219 static void GenKey(const GrProcessor& proc, const GrGLSLCaps&, |
(...skipping 17 matching lines...) Expand all Loading... |
255 if (lightColor != fLightColor) { | 237 if (lightColor != fLightColor) { |
256 pdman.set3fv(fLightColorUni, 1, &lightColor.fX); | 238 pdman.set3fv(fLightColorUni, 1, &lightColor.fX); |
257 fLightColor = lightColor; | 239 fLightColor = lightColor; |
258 } | 240 } |
259 | 241 |
260 const SkColor3f& ambientColor = lightingFP.ambientColor(); | 242 const SkColor3f& ambientColor = lightingFP.ambientColor(); |
261 if (ambientColor != fAmbientColor) { | 243 if (ambientColor != fAmbientColor) { |
262 pdman.set3fv(fAmbientColorUni, 1, &ambientColor.fX); | 244 pdman.set3fv(fAmbientColorUni, 1, &ambientColor.fX); |
263 fAmbientColor = ambientColor; | 245 fAmbientColor = ambientColor; |
264 } | 246 } |
265 | |
266 const SkVector& invNormRotation = lightingFP.invNormRotation(); | |
267 if (invNormRotation != fInvNormRotation) { | |
268 pdman.set2fv(fXformUni, 1, &invNormRotation.fX); | |
269 fInvNormRotation = invNormRotation; | |
270 } | |
271 } | 247 } |
272 | 248 |
273 private: | 249 private: |
274 SkVector3 fLightDir; | 250 SkVector3 fLightDir; |
275 GrGLSLProgramDataManager::UniformHandle fLightDirUni; | 251 GrGLSLProgramDataManager::UniformHandle fLightDirUni; |
276 | 252 |
277 SkColor3f fLightColor; | 253 SkColor3f fLightColor; |
278 GrGLSLProgramDataManager::UniformHandle fLightColorUni; | 254 GrGLSLProgramDataManager::UniformHandle fLightColorUni; |
279 | 255 |
280 SkColor3f fAmbientColor; | 256 SkColor3f fAmbientColor; |
281 GrGLSLProgramDataManager::UniformHandle fAmbientColorUni; | 257 GrGLSLProgramDataManager::UniformHandle fAmbientColorUni; |
282 | |
283 SkVector fInvNormRotation; | |
284 GrGLSLProgramDataManager::UniformHandle fXformUni; | |
285 }; | 258 }; |
286 | 259 |
287 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b)
const override { | 260 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b)
const override { |
288 LightingGLFP::GenKey(*this, caps, b); | 261 GLSLLightingFP::GenKey(*this, caps, b); |
289 } | 262 } |
290 | 263 |
291 const char* name() const override { return "LightingFP"; } | 264 const char* name() const override { return "LightingFP"; } |
292 | 265 |
293 void onComputeInvariantOutput(GrInvariantOutput* inout) const override { | 266 void onComputeInvariantOutput(GrInvariantOutput* inout) const override { |
294 inout->mulByUnknownFourComponents(); | 267 inout->mulByUnknownFourComponents(); |
295 } | 268 } |
296 | 269 |
297 const SkVector3& lightDir() const { return fLightDir; } | 270 const SkVector3& lightDir() const { return fLightDir; } |
298 const SkColor3f& lightColor() const { return fLightColor; } | 271 const SkColor3f& lightColor() const { return fLightColor; } |
299 const SkColor3f& ambientColor() const { return fAmbientColor; } | 272 const SkColor3f& ambientColor() const { return fAmbientColor; } |
300 const SkVector& invNormRotation() const { return fInvNormRotation; } | |
301 | 273 |
302 private: | 274 private: |
303 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return new
LightingGLFP; } | 275 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return new
GLSLLightingFP; } |
304 | 276 |
305 bool onIsEqual(const GrFragmentProcessor& proc) const override { | 277 bool onIsEqual(const GrFragmentProcessor& proc) const override { |
306 const LightingFP& lightingFP = proc.cast<LightingFP>(); | 278 const LightingFP& lightingFP = proc.cast<LightingFP>(); |
307 return fDiffDeviceTransform == lightingFP.fDiffDeviceTransform && | 279 return fDiffDeviceTransform == lightingFP.fDiffDeviceTransform && |
308 fNormDeviceTransform == lightingFP.fNormDeviceTransform && | |
309 fDiffuseTextureAccess == lightingFP.fDiffuseTextureAccess && | 280 fDiffuseTextureAccess == lightingFP.fDiffuseTextureAccess && |
310 fNormalTextureAccess == lightingFP.fNormalTextureAccess && | |
311 fLightDir == lightingFP.fLightDir && | 281 fLightDir == lightingFP.fLightDir && |
312 fLightColor == lightingFP.fLightColor && | 282 fLightColor == lightingFP.fLightColor && |
313 fAmbientColor == lightingFP.fAmbientColor && | 283 fAmbientColor == lightingFP.fAmbientColor; |
314 fInvNormRotation == lightingFP.fInvNormRotation; | |
315 } | 284 } |
316 | 285 |
317 GrCoordTransform fDiffDeviceTransform; | 286 GrCoordTransform fDiffDeviceTransform; |
318 GrCoordTransform fNormDeviceTransform; | |
319 GrTextureAccess fDiffuseTextureAccess; | 287 GrTextureAccess fDiffuseTextureAccess; |
320 GrTextureAccess fNormalTextureAccess; | |
321 SkVector3 fLightDir; | 288 SkVector3 fLightDir; |
322 SkColor3f fLightColor; | 289 SkColor3f fLightColor; |
323 SkColor3f fAmbientColor; | 290 SkColor3f fAmbientColor; |
324 | |
325 SkVector fInvNormRotation; | |
326 }; | 291 }; |
327 | 292 |
328 //////////////////////////////////////////////////////////////////////////// | 293 //////////////////////////////////////////////////////////////////////////// |
329 | 294 |
330 static bool make_mat(const SkBitmap& bm, | 295 static bool make_mat(const SkBitmap& bm, |
331 const SkMatrix& localMatrix1, | 296 const SkMatrix& localMatrix1, |
332 const SkMatrix* localMatrix2, | 297 const SkMatrix* localMatrix2, |
333 SkMatrix* result) { | 298 SkMatrix* result) { |
334 | 299 |
335 result->setIDiv(bm.width(), bm.height()); | 300 result->setIDiv(bm.width(), bm.height()); |
(...skipping 14 matching lines...) Expand all Loading... |
350 return true; | 315 return true; |
351 } | 316 } |
352 | 317 |
353 sk_sp<GrFragmentProcessor> SkLightingShaderImpl::asFragmentProcessor( | 318 sk_sp<GrFragmentProcessor> SkLightingShaderImpl::asFragmentProcessor( |
354 GrContext* context, | 319 GrContext* context, |
355 const SkMatrix& viewM, | 320 const SkMatrix& viewM, |
356 const SkMatrix* localMatrix
, | 321 const SkMatrix* localMatrix
, |
357 SkFilterQuality filterQuali
ty, | 322 SkFilterQuality filterQuali
ty, |
358 SkSourceGammaTreatment gamm
aTreatment) const { | 323 SkSourceGammaTreatment gamm
aTreatment) const { |
359 // we assume diffuse and normal maps have same width and height | 324 // we assume diffuse and normal maps have same width and height |
360 // TODO: support different sizes | 325 // TODO: support different sizes, will be addressed when diffuse maps are fa
ctored out of |
| 326 // SkLightingShader in a future CL |
361 SkASSERT(fDiffuseMap.width() == fNormalMap.width() && | 327 SkASSERT(fDiffuseMap.width() == fNormalMap.width() && |
362 fDiffuseMap.height() == fNormalMap.height()); | 328 fDiffuseMap.height() == fNormalMap.height()); |
363 SkMatrix diffM, normM; | 329 SkMatrix diffM; |
364 | 330 |
365 if (!make_mat(fDiffuseMap, this->getLocalMatrix(), localMatrix, &diffM)) { | 331 if (!make_mat(fDiffuseMap, this->getLocalMatrix(), localMatrix, &diffM)) { |
366 return nullptr; | 332 return nullptr; |
367 } | 333 } |
368 | 334 |
369 if (!make_mat(fNormalMap, fNormLocalMatrix, localMatrix, &normM)) { | |
370 return nullptr; | |
371 } | |
372 | |
373 bool doBicubic; | 335 bool doBicubic; |
374 GrTextureParams::FilterMode diffFilterMode = GrSkFilterQualityToGrFilterMode
( | 336 GrTextureParams::FilterMode diffFilterMode = GrSkFilterQualityToGrFilterMode
( |
375 SkTMin(filterQuality, kMedium_SkFilterQu
ality), | 337 SkTMin(filterQuality, kMediu
m_SkFilterQuality), |
376 viewM, | 338 viewM, |
377 this->getLocalMatrix(), | 339 this->getLocalMatrix(), |
378 &doBicubic); | 340 &doBicubic); |
379 SkASSERT(!doBicubic); | |
380 | |
381 GrTextureParams::FilterMode normFilterMode = GrSkFilterQualityToGrFilterMode
( | |
382 SkTMin(filterQuality, kMedium_SkFilterQu
ality), | |
383 viewM, | |
384 fNormLocalMatrix, | |
385 &doBicubic); | |
386 SkASSERT(!doBicubic); | 341 SkASSERT(!doBicubic); |
387 | 342 |
388 // TODO: support other tile modes | 343 // TODO: support other tile modes |
389 GrTextureParams diffParams(kClamp_TileMode, diffFilterMode); | 344 GrTextureParams diffParams(kClamp_TileMode, diffFilterMode); |
390 SkAutoTUnref<GrTexture> diffuseTexture(GrRefCachedBitmapTexture(context, | 345 SkAutoTUnref<GrTexture> diffuseTexture(GrRefCachedBitmapTexture(context, fDi
ffuseMap, |
391 fDiffuseMap,
diffParams, | 346 diffParams,
gammaTreatment)); |
392 gammaTreatme
nt)); | |
393 if (!diffuseTexture) { | 347 if (!diffuseTexture) { |
394 SkErrorInternals::SetError(kInternalError_SkError, "Couldn't convert bit
map to texture."); | 348 SkErrorInternals::SetError(kInternalError_SkError, "Couldn't convert bit
map to texture."); |
395 return nullptr; | 349 return nullptr; |
396 } | 350 } |
397 | 351 |
398 GrTextureParams normParams(kClamp_TileMode, normFilterMode); | 352 sk_sp<GrFragmentProcessor> normalFP( |
399 SkAutoTUnref<GrTexture> normalTexture(GrRefCachedBitmapTexture(context, | 353 fNormalSource->asFragmentProcessor(context, viewM, localMatrix, filt
erQuality, |
400 fNormalMap, n
ormParams, | 354 gammaTreatment)); |
401 gammaTreatmen
t)); | 355 sk_sp<GrFragmentProcessor> inner ( |
402 if (!normalTexture) { | 356 new LightingFP(diffuseTexture, diffM, diffParams, fLights, std::move
(normalFP))); |
403 SkErrorInternals::SetError(kInternalError_SkError, "Couldn't convert bit
map to texture."); | |
404 return nullptr; | |
405 } | |
406 | 357 |
407 sk_sp<GrFragmentProcessor> inner ( | |
408 new LightingFP(diffuseTexture, normalTexture, diffM, normM, diffParams,
normParams, fLights, | |
409 fInvNormRotation)); | |
410 return GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner)); | 358 return GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner)); |
411 } | 359 } |
412 | 360 |
413 #endif | 361 #endif |
414 | 362 |
415 //////////////////////////////////////////////////////////////////////////// | 363 //////////////////////////////////////////////////////////////////////////// |
416 | 364 |
417 bool SkLightingShaderImpl::isOpaque() const { | 365 bool SkLightingShaderImpl::isOpaque() const { |
418 return fDiffuseMap.isOpaque(); | 366 return fDiffuseMap.isOpaque(); |
419 } | 367 } |
420 | 368 |
421 SkLightingShaderImpl::LightingShaderContext::LightingShaderContext(const SkLight
ingShaderImpl& shader, | 369 SkLightingShaderImpl::LightingShaderContext::LightingShaderContext( |
422 const Context
Rec& rec, | 370 const SkLighting
ShaderImpl& shader, |
423 SkBitmapProcS
tate* diffuseState, | 371 const ContextRec
& rec, |
424 SkBitmapProcS
tate* normalState) | 372 SkBitmapProcStat
e* diffuseState, |
| 373 SkBitmapProcStat
e* normalState) |
425 : INHERITED(shader, rec) | 374 : INHERITED(shader, rec) |
426 , fDiffuseState(diffuseState) | 375 , fDiffuseState(diffuseState) |
427 , fNormalState(normalState) | 376 , fNormalState(normalState) { |
428 { | |
429 const SkPixmap& pixmap = fDiffuseState->fPixmap; | 377 const SkPixmap& pixmap = fDiffuseState->fPixmap; |
430 bool isOpaque = pixmap.isOpaque(); | 378 bool isOpaque = pixmap.isOpaque(); |
431 | 379 |
432 // update fFlags | 380 // update fFlags |
433 uint32_t flags = 0; | 381 uint32_t flags = 0; |
434 if (isOpaque && (255 == this->getPaintAlpha())) { | 382 if (isOpaque && (255 == this->getPaintAlpha())) { |
435 flags |= kOpaqueAlpha_Flag; | 383 flags |= kOpaqueAlpha_Flag; |
436 } | 384 } |
437 | 385 |
438 fFlags = flags; | 386 fFlags = flags; |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
608 } | 556 } |
609 } | 557 } |
610 | 558 |
611 sk_sp<SkLights> lights(builder.finish()); | 559 sk_sp<SkLights> lights(builder.finish()); |
612 | 560 |
613 SkVector invNormRotation = {1,0}; | 561 SkVector invNormRotation = {1,0}; |
614 if (!buf.isVersionLT(SkReadBuffer::kLightingShaderWritesInvNormRotation)) { | 562 if (!buf.isVersionLT(SkReadBuffer::kLightingShaderWritesInvNormRotation)) { |
615 invNormRotation = buf.readPoint(); | 563 invNormRotation = buf.readPoint(); |
616 } | 564 } |
617 | 565 |
| 566 sk_sp<SkLightingShader::NormalSource> normalSource( |
| 567 buf.readFlattenable<SkLightingShader::NormalSource>()); |
| 568 |
618 return sk_make_sp<SkLightingShaderImpl>(diffuse, normal, std::move(lights),
invNormRotation, | 569 return sk_make_sp<SkLightingShaderImpl>(diffuse, normal, std::move(lights),
invNormRotation, |
619 &diffLocalM, &normLocalM); | 570 &diffLocalM, &normLocalM, std::move(
normalSource)); |
620 } | 571 } |
621 | 572 |
622 void SkLightingShaderImpl::flatten(SkWriteBuffer& buf) const { | 573 void SkLightingShaderImpl::flatten(SkWriteBuffer& buf) const { |
623 this->INHERITED::flatten(buf); | 574 this->INHERITED::flatten(buf); |
624 | 575 |
625 bool hasNormLocalM = !fNormLocalMatrix.isIdentity(); | 576 bool hasNormLocalM = !fNormLocalMatrix.isIdentity(); |
626 buf.writeBool(hasNormLocalM); | 577 buf.writeBool(hasNormLocalM); |
627 if (hasNormLocalM) { | 578 if (hasNormLocalM) { |
628 buf.writeMatrix(fNormLocalMatrix); | 579 buf.writeMatrix(fNormLocalMatrix); |
629 } | 580 } |
630 | 581 |
631 buf.writeBitmap(fDiffuseMap); | 582 buf.writeBitmap(fDiffuseMap); |
632 buf.writeBitmap(fNormalMap); | 583 buf.writeBitmap(fNormalMap); |
633 | 584 |
634 buf.writeInt(fLights->numLights()); | 585 buf.writeInt(fLights->numLights()); |
635 for (int l = 0; l < fLights->numLights(); ++l) { | 586 for (int l = 0; l < fLights->numLights(); ++l) { |
636 const SkLights::Light& light = fLights->light(l); | 587 const SkLights::Light& light = fLights->light(l); |
637 | 588 |
638 bool isAmbient = SkLights::Light::kAmbient_LightType == light.type(); | 589 bool isAmbient = SkLights::Light::kAmbient_LightType == light.type(); |
639 | 590 |
640 buf.writeBool(isAmbient); | 591 buf.writeBool(isAmbient); |
641 buf.writeScalarArray(&light.color().fX, 3); | 592 buf.writeScalarArray(&light.color().fX, 3); |
642 if (!isAmbient) { | 593 if (!isAmbient) { |
643 buf.writeScalarArray(&light.dir().fX, 3); | 594 buf.writeScalarArray(&light.dir().fX, 3); |
644 } | 595 } |
645 } | 596 } |
646 buf.writePoint(fInvNormRotation); | 597 buf.writePoint(fInvNormRotation); |
| 598 |
| 599 buf.writeFlattenable(fNormalSource.get()); |
647 } | 600 } |
648 | 601 |
649 bool SkLightingShaderImpl::computeNormTotalInverse(const ContextRec& rec, | 602 bool SkLightingShaderImpl::computeNormTotalInverse(const ContextRec& rec, |
650 SkMatrix* normTotalInverse) c
onst { | 603 SkMatrix* normTotalInverse) c
onst { |
651 SkMatrix total; | 604 SkMatrix total; |
652 total.setConcat(*rec.fMatrix, fNormLocalMatrix); | 605 total.setConcat(*rec.fMatrix, fNormLocalMatrix); |
653 | 606 |
654 const SkMatrix* m = &total; | 607 const SkMatrix* m = &total; |
655 if (rec.fLocalMatrix) { | 608 if (rec.fLocalMatrix) { |
656 total.setConcat(*m, *rec.fLocalMatrix); | 609 total.setConcat(*m, *rec.fLocalMatrix); |
(...skipping 21 matching lines...) Expand all Loading... |
678 void* diffuseStateStorage = (char*)storage + sizeof(LightingShaderContext); | 631 void* diffuseStateStorage = (char*)storage + sizeof(LightingShaderContext); |
679 SkBitmapProcState* diffuseState = new (diffuseStateStorage) SkBitmapProcStat
e(fDiffuseMap, | 632 SkBitmapProcState* diffuseState = new (diffuseStateStorage) SkBitmapProcStat
e(fDiffuseMap, |
680 SkShader::kClamp_TileMode, SkShade
r::kClamp_TileMode, | 633 SkShader::kClamp_TileMode, SkShade
r::kClamp_TileMode, |
681 SkMipMap::De
duceTreatment(rec)); | 634 SkMipMap::De
duceTreatment(rec)); |
682 SkASSERT(diffuseState); | 635 SkASSERT(diffuseState); |
683 if (!diffuseState->setup(diffTotalInv, *rec.fPaint)) { | 636 if (!diffuseState->setup(diffTotalInv, *rec.fPaint)) { |
684 diffuseState->~SkBitmapProcState(); | 637 diffuseState->~SkBitmapProcState(); |
685 return nullptr; | 638 return nullptr; |
686 } | 639 } |
687 | 640 |
688 void* normalStateStorage = (char*)storage + sizeof(LightingShaderContext) +
sizeof(SkBitmapProcState); | 641 void* normalStateStorage = (char*)storage + |
| 642 sizeof(LightingShaderContext) + |
| 643 sizeof(SkBitmapProcState); |
689 SkBitmapProcState* normalState = new (normalStateStorage) SkBitmapProcState(
fNormalMap, | 644 SkBitmapProcState* normalState = new (normalStateStorage) SkBitmapProcState(
fNormalMap, |
690 SkShader::kClamp_TileMode, SkShader:
:kClamp_TileMode, | 645 SkShader::kClamp_TileMode, SkShader:
:kClamp_TileMode, |
691 SkMipMap::De
duceTreatment(rec)); | 646 SkMipMap::De
duceTreatment(rec)); |
692 SkASSERT(normalState); | 647 SkASSERT(normalState); |
693 if (!normalState->setup(normTotalInv, *rec.fPaint)) { | 648 if (!normalState->setup(normTotalInv, *rec.fPaint)) { |
694 diffuseState->~SkBitmapProcState(); | 649 diffuseState->~SkBitmapProcState(); |
695 normalState->~SkBitmapProcState(); | 650 normalState->~SkBitmapProcState(); |
696 return nullptr; | 651 return nullptr; |
697 } | 652 } |
698 | 653 |
699 return new (storage) LightingShaderContext(*this, rec, diffuseState, normalS
tate); | 654 return new (storage) LightingShaderContext(*this, rec, diffuseState, normalS
tate); |
700 } | 655 } |
701 | 656 |
702 /////////////////////////////////////////////////////////////////////////////// | 657 /////////////////////////////////////////////////////////////////////////////// |
703 | 658 |
704 static bool bitmap_is_too_big(const SkBitmap& bm) { | |
705 // SkBitmapProcShader stores bitmap coordinates in a 16bit buffer, as it | |
706 // communicates between its matrix-proc and its sampler-proc. Until we can | |
707 // widen that, we have to reject bitmaps that are larger. | |
708 // | |
709 static const int kMaxSize = 65535; | |
710 | |
711 return bm.width() > kMaxSize || bm.height() > kMaxSize; | |
712 } | |
713 | |
714 sk_sp<SkShader> SkLightingShader::Make(const SkBitmap& diffuse, const SkBitmap&
normal, | 659 sk_sp<SkShader> SkLightingShader::Make(const SkBitmap& diffuse, const SkBitmap&
normal, |
715 sk_sp<SkLights> lights, | 660 sk_sp<SkLights> lights, |
716 const SkVector& invNormRotation, | 661 const SkVector& invNormRotation, |
717 const SkMatrix* diffLocalM, const SkMatri
x* normLocalM) { | 662 const SkMatrix* diffLocalM, const SkMatri
x* normLocalM) { |
718 if (diffuse.isNull() || bitmap_is_too_big(diffuse) || | 663 if (diffuse.isNull() || SkBitmapProcShader::BitmapIsTooBig(diffuse) || |
719 normal.isNull() || bitmap_is_too_big(normal) || | 664 normal.isNull() || SkBitmapProcShader::BitmapIsTooBig(normal) || |
720 diffuse.width() != normal.width() || | 665 diffuse.width() != normal.width() || |
721 diffuse.height() != normal.height()) { | 666 diffuse.height() != normal.height()) { |
722 return nullptr; | 667 return nullptr; |
723 } | 668 } |
724 | |
725 SkASSERT(SkScalarNearlyEqual(invNormRotation.lengthSqd(), SK_Scalar1)); | 669 SkASSERT(SkScalarNearlyEqual(invNormRotation.lengthSqd(), SK_Scalar1)); |
726 | 670 |
| 671 sk_sp<SkLightingShader::NormalSource> normalSource = |
| 672 SkLightingShader::NormalSource::MakeMap(normal, invNormRotation, nor
mLocalM); |
| 673 |
727 return sk_make_sp<SkLightingShaderImpl>(diffuse, normal, std::move(lights), | 674 return sk_make_sp<SkLightingShaderImpl>(diffuse, normal, std::move(lights), |
728 invNormRotation, diffLocalM, normLoc
alM); | 675 invNormRotation, diffLocalM, normLocalM, std::move(normalSource)); |
729 } | 676 } |
730 | 677 |
731 /////////////////////////////////////////////////////////////////////////////// | 678 /////////////////////////////////////////////////////////////////////////////// |
732 | 679 |
733 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkLightingShader) | 680 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkLightingShader) |
734 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLightingShaderImpl) | 681 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLightingShaderImpl) |
735 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END | 682 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END |
736 | 683 |
737 /////////////////////////////////////////////////////////////////////////////// | 684 /////////////////////////////////////////////////////////////////////////////// |
OLD | NEW |