aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--gm/lightingshader.cpp6
-rw-r--r--include/effects/SkPoint3.h1
-rwxr-xr-xsamplecode/SampleLighting.cpp17
-rw-r--r--src/effects/SkLightingShader.cpp95
-rw-r--r--src/effects/SkLightingShader.h18
5 files changed, 74 insertions, 63 deletions
diff --git a/gm/lightingshader.cpp b/gm/lightingshader.cpp
index ad8823d27d..687968abb6 100644
--- a/gm/lightingshader.cpp
+++ b/gm/lightingshader.cpp
@@ -105,12 +105,12 @@ public:
LightingShaderGM() {
this->setBGColor(sk_tool_utils::color_to_565(0xFFCCCCCC));
- fLight.fColor = SkColorSetRGB(0xff, 0xff, 0xff);
+ fLight.fColor = SkColor3f::Make(1.0f, 1.0f, 1.0f);
fLight.fDirection.fX = 0.0f;
fLight.fDirection.fY = 0.0f;
fLight.fDirection.fZ = 1.0f;
- fAmbient = SkColorSetRGB(0x1f, 0x1f, 0x1f);
+ fAmbient = SkColor3f::Make(0.1f, 0.1f, 0.1f);
}
protected:
@@ -171,7 +171,7 @@ private:
SkBitmap fFrustumNormalMap;
SkLightingShader::Light fLight;
- SkColor fAmbient;
+ SkColor3f fAmbient;
typedef GM INHERITED;
};
diff --git a/include/effects/SkPoint3.h b/include/effects/SkPoint3.h
index f9b727b998..c086931c08 100644
--- a/include/effects/SkPoint3.h
+++ b/include/effects/SkPoint3.h
@@ -109,5 +109,6 @@ struct SK_API SkPoint3 {
};
typedef SkPoint3 SkVector3;
+typedef SkPoint3 SkColor3f;
#endif
diff --git a/samplecode/SampleLighting.cpp b/samplecode/SampleLighting.cpp
index 3cda0c6a56..5b4f2e0931 100755
--- a/samplecode/SampleLighting.cpp
+++ b/samplecode/SampleLighting.cpp
@@ -20,8 +20,8 @@ public:
SkBitmap fDiffuseBitmap;
SkBitmap fNormalBitmap;
SkScalar fLightAngle;
- int fColorFactor;
- SkColor fAmbientColor;
+ SkScalar fColorFactor;
+ SkColor3f fAmbientColor;
LightingView() {
SkString diffusePath = GetResourcePath("brickwork-texture.jpg");
@@ -30,15 +30,15 @@ public:
SkImageDecoder::DecodeFile(normalPath.c_str(), &fNormalBitmap);
fLightAngle = 0.0f;
- fColorFactor = 0;
+ fColorFactor = 0.0f;
SkLightingShader::Light light;
- light.fColor = SkColorSetRGB(0xff, 0xff, 0xff);
+ light.fColor = SkColor3f::Make(1.0f, 1.0f, 1.0f);
light.fDirection.fX = SkScalarSin(fLightAngle)*SkScalarSin(SK_ScalarPI*0.25f);
light.fDirection.fY = SkScalarCos(fLightAngle)*SkScalarSin(SK_ScalarPI*0.25f);
light.fDirection.fZ = SkScalarCos(SK_ScalarPI*0.25f);
- fAmbientColor = SkColorSetRGB(0x1f, 0x1f, 0x1f);
+ fAmbientColor = SkColor3f::Make(0.1f, 0.1f, 0.1f);
fShader.reset(SkLightingShader::Create(fDiffuseBitmap, fNormalBitmap,
light, fAmbientColor, nullptr));
@@ -58,10 +58,13 @@ protected:
void onDrawContent(SkCanvas* canvas) override {
fLightAngle += 0.015f;
- fColorFactor++;
+ fColorFactor += 0.01f;
+ if (fColorFactor > 1.0f) {
+ fColorFactor = 0.0f;
+ }
SkLightingShader::Light light;
- light.fColor = SkColorSetRGB(0xff, 0xff, (fColorFactor >> 1) & 0xff);
+ light.fColor = SkColor3f::Make(1.0f, 1.0f, fColorFactor);
light.fDirection.fX = SkScalarSin(fLightAngle)*SkScalarSin(SK_ScalarPI*0.25f);
light.fDirection.fY = SkScalarCos(fLightAngle)*SkScalarSin(SK_ScalarPI*0.25f);
light.fDirection.fZ = SkScalarCos(SK_ScalarPI*0.25f);
diff --git a/src/effects/SkLightingShader.cpp b/src/effects/SkLightingShader.cpp
index 7b55626f55..4dcfa527f9 100644
--- a/src/effects/SkLightingShader.cpp
+++ b/src/effects/SkLightingShader.cpp
@@ -25,8 +25,6 @@
support multiple lights
enforce normal map is 4 channel
use SkImages instead if SkBitmaps
- vec3 for ambient and light-color
- add dox for both lighting equation, and how we compute normal from bitmap
To Test:
non-opaque diffuse textures
@@ -51,7 +49,7 @@ public:
*/
SkLightingShaderImpl(const SkBitmap& diffuse, const SkBitmap& normal,
const SkLightingShader::Light& light,
- const SkColor ambient, const SkMatrix* localMatrix)
+ const SkColor3f& ambient, const SkMatrix* localMatrix)
: INHERITED(localMatrix)
, fDiffuseMap(diffuse)
, fNormalMap(normal)
@@ -60,8 +58,6 @@ public:
if (!fLight.fDirection.normalize()) {
fLight.fDirection = SkPoint3::Make(0.0f, 0.0f, 1.0f);
}
- SkColorSetA(fLight.fColor, 0xFF);
- SkColorSetA(fAmbientColor, 0xFF);
}
bool isOpaque() const override;
@@ -103,7 +99,7 @@ private:
SkBitmap fDiffuseMap;
SkBitmap fNormalMap;
SkLightingShader::Light fLight;
- SkColor fAmbientColor; // linear (unpremul) color
+ SkColor3f fAmbientColor; // linear (unpremul) color. Range is 0..1/channel.
friend class SkLightingShader;
@@ -124,7 +120,8 @@ private:
class LightingFP : public GrFragmentProcessor {
public:
LightingFP(GrTexture* diffuse, GrTexture* normal, const SkMatrix& matrix,
- SkVector3 lightDir, GrColor lightColor, GrColor ambientColor)
+ const SkVector3& lightDir, const SkColor3f& lightColor,
+ const SkColor3f& ambientColor)
: fDeviceTransform(kDevice_GrCoordSet, matrix)
, fDiffuseTextureAccess(diffuse)
, fNormalTextureAccess(normal)
@@ -140,8 +137,10 @@ public:
class LightingGLFP : public GrGLFragmentProcessor {
public:
- LightingGLFP() : fLightColor(GrColor_ILLEGAL), fAmbientColor(GrColor_ILLEGAL) {
+ LightingGLFP() {
fLightDir.fX = 10000.0f;
+ fLightColor.fX = 0.0f;
+ fAmbientColor.fX = 0.0f;
}
void emitCode(EmitArgs& args) override {
@@ -156,12 +155,12 @@ public:
const char* lightColorUniName = NULL;
fLightColorUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
- kVec4f_GrSLType, kDefault_GrSLPrecision,
+ kVec3f_GrSLType, kDefault_GrSLPrecision,
"LightColor", &lightColorUniName);
const char* ambientColorUniName = NULL;
fAmbientColorUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
- kVec4f_GrSLType, kDefault_GrSLPrecision,
+ kVec3f_GrSLType, kDefault_GrSLPrecision,
"AmbientColor", &ambientColorUniName);
fpb->codeAppend("vec4 diffuseColor = ");
@@ -180,34 +179,30 @@ public:
fpb->codeAppendf("vec3 lightDir = normalize(%s);", lightDirUniName);
fpb->codeAppend("float NdotL = dot(normal, lightDir);");
// diffuse light
- fpb->codeAppendf("vec3 result = %s.rgb*diffuseColor.rgb*NdotL;", lightColorUniName);
+ fpb->codeAppendf("vec3 result = %s*diffuseColor.rgb*NdotL;", lightColorUniName);
// ambient light
- fpb->codeAppendf("result += %s.rgb;", ambientColorUniName);
+ fpb->codeAppendf("result += %s;", ambientColorUniName);
fpb->codeAppendf("%s = vec4(result.rgb, diffuseColor.a);", args.fOutputColor);
}
void setData(const GrGLProgramDataManager& pdman, const GrProcessor& proc) override {
const LightingFP& lightingFP = proc.cast<LightingFP>();
- SkVector3 lightDir = lightingFP.lightDir();
+ const SkVector3& lightDir = lightingFP.lightDir();
if (lightDir != fLightDir) {
pdman.set3fv(fLightDirUni, 1, &lightDir.fX);
fLightDir = lightDir;
}
- GrColor lightColor = lightingFP.lightColor();
+ const SkColor3f& lightColor = lightingFP.lightColor();
if (lightColor != fLightColor) {
- GrGLfloat c[4];
- GrColorToRGBAFloat(lightColor, c);
- pdman.set4fv(fLightColorUni, 1, c);
+ pdman.set3fv(fLightColorUni, 1, &lightColor.fX);
fLightColor = lightColor;
}
- GrColor ambientColor = lightingFP.ambientColor();
+ const SkColor3f& ambientColor = lightingFP.ambientColor();
if (ambientColor != fAmbientColor) {
- GrGLfloat c[4];
- GrColorToRGBAFloat(ambientColor, c);
- pdman.set4fv(fAmbientColorUni, 1, c);
+ pdman.set3fv(fAmbientColorUni, 1, &ambientColor.fX);
fAmbientColor = ambientColor;
}
}
@@ -223,10 +218,10 @@ public:
SkVector3 fLightDir;
GrGLProgramDataManager::UniformHandle fLightDirUni;
- GrColor fLightColor;
+ SkColor3f fLightColor;
GrGLProgramDataManager::UniformHandle fLightColorUni;
- GrColor fAmbientColor;
+ SkColor3f fAmbientColor;
GrGLProgramDataManager::UniformHandle fAmbientColorUni;
};
@@ -242,9 +237,9 @@ public:
inout->mulByUnknownFourComponents();
}
- SkVector3 lightDir() const { return fLightDir; }
- GrColor lightColor() const { return fLightColor; }
- GrColor ambientColor() const { return fAmbientColor; }
+ const SkVector3& lightDir() const { return fLightDir; }
+ const SkColor3f& lightColor() const { return fLightColor; }
+ const SkColor3f& ambientColor() const { return fAmbientColor; }
private:
bool onIsEqual(const GrFragmentProcessor& proc) const override {
@@ -261,8 +256,8 @@ private:
GrTextureAccess fDiffuseTextureAccess;
GrTextureAccess fNormalTextureAccess;
SkVector3 fLightDir;
- GrColor fLightColor;
- GrColor fAmbientColor;
+ SkColor3f fLightColor;
+ SkColor3f fAmbientColor;
};
////////////////////////////////////////////////////////////////////////////
@@ -341,13 +336,8 @@ bool SkLightingShaderImpl::asFragmentProcessor(GrContext* context, const SkPaint
return false;
}
- GrColor lightColor = GrColorPackRGBA(SkColorGetR(fLight.fColor), SkColorGetG(fLight.fColor),
- SkColorGetB(fLight.fColor), SkColorGetA(fLight.fColor));
- GrColor ambientColor = GrColorPackRGBA(SkColorGetR(fAmbientColor), SkColorGetG(fAmbientColor),
- SkColorGetB(fAmbientColor), SkColorGetA(fAmbientColor));
-
*fp = SkNEW_ARGS(LightingFP, (diffuseTexture, normalTexture, matrix,
- fLight.fDirection, lightColor, ambientColor));
+ fLight.fDirection, fLight.fColor, fAmbientColor));
*color = GrColorPackA4(paint.getAlpha());
return true;
}
@@ -400,14 +390,14 @@ SkLightingShaderImpl::LightingShaderContext::~LightingShaderContext() {
fNormalState->~SkBitmapProcState();
}
-static inline int light(int light, int diff, SkScalar NdotL, int ambient) {
- int color = int(light * diff * NdotL + 255 * ambient);
- if (color <= 0) {
+static inline int light(SkScalar light, int diff, SkScalar NdotL, SkScalar ambient) {
+ SkScalar color = light * diff * NdotL + 255 * ambient;
+ if (color <= 0.0f) {
return 0;
- } else if (color >= 255*255) {
+ } else if (color >= 255.0f) {
return 255;
} else {
- return SkDiv255Round(color);
+ return (int) color;
}
}
@@ -458,12 +448,12 @@ void SkLightingShaderImpl::LightingShaderContext::shadeSpan(int x, int y,
NdotL = norm.dot(lightShader.fLight.fDirection);
// This is all done in linear unpremul color space
- r = light(SkColorGetR(lightShader.fLight.fColor), SkColorGetR(diffColor), NdotL,
- SkColorGetR(lightShader.fAmbientColor));
- g = light(SkColorGetG(lightShader.fLight.fColor), SkColorGetG(diffColor), NdotL,
- SkColorGetG(lightShader.fAmbientColor));
- b = light(SkColorGetB(lightShader.fLight.fColor), SkColorGetB(diffColor), NdotL,
- SkColorGetB(lightShader.fAmbientColor));
+ r = light(lightShader.fLight.fColor.fX, SkColorGetR(diffColor), NdotL,
+ lightShader.fAmbientColor.fX);
+ g = light(lightShader.fLight.fColor.fY, SkColorGetG(diffColor), NdotL,
+ lightShader.fAmbientColor.fY);
+ b = light(lightShader.fLight.fColor.fZ, SkColorGetB(diffColor), NdotL,
+ lightShader.fAmbientColor.fZ);
result[i] = SkPreMultiplyARGB(SkColorGetA(diffColor), r, g, b);
}
@@ -502,9 +492,14 @@ SkFlattenable* SkLightingShaderImpl::CreateProc(SkReadBuffer& buf) {
if (!buf.readScalarArray(&light.fDirection.fX, 3)) {
return NULL;
}
- light.fColor = buf.readColor();
+ if (!buf.readScalarArray(&light.fColor.fX, 3)) {
+ return NULL;
+ }
- SkColor ambient = buf.readColor();
+ SkColor3f ambient;
+ if (!buf.readScalarArray(&ambient.fX, 3)) {
+ return NULL;
+ }
return SkNEW_ARGS(SkLightingShaderImpl, (diffuse, normal, light, ambient, &localMatrix));
}
@@ -515,8 +510,8 @@ void SkLightingShaderImpl::flatten(SkWriteBuffer& buf) const {
buf.writeBitmap(fDiffuseMap);
buf.writeBitmap(fNormalMap);
buf.writeScalarArray(&fLight.fDirection.fX, 3);
- buf.writeColor(fLight.fColor);
- buf.writeColor(fAmbientColor);
+ buf.writeScalarArray(&fLight.fColor.fX, 3);
+ buf.writeScalarArray(&fAmbientColor.fX, 3);
}
SkShader::Context* SkLightingShaderImpl::onCreateContext(const ContextRec& rec,
@@ -571,7 +566,7 @@ static bool bitmap_is_too_big(const SkBitmap& bm) {
SkShader* SkLightingShader::Create(const SkBitmap& diffuse, const SkBitmap& normal,
const SkLightingShader::Light& light,
- const SkColor ambient,
+ const SkColor3f& ambient,
const SkMatrix* localMatrix) {
if (diffuse.isNull() || bitmap_is_too_big(diffuse) ||
normal.isNull() || bitmap_is_too_big(normal) ||
diff --git a/src/effects/SkLightingShader.h b/src/effects/SkLightingShader.h
index b85e4318d3..64d41a291e 100644
--- a/src/effects/SkLightingShader.h
+++ b/src/effects/SkLightingShader.h
@@ -18,7 +18,7 @@ public:
struct Light {
SkVector3 fDirection; // direction towards the light (+Z is out of the screen).
// If degenerate, it will be replaced with (0, 0, 1).
- SkColor fColor; // linear (unpremul) color. Note: alpha assumed to be 255.
+ SkColor3f fColor; // linear (unpremul) color. Range is 0..1 in each channel.
};
/** Returns a shader that lights the diffuse and normal maps with a single light.
@@ -29,16 +29,28 @@ public:
@param diffuse the diffuse bitmap
@param normal the normal map
@param light the light applied to the normal map
- @param ambient the linear (unpremul) ambient light color. Note: alpha assumed to be 255.
+ @param ambient the linear (unpremul) ambient light color. Range is 0..1/channel.
@param localMatrix the matrix mapping the textures to the dest rect
NULL will be returned if:
either 'diffuse' or 'normal' are empty
either 'diffuse' or 'normal' are too big (> 65535 on a side)
'diffuse' and 'normal' aren't the same size
+
+ The lighting equation is currently:
+ result = LightColor * DiffuseColor * (Normal * LightDir) + AmbientColor
+
+ The normal map is currently assumed to be an 8888 image where the normal at a texel
+ is retrieved by:
+ N.x = R-127;
+ N.y = G-127;
+ N.z = B-127;
+ N.normalize();
+ The +Z axis is thus encoded in RGB as (127, 127, 255) while the -Z axis is
+ (127, 127, 0).
*/
static SkShader* Create(const SkBitmap& diffuse, const SkBitmap& normal,
- const SkLightingShader::Light& light, const SkColor ambient,
+ const SkLightingShader::Light& light, const SkColor3f& ambient,
const SkMatrix* localMatrix);
SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP()