| OLD | NEW |
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2015 Google Inc. | 3 * Copyright 2015 Google Inc. |
| 4 * | 4 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 #include "SkBitmapProcState.h" | 9 #include "SkBitmapProcState.h" |
| 10 #include "SkColor.h" | 10 #include "SkColor.h" |
| 11 #include "SkEmptyShader.h" | 11 #include "SkEmptyShader.h" |
| 12 #include "SkErrorInternals.h" | 12 #include "SkErrorInternals.h" |
| 13 #include "SkLightingShader.h" | 13 #include "SkLightingShader.h" |
| 14 #include "SkMathPriv.h" | 14 #include "SkMathPriv.h" |
| 15 #include "SkReadBuffer.h" | 15 #include "SkReadBuffer.h" |
| 16 #include "SkWriteBuffer.h" | 16 #include "SkWriteBuffer.h" |
| 17 | 17 |
| 18 //////////////////////////////////////////////////////////////////////////// | 18 //////////////////////////////////////////////////////////////////////////// |
| 19 | 19 |
| 20 /* | 20 /* |
| 21 SkLightingShader TODOs: | 21 SkLightingShader TODOs: |
| 22 support other than clamp mode | 22 support other than clamp mode |
| 23 allow 'diffuse' & 'normal' to be of different dimensions? | 23 allow 'diffuse' & 'normal' to be of different dimensions? |
| 24 support different light types | 24 support different light types |
| 25 support multiple lights | 25 support multiple lights |
| 26 enforce normal map is 4 channel | 26 enforce normal map is 4 channel |
| 27 use SkImages instead if SkBitmaps | 27 use SkImages instead if SkBitmaps |
| 28 vec3 for ambient and light-color | |
| 29 add dox for both lighting equation, and how we compute normal from bitma
p | |
| 30 | 28 |
| 31 To Test: | 29 To Test: |
| 32 non-opaque diffuse textures | 30 non-opaque diffuse textures |
| 33 A8 diffuse textures | 31 A8 diffuse textures |
| 34 down & upsampled draws | 32 down & upsampled draws |
| 35 */ | 33 */ |
| 36 | 34 |
| 37 | 35 |
| 38 | 36 |
| 39 /** \class SkLightingShaderImpl | 37 /** \class SkLightingShaderImpl |
| 40 This subclass of shader applies lighting. | 38 This subclass of shader applies lighting. |
| 41 */ | 39 */ |
| 42 class SK_API SkLightingShaderImpl : public SkShader { | 40 class SK_API SkLightingShaderImpl : public SkShader { |
| 43 public: | 41 public: |
| 44 | 42 |
| 45 /** Create a new lighting shader that use the provided normal map, light | 43 /** Create a new lighting shader that use the provided normal map, light |
| 46 and ambient color to light the diffuse bitmap. | 44 and ambient color to light the diffuse bitmap. |
| 47 @param diffuse the diffuse bitmap | 45 @param diffuse the diffuse bitmap |
| 48 @param normal the normal map | 46 @param normal the normal map |
| 49 @param light the light applied to the normal map | 47 @param light the light applied to the normal map |
| 50 @param ambient the linear (unpremul) ambient light color | 48 @param ambient the linear (unpremul) ambient light color |
| 51 */ | 49 */ |
| 52 SkLightingShaderImpl(const SkBitmap& diffuse, const SkBitmap& normal, | 50 SkLightingShaderImpl(const SkBitmap& diffuse, const SkBitmap& normal, |
| 53 const SkLightingShader::Light& light, | 51 const SkLightingShader::Light& light, |
| 54 const SkColor ambient, const SkMatrix* localMatrix) | 52 const SkColor3f& ambient, const SkMatrix* localMatrix) |
| 55 : INHERITED(localMatrix) | 53 : INHERITED(localMatrix) |
| 56 , fDiffuseMap(diffuse) | 54 , fDiffuseMap(diffuse) |
| 57 , fNormalMap(normal) | 55 , fNormalMap(normal) |
| 58 , fLight(light) | 56 , fLight(light) |
| 59 , fAmbientColor(ambient) { | 57 , fAmbientColor(ambient) { |
| 60 if (!fLight.fDirection.normalize()) { | 58 if (!fLight.fDirection.normalize()) { |
| 61 fLight.fDirection = SkPoint3::Make(0.0f, 0.0f, 1.0f); | 59 fLight.fDirection = SkPoint3::Make(0.0f, 0.0f, 1.0f); |
| 62 } | 60 } |
| 63 SkColorSetA(fLight.fColor, 0xFF); | |
| 64 SkColorSetA(fAmbientColor, 0xFF); | |
| 65 } | 61 } |
| 66 | 62 |
| 67 bool isOpaque() const override; | 63 bool isOpaque() const override; |
| 68 | 64 |
| 69 bool asFragmentProcessor(GrContext*, const SkPaint& paint, const SkMatrix& v
iewM, | 65 bool asFragmentProcessor(GrContext*, const SkPaint& paint, const SkMatrix& v
iewM, |
| 70 const SkMatrix* localMatrix, GrColor* color, | 66 const SkMatrix* localMatrix, GrColor* color, |
| 71 GrProcessorDataManager*, GrFragmentProcessor** fp)
const override; | 67 GrProcessorDataManager*, GrFragmentProcessor** fp)
const override; |
| 72 | 68 |
| 73 size_t contextSize() const override; | 69 size_t contextSize() const override; |
| 74 | 70 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 96 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLightingShaderImpl) | 92 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLightingShaderImpl) |
| 97 | 93 |
| 98 protected: | 94 protected: |
| 99 void flatten(SkWriteBuffer&) const override; | 95 void flatten(SkWriteBuffer&) const override; |
| 100 Context* onCreateContext(const ContextRec&, void*) const override; | 96 Context* onCreateContext(const ContextRec&, void*) const override; |
| 101 | 97 |
| 102 private: | 98 private: |
| 103 SkBitmap fDiffuseMap; | 99 SkBitmap fDiffuseMap; |
| 104 SkBitmap fNormalMap; | 100 SkBitmap fNormalMap; |
| 105 SkLightingShader::Light fLight; | 101 SkLightingShader::Light fLight; |
| 106 SkColor fAmbientColor; // linear (unpremul) color | 102 SkColor3f fAmbientColor; // linear (unpremul) color. Range is
0..1/channel. |
| 107 | 103 |
| 108 friend class SkLightingShader; | 104 friend class SkLightingShader; |
| 109 | 105 |
| 110 typedef SkShader INHERITED; | 106 typedef SkShader INHERITED; |
| 111 }; | 107 }; |
| 112 | 108 |
| 113 //////////////////////////////////////////////////////////////////////////// | 109 //////////////////////////////////////////////////////////////////////////// |
| 114 | 110 |
| 115 #if SK_SUPPORT_GPU | 111 #if SK_SUPPORT_GPU |
| 116 | 112 |
| 117 #include "GrCoordTransform.h" | 113 #include "GrCoordTransform.h" |
| 118 #include "GrFragmentProcessor.h" | 114 #include "GrFragmentProcessor.h" |
| 119 #include "GrTextureAccess.h" | 115 #include "GrTextureAccess.h" |
| 120 #include "gl/GrGLProcessor.h" | 116 #include "gl/GrGLProcessor.h" |
| 121 #include "gl/builders/GrGLProgramBuilder.h" | 117 #include "gl/builders/GrGLProgramBuilder.h" |
| 122 #include "SkGr.h" | 118 #include "SkGr.h" |
| 123 | 119 |
| 124 class LightingFP : public GrFragmentProcessor { | 120 class LightingFP : public GrFragmentProcessor { |
| 125 public: | 121 public: |
| 126 LightingFP(GrTexture* diffuse, GrTexture* normal, const SkMatrix& matrix, | 122 LightingFP(GrTexture* diffuse, GrTexture* normal, const SkMatrix& matrix, |
| 127 SkVector3 lightDir, GrColor lightColor, GrColor ambientColor) | 123 const SkVector3& lightDir, const SkColor3f& lightColor, |
| 124 const SkColor3f& ambientColor) |
| 128 : fDeviceTransform(kDevice_GrCoordSet, matrix) | 125 : fDeviceTransform(kDevice_GrCoordSet, matrix) |
| 129 , fDiffuseTextureAccess(diffuse) | 126 , fDiffuseTextureAccess(diffuse) |
| 130 , fNormalTextureAccess(normal) | 127 , fNormalTextureAccess(normal) |
| 131 , fLightDir(lightDir) | 128 , fLightDir(lightDir) |
| 132 , fLightColor(lightColor) | 129 , fLightColor(lightColor) |
| 133 , fAmbientColor(ambientColor) { | 130 , fAmbientColor(ambientColor) { |
| 134 this->addCoordTransform(&fDeviceTransform); | 131 this->addCoordTransform(&fDeviceTransform); |
| 135 this->addTextureAccess(&fDiffuseTextureAccess); | 132 this->addTextureAccess(&fDiffuseTextureAccess); |
| 136 this->addTextureAccess(&fNormalTextureAccess); | 133 this->addTextureAccess(&fNormalTextureAccess); |
| 137 | 134 |
| 138 this->initClassID<LightingFP>(); | 135 this->initClassID<LightingFP>(); |
| 139 } | 136 } |
| 140 | 137 |
| 141 class LightingGLFP : public GrGLFragmentProcessor { | 138 class LightingGLFP : public GrGLFragmentProcessor { |
| 142 public: | 139 public: |
| 143 LightingGLFP() : fLightColor(GrColor_ILLEGAL), fAmbientColor(GrColor_ILL
EGAL) { | 140 LightingGLFP() { |
| 144 fLightDir.fX = 10000.0f; | 141 fLightDir.fX = 10000.0f; |
| 142 fLightColor.fX = 0.0f; |
| 143 fAmbientColor.fX = 0.0f; |
| 145 } | 144 } |
| 146 | 145 |
| 147 void emitCode(EmitArgs& args) override { | 146 void emitCode(EmitArgs& args) override { |
| 148 | 147 |
| 149 GrGLFragmentBuilder* fpb = args.fBuilder->getFragmentShaderBuilder()
; | 148 GrGLFragmentBuilder* fpb = args.fBuilder->getFragmentShaderBuilder()
; |
| 150 | 149 |
| 151 // add uniforms | 150 // add uniforms |
| 152 const char* lightDirUniName = NULL; | 151 const char* lightDirUniName = NULL; |
| 153 fLightDirUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragme
nt_Visibility, | 152 fLightDirUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragme
nt_Visibility, |
| 154 kVec3f_GrSLType, kDefault_G
rSLPrecision, | 153 kVec3f_GrSLType, kDefault_G
rSLPrecision, |
| 155 "LightDir", &lightDirUniNam
e); | 154 "LightDir", &lightDirUniNam
e); |
| 156 | 155 |
| 157 const char* lightColorUniName = NULL; | 156 const char* lightColorUniName = NULL; |
| 158 fLightColorUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFrag
ment_Visibility, | 157 fLightColorUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFrag
ment_Visibility, |
| 159 kVec4f_GrSLType, kDefault
_GrSLPrecision, | 158 kVec3f_GrSLType, kDefault
_GrSLPrecision, |
| 160 "LightColor", &lightColor
UniName); | 159 "LightColor", &lightColor
UniName); |
| 161 | 160 |
| 162 const char* ambientColorUniName = NULL; | 161 const char* ambientColorUniName = NULL; |
| 163 fAmbientColorUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFr
agment_Visibility, | 162 fAmbientColorUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFr
agment_Visibility, |
| 164 kVec4f_GrSLType, kDefau
lt_GrSLPrecision, | 163 kVec3f_GrSLType, kDefau
lt_GrSLPrecision, |
| 165 "AmbientColor", &ambien
tColorUniName); | 164 "AmbientColor", &ambien
tColorUniName); |
| 166 | 165 |
| 167 fpb->codeAppend("vec4 diffuseColor = "); | 166 fpb->codeAppend("vec4 diffuseColor = "); |
| 168 fpb->appendTextureLookupAndModulate(args.fInputColor, args.fSamplers
[0], | 167 fpb->appendTextureLookupAndModulate(args.fInputColor, args.fSamplers
[0], |
| 169 args.fCoords[0].c_str(), | 168 args.fCoords[0].c_str(), |
| 170 args.fCoords[0].getType()); | 169 args.fCoords[0].getType()); |
| 171 fpb->codeAppend(";"); | 170 fpb->codeAppend(";"); |
| 172 | 171 |
| 173 fpb->codeAppend("vec4 normalColor = "); | 172 fpb->codeAppend("vec4 normalColor = "); |
| 174 fpb->appendTextureLookup(args.fSamplers[1], | 173 fpb->appendTextureLookup(args.fSamplers[1], |
| 175 args.fCoords[0].c_str(), | 174 args.fCoords[0].c_str(), |
| 176 args.fCoords[0].getType()); | 175 args.fCoords[0].getType()); |
| 177 fpb->codeAppend(";"); | 176 fpb->codeAppend(";"); |
| 178 | 177 |
| 179 fpb->codeAppend("vec3 normal = normalize(normalColor.rgb - vec3(0.5)
);"); | 178 fpb->codeAppend("vec3 normal = normalize(normalColor.rgb - vec3(0.5)
);"); |
| 180 fpb->codeAppendf("vec3 lightDir = normalize(%s);", lightDirUniName); | 179 fpb->codeAppendf("vec3 lightDir = normalize(%s);", lightDirUniName); |
| 181 fpb->codeAppend("float NdotL = dot(normal, lightDir);"); | 180 fpb->codeAppend("float NdotL = dot(normal, lightDir);"); |
| 182 // diffuse light | 181 // diffuse light |
| 183 fpb->codeAppendf("vec3 result = %s.rgb*diffuseColor.rgb*NdotL;", lig
htColorUniName); | 182 fpb->codeAppendf("vec3 result = %s*diffuseColor.rgb*NdotL;", lightCo
lorUniName); |
| 184 // ambient light | 183 // ambient light |
| 185 fpb->codeAppendf("result += %s.rgb;", ambientColorUniName); | 184 fpb->codeAppendf("result += %s;", ambientColorUniName); |
| 186 fpb->codeAppendf("%s = vec4(result.rgb, diffuseColor.a);", args.fOut
putColor); | 185 fpb->codeAppendf("%s = vec4(result.rgb, diffuseColor.a);", args.fOut
putColor); |
| 187 } | 186 } |
| 188 | 187 |
| 189 void setData(const GrGLProgramDataManager& pdman, const GrProcessor& pro
c) override { | 188 void setData(const GrGLProgramDataManager& pdman, const GrProcessor& pro
c) override { |
| 190 const LightingFP& lightingFP = proc.cast<LightingFP>(); | 189 const LightingFP& lightingFP = proc.cast<LightingFP>(); |
| 191 | 190 |
| 192 SkVector3 lightDir = lightingFP.lightDir(); | 191 const SkVector3& lightDir = lightingFP.lightDir(); |
| 193 if (lightDir != fLightDir) { | 192 if (lightDir != fLightDir) { |
| 194 pdman.set3fv(fLightDirUni, 1, &lightDir.fX); | 193 pdman.set3fv(fLightDirUni, 1, &lightDir.fX); |
| 195 fLightDir = lightDir; | 194 fLightDir = lightDir; |
| 196 } | 195 } |
| 197 | 196 |
| 198 GrColor lightColor = lightingFP.lightColor(); | 197 const SkColor3f& lightColor = lightingFP.lightColor(); |
| 199 if (lightColor != fLightColor) { | 198 if (lightColor != fLightColor) { |
| 200 GrGLfloat c[4]; | 199 pdman.set3fv(fLightColorUni, 1, &lightColor.fX); |
| 201 GrColorToRGBAFloat(lightColor, c); | |
| 202 pdman.set4fv(fLightColorUni, 1, c); | |
| 203 fLightColor = lightColor; | 200 fLightColor = lightColor; |
| 204 } | 201 } |
| 205 | 202 |
| 206 GrColor ambientColor = lightingFP.ambientColor(); | 203 const SkColor3f& ambientColor = lightingFP.ambientColor(); |
| 207 if (ambientColor != fAmbientColor) { | 204 if (ambientColor != fAmbientColor) { |
| 208 GrGLfloat c[4]; | 205 pdman.set3fv(fAmbientColorUni, 1, &ambientColor.fX); |
| 209 GrColorToRGBAFloat(ambientColor, c); | |
| 210 pdman.set4fv(fAmbientColorUni, 1, c); | |
| 211 fAmbientColor = ambientColor; | 206 fAmbientColor = ambientColor; |
| 212 } | 207 } |
| 213 } | 208 } |
| 214 | 209 |
| 215 static void GenKey(const GrProcessor& proc, const GrGLSLCaps&, | 210 static void GenKey(const GrProcessor& proc, const GrGLSLCaps&, |
| 216 GrProcessorKeyBuilder* b) { | 211 GrProcessorKeyBuilder* b) { |
| 217 // const LightingFP& lightingFP = proc.cast<LightingFP>(); | 212 // const LightingFP& lightingFP = proc.cast<LightingFP>(); |
| 218 // only one shader generated currently | 213 // only one shader generated currently |
| 219 b->add32(0x0); | 214 b->add32(0x0); |
| 220 } | 215 } |
| 221 | 216 |
| 222 private: | 217 private: |
| 223 SkVector3 fLightDir; | 218 SkVector3 fLightDir; |
| 224 GrGLProgramDataManager::UniformHandle fLightDirUni; | 219 GrGLProgramDataManager::UniformHandle fLightDirUni; |
| 225 | 220 |
| 226 GrColor fLightColor; | 221 SkColor3f fLightColor; |
| 227 GrGLProgramDataManager::UniformHandle fLightColorUni; | 222 GrGLProgramDataManager::UniformHandle fLightColorUni; |
| 228 | 223 |
| 229 GrColor fAmbientColor; | 224 SkColor3f fAmbientColor; |
| 230 GrGLProgramDataManager::UniformHandle fAmbientColorUni; | 225 GrGLProgramDataManager::UniformHandle fAmbientColorUni; |
| 231 }; | 226 }; |
| 232 | 227 |
| 233 GrGLFragmentProcessor* createGLInstance() const override { return SkNEW(Ligh
tingGLFP); } | 228 GrGLFragmentProcessor* createGLInstance() const override { return SkNEW(Ligh
tingGLFP); } |
| 234 | 229 |
| 235 void getGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) con
st override { | 230 void getGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) con
st override { |
| 236 LightingGLFP::GenKey(*this, caps, b); | 231 LightingGLFP::GenKey(*this, caps, b); |
| 237 } | 232 } |
| 238 | 233 |
| 239 const char* name() const override { return "LightingFP"; } | 234 const char* name() const override { return "LightingFP"; } |
| 240 | 235 |
| 241 void onComputeInvariantOutput(GrInvariantOutput* inout) const override { | 236 void onComputeInvariantOutput(GrInvariantOutput* inout) const override { |
| 242 inout->mulByUnknownFourComponents(); | 237 inout->mulByUnknownFourComponents(); |
| 243 } | 238 } |
| 244 | 239 |
| 245 SkVector3 lightDir() const { return fLightDir; } | 240 const SkVector3& lightDir() const { return fLightDir; } |
| 246 GrColor lightColor() const { return fLightColor; } | 241 const SkColor3f& lightColor() const { return fLightColor; } |
| 247 GrColor ambientColor() const { return fAmbientColor; } | 242 const SkColor3f& ambientColor() const { return fAmbientColor; } |
| 248 | 243 |
| 249 private: | 244 private: |
| 250 bool onIsEqual(const GrFragmentProcessor& proc) const override { | 245 bool onIsEqual(const GrFragmentProcessor& proc) const override { |
| 251 const LightingFP& lightingFP = proc.cast<LightingFP>(); | 246 const LightingFP& lightingFP = proc.cast<LightingFP>(); |
| 252 return fDeviceTransform == lightingFP.fDeviceTransform && | 247 return fDeviceTransform == lightingFP.fDeviceTransform && |
| 253 fDiffuseTextureAccess == lightingFP.fDiffuseTextureAccess && | 248 fDiffuseTextureAccess == lightingFP.fDiffuseTextureAccess && |
| 254 fNormalTextureAccess == lightingFP.fNormalTextureAccess && | 249 fNormalTextureAccess == lightingFP.fNormalTextureAccess && |
| 255 fLightDir == lightingFP.fLightDir && | 250 fLightDir == lightingFP.fLightDir && |
| 256 fLightColor == lightingFP.fLightColor && | 251 fLightColor == lightingFP.fLightColor && |
| 257 fAmbientColor == lightingFP.fAmbientColor; | 252 fAmbientColor == lightingFP.fAmbientColor; |
| 258 } | 253 } |
| 259 | 254 |
| 260 GrCoordTransform fDeviceTransform; | 255 GrCoordTransform fDeviceTransform; |
| 261 GrTextureAccess fDiffuseTextureAccess; | 256 GrTextureAccess fDiffuseTextureAccess; |
| 262 GrTextureAccess fNormalTextureAccess; | 257 GrTextureAccess fNormalTextureAccess; |
| 263 SkVector3 fLightDir; | 258 SkVector3 fLightDir; |
| 264 GrColor fLightColor; | 259 SkColor3f fLightColor; |
| 265 GrColor fAmbientColor; | 260 SkColor3f fAmbientColor; |
| 266 }; | 261 }; |
| 267 | 262 |
| 268 //////////////////////////////////////////////////////////////////////////// | 263 //////////////////////////////////////////////////////////////////////////// |
| 269 | 264 |
| 270 bool SkLightingShaderImpl::asFragmentProcessor(GrContext* context, const SkPaint
& paint, | 265 bool SkLightingShaderImpl::asFragmentProcessor(GrContext* context, const SkPaint
& paint, |
| 271 const SkMatrix& viewM, const SkMa
trix* localMatrix, | 266 const SkMatrix& viewM, const SkMa
trix* localMatrix, |
| 272 GrColor* color, GrProcessorDataMa
nager*, | 267 GrColor* color, GrProcessorDataMa
nager*, |
| 273 GrFragmentProcessor** fp) const { | 268 GrFragmentProcessor** fp) const { |
| 274 // we assume diffuse and normal maps have same width and height | 269 // we assume diffuse and normal maps have same width and height |
| 275 // TODO: support different sizes | 270 // TODO: support different sizes |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 334 return false; | 329 return false; |
| 335 } | 330 } |
| 336 | 331 |
| 337 SkAutoTUnref<GrTexture> normalTexture(GrRefCachedBitmapTexture(context, fNor
malMap, ¶ms)); | 332 SkAutoTUnref<GrTexture> normalTexture(GrRefCachedBitmapTexture(context, fNor
malMap, ¶ms)); |
| 338 if (!normalTexture) { | 333 if (!normalTexture) { |
| 339 SkErrorInternals::SetError(kInternalError_SkError, | 334 SkErrorInternals::SetError(kInternalError_SkError, |
| 340 "Couldn't convert bitmap to texture."); | 335 "Couldn't convert bitmap to texture."); |
| 341 return false; | 336 return false; |
| 342 } | 337 } |
| 343 | 338 |
| 344 GrColor lightColor = GrColorPackRGBA(SkColorGetR(fLight.fColor), SkColorGetG
(fLight.fColor), | |
| 345 SkColorGetB(fLight.fColor), SkColorGetA
(fLight.fColor)); | |
| 346 GrColor ambientColor = GrColorPackRGBA(SkColorGetR(fAmbientColor), SkColorGe
tG(fAmbientColor), | |
| 347 SkColorGetB(fAmbientColor), SkColorGe
tA(fAmbientColor)); | |
| 348 | |
| 349 *fp = SkNEW_ARGS(LightingFP, (diffuseTexture, normalTexture, matrix, | 339 *fp = SkNEW_ARGS(LightingFP, (diffuseTexture, normalTexture, matrix, |
| 350 fLight.fDirection, lightColor, ambientColor)); | 340 fLight.fDirection, fLight.fColor, fAmbientColo
r)); |
| 351 *color = GrColorPackA4(paint.getAlpha()); | 341 *color = GrColorPackA4(paint.getAlpha()); |
| 352 return true; | 342 return true; |
| 353 } | 343 } |
| 354 #else | 344 #else |
| 355 | 345 |
| 356 bool SkLightingShaderImpl::asFragmentProcessor(GrContext* context, const SkPaint
& paint, | 346 bool SkLightingShaderImpl::asFragmentProcessor(GrContext* context, const SkPaint
& paint, |
| 357 const SkMatrix& viewM, const SkMa
trix* localMatrix, | 347 const SkMatrix& viewM, const SkMa
trix* localMatrix, |
| 358 GrColor* color, GrProcessorDataMa
nager*, | 348 GrColor* color, GrProcessorDataMa
nager*, |
| 359 GrFragmentProcessor** fp) const { | 349 GrFragmentProcessor** fp) const { |
| 360 SkDEBUGFAIL("Should not call in GPU-less build"); | 350 SkDEBUGFAIL("Should not call in GPU-less build"); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 393 fFlags = flags; | 383 fFlags = flags; |
| 394 } | 384 } |
| 395 | 385 |
| 396 SkLightingShaderImpl::LightingShaderContext::~LightingShaderContext() { | 386 SkLightingShaderImpl::LightingShaderContext::~LightingShaderContext() { |
| 397 // The bitmap proc states have been created outside of the context on memory
that will be freed | 387 // The bitmap proc states have been created outside of the context on memory
that will be freed |
| 398 // elsewhere. Call the destructors but leave the freeing of the memory to th
e caller. | 388 // elsewhere. Call the destructors but leave the freeing of the memory to th
e caller. |
| 399 fDiffuseState->~SkBitmapProcState(); | 389 fDiffuseState->~SkBitmapProcState(); |
| 400 fNormalState->~SkBitmapProcState(); | 390 fNormalState->~SkBitmapProcState(); |
| 401 } | 391 } |
| 402 | 392 |
| 403 static inline int light(int light, int diff, SkScalar NdotL, int ambient) { | 393 static inline int light(SkScalar light, int diff, SkScalar NdotL, SkScalar ambie
nt) { |
| 404 int color = int(light * diff * NdotL + 255 * ambient); | 394 SkScalar color = light * diff * NdotL + 255 * ambient; |
| 405 if (color <= 0) { | 395 if (color <= 0.0f) { |
| 406 return 0; | 396 return 0; |
| 407 } else if (color >= 255*255) { | 397 } else if (color >= 255.0f) { |
| 408 return 255; | 398 return 255; |
| 409 } else { | 399 } else { |
| 410 return SkDiv255Round(color); | 400 return (int) color; |
| 411 } | 401 } |
| 412 } | 402 } |
| 413 | 403 |
| 414 // larger is better (fewer times we have to loop), but we shouldn't | 404 // larger is better (fewer times we have to loop), but we shouldn't |
| 415 // take up too much stack-space (each could here costs 16 bytes) | 405 // take up too much stack-space (each could here costs 16 bytes) |
| 416 #define TMP_COUNT 16 | 406 #define TMP_COUNT 16 |
| 417 | 407 |
| 418 void SkLightingShaderImpl::LightingShaderContext::shadeSpan(int x, int y, | 408 void SkLightingShaderImpl::LightingShaderContext::shadeSpan(int x, int y, |
| 419 SkPMColor result[],
int count) { | 409 SkPMColor result[],
int count) { |
| 420 const SkLightingShaderImpl& lightShader = static_cast<const SkLightingShader
Impl&>(fShader); | 410 const SkLightingShaderImpl& lightShader = static_cast<const SkLightingShader
Impl&>(fShader); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 451 SkASSERT(0xFF == SkColorGetA(tmpNormal2[i])); // opaque -> unpremul | 441 SkASSERT(0xFF == SkColorGetA(tmpNormal2[i])); // opaque -> unpremul |
| 452 norm.set(SkIntToScalar(SkGetPackedR32(tmpNormal2[i]))-127.0f, | 442 norm.set(SkIntToScalar(SkGetPackedR32(tmpNormal2[i]))-127.0f, |
| 453 SkIntToScalar(SkGetPackedG32(tmpNormal2[i]))-127.0f, | 443 SkIntToScalar(SkGetPackedG32(tmpNormal2[i]))-127.0f, |
| 454 SkIntToScalar(SkGetPackedB32(tmpNormal2[i]))-127.0f); | 444 SkIntToScalar(SkGetPackedB32(tmpNormal2[i]))-127.0f); |
| 455 norm.normalize(); | 445 norm.normalize(); |
| 456 | 446 |
| 457 SkColor diffColor = SkUnPreMultiply::PMColorToColor(tmpColor2[i]); | 447 SkColor diffColor = SkUnPreMultiply::PMColorToColor(tmpColor2[i]); |
| 458 NdotL = norm.dot(lightShader.fLight.fDirection); | 448 NdotL = norm.dot(lightShader.fLight.fDirection); |
| 459 | 449 |
| 460 // This is all done in linear unpremul color space | 450 // This is all done in linear unpremul color space |
| 461 r = light(SkColorGetR(lightShader.fLight.fColor), SkColorGetR(diffCo
lor), NdotL, | 451 r = light(lightShader.fLight.fColor.fX, SkColorGetR(diffColor), Ndot
L, |
| 462 SkColorGetR(lightShader.fAmbientColor)); | 452 lightShader.fAmbientColor.fX); |
| 463 g = light(SkColorGetG(lightShader.fLight.fColor), SkColorGetG(diffCo
lor), NdotL, | 453 g = light(lightShader.fLight.fColor.fY, SkColorGetG(diffColor), Ndot
L, |
| 464 SkColorGetG(lightShader.fAmbientColor)); | 454 lightShader.fAmbientColor.fY); |
| 465 b = light(SkColorGetB(lightShader.fLight.fColor), SkColorGetB(diffCo
lor), NdotL, | 455 b = light(lightShader.fLight.fColor.fZ, SkColorGetB(diffColor), Ndot
L, |
| 466 SkColorGetB(lightShader.fAmbientColor)); | 456 lightShader.fAmbientColor.fZ); |
| 467 | 457 |
| 468 result[i] = SkPreMultiplyARGB(SkColorGetA(diffColor), r, g, b); | 458 result[i] = SkPreMultiplyARGB(SkColorGetA(diffColor), r, g, b); |
| 469 } | 459 } |
| 470 | 460 |
| 471 result += n; | 461 result += n; |
| 472 x += n; | 462 x += n; |
| 473 count -= n; | 463 count -= n; |
| 474 } while (count > 0); | 464 } while (count > 0); |
| 475 } | 465 } |
| 476 | 466 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 495 SkBitmap normal; | 485 SkBitmap normal; |
| 496 if (!buf.readBitmap(&normal)) { | 486 if (!buf.readBitmap(&normal)) { |
| 497 return NULL; | 487 return NULL; |
| 498 } | 488 } |
| 499 normal.setImmutable(); | 489 normal.setImmutable(); |
| 500 | 490 |
| 501 SkLightingShader::Light light; | 491 SkLightingShader::Light light; |
| 502 if (!buf.readScalarArray(&light.fDirection.fX, 3)) { | 492 if (!buf.readScalarArray(&light.fDirection.fX, 3)) { |
| 503 return NULL; | 493 return NULL; |
| 504 } | 494 } |
| 505 light.fColor = buf.readColor(); | 495 if (!buf.readScalarArray(&light.fColor.fX, 3)) { |
| 496 return NULL; |
| 497 } |
| 506 | 498 |
| 507 SkColor ambient = buf.readColor(); | 499 SkColor3f ambient; |
| 500 if (!buf.readScalarArray(&ambient.fX, 3)) { |
| 501 return NULL; |
| 502 } |
| 508 | 503 |
| 509 return SkNEW_ARGS(SkLightingShaderImpl, (diffuse, normal, light, ambient, &l
ocalMatrix)); | 504 return SkNEW_ARGS(SkLightingShaderImpl, (diffuse, normal, light, ambient, &l
ocalMatrix)); |
| 510 } | 505 } |
| 511 | 506 |
| 512 void SkLightingShaderImpl::flatten(SkWriteBuffer& buf) const { | 507 void SkLightingShaderImpl::flatten(SkWriteBuffer& buf) const { |
| 513 buf.writeMatrix(this->getLocalMatrix()); | 508 buf.writeMatrix(this->getLocalMatrix()); |
| 514 | 509 |
| 515 buf.writeBitmap(fDiffuseMap); | 510 buf.writeBitmap(fDiffuseMap); |
| 516 buf.writeBitmap(fNormalMap); | 511 buf.writeBitmap(fNormalMap); |
| 517 buf.writeScalarArray(&fLight.fDirection.fX, 3); | 512 buf.writeScalarArray(&fLight.fDirection.fX, 3); |
| 518 buf.writeColor(fLight.fColor); | 513 buf.writeScalarArray(&fLight.fColor.fX, 3); |
| 519 buf.writeColor(fAmbientColor); | 514 buf.writeScalarArray(&fAmbientColor.fX, 3); |
| 520 } | 515 } |
| 521 | 516 |
| 522 SkShader::Context* SkLightingShaderImpl::onCreateContext(const ContextRec& rec, | 517 SkShader::Context* SkLightingShaderImpl::onCreateContext(const ContextRec& rec, |
| 523 void* storage) const { | 518 void* storage) const { |
| 524 | 519 |
| 525 SkMatrix totalInverse; | 520 SkMatrix totalInverse; |
| 526 // Do this first, so we know the matrix can be inverted. | 521 // Do this first, so we know the matrix can be inverted. |
| 527 if (!this->computeTotalInverse(rec, &totalInverse)) { | 522 if (!this->computeTotalInverse(rec, &totalInverse)) { |
| 528 return NULL; | 523 return NULL; |
| 529 } | 524 } |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 564 // communicates between its matrix-proc and its sampler-proc. Until we can | 559 // communicates between its matrix-proc and its sampler-proc. Until we can |
| 565 // widen that, we have to reject bitmaps that are larger. | 560 // widen that, we have to reject bitmaps that are larger. |
| 566 // | 561 // |
| 567 static const int kMaxSize = 65535; | 562 static const int kMaxSize = 65535; |
| 568 | 563 |
| 569 return bm.width() > kMaxSize || bm.height() > kMaxSize; | 564 return bm.width() > kMaxSize || bm.height() > kMaxSize; |
| 570 } | 565 } |
| 571 | 566 |
| 572 SkShader* SkLightingShader::Create(const SkBitmap& diffuse, const SkBitmap& norm
al, | 567 SkShader* SkLightingShader::Create(const SkBitmap& diffuse, const SkBitmap& norm
al, |
| 573 const SkLightingShader::Light& light, | 568 const SkLightingShader::Light& light, |
| 574 const SkColor ambient, | 569 const SkColor3f& ambient, |
| 575 const SkMatrix* localMatrix) { | 570 const SkMatrix* localMatrix) { |
| 576 if (diffuse.isNull() || bitmap_is_too_big(diffuse) || | 571 if (diffuse.isNull() || bitmap_is_too_big(diffuse) || |
| 577 normal.isNull() || bitmap_is_too_big(normal) || | 572 normal.isNull() || bitmap_is_too_big(normal) || |
| 578 diffuse.width() != normal.width() || | 573 diffuse.width() != normal.width() || |
| 579 diffuse.height() != normal.height()) { | 574 diffuse.height() != normal.height()) { |
| 580 return nullptr; | 575 return nullptr; |
| 581 } | 576 } |
| 582 | 577 |
| 583 return SkNEW_ARGS(SkLightingShaderImpl, (diffuse, normal, light, ambient, lo
calMatrix)); | 578 return SkNEW_ARGS(SkLightingShaderImpl, (diffuse, normal, light, ambient, lo
calMatrix)); |
| 584 } | 579 } |
| 585 | 580 |
| 586 /////////////////////////////////////////////////////////////////////////////// | 581 /////////////////////////////////////////////////////////////////////////////// |
| 587 | 582 |
| 588 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkLightingShader) | 583 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkLightingShader) |
| 589 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLightingShaderImpl) | 584 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLightingShaderImpl) |
| 590 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END | 585 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END |
| 591 | 586 |
| 592 /////////////////////////////////////////////////////////////////////////////// | 587 /////////////////////////////////////////////////////////////////////////////// |
| OLD | NEW |