Chromium Code Reviews| 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 #include "SampleCode.h" | |
| 9 #include "Resources.h" | |
| 10 | 8 |
| 11 #include "SkCanvas.h" | 9 #include "SkBitmapProcState.h" |
| 10 #include "SkColor.h" | |
| 11 #include "SkEmptyShader.h" | |
| 12 #include "SkErrorInternals.h" | 12 #include "SkErrorInternals.h" |
| 13 #include "SkGr.h" | 13 #include "SkLightingShader.h" |
| 14 #include "SkPoint3.h" | 14 #include "SkMathPriv.h" |
| 15 #include "SkReadBuffer.h" | 15 #include "SkReadBuffer.h" |
| 16 #include "SkShader.h" | |
| 17 #include "SkWriteBuffer.h" | 16 #include "SkWriteBuffer.h" |
| 18 #include "GrFragmentProcessor.h" | |
| 19 #include "GrCoordTransform.h" | |
| 20 #include "gl/GrGLProcessor.h" | |
| 21 #include "gl/builders/GrGLProgramBuilder.h" | |
| 22 | |
| 23 /////////////////////////////////////////////////////////////////////////////// | |
| 24 | |
| 25 class LightingShader : public SkShader { | |
| 26 public: | |
| 27 struct Light { | |
| 28 SkVector3 fDirection; | |
| 29 SkColor fColor; // assumed to be linear color | |
| 30 }; | |
| 31 | |
| 32 LightingShader(const SkBitmap& diffuse, const SkBitmap& normal, const Light& light, | |
| 33 const SkColor ambient) | |
| 34 : fDiffuseMap(diffuse) | |
| 35 , fNormalMap(normal) | |
| 36 , fLight(light) | |
| 37 , fAmbientColor(ambient) {} | |
| 38 | |
| 39 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(LightingShader); | |
| 40 | |
| 41 void flatten(SkWriteBuffer& buf) const override { | |
| 42 buf.writeBitmap(fDiffuseMap); | |
| 43 buf.writeBitmap(fNormalMap); | |
| 44 buf.writeScalarArray(&fLight.fDirection.fX, 3); | |
| 45 buf.writeColor(fLight.fColor); | |
| 46 buf.writeColor(fAmbientColor); | |
| 47 } | |
| 48 | |
| 49 bool asFragmentProcessor(GrContext*, const SkPaint& paint, const SkMatrix& v iewM, | |
| 50 const SkMatrix* localMatrix, GrColor* color, | |
| 51 GrProcessorDataManager*, GrFragmentProcessor** fp) const override; | |
| 52 | |
| 53 SkShader::BitmapType asABitmap(SkBitmap* bitmap, SkMatrix* matrix, | |
| 54 SkShader::TileMode* xy) const override { | |
| 55 if (bitmap) { | |
| 56 *bitmap = fDiffuseMap; | |
| 57 } | |
| 58 if (matrix) { | |
| 59 matrix->reset(); | |
| 60 } | |
| 61 if (xy) { | |
| 62 xy[0] = kClamp_TileMode; | |
| 63 xy[1] = kClamp_TileMode; | |
| 64 } | |
| 65 return kDefault_BitmapType; | |
| 66 } | |
| 67 | |
| 68 #ifndef SK_IGNORE_TO_STRING | |
| 69 void toString(SkString* str) const override { | |
| 70 str->appendf("LightingShader: ()"); | |
| 71 } | |
| 72 #endif | |
| 73 | |
| 74 void setLight(const Light& light) { fLight = light; } | |
| 75 | |
| 76 private: | |
| 77 SkBitmap fDiffuseMap; | |
| 78 SkBitmap fNormalMap; | |
| 79 Light fLight; | |
| 80 SkColor fAmbientColor; | |
| 81 }; | |
| 82 | |
| 83 SkFlattenable* LightingShader::CreateProc(SkReadBuffer& buf) { | |
| 84 SkBitmap diffuse; | |
| 85 if (!buf.readBitmap(&diffuse)) { | |
| 86 return NULL; | |
| 87 } | |
| 88 diffuse.setImmutable(); | |
| 89 | |
| 90 SkBitmap normal; | |
| 91 if (!buf.readBitmap(&normal)) { | |
| 92 return NULL; | |
| 93 } | |
| 94 normal.setImmutable(); | |
| 95 | |
| 96 Light light; | |
| 97 if (!buf.readScalarArray(&light.fDirection.fX, 3)) { | |
| 98 return NULL; | |
| 99 } | |
| 100 light.fColor = buf.readColor(); | |
| 101 | |
| 102 SkColor ambient = buf.readColor(); | |
| 103 | |
| 104 return SkNEW_ARGS(LightingShader, (diffuse, normal, light, ambient)); | |
| 105 } | |
| 106 | 17 |
| 107 //////////////////////////////////////////////////////////////////////////// | 18 //////////////////////////////////////////////////////////////////////////// |
| 108 | 19 |
| 20 #if SK_SUPPORT_GPU | |
| 21 | |
| 22 #include "GrCoordTransform.h" | |
| 23 #include "GrFragmentProcessor.h" | |
| 24 #include "GrTextureAccess.h" | |
| 25 #include "gl/GrGLProcessor.h" | |
| 26 #include "gl/builders/GrGLProgramBuilder.h" | |
| 27 #include "SkGr.h" | |
| 28 | |
| 109 class LightingFP : public GrFragmentProcessor { | 29 class LightingFP : public GrFragmentProcessor { |
| 110 public: | 30 public: |
| 111 LightingFP(GrTexture* diffuse, GrTexture* normal, const SkMatrix& matrix, | 31 LightingFP(GrTexture* diffuse, GrTexture* normal, const SkMatrix& matrix, |
| 112 SkVector3 lightDir, GrColor lightColor, GrColor ambientColor) | 32 SkVector3 lightDir, GrColor lightColor, GrColor ambientColor) |
| 113 : fDeviceTransform(kDevice_GrCoordSet, matrix) | 33 : fDeviceTransform(kDevice_GrCoordSet, matrix) |
| 114 , fDiffuseTextureAccess(diffuse) | 34 , fDiffuseTextureAccess(diffuse) |
| 115 , fNormalTextureAccess(normal) | 35 , fNormalTextureAccess(normal) |
| 116 , fLightDir(lightDir) | 36 , fLightDir(lightDir) |
| 117 , fLightColor(lightColor) | 37 , fLightColor(lightColor) |
| 118 , fAmbientColor(ambientColor) { | 38 , fAmbientColor(ambientColor) { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 156 | 76 |
| 157 fpb->codeAppend("vec4 diffuseColor = "); | 77 fpb->codeAppend("vec4 diffuseColor = "); |
| 158 fpb->appendTextureLookupAndModulate(inputColor, samplers[0], | 78 fpb->appendTextureLookupAndModulate(inputColor, samplers[0], |
| 159 coords[0].c_str(), coords[0].get Type()); | 79 coords[0].c_str(), coords[0].get Type()); |
| 160 fpb->codeAppend(";"); | 80 fpb->codeAppend(";"); |
| 161 | 81 |
| 162 fpb->codeAppend("vec4 normalColor = "); | 82 fpb->codeAppend("vec4 normalColor = "); |
| 163 fpb->appendTextureLookup(samplers[1], coords[0].c_str(), coords[0].g etType()); | 83 fpb->appendTextureLookup(samplers[1], coords[0].c_str(), coords[0].g etType()); |
| 164 fpb->codeAppend(";"); | 84 fpb->codeAppend(";"); |
| 165 | 85 |
| 166 fpb->codeAppend("vec3 normal = normalize(2.0*(normalColor.rgb - vec3 (0.5)));"); | 86 fpb->codeAppend("vec3 normal = normalize(normalColor.rgb - vec3(0.5) );"); |
| 167 fpb->codeAppendf("vec3 lightDir = normalize(%s);", lightDirUniName); | 87 fpb->codeAppendf("vec3 lightDir = normalize(%s);", lightDirUniName); |
|
jvanverth1
2015/07/23 17:40:14
From external discussion, and for a future change:
| |
| 168 fpb->codeAppend("float NdotL = dot(normal, lightDir);"); | 88 fpb->codeAppend("float NdotL = dot(normal, lightDir);"); |
| 169 // diffuse light | 89 // diffuse light |
| 170 fpb->codeAppendf("vec3 result = %s.rgb*diffuseColor.rgb*NdotL;", lig htColorUniName); | 90 fpb->codeAppendf("vec3 result = %s.rgb*diffuseColor.rgb*NdotL;", lig htColorUniName); |
| 171 // ambient light | 91 // ambient light |
| 172 fpb->codeAppendf("result += %s.rgb;", ambientColorUniName); | 92 fpb->codeAppendf("result += %s.rgb;", ambientColorUniName); |
| 173 fpb->codeAppendf("%s = vec4(result.rgb, diffuseColor.a);", outputCol or); | 93 fpb->codeAppendf("%s = vec4(result.rgb, diffuseColor.a);", outputCol or); |
| 174 } | 94 } |
| 175 | 95 |
| 176 void setData(const GrGLProgramDataManager& pdman, const GrProcessor& pro c) override { | 96 void setData(const GrGLProgramDataManager& pdman, const GrProcessor& pro c) override { |
| 177 const LightingFP& lightingFP = proc.cast<LightingFP>(); | 97 const LightingFP& lightingFP = proc.cast<LightingFP>(); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 245 } | 165 } |
| 246 | 166 |
| 247 GrCoordTransform fDeviceTransform; | 167 GrCoordTransform fDeviceTransform; |
| 248 GrTextureAccess fDiffuseTextureAccess; | 168 GrTextureAccess fDiffuseTextureAccess; |
| 249 GrTextureAccess fNormalTextureAccess; | 169 GrTextureAccess fNormalTextureAccess; |
| 250 SkVector3 fLightDir; | 170 SkVector3 fLightDir; |
| 251 GrColor fLightColor; | 171 GrColor fLightColor; |
| 252 GrColor fAmbientColor; | 172 GrColor fAmbientColor; |
| 253 }; | 173 }; |
| 254 | 174 |
| 255 bool LightingShader::asFragmentProcessor(GrContext* context, const SkPaint& pain t, | 175 //////////////////////////////////////////////////////////////////////////// |
| 256 const SkMatrix& viewM, const SkMatrix* localMatrix, | 176 |
| 257 GrColor* color, GrProcessorDataManager* , | 177 bool SkLightingShader::asFragmentProcessor(GrContext* context, const SkPaint& pa int, |
| 258 GrFragmentProcessor** fp) const { | 178 const SkMatrix& viewM, const SkMatrix * localMatrix, |
| 179 GrColor* color, GrProcessorDataManage r*, | |
| 180 GrFragmentProcessor** fp) const { | |
| 259 // we assume diffuse and normal maps have same width and height | 181 // we assume diffuse and normal maps have same width and height |
| 260 // TODO: support different sizes | 182 // TODO: support different sizes |
| 261 SkASSERT(fDiffuseMap.width() == fNormalMap.width() && | 183 SkASSERT(fDiffuseMap.width() == fNormalMap.width() && |
| 262 fDiffuseMap.height() == fNormalMap.height()); | 184 fDiffuseMap.height() == fNormalMap.height()); |
| 263 SkMatrix matrix; | 185 SkMatrix matrix; |
| 264 matrix.setIDiv(fDiffuseMap.width(), fDiffuseMap.height()); | 186 matrix.setIDiv(fDiffuseMap.width(), fDiffuseMap.height()); |
| 265 | 187 |
| 266 SkMatrix lmInverse; | 188 SkMatrix lmInverse; |
| 267 if (!this->getLocalMatrix().invert(&lmInverse)) { | 189 if (!this->getLocalMatrix().invert(&lmInverse)) { |
| 268 return false; | 190 return false; |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 329 GrColor lightColor = GrColorPackRGBA(SkColorGetR(fLight.fColor), SkColorGetG (fLight.fColor), | 251 GrColor lightColor = GrColorPackRGBA(SkColorGetR(fLight.fColor), SkColorGetG (fLight.fColor), |
| 330 SkColorGetB(fLight.fColor), SkColorGetA (fLight.fColor)); | 252 SkColorGetB(fLight.fColor), SkColorGetA (fLight.fColor)); |
| 331 GrColor ambientColor = GrColorPackRGBA(SkColorGetR(fAmbientColor), SkColorGe tG(fAmbientColor), | 253 GrColor ambientColor = GrColorPackRGBA(SkColorGetR(fAmbientColor), SkColorGe tG(fAmbientColor), |
| 332 SkColorGetB(fAmbientColor), SkColorGe tA(fAmbientColor)); | 254 SkColorGetB(fAmbientColor), SkColorGe tA(fAmbientColor)); |
| 333 | 255 |
| 334 *fp = SkNEW_ARGS(LightingFP, (diffuseTexture, normalTexture, matrix, | 256 *fp = SkNEW_ARGS(LightingFP, (diffuseTexture, normalTexture, matrix, |
| 335 fLight.fDirection, lightColor, ambientColor)); | 257 fLight.fDirection, lightColor, ambientColor)); |
| 336 *color = GrColorPackA4(paint.getAlpha()); | 258 *color = GrColorPackA4(paint.getAlpha()); |
| 337 return true; | 259 return true; |
| 338 } | 260 } |
| 261 #else | |
| 262 | |
| 263 bool SkLightingShader::asFragmentProcessor(GrContext* context, const SkPaint& pa int, | |
| 264 const SkMatrix& viewM, const SkMatrix * localMatrix, | |
| 265 GrColor* color, GrProcessorDataManage r*, | |
| 266 GrFragmentProcessor** fp) const { | |
| 267 SkDEBUGFAIL("Should not call in GPU-less build"); | |
| 268 return false; | |
| 269 } | |
| 270 | |
| 271 #endif | |
| 339 | 272 |
| 340 //////////////////////////////////////////////////////////////////////////// | 273 //////////////////////////////////////////////////////////////////////////// |
| 341 | 274 |
| 342 class LightingView : public SampleView { | 275 bool SkLightingShader::isOpaque() const { |
| 343 public: | 276 return fDiffuseMap.isOpaque(); |
| 344 SkAutoTUnref<LightingShader> fShader; | 277 } |
| 345 SkBitmap fDiffuseBitmap; | 278 |
| 346 SkBitmap fNormalBitmap; | 279 size_t SkLightingShader::contextSize() const { |
| 347 SkScalar fLightAngle; | 280 return 2 * sizeof(SkBitmapProcState) + sizeof(LightingShaderContext); |
| 348 int fColorFactor; | 281 } |
| 349 | 282 |
| 350 LightingView() { | 283 SkLightingShader::LightingShaderContext::LightingShaderContext(const SkLightingS hader& shader, |
| 351 SkString diffusePath = GetResourcePath("brickwork-texture.jpg"); | 284 const ContextRec& rec, |
| 352 SkImageDecoder::DecodeFile(diffusePath.c_str(), &fDiffuseBitmap); | 285 SkBitmapProcState * diffuseState, |
| 353 SkString normalPath = GetResourcePath("brickwork_normal-map.jpg"); | 286 SkBitmapProcState * normalState) |
| 354 SkImageDecoder::DecodeFile(normalPath.c_str(), &fNormalBitmap); | 287 : INHERITED(shader, rec) |
| 355 | 288 , fDiffuseState(diffuseState) |
| 356 fLightAngle = 0.0f; | 289 , fNormalState(normalState) |
| 357 fColorFactor = 0; | 290 { |
| 358 | 291 const SkPixmap& pixmap = fDiffuseState->fPixmap; |
| 359 LightingShader::Light light; | 292 bool isOpaque = pixmap.isOpaque(); |
| 360 light.fColor = SkColorSetRGB(0xff, 0xff, 0xff); | 293 |
| 361 light.fDirection.fX = SkScalarSin(fLightAngle)*SkScalarSin(SK_ScalarPI*0 .25f); | 294 // update fFlags |
| 362 light.fDirection.fY = SkScalarCos(fLightAngle)*SkScalarSin(SK_ScalarPI*0 .25f); | 295 uint32_t flags = 0; |
| 363 light.fDirection.fZ = SkScalarCos(SK_ScalarPI*0.25f); | 296 if (isOpaque && (255 == this->getPaintAlpha())) { |
| 364 | 297 flags |= kOpaqueAlpha_Flag; |
| 365 SkColor ambient = SkColorSetRGB(0x1f, 0x1f, 0x1f); | 298 } |
| 366 | 299 |
| 367 fShader.reset(SkNEW_ARGS(LightingShader, (fDiffuseBitmap, fNormalBitmap, light, ambient))); | 300 fFlags = flags; |
| 368 } | 301 } |
| 369 | 302 |
| 370 virtual ~LightingView() {} | 303 SkLightingShader::LightingShaderContext::~LightingShaderContext() { |
| 371 | 304 // The bitmap proc states have been created outside of the context on memory that will be freed |
| 372 protected: | 305 // elsewhere. Call the destructors but leave the freeing of the memory to th e caller. |
| 373 // overrides from SkEventSink | 306 fDiffuseState->~SkBitmapProcState(); |
| 374 bool onQuery(SkEvent* evt) override { | 307 fNormalState->~SkBitmapProcState(); |
| 375 if (SampleCode::TitleQ(*evt)) { | 308 } |
| 376 SampleCode::TitleR(evt, "Lighting"); | 309 |
| 377 return true; | 310 static inline int light(int light, int diff, SkScalar NdotL, int ambient) { |
| 378 } | 311 int color = int(light * diff * NdotL + 255 * ambient); |
| 379 return this->INHERITED::onQuery(evt); | 312 if (color <= 0) { |
| 380 } | 313 return 0; |
| 381 | 314 } else if (color >= 255*255) { |
| 382 void onDrawContent(SkCanvas* canvas) override { | 315 return 255; |
| 383 fLightAngle += 0.015f; | 316 } else { |
| 384 fColorFactor++; | 317 return SkDiv255Round(color); |
| 385 | 318 } |
| 386 LightingShader::Light light; | 319 } |
| 387 light.fColor = SkColorSetRGB(0xff, 0xff, (fColorFactor >> 1) & 0xff); | 320 |
| 388 light.fDirection.fX = SkScalarSin(fLightAngle)*SkScalarSin(SK_ScalarPI*0 .25f); | 321 // larger is better (fewer times we have to loop), but we shouldn't |
| 389 light.fDirection.fY = SkScalarCos(fLightAngle)*SkScalarSin(SK_ScalarPI*0 .25f); | 322 // take up too much stack-space (each could here costs 16 bytes) |
| 390 light.fDirection.fZ = SkScalarCos(SK_ScalarPI*0.25f); | 323 #define TMP_COUNT 16 |
| 391 | 324 |
| 392 fShader.get()->setLight(light); | 325 void SkLightingShader::LightingShaderContext::shadeSpan(int x, int y, |
| 393 | 326 SkPMColor result[], int count) { |
| 394 SkPaint paint; | 327 const SkLightingShader& lightShader = static_cast<const SkLightingShader&>(f Shader); |
| 395 paint.setShader(fShader); | 328 |
| 396 paint.setColor(SK_ColorBLACK); | 329 SkPMColor tmpColor[TMP_COUNT], tmpColor2[TMP_COUNT]; |
| 397 | 330 SkPMColor tmpNormal[TMP_COUNT], tmpNormal2[TMP_COUNT]; |
| 398 SkRect r = SkRect::MakeWH((SkScalar)fDiffuseBitmap.width(), | 331 |
| 399 (SkScalar)fDiffuseBitmap.height()); | 332 SkBitmapProcState::MatrixProc diffMProc = fDiffuseState->getMatrixProc(); |
| 400 canvas->drawRect(r, paint); | 333 SkBitmapProcState::SampleProc32 diffSProc = fDiffuseState->getSampleProc32() ; |
| 401 | 334 |
| 402 // so we're constantly updating | 335 SkBitmapProcState::MatrixProc normalMProc = fNormalState->getMatrixProc(); |
| 403 this->inval(NULL); | 336 SkBitmapProcState::SampleProc32 normalSProc = fNormalState->getSampleProc32( ); |
| 404 } | 337 |
| 405 | 338 SkASSERT(fDiffuseState->fPixmap.addr()); |
| 406 SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) ove rride { | 339 SkASSERT(fNormalState->fPixmap.addr()); |
| 407 this->inval(NULL); | 340 |
| 408 return this->INHERITED::onFindClickHandler(x, y, modi); | 341 SkPoint3 norm; |
| 409 } | 342 SkScalar NdotL; |
| 410 | 343 int r, g, b; |
| 411 private: | 344 |
| 412 typedef SampleView INHERITED; | 345 do { |
| 413 }; | 346 int n = count; |
| 414 | 347 if (n > TMP_COUNT) { |
| 415 ////////////////////////////////////////////////////////////////////////////// | 348 n = TMP_COUNT; |
| 416 | 349 } |
| 417 static SkView* MyFactory() { return new LightingView; } | 350 |
| 418 static SkViewRegister reg(MyFactory); | 351 diffMProc(*fDiffuseState, tmpColor, n, x, y); |
| 352 diffSProc(*fDiffuseState, tmpColor, n, tmpColor2); | |
| 353 | |
| 354 normalMProc(*fNormalState, tmpNormal, n, x, y); | |
| 355 normalSProc(*fNormalState, tmpNormal, n, tmpNormal2); | |
| 356 | |
| 357 for (int i = 0; i < n; ++i) { | |
| 358 SkASSERT(0xFF == SkColorGetA(tmpNormal2[i])); // opaque -> unpremul | |
| 359 norm.set(SkIntToScalar(SkColorGetR(tmpNormal2[i]))-127.0f, | |
| 360 SkIntToScalar(SkColorGetG(tmpNormal2[i]))-127.0f, | |
| 361 SkIntToScalar(SkColorGetB(tmpNormal2[i]))-127.0f); | |
| 362 norm.normalize(); | |
| 363 | |
| 364 SkColor diffColor = SkUnPreMultiply::PMColorToColor(tmpColor2[i]); | |
| 365 NdotL = norm.dot(lightShader.fLight.fDirection); | |
| 366 | |
| 367 // This is all done in linear unpremul color space | |
| 368 r = light(SkColorGetR(lightShader.fLight.fColor), SkColorGetR(diffCo lor), NdotL, | |
| 369 SkColorGetR(lightShader.fAmbientColor)); | |
| 370 g = light(SkColorGetG(lightShader.fLight.fColor), SkColorGetG(diffCo lor), NdotL, | |
| 371 SkColorGetG(lightShader.fAmbientColor)); | |
| 372 b = light(SkColorGetB(lightShader.fLight.fColor), SkColorGetB(diffCo lor), NdotL, | |
| 373 SkColorGetB(lightShader.fAmbientColor)); | |
| 374 | |
| 375 result[i] = SkPreMultiplyARGB(SkColorGetA(diffColor), r, g, b); | |
| 376 } | |
| 377 | |
| 378 result += n; | |
| 379 x += n; | |
| 380 count -= n; | |
| 381 } while (count > 0); | |
| 382 } | |
| 383 | |
| 384 //////////////////////////////////////////////////////////////////////////// | |
| 385 | |
| 386 #ifndef SK_IGNORE_TO_STRING | |
| 387 void SkLightingShader::toString(SkString* str) const { | |
| 388 str->appendf("LightingShader: ()"); | |
| 389 } | |
| 390 #endif | |
| 391 | |
| 392 SkFlattenable* SkLightingShader::CreateProc(SkReadBuffer& buf) { | |
| 393 SkBitmap diffuse; | |
| 394 if (!buf.readBitmap(&diffuse)) { | |
| 395 return NULL; | |
| 396 } | |
| 397 diffuse.setImmutable(); | |
| 398 | |
| 399 SkBitmap normal; | |
| 400 if (!buf.readBitmap(&normal)) { | |
| 401 return NULL; | |
| 402 } | |
| 403 normal.setImmutable(); | |
| 404 | |
| 405 Light light; | |
| 406 if (!buf.readScalarArray(&light.fDirection.fX, 3)) { | |
| 407 return NULL; | |
| 408 } | |
| 409 light.fColor = buf.readColor(); | |
| 410 | |
| 411 SkColor ambient = buf.readColor(); | |
| 412 | |
| 413 // TODO: this would be nice to enable | |
| 414 // return SkCreateLightingShader(diffuse, normal, light, ambient, NULL); | |
| 415 return SkNEW_ARGS(SkLightingShader, (diffuse, normal, light, ambient)); | |
| 416 } | |
| 417 | |
| 418 void SkLightingShader::flatten(SkWriteBuffer& buf) const { | |
| 419 buf.writeBitmap(fDiffuseMap); | |
| 420 buf.writeBitmap(fNormalMap); | |
| 421 buf.writeScalarArray(&fLight.fDirection.fX, 3); | |
| 422 buf.writeColor(fLight.fColor); | |
| 423 buf.writeColor(fAmbientColor); | |
| 424 } | |
| 425 | |
| 426 SkShader::Context* SkLightingShader::onCreateContext(const ContextRec& rec, void * storage) const { | |
| 427 | |
| 428 SkMatrix totalInverse; | |
| 429 // Do this first, so we know the matrix can be inverted. | |
| 430 if (!this->computeTotalInverse(rec, &totalInverse)) { | |
| 431 return NULL; | |
| 432 } | |
| 433 | |
| 434 void* diffuseStateStorage = (char*)storage + sizeof(LightingShaderContext); | |
| 435 SkBitmapProcState* diffuseState = SkNEW_PLACEMENT(diffuseStateStorage, SkBit mapProcState); | |
| 436 SkASSERT(diffuseState); | |
| 437 | |
| 438 diffuseState->fTileModeX = SkShader::kClamp_TileMode; | |
| 439 diffuseState->fTileModeY = SkShader::kClamp_TileMode; | |
| 440 diffuseState->fOrigBitmap = fDiffuseMap; | |
| 441 if (!diffuseState->chooseProcs(totalInverse, *rec.fPaint)) { | |
| 442 diffuseState->~SkBitmapProcState(); | |
| 443 return NULL; | |
| 444 } | |
| 445 | |
| 446 void* normalStateStorage = (char*)storage + sizeof(LightingShaderContext) + sizeof(SkBitmapProcState); | |
| 447 SkBitmapProcState* normalState = SkNEW_PLACEMENT(normalStateStorage, SkBitma pProcState); | |
| 448 SkASSERT(normalState); | |
| 449 | |
| 450 normalState->fTileModeX = SkShader::kClamp_TileMode; | |
| 451 normalState->fTileModeY = SkShader::kClamp_TileMode; | |
| 452 normalState->fOrigBitmap = fNormalMap; | |
| 453 if (!normalState->chooseProcs(totalInverse, *rec.fPaint)) { | |
| 454 diffuseState->~SkBitmapProcState(); | |
| 455 normalState->~SkBitmapProcState(); | |
| 456 return NULL; | |
| 457 } | |
| 458 | |
| 459 return SkNEW_PLACEMENT_ARGS(storage, LightingShaderContext, (*this, rec, | |
| 460 diffuseState, n ormalState)); | |
| 461 } | |
| 462 | |
| 463 /////////////////////////////////////////////////////////////////////////////// | |
| 464 | |
| 465 // TODO: it would be nice to be able to call this from SkShader but this | |
| 466 // would need to reside in core. | |
| 467 #if 0 | |
| 468 static bool bitmap_is_too_big(const SkBitmap& bm) { | |
| 469 // SkBitmapProcShader stores bitmap coordinates in a 16bit buffer, as it | |
| 470 // communicates between its matrix-proc and its sampler-proc. Until we can | |
| 471 // widen that, we have to reject bitmaps that are larger. | |
| 472 // | |
| 473 static const int kMaxSize = 65535; | |
| 474 | |
| 475 return bm.width() > kMaxSize || bm.height() > kMaxSize; | |
| 476 } | |
| 477 | |
| 478 SkShader* SkCreateLightingShader(const SkBitmap& diffuse, const SkBitmap& normal , | |
| 479 const SkLightingShader::Light& light, const SkC olor ambient, | |
| 480 SkTBlitterAllocator* allocator) { | |
| 481 SkShader* shader; | |
| 482 | |
| 483 if (diffuse.isNull() || bitmap_is_too_big(diffuse) || | |
| 484 normal.isNull() || bitmap_is_too_big(normal) || | |
| 485 diffuse.width() != normal.width() || | |
| 486 diffuse.height() != normal.height()) { | |
| 487 if (!allocator) { | |
| 488 shader = SkNEW(SkEmptyShader); | |
| 489 } else { | |
| 490 shader = allocator->createT<SkEmptyShader>(); | |
| 491 } | |
| 492 } else { | |
| 493 if (!allocator) { | |
| 494 shader = SkNEW_ARGS(SkLightingShader, (diffuse, normal, light, ambie nt)); | |
| 495 } else { | |
| 496 shader = allocator->createT<SkLightingShader>(diffuse, normal, light , ambient); | |
| 497 } | |
| 498 } | |
| 499 return shader; | |
| 500 } | |
| 501 #endif | |
| 502 | |
| 503 /////////////////////////////////////////////////////////////////////////////// | |
| OLD | NEW |