diff options
author | 2016-08-30 07:13:04 -0700 | |
---|---|---|
committer | 2016-08-30 07:13:04 -0700 | |
commit | babc697ae8f7cb2191b049f446bf44d029376d69 (patch) | |
tree | fcef18d8da4b0ac3d45e2486263128a665923e66 /src/core/SkShadowShader.cpp | |
parent | 7a99a0a30194805329c5d2368dc36c61b449d0f9 (diff) |
raster shadows
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2248493002
Review-Url: https://codereview.chromium.org/2248493002
Diffstat (limited to 'src/core/SkShadowShader.cpp')
-rw-r--r-- | src/core/SkShadowShader.cpp | 76 |
1 files changed, 56 insertions, 20 deletions
diff --git a/src/core/SkShadowShader.cpp b/src/core/SkShadowShader.cpp index b1f49b851d..6ca82fb65d 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; |