Chromium Code Reviews| Index: src/core/SkShadowShader.cpp |
| diff --git a/src/core/SkShadowShader.cpp b/src/core/SkShadowShader.cpp |
| index 804258321a80f9ab0bd20b7ffa995878ab079b17..088d1b2769ed5a271db0c506366e37265e0d1626 100644 |
| --- a/src/core/SkShadowShader.cpp |
| +++ b/src/core/SkShadowShader.cpp |
| @@ -117,7 +117,14 @@ public: |
| fAmbientColor += lights->light(i).color(); |
| } else if (fNumDirLights < SkShadowShader::kMaxNonAmbientLights) { |
| fLightColor[fNumDirLights] = lights->light(i).color(); |
| - fLightDir[fNumDirLights] = lights->light(i).dir(); |
| + if (lights->light(i).type() == SkLights::Light::kPoint_LightType) { |
| + fLightDir[fNumDirLights] = lights->light(i).pos(); |
| + } else { |
| + fLightDir[fNumDirLights] = lights->light(i).dir(); |
| + } |
| + fIsPointLight[fNumDirLights] = |
| + lights->light(i).type() == SkLights::Light::kPoint_LightType; |
| + |
| SkImage_Base* shadowMap = ((SkImage_Base*)lights->light(i).getShadowMap()); |
| // gets deleted when the ShadowFP is destroyed, and frees the GrTexture* |
| @@ -155,16 +162,21 @@ public: |
| int32_t numLights = args.fFp.cast<ShadowFP>().fNumDirLights; |
| SkASSERT(numLights <= SkShadowShader::kMaxNonAmbientLights); |
| + bool isPointLight[SkShadowShader::kMaxNonAmbientLights]; |
| + for (int i = 0; i < SkShadowShader::kMaxNonAmbientLights; i++) { |
| + isPointLight[i] = args.fFp.cast<ShadowFP>().fIsPointLight[i]; |
| + } |
| + |
| const char* lightDirUniName[SkShadowShader::kMaxNonAmbientLights] = {nullptr}; |
| + const char* isPointLightUniName[SkShadowShader::kMaxNonAmbientLights] = {nullptr}; |
| const char* lightColorUniName[SkShadowShader::kMaxNonAmbientLights] = {nullptr}; |
| - const char* depthMapWidthUniName[SkShadowShader::kMaxNonAmbientLights] |
| - = {nullptr}; |
| - const char* depthMapHeightUniName[SkShadowShader::kMaxNonAmbientLights] |
| - = {nullptr}; |
| + const char* depthMapWidthUniName[SkShadowShader::kMaxNonAmbientLights] = {nullptr}; |
| + const char* depthMapHeightUniName[SkShadowShader::kMaxNonAmbientLights] = {nullptr}; |
| SkString lightDirUniNameBase("lightDir"); |
| SkString lightColorUniNameBase("lightColor"); |
| + SkString isPointLightUniNameBase("isPointLight"); |
| SkString depthMapWidthUniNameBase("dmapWidth"); |
| SkString depthMapHeightUniNameBase("dmapHeight"); |
| @@ -174,6 +186,8 @@ public: |
| lightDirUniNameStr.appendf("%d", i); |
| SkString lightColorUniNameStr(lightColorUniNameBase); |
| lightColorUniNameStr.appendf("%d", i); |
| + SkString isPointLightUniNameStr(isPointLightUniNameBase); |
| + isPointLightUniNameStr.appendf("%d", i); |
| SkString depthMapWidthUniNameStr(depthMapWidthUniNameBase); |
| depthMapWidthUniNameStr.appendf("%d", i); |
| @@ -185,6 +199,11 @@ public: |
| kDefault_GrSLPrecision, |
| lightDirUniNameStr.c_str(), |
| &lightDirUniName[i]); |
| + fIsPointLightUni[i] = uniformHandler->addUniform(kFragment_GrShaderFlag, |
| + kFloat_GrSLType, |
|
jvanverth1
2016/08/16 01:17:25
we have kBool_GrSLType
vjiaoblack
2016/08/16 20:33:40
Done.
|
| + kDefault_GrSLPrecision, |
| + isPointLightUniNameStr.c_str(), |
| + &isPointLightUniName[i]); |
| fLightColorUni[i] = uniformHandler->addUniform(kFragment_GrShaderFlag, |
| kVec3f_GrSLType, |
| kDefault_GrSLPrecision, |
| @@ -203,7 +222,6 @@ public: |
| &depthMapHeightUniName[i]); |
| } |
| - |
| const char* widthUniName = nullptr; |
| const char* heightUniName = nullptr; |
| @@ -216,7 +234,6 @@ public: |
| kDefault_GrSLPrecision, |
| "height", &heightUniName); |
| - |
| SkString povDepth("povDepth"); |
| this->emitChild(0, nullptr, &povDepth, args); |
| @@ -225,6 +242,10 @@ public: |
| SkString depthMaps[SkShadowShader::kMaxNonAmbientLights]; |
| + fragBuilder->codeAppendf("vec3 worldCor = vec3(vMatrixCoord_0_1_Stage0 * " |
| + "vec2(%s, %s), %s.b * 256);\n", |
|
jvanverth1
2016/08/16 01:17:25
Why 256? And create a constant for this magic numb
vjiaoblack
2016/08/16 20:33:40
Done.
|
| + widthUniName, heightUniName, povDepth.c_str()); |
| + |
| for (int i = 0; i < numLights; i++) { |
| SkString povCoord("povCoord"); |
| povCoord.appendf("%d", i); |
| @@ -243,9 +264,22 @@ public: |
| SkString scaleOffsetVec("scaleOffsetVec"); |
| scaleOffsetVec.appendf("%d", i); |
| - fragBuilder->codeAppendf("vec2 %s = vec2(%s) * povDepth.b * 255 / 400;\n", |
| - offset.c_str(), lightDirUniName[i]); |
| - |
| + fragBuilder->codeAppendf("vec2 %s;", offset.c_str()); |
| + |
| + if (isPointLight[i]) { |
| + fragBuilder->codeAppendf("vec3 fragToLight%d = %s - worldCor;\n", |
| + i, lightDirUniName[i]); |
| + fragBuilder->codeAppendf("float dist%d = length(fragToLight%d);" |
|
jvanverth1
2016/08/16 01:17:25
Do you use dist? If not, why not use normalize()?
vjiaoblack
2016/08/16 20:33:40
Done.
|
| + "fragToLight%d = fragToLight%d / dist%d;", |
| + i, i, i, i, i); |
| + fragBuilder->codeAppendf("%s = -vec2(%s.x - worldCor.x, worldCor.y - %s.y)*" |
| + "(povDepth.b) / 400;\n", |
| + offset.c_str(), lightDirUniName[i], |
| + lightDirUniName[i]); |
| + } else { |
| + fragBuilder->codeAppendf("%s = vec2(%s) * povDepth.b * 256 / 400;\n", |
| + offset.c_str(), lightDirUniName[i]); |
| + } |
| fragBuilder->codeAppendf("vec2 %s = (vec2(%s, %s) / vec2(%s, %s));\n", |
| scaleVec.c_str(), |
| widthUniName, heightUniName, |
| @@ -254,13 +288,11 @@ public: |
| fragBuilder->codeAppendf("vec2 %s = 1 - %s;\n", |
| scaleOffsetVec.c_str(), scaleVec.c_str()); |
| - |
| fragBuilder->codeAppendf("vec2 %s = (vMatrixCoord_0_1_Stage0 + " |
| - "vec2(%s.x, 0 - %s.y)) " |
| - " * %s + vec2(0,1) * %s;\n", |
| - |
| - povCoord.c_str(), offset.c_str(), offset.c_str(), |
| - scaleVec.c_str(), scaleOffsetVec.c_str()); |
| + "vec2(%s.x, 0 - %s.y)) " |
| + " * %s + vec2(0,1) * %s;\n", |
| + povCoord.c_str(), offset.c_str(), offset.c_str(), |
| + scaleVec.c_str(), scaleOffsetVec.c_str()); |
| fragBuilder->appendTextureLookup(&depthMaps[i], args.fTexSamplers[i], |
| povCoord.c_str(), |
| @@ -274,20 +306,26 @@ public: |
| fragBuilder->codeAppendf("vec4 resultDiffuseColor = %s;", diffuseColor.c_str()); |
| - // Essentially, |
| // diffColor * (ambientLightTot + foreachDirLight(lightColor * (N . L))) |
| SkString totalLightColor("totalLightColor"); |
| fragBuilder->codeAppendf("vec3 %s = vec3(0);", totalLightColor.c_str()); |
| for (int i = 0; i < numLights; i++) { |
| - fragBuilder->codeAppendf("if (%s.b >= %s.b) {", |
| - povDepth.c_str(), depthMaps[i].c_str()); |
| - // Note that dot(vec3(0,0,1), %s) == %s.z * %s |
| - fragBuilder->codeAppendf("%s += %s.z * %s;", |
| - totalLightColor.c_str(), |
| - lightDirUniName[i], |
| - lightColorUniName[i]); |
| - fragBuilder->codeAppendf("}"); |
| + if (!isPointLight[i]) { |
| + fragBuilder->codeAppendf("if (%s.b >= %s.b) {", |
| + povDepth.c_str(), depthMaps[i].c_str()); |
| + // Note that dot(vec3(0,0,1), %s) == %s.z * %s |
| + fragBuilder->codeAppendf("%s += %s.z * %s;", |
| + totalLightColor.c_str(), |
| + lightDirUniName[i], |
| + lightColorUniName[i]); |
| + fragBuilder->codeAppendf("}"); |
| + } else { |
| + // fragToLight%d.z is equal to the fragToLight dot the surface normal. |
| + fragBuilder->codeAppendf("%s += fragToLight%d.z * %s / pow(((dist%d / 1024.0) + 1.0), 2);", |
|
jvanverth1
2016/08/16 01:17:25
Ah, I see you use dist here. Using pow to do a squ
vjiaoblack
2016/08/16 20:33:40
Done.
|
| + totalLightColor.c_str(), i, |
| + lightColorUniName[i], i); |
| + } |
| } |
| fragBuilder->codeAppendf("%s += %s;", |
| @@ -304,6 +342,11 @@ public: |
| GrProcessorKeyBuilder* b) { |
| const ShadowFP& shadowFP = proc.cast<ShadowFP>(); |
| b->add32(shadowFP.fNumDirLights); |
| + int isPL = 0; |
| + for (int i = 0; i < SkShadowShader::kMaxNonAmbientLights; i++) { |
| + isPL = isPL | ((shadowFP.fIsPointLight[i] ? 1 : 0) << i); |
| + } |
| + b->add32(isPL); |
| } |
| protected: |
| @@ -314,6 +357,12 @@ public: |
| for (int i = 0; i < fNumDirLights; i++) { |
| const SkVector3& lightDir = shadowFP.lightDir(i); |
| + |
| + bool isPoint = shadowFP.isPointLight(i); |
| + SkScalar isPointf = isPoint ? 1.0f : 0.0f; |
| + pdman.set1f(fIsPointLightUni[i], isPointf); |
| + fIsPointLight[i] = isPoint; |
| + |
| if (lightDir != fLightDir[i]) { |
| pdman.set3fv(fLightDirUni[i], 1, &lightDir.fX); |
| fLightDir[i] = lightDir; |
| @@ -355,6 +404,10 @@ public: |
| } |
| private: |
| + bool fIsPointLight[SkShadowShader::kMaxNonAmbientLights]; |
| + GrGLSLProgramDataManager::UniformHandle |
| + fIsPointLightUni[SkShadowShader::kMaxNonAmbientLights]; |
| + |
| SkVector3 fLightDir[SkShadowShader::kMaxNonAmbientLights]; |
| GrGLSLProgramDataManager::UniformHandle |
| fLightDirUni[SkShadowShader::kMaxNonAmbientLights]; |
| @@ -393,6 +446,10 @@ public: |
| } |
| int32_t numLights() const { return fNumDirLights; } |
| const SkColor3f& ambientColor() const { return fAmbientColor; } |
| + const bool& isPointLight(int i) const { |
| + SkASSERT(i < fNumDirLights); |
| + return fIsPointLight[i]; |
| + } |
| const SkVector3& lightDir(int i) const { |
| SkASSERT(i < fNumDirLights); |
| return fLightDir[i]; |
| @@ -428,7 +485,8 @@ private: |
| for (int i = 0; i < fNumDirLights; i++) { |
| if (fLightDir[i] != shadowFP.fLightDir[i] || |
| - fLightColor[i] != shadowFP.fLightColor[i]) { |
| + fLightColor[i] != shadowFP.fLightColor[i] || |
| + fIsPointLight[i] != shadowFP.fIsPointLight[i]) { |
| return false; |
| } |
| @@ -443,6 +501,7 @@ private: |
| int fNumDirLights; |
| + bool fIsPointLight[SkShadowShader::kMaxNonAmbientLights]; |
| SkVector3 fLightDir[SkShadowShader::kMaxNonAmbientLights]; |
| SkColor3f fLightColor[SkShadowShader::kMaxNonAmbientLights]; |
| GrTextureAccess fDepthMapAccess[SkShadowShader::kMaxNonAmbientLights]; |
| @@ -561,11 +620,19 @@ void SkShadowShaderImpl::ShadowShaderContext::shadeSpan(int x, int y, |
| accum.fX += light.color().fX * SkColorGetR(diffColor); |
| accum.fY += light.color().fY * SkColorGetG(diffColor); |
| accum.fZ += light.color().fZ * SkColorGetB(diffColor); |
| - } else { |
| + } else 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); |
| + 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); |
| + } else { |
| + // TODO: do point lights for raster, currently treated like ambient |
| + accum.fX += light.color().fX * SkColorGetR(diffColor); |
| + accum.fY += light.color().fY * SkColorGetG(diffColor); |
| + accum.fZ += light.color().fZ * SkColorGetB(diffColor); |
| } |
| } |