|
|
|
@ -8,6 +8,14 @@
|
|
|
|
|
#include "SkLightingImageFilter.h"
|
|
|
|
|
#include "SkBitmap.h"
|
|
|
|
|
#include "SkColorPriv.h"
|
|
|
|
|
#include "GrProgramStageFactory.h"
|
|
|
|
|
#include "gl/GrGLProgramStage.h"
|
|
|
|
|
#include "gl/GrGLSL.h"
|
|
|
|
|
#include "gl/GrGLTexture.h"
|
|
|
|
|
#include "GrCustomStage.h"
|
|
|
|
|
|
|
|
|
|
class GrGLDiffuseLightingEffect;
|
|
|
|
|
class GrGLSpecularLightingEffect;
|
|
|
|
|
|
|
|
|
|
// FIXME: Eventually, this should be implemented properly, and put in
|
|
|
|
|
// SkScalar.h.
|
|
|
|
@ -19,6 +27,13 @@ const SkScalar gTwoThirds = SkScalarDiv(SkIntToScalar(2), SkIntToScalar(3));
|
|
|
|
|
const SkScalar gOneHalf = SkFloatToScalar(0.5f);
|
|
|
|
|
const SkScalar gOneQuarter = SkFloatToScalar(0.25f);
|
|
|
|
|
|
|
|
|
|
void setUniformPoint3(const GrGLInterface* gl, GrGLint location, const SkPoint3& point) {
|
|
|
|
|
float x = SkScalarToFloat(point.fX);
|
|
|
|
|
float y = SkScalarToFloat(point.fY);
|
|
|
|
|
float z = SkScalarToFloat(point.fZ);
|
|
|
|
|
GR_GL_CALL(gl, Uniform3f(location, x, y, z));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Shift matrix components to the left, as we advance pixels to the right.
|
|
|
|
|
inline void shiftMatrixLeft(int m[9]) {
|
|
|
|
|
m[0] = m[1];
|
|
|
|
@ -236,6 +251,7 @@ public:
|
|
|
|
|
SkDiffuseLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar kd);
|
|
|
|
|
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDiffuseLightingImageFilter)
|
|
|
|
|
|
|
|
|
|
virtual bool asNewCustomStage(GrCustomStage** stage) const SK_OVERRIDE;
|
|
|
|
|
SkScalar kd() const { return fKD; }
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
@ -255,6 +271,10 @@ public:
|
|
|
|
|
SkSpecularLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar ks, SkScalar shininess);
|
|
|
|
|
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSpecularLightingImageFilter)
|
|
|
|
|
|
|
|
|
|
virtual bool asNewCustomStage(GrCustomStage** stage) const SK_OVERRIDE;
|
|
|
|
|
SkScalar ks() const { return fKS; }
|
|
|
|
|
SkScalar shininess() const { return fShininess; }
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
explicit SkSpecularLightingImageFilter(SkFlattenableReadBuffer& buffer);
|
|
|
|
|
virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE;
|
|
|
|
@ -267,8 +287,144 @@ private:
|
|
|
|
|
SkScalar fShininess;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class GrLightingEffect : public GrCustomStage {
|
|
|
|
|
public:
|
|
|
|
|
GrLightingEffect(const SkLight* light, SkScalar surfaceScale);
|
|
|
|
|
virtual ~GrLightingEffect();
|
|
|
|
|
|
|
|
|
|
virtual bool isEqual(const GrCustomStage&) const SK_OVERRIDE;
|
|
|
|
|
|
|
|
|
|
const SkLight* light() const { return fLight; }
|
|
|
|
|
SkScalar surfaceScale() const { return fSurfaceScale; }
|
|
|
|
|
private:
|
|
|
|
|
typedef GrCustomStage INHERITED;
|
|
|
|
|
const SkLight* fLight;
|
|
|
|
|
SkScalar fSurfaceScale;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class GrDiffuseLightingEffect : public GrLightingEffect {
|
|
|
|
|
public:
|
|
|
|
|
GrDiffuseLightingEffect(const SkLight* light, SkScalar surfaceScale, SkScalar kd);
|
|
|
|
|
|
|
|
|
|
static const char* Name() { return "DiffuseLighting"; }
|
|
|
|
|
|
|
|
|
|
typedef GrGLDiffuseLightingEffect GLProgramStage;
|
|
|
|
|
|
|
|
|
|
virtual const GrProgramStageFactory& getFactory() const SK_OVERRIDE;
|
|
|
|
|
virtual bool isEqual(const GrCustomStage&) const SK_OVERRIDE;
|
|
|
|
|
SkScalar kd() const { return fKD; }
|
|
|
|
|
private:
|
|
|
|
|
typedef GrLightingEffect INHERITED;
|
|
|
|
|
SkScalar fKD;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class GrSpecularLightingEffect : public GrLightingEffect {
|
|
|
|
|
public:
|
|
|
|
|
GrSpecularLightingEffect(const SkLight* light, SkScalar surfaceScale, SkScalar ks, SkScalar shininess);
|
|
|
|
|
|
|
|
|
|
static const char* Name() { return "SpecularLighting"; }
|
|
|
|
|
|
|
|
|
|
typedef GrGLSpecularLightingEffect GLProgramStage;
|
|
|
|
|
|
|
|
|
|
virtual const GrProgramStageFactory& getFactory() const SK_OVERRIDE;
|
|
|
|
|
virtual bool isEqual(const GrCustomStage&) const SK_OVERRIDE;
|
|
|
|
|
SkScalar ks() const { return fKS; }
|
|
|
|
|
SkScalar shininess() const { return fShininess; }
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
typedef GrLightingEffect INHERITED;
|
|
|
|
|
SkScalar fKS;
|
|
|
|
|
SkScalar fShininess;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
class GrGLLight {
|
|
|
|
|
public:
|
|
|
|
|
virtual void setupVariables(GrGLShaderBuilder* state, int stage);
|
|
|
|
|
virtual void emitVS(SkString* builder) const {}
|
|
|
|
|
virtual void emitFuncs(SkString* builder) const {}
|
|
|
|
|
virtual void emitSurfaceToLight(SkString* builder, const char* z) const = 0;
|
|
|
|
|
virtual void emitLightColor(SkString* builder, const char *surfaceToLight) const;
|
|
|
|
|
virtual void initUniforms(const GrGLInterface* gl, int programID);
|
|
|
|
|
virtual void setData(const GrGLInterface*, const SkLight* light) const;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
typedef SkRefCnt INHERITED;
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
const GrGLShaderVar* fColorVar;
|
|
|
|
|
int fColorVarLocation;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
class GrGLDistantLight : public GrGLLight {
|
|
|
|
|
public:
|
|
|
|
|
virtual void setupVariables(GrGLShaderBuilder* state, int stage) SK_OVERRIDE;
|
|
|
|
|
virtual void initUniforms(const GrGLInterface* gl, int programID) SK_OVERRIDE;
|
|
|
|
|
virtual void setData(const GrGLInterface* gl, const SkLight* light) const SK_OVERRIDE;
|
|
|
|
|
virtual void emitSurfaceToLight(SkString* builder, const char* z) const SK_OVERRIDE;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
typedef GrGLLight INHERITED;
|
|
|
|
|
const GrGLShaderVar* fDirectionVar;
|
|
|
|
|
int fDirectionLocation;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
class GrGLPointLight : public GrGLLight {
|
|
|
|
|
public:
|
|
|
|
|
virtual void setupVariables(GrGLShaderBuilder* state, int stage);
|
|
|
|
|
virtual void initUniforms(const GrGLInterface* gl, int programID);
|
|
|
|
|
virtual void setData(const GrGLInterface* gl, const SkLight* light) const SK_OVERRIDE;
|
|
|
|
|
virtual void emitVS(SkString* builder) const;
|
|
|
|
|
virtual void emitSurfaceToLight(SkString* builder, const char* z) const SK_OVERRIDE;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
typedef GrGLLight INHERITED;
|
|
|
|
|
SkPoint3 fLocation;
|
|
|
|
|
const GrGLShaderVar* fLocationVar;
|
|
|
|
|
int fLocationLocation;
|
|
|
|
|
const char* fHeightVaryingName;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
class GrGLSpotLight : public GrGLLight {
|
|
|
|
|
public:
|
|
|
|
|
virtual void setupVariables(GrGLShaderBuilder* state, int stage);
|
|
|
|
|
virtual void initUniforms(const GrGLInterface* gl, int programID);
|
|
|
|
|
virtual void setData(const GrGLInterface* gl, const SkLight* light) const SK_OVERRIDE;
|
|
|
|
|
virtual void emitVS(SkString* builder) const;
|
|
|
|
|
virtual void emitFuncs(SkString* builder) const;
|
|
|
|
|
virtual void emitSurfaceToLight(SkString* builder, const char* z) const SK_OVERRIDE;
|
|
|
|
|
virtual void emitLightColor(SkString* builder, const char *surfaceToLight) const;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
typedef GrGLLight INHERITED;
|
|
|
|
|
|
|
|
|
|
const GrGLShaderVar* fLocationVar;
|
|
|
|
|
int fLocationLocation;
|
|
|
|
|
const GrGLShaderVar* fExponentVar;
|
|
|
|
|
int fExponentLocation;
|
|
|
|
|
const GrGLShaderVar* fCosOuterConeAngleVar;
|
|
|
|
|
int fCosOuterConeAngleLocation;
|
|
|
|
|
const GrGLShaderVar* fCosInnerConeAngleVar;
|
|
|
|
|
int fCosInnerConeAngleLocation;
|
|
|
|
|
const GrGLShaderVar* fConeScaleVar;
|
|
|
|
|
int fConeScaleLocation;
|
|
|
|
|
const GrGLShaderVar* fSVar;
|
|
|
|
|
int fSLocation;
|
|
|
|
|
const char* fHeightVaryingName;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
class SkLight : public SkFlattenable {
|
|
|
|
|
public:
|
|
|
|
|
SK_DECLARE_INST_COUNT(SkLight)
|
|
|
|
@ -280,6 +436,10 @@ public:
|
|
|
|
|
};
|
|
|
|
|
virtual LightType type() const = 0;
|
|
|
|
|
const SkPoint3& color() const { return fColor; }
|
|
|
|
|
virtual GrGLLight* createGLLight() const = 0;
|
|
|
|
|
virtual bool isEqual(const SkLight& other) const {
|
|
|
|
|
return fColor == other.fColor;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
SkLight(SkColor color)
|
|
|
|
@ -302,6 +462,8 @@ private:
|
|
|
|
|
|
|
|
|
|
SK_DEFINE_INST_COUNT(SkLight)
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
class SkDistantLight : public SkLight {
|
|
|
|
|
public:
|
|
|
|
|
SkDistantLight(const SkPoint3& direction, SkColor color)
|
|
|
|
@ -313,7 +475,8 @@ public:
|
|
|
|
|
};
|
|
|
|
|
SkPoint3 lightColor(const SkPoint3&) const { return color(); }
|
|
|
|
|
virtual LightType type() const { return kDistant_LightType; }
|
|
|
|
|
SkPoint3 direction() const { return fDirection; }
|
|
|
|
|
const SkPoint3& direction() const { return fDirection; }
|
|
|
|
|
virtual GrGLLight* createGLLight() const SK_OVERRIDE;
|
|
|
|
|
|
|
|
|
|
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDistantLight)
|
|
|
|
|
|
|
|
|
@ -331,6 +494,8 @@ private:
|
|
|
|
|
SkPoint3 fDirection;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
class SkPointLight : public SkLight {
|
|
|
|
|
public:
|
|
|
|
|
SkPointLight(const SkPoint3& location, SkColor color)
|
|
|
|
@ -345,6 +510,18 @@ public:
|
|
|
|
|
};
|
|
|
|
|
SkPoint3 lightColor(const SkPoint3&) const { return color(); }
|
|
|
|
|
virtual LightType type() const { return kPoint_LightType; }
|
|
|
|
|
const SkPoint3& location() const { return fLocation; }
|
|
|
|
|
virtual GrGLLight* createGLLight() const SK_OVERRIDE {
|
|
|
|
|
return new GrGLPointLight();
|
|
|
|
|
}
|
|
|
|
|
bool isEqual(const SkLight& other) SK_OVERRIDE {
|
|
|
|
|
if (other.type() != kPoint_LightType) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
const SkPointLight& o = static_cast<const SkPointLight&>(other);
|
|
|
|
|
return INHERITED::isEqual(other) &&
|
|
|
|
|
fLocation == o.fLocation;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkPointLight)
|
|
|
|
|
|
|
|
|
@ -362,6 +539,8 @@ private:
|
|
|
|
|
SkPoint3 fLocation;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
class SkSpotLight : public SkLight {
|
|
|
|
|
public:
|
|
|
|
|
SkSpotLight(const SkPoint3& location, const SkPoint3& target, SkScalar specularExponent, SkScalar cutoffAngle, SkColor color)
|
|
|
|
@ -397,8 +576,17 @@ public:
|
|
|
|
|
}
|
|
|
|
|
return color() * scale;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual GrGLLight* createGLLight() const SK_OVERRIDE {
|
|
|
|
|
return new GrGLSpotLight();
|
|
|
|
|
}
|
|
|
|
|
virtual LightType type() const { return kSpot_LightType; }
|
|
|
|
|
const SkPoint3& location() const { return fLocation; }
|
|
|
|
|
const SkPoint3& target() const { return fTarget; }
|
|
|
|
|
SkScalar specularExponent() const { return fSpecularExponent; }
|
|
|
|
|
SkScalar cosInnerConeAngle() const { return fCosInnerConeAngle; }
|
|
|
|
|
SkScalar cosOuterConeAngle() const { return fCosOuterConeAngle; }
|
|
|
|
|
SkScalar coneScale() const { return fConeScale; }
|
|
|
|
|
SkPoint3 s() const { return fS; }
|
|
|
|
|
|
|
|
|
|
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSpotLight)
|
|
|
|
|
|
|
|
|
@ -423,6 +611,19 @@ protected:
|
|
|
|
|
writePoint3(fS, buffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual bool isEqual(const SkLight& other) SK_OVERRIDE {
|
|
|
|
|
if (other.type() != kSpot_LightType) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const SkSpotLight& o = static_cast<const SkSpotLight&>(other);
|
|
|
|
|
return INHERITED::isEqual(other) &&
|
|
|
|
|
fLocation == o.fLocation &&
|
|
|
|
|
fTarget == o.fTarget &&
|
|
|
|
|
fSpecularExponent == o.fSpecularExponent &&
|
|
|
|
|
fCosOuterConeAngle == o.fCosOuterConeAngle;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
typedef SkLight INHERITED;
|
|
|
|
|
SkPoint3 fLocation;
|
|
|
|
@ -434,6 +635,8 @@ private:
|
|
|
|
|
SkPoint3 fS;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
SkLightingImageFilter::SkLightingImageFilter(SkLight* light, SkScalar surfaceScale)
|
|
|
|
|
: fLight(light),
|
|
|
|
|
fSurfaceScale(SkScalarDiv(surfaceScale, SkIntToScalar(255)))
|
|
|
|
@ -507,6 +710,8 @@ void SkLightingImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
|
|
|
|
|
buffer.writeScalar(fSurfaceScale);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
SkDiffuseLightingImageFilter::SkDiffuseLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar kd)
|
|
|
|
|
: SkLightingImageFilter(light, surfaceScale),
|
|
|
|
|
fKD(kd)
|
|
|
|
@ -557,6 +762,16 @@ bool SkDiffuseLightingImageFilter::onFilterImage(Proxy*,
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SkDiffuseLightingImageFilter::asNewCustomStage(GrCustomStage** stage) const {
|
|
|
|
|
if (stage) {
|
|
|
|
|
SkScalar scale = SkScalarMul(surfaceScale(), SkIntToScalar(255));
|
|
|
|
|
*stage = new GrDiffuseLightingEffect(light(), scale, kd());
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
SkSpecularLightingImageFilter::SkSpecularLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar ks, SkScalar shininess)
|
|
|
|
|
: SkLightingImageFilter(light, surfaceScale),
|
|
|
|
|
fKS(ks),
|
|
|
|
@ -610,6 +825,517 @@ bool SkSpecularLightingImageFilter::onFilterImage(Proxy*,
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SkSpecularLightingImageFilter::asNewCustomStage(GrCustomStage** stage) const {
|
|
|
|
|
if (stage) {
|
|
|
|
|
SkScalar scale = SkScalarMul(surfaceScale(), SkIntToScalar(255));
|
|
|
|
|
*stage = new GrSpecularLightingEffect(light(), scale, ks(), shininess());
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
class GrGLLightingEffect : public GrGLProgramStage {
|
|
|
|
|
public:
|
|
|
|
|
GrGLLightingEffect(const GrProgramStageFactory& factory,
|
|
|
|
|
const GrCustomStage& stage);
|
|
|
|
|
virtual ~GrGLLightingEffect();
|
|
|
|
|
|
|
|
|
|
virtual void setupVariables(GrGLShaderBuilder* state,
|
|
|
|
|
int stage) SK_OVERRIDE;
|
|
|
|
|
virtual void emitVS(GrGLShaderBuilder* state,
|
|
|
|
|
const char* vertexCoords) SK_OVERRIDE;
|
|
|
|
|
virtual void emitFS(GrGLShaderBuilder* state,
|
|
|
|
|
const char* outputColor,
|
|
|
|
|
const char* inputColor,
|
|
|
|
|
const char* samplerName) SK_OVERRIDE;
|
|
|
|
|
|
|
|
|
|
virtual void emitLightFunc(SkString* funcs) = 0;
|
|
|
|
|
|
|
|
|
|
static inline StageKey GenKey(const GrCustomStage& s);
|
|
|
|
|
|
|
|
|
|
virtual void initUniforms(const GrGLInterface*, int programID) SK_OVERRIDE;
|
|
|
|
|
virtual void setData(const GrGLInterface*,
|
|
|
|
|
const GrGLTexture&,
|
|
|
|
|
const GrCustomStage&,
|
|
|
|
|
int stageNum) SK_OVERRIDE;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
typedef GrGLProgramStage INHERITED;
|
|
|
|
|
|
|
|
|
|
const GrGLShaderVar* fImageIncrementVar;
|
|
|
|
|
GrGLint fImageIncrementLocation;
|
|
|
|
|
const GrGLShaderVar* fSurfaceScaleVar;
|
|
|
|
|
GrGLint fSurfaceScaleLocation;
|
|
|
|
|
GrGLLight* fLight;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
class GrGLDiffuseLightingEffect : public GrGLLightingEffect {
|
|
|
|
|
public:
|
|
|
|
|
GrGLDiffuseLightingEffect(const GrProgramStageFactory& factory,
|
|
|
|
|
const GrCustomStage& stage);
|
|
|
|
|
virtual void setupVariables(GrGLShaderBuilder* state,
|
|
|
|
|
int stage) SK_OVERRIDE;
|
|
|
|
|
virtual void emitLightFunc(SkString* funcs) SK_OVERRIDE;
|
|
|
|
|
virtual void initUniforms(const GrGLInterface*, int programID) SK_OVERRIDE;
|
|
|
|
|
virtual void setData(const GrGLInterface*,
|
|
|
|
|
const GrGLTexture&,
|
|
|
|
|
const GrCustomStage&,
|
|
|
|
|
int stageNum) SK_OVERRIDE;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
typedef GrGLLightingEffect INHERITED;
|
|
|
|
|
|
|
|
|
|
const GrGLShaderVar* fKDVar;
|
|
|
|
|
GrGLint fKDLocation;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
class GrGLSpecularLightingEffect : public GrGLLightingEffect {
|
|
|
|
|
public:
|
|
|
|
|
GrGLSpecularLightingEffect(const GrProgramStageFactory& factory,
|
|
|
|
|
const GrCustomStage& stage);
|
|
|
|
|
virtual void setupVariables(GrGLShaderBuilder* state,
|
|
|
|
|
int stage) SK_OVERRIDE;
|
|
|
|
|
virtual void emitLightFunc(SkString* funcs) SK_OVERRIDE;
|
|
|
|
|
virtual void initUniforms(const GrGLInterface*, int programID) SK_OVERRIDE;
|
|
|
|
|
virtual void setData(const GrGLInterface*,
|
|
|
|
|
const GrGLTexture&,
|
|
|
|
|
const GrCustomStage&,
|
|
|
|
|
int stageNum) SK_OVERRIDE;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
typedef GrGLLightingEffect INHERITED;
|
|
|
|
|
|
|
|
|
|
const GrGLShaderVar* fKSVar;
|
|
|
|
|
GrGLint fKSLocation;
|
|
|
|
|
const GrGLShaderVar* fShininessVar;
|
|
|
|
|
GrGLint fShininessLocation;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
GrLightingEffect::GrLightingEffect(const SkLight* light, SkScalar surfaceScale)
|
|
|
|
|
: fLight(light)
|
|
|
|
|
, fSurfaceScale(surfaceScale) {
|
|
|
|
|
fLight->ref();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GrLightingEffect::~GrLightingEffect() {
|
|
|
|
|
fLight->unref();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool GrLightingEffect::isEqual(const GrCustomStage& sBase) const {
|
|
|
|
|
const GrLightingEffect& s =
|
|
|
|
|
static_cast<const GrLightingEffect&>(sBase);
|
|
|
|
|
return fLight->isEqual(*s.fLight) &&
|
|
|
|
|
fSurfaceScale == s.fSurfaceScale;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
GrDiffuseLightingEffect::GrDiffuseLightingEffect(const SkLight* light, SkScalar surfaceScale, SkScalar kd)
|
|
|
|
|
: INHERITED(light, surfaceScale), fKD(kd) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const GrProgramStageFactory& GrDiffuseLightingEffect::getFactory() const {
|
|
|
|
|
return GrTProgramStageFactory<GrDiffuseLightingEffect>::getInstance();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool GrDiffuseLightingEffect::isEqual(const GrCustomStage& sBase) const {
|
|
|
|
|
const GrDiffuseLightingEffect& s =
|
|
|
|
|
static_cast<const GrDiffuseLightingEffect&>(sBase);
|
|
|
|
|
return INHERITED::isEqual(sBase) &&
|
|
|
|
|
this->kd() == s.kd();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
GrGLLightingEffect::GrGLLightingEffect(const GrProgramStageFactory& factory,
|
|
|
|
|
const GrCustomStage& stage)
|
|
|
|
|
: GrGLProgramStage(factory)
|
|
|
|
|
, fImageIncrementVar(NULL)
|
|
|
|
|
, fImageIncrementLocation(0)
|
|
|
|
|
, fSurfaceScaleVar(NULL)
|
|
|
|
|
, fSurfaceScaleLocation(0) {
|
|
|
|
|
const GrLightingEffect& m = static_cast<const GrLightingEffect&>(stage);
|
|
|
|
|
fLight = m.light()->createGLLight();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GrGLLightingEffect::~GrGLLightingEffect() {
|
|
|
|
|
delete fLight;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GrGLLightingEffect::setupVariables(GrGLShaderBuilder* state, int stage) {
|
|
|
|
|
fImageIncrementVar = &state->addUniform(
|
|
|
|
|
GrGLShaderBuilder::kFragment_ShaderType,
|
|
|
|
|
kVec2f_GrSLType, "uImageIncrement", stage);
|
|
|
|
|
fSurfaceScaleVar = &state->addUniform(
|
|
|
|
|
GrGLShaderBuilder::kFragment_ShaderType,
|
|
|
|
|
kFloat_GrSLType, "uSurfaceScale", stage);
|
|
|
|
|
fLight->setupVariables(state, stage);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GrGLLightingEffect::emitVS(GrGLShaderBuilder* state,
|
|
|
|
|
const char* vertexCoords) {
|
|
|
|
|
fLight->emitVS(&state->fVSCode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GrGLLightingEffect::initUniforms(const GrGLInterface* gl,
|
|
|
|
|
int programID) {
|
|
|
|
|
GR_GL_CALL_RET(gl, fSurfaceScaleLocation,
|
|
|
|
|
GetUniformLocation(programID,
|
|
|
|
|
fSurfaceScaleVar->getName().c_str()));
|
|
|
|
|
GR_GL_CALL_RET(gl, fImageIncrementLocation,
|
|
|
|
|
GetUniformLocation(programID,
|
|
|
|
|
fImageIncrementVar->getName().c_str()));
|
|
|
|
|
fLight->initUniforms(gl, programID);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GrGLLightingEffect::emitFS(GrGLShaderBuilder* state,
|
|
|
|
|
const char* outputColor,
|
|
|
|
|
const char* inputColor,
|
|
|
|
|
const char* samplerName) {
|
|
|
|
|
SkString* code = &state->fFSCode;
|
|
|
|
|
SkString* funcs = &state->fFSFunctions;
|
|
|
|
|
fLight->emitFuncs(funcs);
|
|
|
|
|
emitLightFunc(funcs);
|
|
|
|
|
funcs->appendf("float sobel(float a, float b, float c, float d, float e, float f, float scale) {\n");
|
|
|
|
|
funcs->appendf("\treturn (-a + b - 2 * c + 2 * d -e + f) * scale;\n");
|
|
|
|
|
funcs->appendf("}\n");
|
|
|
|
|
funcs->appendf("vec3 pointToNormal(float x, float y, float scale) {\n");
|
|
|
|
|
funcs->appendf("\treturn normalize(vec3(-x * scale, -y * scale, 1));\n");
|
|
|
|
|
funcs->appendf("}\n");
|
|
|
|
|
funcs->append("\n\
|
|
|
|
|
vec3 interiorNormal(float m[9], float surfaceScale) {\n\
|
|
|
|
|
return pointToNormal(sobel(m[0], m[2], m[3], m[5], m[6], m[8], 0.25),\n\
|
|
|
|
|
sobel(m[0], m[6], m[1], m[7], m[2], m[8], 0.25),\n\
|
|
|
|
|
surfaceScale);\n}\n");
|
|
|
|
|
|
|
|
|
|
code->appendf("\t\tvec2 coord = %s;\n", state->fSampleCoords.c_str());
|
|
|
|
|
code->appendf("\t\tfloat m[9];\n");
|
|
|
|
|
int index = 0;
|
|
|
|
|
for (int dy = -1; dy <= 1; dy++) {
|
|
|
|
|
for (int dx = -1; dx <= 1; dx++) {
|
|
|
|
|
SkString texCoords;
|
|
|
|
|
texCoords.appendf("coord + vec2(%d, %d) * %s", dx, dy, fImageIncrementVar->getName().c_str());
|
|
|
|
|
code->appendf("\t\tm[%d] = ", index++);
|
|
|
|
|
state->emitTextureLookup(samplerName, texCoords.c_str());
|
|
|
|
|
code->appendf(".a;\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
code->appendf("\t\tvec3 surfaceToLight = ");
|
|
|
|
|
SkString arg;
|
|
|
|
|
arg.appendf("%s * m[4]", fSurfaceScaleVar->getName().c_str());
|
|
|
|
|
fLight->emitSurfaceToLight(code, arg.c_str());
|
|
|
|
|
code->appendf(";\n");
|
|
|
|
|
code->appendf("\t\t%s = light(interiorNormal(m, %s), surfaceToLight, ", outputColor, fSurfaceScaleVar->getName().c_str());
|
|
|
|
|
fLight->emitLightColor(code, "surfaceToLight");
|
|
|
|
|
code->appendf(")%s;\n", state->fModulate.c_str());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GrGLProgramStage::StageKey GrGLLightingEffect::GenKey(
|
|
|
|
|
const GrCustomStage& s) {
|
|
|
|
|
return static_cast<const GrLightingEffect&>(s).light()->type();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GrGLLightingEffect::setData(const GrGLInterface* gl,
|
|
|
|
|
const GrGLTexture& texture,
|
|
|
|
|
const GrCustomStage& data,
|
|
|
|
|
int stageNum) {
|
|
|
|
|
const GrLightingEffect& effect =
|
|
|
|
|
static_cast<const GrLightingEffect&>(data);
|
|
|
|
|
GR_GL_CALL(gl, Uniform2f(fImageIncrementLocation, 1.0f / texture.width(), 1.0f / texture.height()));
|
|
|
|
|
GR_GL_CALL(gl, Uniform1f(fSurfaceScaleLocation, effect.surfaceScale()));
|
|
|
|
|
fLight->setData(gl, effect.light());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
GrGLDiffuseLightingEffect::GrGLDiffuseLightingEffect(const GrProgramStageFactory& factory,
|
|
|
|
|
const GrCustomStage& stage)
|
|
|
|
|
: INHERITED(factory, stage)
|
|
|
|
|
, fKDVar(NULL)
|
|
|
|
|
, fKDLocation(0) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GrGLDiffuseLightingEffect::setupVariables(GrGLShaderBuilder* state, int stage) {
|
|
|
|
|
INHERITED::setupVariables(state, stage);
|
|
|
|
|
fKDVar = &state->addUniform(
|
|
|
|
|
GrGLShaderBuilder::kFragment_ShaderType,
|
|
|
|
|
kFloat_GrSLType, "uKD", stage);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GrGLDiffuseLightingEffect::initUniforms(const GrGLInterface* gl,
|
|
|
|
|
int programID) {
|
|
|
|
|
INHERITED::initUniforms(gl, programID);
|
|
|
|
|
GR_GL_CALL_RET(gl, fKDLocation,
|
|
|
|
|
GetUniformLocation(programID,
|
|
|
|
|
fKDVar->getName().c_str()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GrGLDiffuseLightingEffect::emitLightFunc(SkString* funcs) {
|
|
|
|
|
funcs->appendf("vec4 light(vec3 normal, vec3 surfaceToLight, vec3 lightColor) {\n");
|
|
|
|
|
funcs->appendf("\tfloat colorScale = %s * dot(normal, surfaceToLight);\n", fKDVar->getName().c_str());
|
|
|
|
|
funcs->appendf("\treturn vec4(lightColor * clamp(colorScale, 0, 1), 1);\n");
|
|
|
|
|
funcs->appendf("}\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GrGLDiffuseLightingEffect::setData(const GrGLInterface* gl,
|
|
|
|
|
const GrGLTexture& texture,
|
|
|
|
|
const GrCustomStage& data,
|
|
|
|
|
int stageNum) {
|
|
|
|
|
INHERITED::setData(gl, texture, data, stageNum);
|
|
|
|
|
const GrDiffuseLightingEffect& effect =
|
|
|
|
|
static_cast<const GrDiffuseLightingEffect&>(data);
|
|
|
|
|
GR_GL_CALL(gl, Uniform1f(fKDLocation, effect.kd()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
GrSpecularLightingEffect::GrSpecularLightingEffect(const SkLight* light, SkScalar surfaceScale, SkScalar ks, SkScalar shininess)
|
|
|
|
|
: INHERITED(light, surfaceScale),
|
|
|
|
|
fKS(ks),
|
|
|
|
|
fShininess(shininess) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const GrProgramStageFactory& GrSpecularLightingEffect::getFactory() const {
|
|
|
|
|
return GrTProgramStageFactory<GrSpecularLightingEffect>::getInstance();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool GrSpecularLightingEffect::isEqual(const GrCustomStage& sBase) const {
|
|
|
|
|
const GrSpecularLightingEffect& s =
|
|
|
|
|
static_cast<const GrSpecularLightingEffect&>(sBase);
|
|
|
|
|
return INHERITED::isEqual(sBase) &&
|
|
|
|
|
this->ks() == s.ks() &&
|
|
|
|
|
this->shininess() == s.shininess();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
GrGLSpecularLightingEffect::GrGLSpecularLightingEffect(const GrProgramStageFactory& factory,
|
|
|
|
|
const GrCustomStage& stage)
|
|
|
|
|
: GrGLLightingEffect(factory, stage)
|
|
|
|
|
, fKSVar(NULL)
|
|
|
|
|
, fKSLocation(0)
|
|
|
|
|
, fShininessVar(NULL)
|
|
|
|
|
, fShininessLocation(0) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GrGLSpecularLightingEffect::setupVariables(GrGLShaderBuilder* state, int stage) {
|
|
|
|
|
INHERITED::setupVariables(state, stage);
|
|
|
|
|
fKSVar = &state->addUniform(
|
|
|
|
|
GrGLShaderBuilder::kFragment_ShaderType,
|
|
|
|
|
kFloat_GrSLType, "uKS", stage);
|
|
|
|
|
fShininessVar = &state->addUniform(
|
|
|
|
|
GrGLShaderBuilder::kFragment_ShaderType,
|
|
|
|
|
kFloat_GrSLType, "uShininess", stage);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GrGLSpecularLightingEffect::initUniforms(const GrGLInterface* gl,
|
|
|
|
|
int programID) {
|
|
|
|
|
INHERITED::initUniforms(gl, programID);
|
|
|
|
|
GR_GL_CALL_RET(gl, fKSLocation,
|
|
|
|
|
GetUniformLocation(programID, fKSVar->getName().c_str()));
|
|
|
|
|
GR_GL_CALL_RET(gl, fShininessLocation,
|
|
|
|
|
GetUniformLocation(programID, fShininessVar->getName().c_str()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GrGLSpecularLightingEffect::emitLightFunc(SkString* funcs) {
|
|
|
|
|
funcs->appendf("vec4 light(vec3 normal, vec3 surfaceToLight, vec3 lightColor) {\n");
|
|
|
|
|
funcs->appendf("\tvec3 halfDir = vec3(normalize(surfaceToLight + vec3(0, 0, 1)));\n");
|
|
|
|
|
|
|
|
|
|
funcs->appendf("\tfloat colorScale = %s * pow(dot(normal, halfDir), %s);\n",
|
|
|
|
|
fKSVar->getName().c_str(), fShininessVar->getName().c_str());
|
|
|
|
|
funcs->appendf("\treturn vec4(lightColor * clamp(colorScale, 0, 1), 1);\n");
|
|
|
|
|
funcs->appendf("}\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GrGLSpecularLightingEffect::setData(const GrGLInterface* gl,
|
|
|
|
|
const GrGLTexture& texture,
|
|
|
|
|
const GrCustomStage& data,
|
|
|
|
|
int stageNum) {
|
|
|
|
|
INHERITED::setData(gl, texture, data, stageNum);
|
|
|
|
|
const GrSpecularLightingEffect& effect =
|
|
|
|
|
static_cast<const GrSpecularLightingEffect&>(data);
|
|
|
|
|
GR_GL_CALL(gl, Uniform1f(fKSLocation, effect.ks()));
|
|
|
|
|
GR_GL_CALL(gl, Uniform1f(fShininessLocation, effect.shininess()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
void GrGLLight::emitLightColor(SkString* builder, const char *surfaceToLight) const {
|
|
|
|
|
builder->append(fColorVar->getName().c_str());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GrGLLight::setupVariables(GrGLShaderBuilder* state, int stage) {
|
|
|
|
|
fColorVar = &state->addUniform(
|
|
|
|
|
GrGLShaderBuilder::kFragment_ShaderType,
|
|
|
|
|
kVec3f_GrSLType, "uLightColor", stage);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GrGLLight::initUniforms(const GrGLInterface* gl, int programID) {
|
|
|
|
|
GR_GL_CALL_RET(gl, fColorVarLocation,
|
|
|
|
|
GetUniformLocation(programID, fColorVar->getName().c_str()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GrGLLight::setData(const GrGLInterface* gl, const SkLight* light) const {
|
|
|
|
|
setUniformPoint3(gl, fColorVarLocation, light->color() * SkScalarInvert(SkIntToScalar(255)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GrGLLight* SkDistantLight::createGLLight() const {
|
|
|
|
|
return new GrGLDistantLight();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
void GrGLDistantLight::setupVariables(GrGLShaderBuilder* state, int stage) {
|
|
|
|
|
INHERITED::setupVariables(state, stage);
|
|
|
|
|
fDirectionVar = &state->addUniform(
|
|
|
|
|
GrGLShaderBuilder::kFragment_ShaderType, kVec3f_GrSLType,
|
|
|
|
|
"uLightDirection", stage);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GrGLDistantLight::initUniforms(const GrGLInterface* gl, int programID) {
|
|
|
|
|
INHERITED::initUniforms(gl, programID);
|
|
|
|
|
GR_GL_CALL_RET(gl, fDirectionLocation,
|
|
|
|
|
GetUniformLocation(programID, fDirectionVar->getName().c_str()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GrGLDistantLight::setData(const GrGLInterface* gl, const SkLight* light) const {
|
|
|
|
|
INHERITED::setData(gl, light);
|
|
|
|
|
SkASSERT(light->type() == SkLight::kDistant_LightType);
|
|
|
|
|
const SkDistantLight* distantLight = static_cast<const SkDistantLight*>(light);
|
|
|
|
|
setUniformPoint3(gl, fDirectionLocation, distantLight->direction());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GrGLDistantLight::emitSurfaceToLight(SkString* builder,
|
|
|
|
|
const char* z) const {
|
|
|
|
|
builder->append(fDirectionVar->getName().c_str());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
void GrGLPointLight::setupVariables(GrGLShaderBuilder* state, int stage) {
|
|
|
|
|
INHERITED::setupVariables(state, stage);
|
|
|
|
|
fLocationVar = &state->addUniform(
|
|
|
|
|
GrGLShaderBuilder::kFragment_ShaderType, kVec3f_GrSLType,
|
|
|
|
|
"uLightLocation", stage);
|
|
|
|
|
state->addVarying(kFloat_GrSLType, "Height", stage, &fHeightVaryingName);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GrGLPointLight::initUniforms(const GrGLInterface* gl, int programID) {
|
|
|
|
|
INHERITED::initUniforms(gl, programID);
|
|
|
|
|
GR_GL_CALL_RET(gl, fLocationLocation,
|
|
|
|
|
GetUniformLocation(programID, fLocationVar->getName().c_str()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GrGLPointLight::setData(const GrGLInterface* gl, const SkLight* light) const {
|
|
|
|
|
INHERITED::setData(gl, light);
|
|
|
|
|
SkASSERT(light->type() == SkLight::kPoint_LightType);
|
|
|
|
|
const SkPointLight* pointLight = static_cast<const SkPointLight*>(light);
|
|
|
|
|
setUniformPoint3(gl, fLocationLocation, pointLight->location());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GrGLPointLight::emitVS(SkString* builder) const {
|
|
|
|
|
// Compute viewport height from the Y scale of the matrix.
|
|
|
|
|
builder->appendf("\t\t%s = -2.0 / uViewM[1][1];\n", fHeightVaryingName);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GrGLPointLight::emitSurfaceToLight(SkString* builder,
|
|
|
|
|
const char* z) const {
|
|
|
|
|
builder->appendf(
|
|
|
|
|
"normalize(%s - vec3(gl_FragCoord.x, %s - gl_FragCoord.y, %s))",
|
|
|
|
|
fLocationVar->getName().c_str(), fHeightVaryingName, z);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
void GrGLSpotLight::setupVariables(GrGLShaderBuilder* state, int stage) {
|
|
|
|
|
INHERITED::setupVariables(state, stage);
|
|
|
|
|
fLocationVar = &state->addUniform(
|
|
|
|
|
GrGLShaderBuilder::kFragment_ShaderType,
|
|
|
|
|
kVec3f_GrSLType, "uLightLocation", stage);
|
|
|
|
|
fExponentVar = &state->addUniform(
|
|
|
|
|
GrGLShaderBuilder::kFragment_ShaderType,
|
|
|
|
|
kFloat_GrSLType, "uExponent", stage);
|
|
|
|
|
fCosInnerConeAngleVar = &state->addUniform(
|
|
|
|
|
GrGLShaderBuilder::kFragment_ShaderType,
|
|
|
|
|
kFloat_GrSLType, "uCosInnerConeAngle", stage);
|
|
|
|
|
fCosOuterConeAngleVar = &state->addUniform(
|
|
|
|
|
GrGLShaderBuilder::kFragment_ShaderType,
|
|
|
|
|
kFloat_GrSLType, "uCosOuterConeAngle", stage);
|
|
|
|
|
fConeScaleVar = &state->addUniform(
|
|
|
|
|
GrGLShaderBuilder::kFragment_ShaderType,
|
|
|
|
|
kFloat_GrSLType, "uConeScale", stage);
|
|
|
|
|
fSVar = &state->addUniform(
|
|
|
|
|
GrGLShaderBuilder::kFragment_ShaderType,
|
|
|
|
|
kVec3f_GrSLType, "uS", stage);
|
|
|
|
|
state->addVarying(kFloat_GrSLType, "Height", stage, &fHeightVaryingName);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GrGLSpotLight::initUniforms(const GrGLInterface* gl, int programID) {
|
|
|
|
|
INHERITED::initUniforms(gl, programID);
|
|
|
|
|
GR_GL_CALL_RET(gl, fLocationLocation,
|
|
|
|
|
GetUniformLocation(programID, fLocationVar->getName().c_str()));
|
|
|
|
|
GR_GL_CALL_RET(gl, fExponentLocation,
|
|
|
|
|
GetUniformLocation(programID, fExponentVar->getName().c_str()));
|
|
|
|
|
GR_GL_CALL_RET(gl, fCosInnerConeAngleLocation,
|
|
|
|
|
GetUniformLocation(programID, fCosInnerConeAngleVar->getName().c_str()));
|
|
|
|
|
GR_GL_CALL_RET(gl, fCosOuterConeAngleLocation,
|
|
|
|
|
GetUniformLocation(programID, fCosOuterConeAngleVar->getName().c_str()));
|
|
|
|
|
GR_GL_CALL_RET(gl, fCosOuterConeAngleLocation,
|
|
|
|
|
GetUniformLocation(programID, fCosOuterConeAngleVar->getName().c_str()));
|
|
|
|
|
GR_GL_CALL_RET(gl, fConeScaleLocation,
|
|
|
|
|
GetUniformLocation(programID, fConeScaleVar->getName().c_str()));
|
|
|
|
|
GR_GL_CALL_RET(gl, fSLocation,
|
|
|
|
|
GetUniformLocation(programID, fSVar->getName().c_str()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GrGLSpotLight::setData(const GrGLInterface* gl, const SkLight* light) const {
|
|
|
|
|
INHERITED::setData(gl, light);
|
|
|
|
|
SkASSERT(light->type() == SkLight::kSpot_LightType);
|
|
|
|
|
const SkSpotLight* spotLight = static_cast<const SkSpotLight *>(light);
|
|
|
|
|
setUniformPoint3(gl, fLocationLocation, spotLight->location());
|
|
|
|
|
GR_GL_CALL(gl, Uniform1f(fExponentLocation, spotLight->specularExponent()));
|
|
|
|
|
GR_GL_CALL(gl, Uniform1f(fCosInnerConeAngleLocation, spotLight->cosInnerConeAngle()));
|
|
|
|
|
GR_GL_CALL(gl, Uniform1f(fCosOuterConeAngleLocation, spotLight->cosOuterConeAngle()));
|
|
|
|
|
GR_GL_CALL(gl, Uniform1f(fConeScaleLocation, spotLight->coneScale()));
|
|
|
|
|
setUniformPoint3(gl, fSLocation, spotLight->s());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GrGLSpotLight::emitVS(SkString* builder) const {
|
|
|
|
|
// Compute viewport height from the Y scale of the matrix.
|
|
|
|
|
builder->appendf("\t\t%s = -2.0 / uViewM[1][1];\n", fHeightVaryingName);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GrGLSpotLight::emitFuncs(SkString* builder) const {
|
|
|
|
|
builder->appendf("vec3 lightColor(vec3 surfaceToLight) {\n");
|
|
|
|
|
builder->appendf("\tfloat cosAngle = -dot(surfaceToLight, %s);\n", fSVar->getName().c_str());
|
|
|
|
|
builder->appendf("\tif (cosAngle < %s) {\n", fCosOuterConeAngleVar->getName().c_str());
|
|
|
|
|
builder->appendf("\t\treturn vec3(0);\n");
|
|
|
|
|
builder->appendf("\t}\n");
|
|
|
|
|
builder->appendf("\tfloat scale = pow(cosAngle, %s);\n", fExponentVar->getName().c_str());
|
|
|
|
|
builder->appendf("\tif (cosAngle < %s) {\n", fCosInnerConeAngleVar->getName().c_str());
|
|
|
|
|
builder->appendf("\t\treturn %s * scale * (cosAngle - %s) * %s;\n", fColorVar->getName().c_str(), fCosOuterConeAngleVar->getName().c_str(), fConeScaleVar->getName().c_str());
|
|
|
|
|
builder->appendf("\t}\n");
|
|
|
|
|
builder->appendf("\treturn %s;\n", fColorVar->getName().c_str());
|
|
|
|
|
builder->appendf("}\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GrGLSpotLight::emitSurfaceToLight(SkString* builder, const char* z) const {
|
|
|
|
|
builder->appendf("normalize(%s - vec3(gl_FragCoord.x, %s - gl_FragCoord.y, %s))", fLocationVar->getName().c_str(), fHeightVaryingName, z);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GrGLSpotLight::emitLightColor(SkString* builder, const char *surfaceToLight) const {
|
|
|
|
|
builder->appendf("lightColor(%s)", surfaceToLight);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkLightingImageFilter)
|
|
|
|
|
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDiffuseLightingImageFilter)
|
|
|
|
|
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSpecularLightingImageFilter)
|
|
|
|
|