aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gm/lightingshader2.cpp58
-rw-r--r--include/core/SkLights.h14
-rw-r--r--src/core/SkLightingShader.cpp105
3 files changed, 124 insertions, 53 deletions
diff --git a/gm/lightingshader2.cpp b/gm/lightingshader2.cpp
index 70c9e29f69..5afe2558b9 100644
--- a/gm/lightingshader2.cpp
+++ b/gm/lightingshader2.cpp
@@ -23,7 +23,7 @@ static SkBitmap make_frustum_normalmap(int texSize) {
namespace skiagm {
// This GM exercises lighting shaders. Specifically, nullptr arguments, scaling when using
-// normal maps, and paint transparency.
+// normal maps, paint transparency, zero directional lights, multiple directional lights.
class LightingShader2GM : public GM {
public:
LightingShader2GM() {
@@ -40,14 +40,30 @@ protected:
}
void onOnceBeforeDraw() override {
- SkLights::Builder builder;
const SkVector3 kLightFromUpperRight = SkVector3::Make(0.788f, 0.394f, 0.473f);
+ const SkVector3 kLightFromUpperLeft = SkVector3::Make(-0.788f, 0.394f, 0.473f);
+ // Standard set of lights
+ SkLights::Builder builder;
builder.add(SkLights::Light::MakeDirectional(SkColor3f::Make(1.0f, 1.0f, 1.0f),
kLightFromUpperRight));
builder.add(SkLights::Light::MakeAmbient(SkColor3f::Make(0.2f, 0.2f, 0.2f)));
fLights = builder.finish();
+ // No directional lights
+ SkLights::Builder builderNoDir;
+ builderNoDir.add(SkLights::Light::MakeAmbient(SkColor3f::Make(0.2f, 0.2f, 0.2f)));
+ fLightsNoDir = builderNoDir.finish();
+
+ // Two directional lights
+ SkLights::Builder builderTwoDir;
+ builderTwoDir.add(SkLights::Light::MakeDirectional(SkColor3f::Make(1.0f, 0.0f, 1.0f),
+ kLightFromUpperRight));
+ builderTwoDir.add(SkLights::Light::MakeDirectional(SkColor3f::Make(0.0f, 1.0f, 1.0f),
+ kLightFromUpperLeft));
+ builderTwoDir.add(SkLights::Light::MakeAmbient(SkColor3f::Make(0.2f, 0.2f, 0.2f)));
+ fLightsTwoDir = builderTwoDir.finish();
+
fRect = SkRect::MakeIWH(kTexSize, kTexSize);
SkMatrix matrix;
SkRect bitmapBounds = SkRect::MakeIWH(kTexSize, kTexSize);
@@ -87,7 +103,7 @@ protected:
static constexpr int NUM_BOOLEAN_PARAMS = 4;
void drawRect(SkCanvas* canvas, SkScalar scaleX, SkScalar scaleY,
SkScalar rotate, bool useNormalSource, bool useDiffuseShader,
- bool useTranslucentPaint, bool useTranslucentShader) {
+ bool useTranslucentPaint, bool useTranslucentShader, sk_sp<SkLights> lights) {
canvas->save();
this->positionCTM(canvas, scaleX, scaleY, rotate);
@@ -113,7 +129,7 @@ protected:
}
paint.setShader(SkLightingShader::Make(std::move(diffuseShader), std::move(normalSource),
- fLights));
+ std::move(lights)));
canvas->drawRect(fRect, paint);
canvas->restore();
@@ -147,7 +163,7 @@ protected:
canvas->translate(xPos, yPos);
this->drawRect(canvas, 1.0f, 1.0f, 0.f, useNormalSource, useDiffuseShader,
- useTranslucentPaint, useTranslucentShader);
+ useTranslucentPaint, useTranslucentShader, fLights);
// Drawing labels
canvas->translate(0.0f, SkIntToScalar(kTexSize));
{
@@ -191,7 +207,7 @@ protected:
canvas->save();
canvas->translate(xPos, yPos);
- this->drawRect(canvas, 0.6f, 0.6f, 45.0f, true, true, true, true);
+ this->drawRect(canvas, 0.6f, 0.6f, 45.0f, true, true, true, true, fLights);
canvas->restore();
gridNum++;
@@ -204,7 +220,33 @@ protected:
canvas->save();
canvas->translate(xPos, yPos);
- this->drawRect(canvas, 0.6f, 0.4f, 30.0f, true, true, true, true);
+ this->drawRect(canvas, 0.6f, 0.4f, 30.0f, true, true, true, true, fLights);
+ canvas->restore();
+
+ gridNum++;
+ }
+
+ // No directional lights test
+ {
+ SkScalar xPos = (gridNum % GRID_COLUMN_NUM) * GRID_CELL_WIDTH;
+ SkScalar yPos = (gridNum / GRID_COLUMN_NUM) * GRID_CELL_WIDTH;
+
+ canvas->save();
+ canvas->translate(xPos, yPos);
+ this->drawRect(canvas, 1.0f, 1.0f, 0.0f, true, true, false, false, fLightsNoDir);
+ canvas->restore();
+
+ gridNum++;
+ }
+
+ // Two directional lights test
+ {
+ SkScalar xPos = (gridNum % GRID_COLUMN_NUM) * GRID_CELL_WIDTH;
+ SkScalar yPos = (gridNum / GRID_COLUMN_NUM) * GRID_CELL_WIDTH;
+
+ canvas->save();
+ canvas->translate(xPos, yPos);
+ this->drawRect(canvas, 1.0f, 1.0f, 0.0f, true, true, false, false, fLightsTwoDir);
canvas->restore();
gridNum++;
@@ -220,6 +262,8 @@ private:
SkRect fRect;
sk_sp<SkLights> fLights;
+ sk_sp<SkLights> fLightsNoDir;
+ sk_sp<SkLights> fLightsTwoDir;
typedef GM INHERITED;
};
diff --git a/include/core/SkLights.h b/include/core/SkLights.h
index d9ec65b9aa..329e5d387d 100644
--- a/include/core/SkLights.h
+++ b/include/core/SkLights.h
@@ -87,6 +87,20 @@ public:
fShadowMap = b.fShadowMap;
return *this;
}
+
+ bool operator== (const Light& b) {
+ if (this == &b) {
+ return true;
+ }
+
+ return (fColor == b.fColor) &&
+ (fType == b.fType) &&
+ (fDirection == b.fDirection) &&
+ (fShadowMap == b.fShadowMap);
+ }
+
+ bool operator!= (const Light& b) { return !(this->operator==(b)); }
+
private:
LightType fType;
SkColor3f fColor; // linear (unpremul) color. Range is 0..1 in each channel.
diff --git a/src/core/SkLightingShader.cpp b/src/core/SkLightingShader.cpp
index 6f3c23399d..8fde8bfd37 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());
+ 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();
}