| Index: src/core/SkShadowShader.cpp
|
| diff --git a/src/core/SkShadowShader.cpp b/src/core/SkShadowShader.cpp
|
| index b1f49b851d775877d6c711db3089a5456abf44a6..6ca82fb65d8431509e635324af81aa1e5167055f 100644
|
| --- a/src/core/SkShadowShader.cpp
|
| +++ b/src/core/SkShadowShader.cpp
|
| @@ -61,6 +61,10 @@ public:
|
|
|
| void* fHeapAllocated;
|
|
|
| + int fNonAmbLightCnt;
|
| + SkPixmap* fShadowMapPixels;
|
| +
|
| +
|
| typedef SkShader::Context INHERITED;
|
| };
|
|
|
| @@ -642,9 +646,23 @@ SkShadowShaderImpl::ShadowShaderContext::ShadowShaderContext(
|
| }
|
|
|
| fFlags = flags;
|
| +
|
| + const SkShadowShaderImpl& lightShader = static_cast<const SkShadowShaderImpl&>(fShader);
|
| +
|
| + fNonAmbLightCnt = lightShader.fLights->numLights();
|
| + fShadowMapPixels = new SkPixmap[fNonAmbLightCnt];
|
| +
|
| + for (int i = 0; i < fNonAmbLightCnt; i++) {
|
| + if (lightShader.fLights->light(i).type() == SkLights::Light::kDirectional_LightType) {
|
| + lightShader.fLights->light(i).getShadowMap()->
|
| + peekPixels(&fShadowMapPixels[i]);
|
| + }
|
| + }
|
| }
|
|
|
| SkShadowShaderImpl::ShadowShaderContext::~ShadowShaderContext() {
|
| + delete[] fShadowMapPixels;
|
| +
|
| // The dependencies have been created outside of the context on memory that was allocated by
|
| // the onCreateContext() method. Call the destructors and free the memory.
|
| fPovDepthContext->~Context();
|
| @@ -683,44 +701,62 @@ void SkShadowShaderImpl::ShadowShaderContext::shadeSpan(int x, int y,
|
| const SkShadowShaderImpl& lightShader = static_cast<const SkShadowShaderImpl&>(fShader);
|
|
|
| SkPMColor diffuse[BUFFER_MAX];
|
| + SkPMColor povDepth[BUFFER_MAX];
|
|
|
| do {
|
| int n = SkTMin(count, BUFFER_MAX);
|
|
|
| - fPovDepthContext->shadeSpan(x, y, diffuse, n);
|
| fDiffuseContext->shadeSpan(x, y, diffuse, n);
|
| + fPovDepthContext->shadeSpan(x, y, povDepth, n);
|
|
|
| for (int i = 0; i < n; ++i) {
|
| -
|
| SkColor diffColor = SkUnPreMultiply::PMColorToColor(diffuse[i]);
|
| + SkColor povDepthColor = povDepth[i];
|
|
|
| - SkColor3f accum = SkColor3f::Make(0.0f, 0.0f, 0.0f);
|
| + SkColor3f totalLight = lightShader.fLights->ambientLightColor();
|
| // This is all done in linear unpremul color space (each component 0..255.0f though)
|
|
|
| - accum.fX += lightShader.fLights->ambientLightColor().fX * SkColorGetR(diffColor);
|
| - accum.fY += lightShader.fLights->ambientLightColor().fY * SkColorGetG(diffColor);
|
| - accum.fZ += lightShader.fLights->ambientLightColor().fZ * SkColorGetB(diffColor);
|
| -
|
| for (int l = 0; l < lightShader.fLights->numLights(); ++l) {
|
| const SkLights::Light& light = lightShader.fLights->light(l);
|
|
|
| - if (SkLights::Light::kDirectional_LightType == light.type()) {
|
| - // scaling by fZ accounts for lighting direction
|
| - accum.fX += light.color().makeScale(light.dir().fZ).fX *
|
| - SkColorGetR(diffColor);
|
| - accum.fY += light.color().makeScale(light.dir().fZ).fY *
|
| - SkColorGetG(diffColor);
|
| - accum.fZ += light.color().makeScale(light.dir().fZ).fZ *
|
| - SkColorGetB(diffColor);
|
| + if (light.type() == SkLights::Light::kDirectional_LightType) {
|
| + int pvDepth = SkColorGetB(povDepthColor); // depth stored in blue channel
|
| +
|
| + int xOffset = SkScalarRoundToInt(light.dir().fX * pvDepth);
|
| + int yOffset = SkScalarRoundToInt(light.dir().fY * pvDepth);
|
| +
|
| + int shX = SkClampMax(x + i + xOffset, light.getShadowMap()->width() - 1);
|
| + int shY = SkClampMax(y + yOffset, light.getShadowMap()->height() - 1);
|
| +
|
| + int shDepth = 0;
|
| +
|
| + // pixmaps that point to things have nonzero heights
|
| + if (fShadowMapPixels[l].height() > 0) {
|
| + uint32_t pix = *fShadowMapPixels[l].addr32(shX, shY);
|
| + SkColor shColor(pix);
|
| +
|
| + shDepth = SkColorGetB(shColor);
|
| + } else {
|
| + // Make lights w/o a shadow map receive the full light contribution
|
| + shDepth = pvDepth;
|
| + }
|
| +
|
| + if (pvDepth >= shDepth) {
|
| + // assume object normals are pointing straight up
|
| + totalLight.fX += light.dir().fZ * light.color().fX;
|
| + totalLight.fY += light.dir().fZ * light.color().fY;
|
| + totalLight.fZ += light.dir().fZ * light.color().fZ;
|
| + }
|
| } else {
|
| - accum.fX += light.color().fX * SkColorGetR(diffColor);
|
| - accum.fY += light.color().fY * SkColorGetG(diffColor);
|
| - accum.fZ += light.color().fZ * SkColorGetB(diffColor);
|
| + totalLight += light.color();
|
| }
|
| -
|
| }
|
|
|
| - result[i] = convert(accum, SkColorGetA(diffColor));
|
| + SkColor3f totalColor = SkColor3f::Make(SkColorGetR(diffColor) * totalLight.fX,
|
| + SkColorGetG(diffColor) * totalLight.fY,
|
| + SkColorGetB(diffColor) * totalLight.fZ);
|
| +
|
| + result[i] = convert(totalColor, SkColorGetA(diffColor));
|
| }
|
|
|
| result += n;
|
|
|