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; |