Chromium Code Reviews| Index: src/core/SkLightingShader.cpp |
| diff --git a/src/core/SkLightingShader.cpp b/src/core/SkLightingShader.cpp |
| index 6f3c23399df00b21cea511b43aa12a47341181b4..8fde8bfd37dedc66a244d323be8d40fa92ce87ef 100644 |
| --- a/src/core/SkLightingShader.cpp |
| +++ b/src/core/SkLightingShader.cpp |
| @@ -126,11 +126,11 @@ public: |
| for (int i = 0; i < lights->numLights(); ++i) { |
| if (SkLights::Light::kAmbient_LightType == lights->light(i).type()) { |
| fAmbientColor += lights->light(i).color(); |
| - } else { |
| - // TODO: handle more than one of these |
| - fLightColor = lights->light(i).color(); |
| - fLightDir = lights->light(i).dir(); |
| + } else if (SkLights::Light::kDirectional_LightType == lights->light(i).type()) { |
| + fDirectionalLights.push_back(lights->light(i)); |
| // TODO get the handle to the shadow map if there is one |
| + } else { |
| + SkDEBUGFAIL("Unimplemented Light Type passed to LightingFP"); |
| } |
| } |
| @@ -141,8 +141,6 @@ public: |
| class GLSLLightingFP : public GrGLSLFragmentProcessor { |
| public: |
| GLSLLightingFP() { |
| - fLightDir.fX = 10000.0f; |
| - fLightColor.fX = 0.0f; |
| fAmbientColor.fX = 0.0f; |
| } |
| @@ -150,17 +148,26 @@ public: |
| GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder; |
| GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; |
| - |
| - // add uniforms |
| - const char* lightDirUniName = nullptr; |
| - fLightDirUni = uniformHandler->addUniform(kFragment_GrShaderFlag, |
| - kVec3f_GrSLType, kDefault_GrSLPrecision, |
| - "LightDir", &lightDirUniName); |
| - |
| - const char* lightColorUniName = nullptr; |
| - fLightColorUni = uniformHandler->addUniform(kFragment_GrShaderFlag, |
| - kVec3f_GrSLType, kDefault_GrSLPrecision, |
| - "LightColor", &lightColorUniName); |
| + const LightingFP& lightingFP = args.fFp.cast<LightingFP>(); |
| + |
| + const char *lightDirsUniName = nullptr; |
| + const char *lightColorsUniName = nullptr; |
| + if (lightingFP.fDirectionalLights.count() != 0) { |
| + fLightDirsUni = uniformHandler->addUniformArray( |
| + kFragment_GrShaderFlag, |
| + kVec3f_GrSLType, |
| + kDefault_GrSLPrecision, |
| + "LightDir", |
| + lightingFP.fDirectionalLights.count(), |
| + &lightDirsUniName); |
| + fLightColorsUni = uniformHandler->addUniformArray( |
| + kFragment_GrShaderFlag, |
| + kVec3f_GrSLType, |
| + kDefault_GrSLPrecision, |
| + "LightColor", |
| + lightingFP.fDirectionalLights.count(), |
| + &lightColorsUniName); |
| + } |
| const char* ambientColorUniName = nullptr; |
| fAmbientColorUni = uniformHandler->addUniform(kFragment_GrShaderFlag, |
| @@ -174,12 +181,20 @@ public: |
| fragBuilder->codeAppendf("vec3 normal = %s.xyz;", dstNormalName.c_str()); |
| - // TODO: make this a loop and modulate the contribution from each light |
| - // based on the shadow map |
| - fragBuilder->codeAppendf("float NdotL = clamp(dot(normal, %s), 0.0, 1.0);", |
| - lightDirUniName); |
| + fragBuilder->codeAppend( "vec3 result = vec3(0.0);"); |
| + |
| // diffuse light |
| - fragBuilder->codeAppendf("vec3 result = %s*diffuseColor.rgb*NdotL;", lightColorUniName); |
| + if (lightingFP.fDirectionalLights.count() != 0) { |
| + fragBuilder->codeAppendf("for (int i = 0; i < %d; i++) {", |
| + lightingFP.fDirectionalLights.count()); |
| + // TODO: modulate the contribution from each light based on the shadow map |
| + fragBuilder->codeAppendf(" float NdotL = clamp(dot(normal, %s[i]), 0.0, 1.0);", |
| + lightDirsUniName); |
| + fragBuilder->codeAppendf(" result += %s[i]*diffuseColor.rgb*NdotL;", |
| + lightColorsUniName); |
| + fragBuilder->codeAppend("}"); |
| + } |
| + |
| // ambient light |
| fragBuilder->codeAppendf("result += %s * diffuseColor.rgb;", ambientColorUniName); |
| @@ -190,25 +205,27 @@ public: |
| static void GenKey(const GrProcessor& proc, const GrGLSLCaps&, |
| GrProcessorKeyBuilder* b) { |
| -// const LightingFP& lightingFP = proc.cast<LightingFP>(); |
| - // only one shader generated currently |
| - b->add32(0x0); |
| + const LightingFP& lightingFP = proc.cast<LightingFP>(); |
| + b->add32(lightingFP.fDirectionalLights.count()); |
| } |
| protected: |
| void onSetData(const GrGLSLProgramDataManager& pdman, const GrProcessor& proc) override { |
| const LightingFP& lightingFP = proc.cast<LightingFP>(); |
| - const SkVector3& lightDir = lightingFP.lightDir(); |
| - if (lightDir != fLightDir) { |
| - pdman.set3fv(fLightDirUni, 1, &lightDir.fX); |
| - fLightDir = lightDir; |
| - } |
| + const SkTArray<SkLights::Light>& directionalLights = lightingFP.directionalLights(); |
| + if (directionalLights != fDirectionalLights) { |
| + SkTArray<SkColor3f> lightDirs(directionalLights.count()); |
|
egdaniel
2016/08/15 15:13:09
I current don't have a good suggestion how, but it
dvonbeck
2016/08/15 15:25:09
Based on what we talked, I will leave this as-is f
|
| + SkTArray<SkVector3> lightColors(directionalLights.count()); |
| + for (const SkLights::Light& light : directionalLights) { |
| + lightDirs.push_back(light.dir()); |
| + lightColors.push_back(light.color()); |
| + } |
| + |
| + pdman.set3fv(fLightDirsUni, directionalLights.count(), &(lightDirs[0].fX)); |
| + pdman.set3fv(fLightColorsUni, directionalLights.count(), &(lightColors[0].fX)); |
| - const SkColor3f& lightColor = lightingFP.lightColor(); |
| - if (lightColor != fLightColor) { |
| - pdman.set3fv(fLightColorUni, 1, &lightColor.fX); |
| - fLightColor = lightColor; |
| + fDirectionalLights = directionalLights; |
| } |
| const SkColor3f& ambientColor = lightingFP.ambientColor(); |
| @@ -219,11 +236,9 @@ public: |
| } |
| private: |
| - SkVector3 fLightDir; |
| - GrGLSLProgramDataManager::UniformHandle fLightDirUni; |
| - |
| - SkColor3f fLightColor; |
| - GrGLSLProgramDataManager::UniformHandle fLightColorUni; |
| + SkTArray<SkLights::Light> fDirectionalLights; |
| + GrGLSLProgramDataManager::UniformHandle fLightDirsUni; |
| + GrGLSLProgramDataManager::UniformHandle fLightColorsUni; |
| SkColor3f fAmbientColor; |
| GrGLSLProgramDataManager::UniformHandle fAmbientColorUni; |
| @@ -239,8 +254,7 @@ public: |
| inout->mulByUnknownFourComponents(); |
| } |
| - const SkVector3& lightDir() const { return fLightDir; } |
| - const SkColor3f& lightColor() const { return fLightColor; } |
| + const SkTArray<SkLights::Light>& directionalLights() const { return fDirectionalLights; } |
| const SkColor3f& ambientColor() const { return fAmbientColor; } |
| private: |
| @@ -248,14 +262,12 @@ private: |
| bool onIsEqual(const GrFragmentProcessor& proc) const override { |
| const LightingFP& lightingFP = proc.cast<LightingFP>(); |
| - return fLightDir == lightingFP.fLightDir && |
| - fLightColor == lightingFP.fLightColor && |
| + return fDirectionalLights == lightingFP.fDirectionalLights && |
| fAmbientColor == lightingFP.fAmbientColor; |
| } |
| - SkVector3 fLightDir; |
| - SkColor3f fLightColor; |
| - SkColor3f fAmbientColor; |
| + SkTArray<SkLights::Light> fDirectionalLights; |
| + SkColor3f fAmbientColor; |
| }; |
| //////////////////////////////////////////////////////////////////////////// |
| @@ -482,6 +494,7 @@ SkShader::Context* SkLightingShaderImpl::onCreateContext(const ContextRec& rec, |
| sk_sp<SkShader> SkLightingShader::Make(sk_sp<SkShader> diffuseShader, |
| sk_sp<SkNormalSource> normalSource, |
| sk_sp<SkLights> lights) { |
| + SkASSERT(lights); |
| if (!normalSource) { |
| normalSource = SkNormalSource::MakeFlat(); |
| } |