| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkError.h" | 8 #include "SkError.h" |
| 9 #include "SkErrorInternals.h" | 9 #include "SkErrorInternals.h" |
| 10 #include "SkLightingShader.h" | 10 #include "SkLightingShader.h" |
| 11 #include "SkMatrix.h" |
| 11 #include "SkNormalSource.h" | 12 #include "SkNormalSource.h" |
| 12 #include "SkReadBuffer.h" | 13 #include "SkReadBuffer.h" |
| 13 #include "SkWriteBuffer.h" | 14 #include "SkWriteBuffer.h" |
| 14 | 15 |
| 15 // Genretating vtable | 16 // Genretating vtable |
| 16 SkNormalSource::~SkNormalSource() {} | 17 SkNormalSource::~SkNormalSource() {} |
| 17 | 18 |
| 18 /////////////////////////////////////////////////////////////////////////////// | 19 /////////////////////////////////////////////////////////////////////////////// |
| 19 | 20 |
| 20 class NormalMapSourceImpl : public SkNormalSource { | 21 class NormalMapSourceImpl : public SkNormalSource { |
| 21 public: | 22 public: |
| 22 NormalMapSourceImpl(sk_sp<SkShader> mapShader, const SkVector &normRotation) | 23 NormalMapSourceImpl(sk_sp<SkShader> mapShader, const SkMatrix& invCTM) |
| 23 : fMapShader(std::move(mapShader)) | 24 : fMapShader(std::move(mapShader)) |
| 24 , fNormRotation(normRotation) {} | 25 , fInvCTM(invCTM) {} |
| 25 | 26 |
| 26 #if SK_SUPPORT_GPU | 27 #if SK_SUPPORT_GPU |
| 27 sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*, | 28 sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*, |
| 28 const SkMatrix& viewM, | 29 const SkMatrix& viewM, |
| 29 const SkMatrix* localMatrix, | 30 const SkMatrix* localMatrix, |
| 30 SkFilterQuality, | 31 SkFilterQuality, |
| 31 SkSourceGammaTreatment) const
override; | 32 SkSourceGammaTreatment) const
override; |
| 32 #endif | 33 #endif |
| 33 | 34 |
| 34 SkNormalSource::Provider* asProvider(const SkShader::ContextRec& rec, | 35 SkNormalSource::Provider* asProvider(const SkShader::ContextRec& rec, |
| (...skipping 16 matching lines...) Expand all Loading... |
| 51 | 52 |
| 52 void fillScanLine(int x, int y, SkPoint3 output[], int count) const over
ride; | 53 void fillScanLine(int x, int y, SkPoint3 output[], int count) const over
ride; |
| 53 private: | 54 private: |
| 54 const NormalMapSourceImpl& fSource; | 55 const NormalMapSourceImpl& fSource; |
| 55 SkShader::Context* fMapContext; | 56 SkShader::Context* fMapContext; |
| 56 | 57 |
| 57 typedef SkNormalSource::Provider INHERITED; | 58 typedef SkNormalSource::Provider INHERITED; |
| 58 }; | 59 }; |
| 59 | 60 |
| 60 sk_sp<SkShader> fMapShader; | 61 sk_sp<SkShader> fMapShader; |
| 61 SkVector fNormRotation; | 62 SkMatrix fInvCTM; // Inverse of the canvas total matrix, used for rot
ating normals. |
| 62 | 63 |
| 63 friend class SkNormalSource; | 64 friend class SkNormalSource; |
| 64 | 65 |
| 65 typedef SkNormalSource INHERITED; | 66 typedef SkNormalSource INHERITED; |
| 66 }; | 67 }; |
| 67 | 68 |
| 68 //////////////////////////////////////////////////////////////////////////// | 69 //////////////////////////////////////////////////////////////////////////// |
| 69 | 70 |
| 70 #if SK_SUPPORT_GPU | 71 #if SK_SUPPORT_GPU |
| 71 | 72 |
| 72 #include "GrCoordTransform.h" | 73 #include "GrCoordTransform.h" |
| 73 #include "GrInvariantOutput.h" | 74 #include "GrInvariantOutput.h" |
| 74 #include "GrTextureParams.h" | 75 #include "GrTextureParams.h" |
| 75 #include "glsl/GrGLSLFragmentProcessor.h" | 76 #include "glsl/GrGLSLFragmentProcessor.h" |
| 76 #include "glsl/GrGLSLFragmentShaderBuilder.h" | 77 #include "glsl/GrGLSLFragmentShaderBuilder.h" |
| 77 #include "SkGr.h" | 78 #include "SkGr.h" |
| 78 | 79 |
| 79 class NormalMapFP : public GrFragmentProcessor { | 80 class NormalMapFP : public GrFragmentProcessor { |
| 80 public: | 81 public: |
| 81 NormalMapFP(sk_sp<GrFragmentProcessor> mapFP, const SkVector& normRotation) | 82 NormalMapFP(sk_sp<GrFragmentProcessor> mapFP, const SkMatrix& invCTM) |
| 82 : fNormRotation(normRotation) { | 83 : fInvCTM(invCTM) { |
| 83 this->registerChildProcessor(mapFP); | 84 this->registerChildProcessor(mapFP); |
| 84 | 85 |
| 85 this->initClassID<NormalMapFP>(); | 86 this->initClassID<NormalMapFP>(); |
| 86 } | 87 } |
| 87 | 88 |
| 88 class GLSLNormalMapFP : public GrGLSLFragmentProcessor { | 89 class GLSLNormalMapFP : public GrGLSLFragmentProcessor { |
| 89 public: | 90 public: |
| 90 GLSLNormalMapFP() { | 91 GLSLNormalMapFP() |
| 91 fNormRotation.set(0.0f, 0.0f); | 92 : fColumnMajorInvCTM22{0.0f} {} |
| 92 } | |
| 93 | 93 |
| 94 void emitCode(EmitArgs& args) override { | 94 void emitCode(EmitArgs& args) override { |
| 95 | |
| 96 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder; | 95 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder; |
| 97 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; | 96 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; |
| 98 | 97 |
| 99 // add uniform | 98 // add uniform |
| 100 const char* xformUniName = nullptr; | 99 const char* xformUniName = nullptr; |
| 101 fXformUni = uniformHandler->addUniform(kFragment_GrShaderFlag, | 100 fXformUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kMat2
2f_GrSLType, |
| 102 kVec2f_GrSLType, kDefault_GrS
LPrecision, | 101 kDefault_GrSLPrecision, "Xfor
m", &xformUniName); |
| 103 "Xform", &xformUniName); | |
| 104 | 102 |
| 105 SkString dstNormalColorName("dstNormalColor"); | 103 SkString dstNormalColorName("dstNormalColor"); |
| 106 this->emitChild(0, nullptr, &dstNormalColorName, args); | 104 this->emitChild(0, nullptr, &dstNormalColorName, args); |
| 107 fragBuilder->codeAppendf("vec3 normal = %s.rgb - vec3(0.5);", | 105 fragBuilder->codeAppendf("vec3 normal = normalize(%s.rgb - vec3(0.5)
);", |
| 108 dstNormalColorName.c_str()); | 106 dstNormalColorName.c_str()); |
| 109 | 107 |
| 110 // TODO: inverse map the light direction vectors in the vertex shade
r rather than | 108 // TODO: inverse map the light direction vectors in the vertex shade
r rather than |
| 111 // transforming all the normals here! | 109 // transforming all the normals here! |
| 112 fragBuilder->codeAppendf( | |
| 113 "mat3 m = mat3(%s.x, -%s.y, 0.0, %s.y, %s.x, 0.0, 0.0, 0.0,
1.0);", | |
| 114 xformUniName, xformUniName, xformUniName, xformUniName); | |
| 115 | 110 |
| 116 fragBuilder->codeAppend("normal = normalize(m*normal);"); | 111 // If there's no x & y components, return (0, 0, +/- 1) instead to a
void division by 0 |
| 117 fragBuilder->codeAppendf("%s = vec4(normal, 0);", args.fOutputColor)
; | 112 fragBuilder->codeAppend( "if (abs(normal.z) > 0.9999) {"); |
| 113 fragBuilder->codeAppendf(" %s = normalize(vec4(0.0, 0.0, normal.z
, 0.0));", |
| 114 args.fOutputColor); |
| 115 // Else, Normalizing the transformed X and Y, while keeping constant
both Z and the |
| 116 // vector's angle in the XY plane. This maintains the "slope" for th
e surface while |
| 117 // appropriately rotating the normal for any anisotropic scaling tha
t occurs. |
| 118 // Here, we call scaling factor the number that must divide the tran
sformed X and Y so |
| 119 // that the normal's length remains equal to 1. |
| 120 fragBuilder->codeAppend( "} else {"); |
| 121 fragBuilder->codeAppendf(" vec2 transformed = %s * normal.xy;", |
| 122 xformUniName); |
| 123 fragBuilder->codeAppend( " float scalingFactorSquared = " |
| 124 "( (transformed.x * transformed
.x) " |
| 125 "+ (transformed.y * transform
ed.y) )" |
| 126 "/(1.0 - (normal.z * normal.z))
;"); |
| 127 fragBuilder->codeAppendf(" %s = vec4(transformed*inversesqrt(scal
ingFactorSquared)," |
| 128 "normal.z, 0.0);", |
| 129 args.fOutputColor); |
| 130 fragBuilder->codeAppend( "}"); |
| 118 } | 131 } |
| 119 | 132 |
| 120 static void GenKey(const GrProcessor& proc, const GrGLSLCaps&, | 133 static void GenKey(const GrProcessor& proc, const GrGLSLCaps&, |
| 121 GrProcessorKeyBuilder* b) { | 134 GrProcessorKeyBuilder* b) { |
| 122 b->add32(0x0); | 135 b->add32(0x0); |
| 123 } | 136 } |
| 124 | 137 |
| 125 protected: | 138 protected: |
| 126 void onSetData(const GrGLSLProgramDataManager& pdman, const GrProcessor&
proc) override { | 139 void onSetData(const GrGLSLProgramDataManager& pdman, const GrProcessor&
proc) override { |
| 127 const NormalMapFP& normalMapFP = proc.cast<NormalMapFP>(); | 140 const NormalMapFP& normalMapFP = proc.cast<NormalMapFP>(); |
| 128 | 141 |
| 129 const SkVector& normRotation = normalMapFP.normRotation(); | 142 const SkMatrix& invCTM = normalMapFP.invCTM(); |
| 130 if (normRotation != fNormRotation) { | 143 fColumnMajorInvCTM22[0] = invCTM.get(SkMatrix::kMScaleX); |
| 131 pdman.set2fv(fXformUni, 1, &normRotation.fX); | 144 fColumnMajorInvCTM22[1] = invCTM.get(SkMatrix::kMSkewY); |
| 132 fNormRotation = normRotation; | 145 fColumnMajorInvCTM22[2] = invCTM.get(SkMatrix::kMSkewX); |
| 133 } | 146 fColumnMajorInvCTM22[3] = invCTM.get(SkMatrix::kMScaleY); |
| 147 pdman.setMatrix2f(fXformUni, fColumnMajorInvCTM22); |
| 134 } | 148 } |
| 135 | 149 |
| 136 private: | 150 private: |
| 137 SkVector fNormRotation; | 151 float fColumnMajorInvCTM22[4]; |
| 138 GrGLSLProgramDataManager::UniformHandle fXformUni; | 152 GrGLSLProgramDataManager::UniformHandle fXformUni; |
| 139 }; | 153 }; |
| 140 | 154 |
| 141 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b)
const override { | 155 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b)
const override { |
| 142 GLSLNormalMapFP::GenKey(*this, caps, b); | 156 GLSLNormalMapFP::GenKey(*this, caps, b); |
| 143 } | 157 } |
| 144 | 158 |
| 145 const char* name() const override { return "NormalMapFP"; } | 159 const char* name() const override { return "NormalMapFP"; } |
| 146 | 160 |
| 147 void onComputeInvariantOutput(GrInvariantOutput* inout) const override { | 161 void onComputeInvariantOutput(GrInvariantOutput* inout) const override { |
| 148 inout->setToUnknown(GrInvariantOutput::ReadInput::kWillNot_ReadInput); | 162 inout->setToUnknown(GrInvariantOutput::ReadInput::kWillNot_ReadInput); |
| 149 } | 163 } |
| 150 | 164 |
| 151 const SkVector& normRotation() const { return fNormRotation; } | 165 const SkMatrix& invCTM() const { return fInvCTM; } |
| 152 | 166 |
| 153 private: | 167 private: |
| 154 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return new
GLSLNormalMapFP; } | 168 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return new
GLSLNormalMapFP; } |
| 155 | 169 |
| 156 bool onIsEqual(const GrFragmentProcessor& proc) const override { | 170 bool onIsEqual(const GrFragmentProcessor& proc) const override { |
| 157 const NormalMapFP& normalMapFP = proc.cast<NormalMapFP>(); | 171 const NormalMapFP& normalMapFP = proc.cast<NormalMapFP>(); |
| 158 return fNormRotation == normalMapFP.fNormRotation; | 172 return fInvCTM == normalMapFP.fInvCTM; |
| 159 } | 173 } |
| 160 | 174 |
| 161 SkVector fNormRotation; | 175 SkMatrix fInvCTM; |
| 162 }; | 176 }; |
| 163 | 177 |
| 164 sk_sp<GrFragmentProcessor> NormalMapSourceImpl::asFragmentProcessor( | 178 sk_sp<GrFragmentProcessor> NormalMapSourceImpl::asFragmentProcessor( |
| 165 GrContext *context, | 179 GrContext *context, |
| 166 const SkMatrix &viewM, | 180 const SkMatrix &viewM, |
| 167 const SkMatrix *localMatrix
, | 181 const SkMatrix *localMatrix
, |
| 168 SkFilterQuality filterQuali
ty, | 182 SkFilterQuality filterQuali
ty, |
| 169 SkSourceGammaTreatment gamm
aTreatment) const { | 183 SkSourceGammaTreatment gamm
aTreatment) const { |
| 170 | 184 |
| 171 sk_sp<GrFragmentProcessor> mapFP = fMapShader->asFragmentProcessor(context,
viewM, | 185 sk_sp<GrFragmentProcessor> mapFP = fMapShader->asFragmentProcessor(context,
viewM, |
| 172 localMatrix, filterQuality, gammaTreatment); | 186 localMatrix, filterQuality, gammaTreatment); |
| 173 | 187 |
| 174 return sk_make_sp<NormalMapFP>(std::move(mapFP), fNormRotation); | 188 return sk_make_sp<NormalMapFP>(std::move(mapFP), fInvCTM); |
| 175 } | 189 } |
| 176 | 190 |
| 177 #endif // SK_SUPPORT_GPU | 191 #endif // SK_SUPPORT_GPU |
| 178 | 192 |
| 179 //////////////////////////////////////////////////////////////////////////// | 193 //////////////////////////////////////////////////////////////////////////// |
| 180 | 194 |
| 181 NormalMapSourceImpl::Provider::Provider(const NormalMapSourceImpl& source, | 195 NormalMapSourceImpl::Provider::Provider(const NormalMapSourceImpl& source, |
| 182 SkShader::Context* mapContext) | 196 SkShader::Context* mapContext) |
| 183 : fSource(source) | 197 : fSource(source) |
| 184 , fMapContext(mapContext) { | 198 , fMapContext(mapContext) { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 232 fMapContext->shadeSpan(x, y, tmpNormalColors, n); | 246 fMapContext->shadeSpan(x, y, tmpNormalColors, n); |
| 233 | 247 |
| 234 for (int i = 0; i < n; i++) { | 248 for (int i = 0; i < n; i++) { |
| 235 SkPoint3 tempNorm; | 249 SkPoint3 tempNorm; |
| 236 | 250 |
| 237 tempNorm.set(SkIntToScalar(SkGetPackedR32(tmpNormalColors[i])) - 127
.0f, | 251 tempNorm.set(SkIntToScalar(SkGetPackedR32(tmpNormalColors[i])) - 127
.0f, |
| 238 SkIntToScalar(SkGetPackedG32(tmpNormalColors[i])) - 127
.0f, | 252 SkIntToScalar(SkGetPackedG32(tmpNormalColors[i])) - 127
.0f, |
| 239 SkIntToScalar(SkGetPackedB32(tmpNormalColors[i])) - 127
.0f); | 253 SkIntToScalar(SkGetPackedB32(tmpNormalColors[i])) - 127
.0f); |
| 240 tempNorm.normalize(); | 254 tempNorm.normalize(); |
| 241 | 255 |
| 242 output[i].fX = fSource.fNormRotation.fX * tempNorm.fX + | 256 if (!SkScalarNearlyEqual(SkScalarAbs(tempNorm.fZ), 1.0f)) { |
| 243 fSource.fNormRotation.fY * tempNorm.fY; | 257 SkVector transformed = fSource.fInvCTM.mapVector(tempNorm.fX, te
mpNorm.fY); |
| 244 output[i].fY = -fSource.fNormRotation.fY * tempNorm.fX + | 258 |
| 245 fSource.fNormRotation.fX * tempNorm.fY; | 259 // Normalizing the transformed X and Y, while keeping constant b
oth Z and the |
| 246 output[i].fZ = tempNorm.fZ; | 260 // vector's angle in the XY plane. This maintains the "slope" fo
r the surface while |
| 261 // appropriately rotating the normal for any anisotropic scaling
that occurs. |
| 262 // Here, we call scaling factor the number that must divide the
transformed X and Y |
| 263 // so that the normal's length remains equal to 1. |
| 264 SkScalar scalingFactorSquared = |
| 265 (SkScalarSquare(transformed.fX) + SkScalarSquare(transfo
rmed.fY)) |
| 266 / (1.0f - SkScalarSquare(tempNorm.fZ)); |
| 267 SkScalar invScalingFactor = SkScalarInvert(SkScalarSqrt(scalingF
actorSquared)); |
| 268 |
| 269 output[i].fX = transformed.fX * invScalingFactor; |
| 270 output[i].fY = transformed.fY * invScalingFactor; |
| 271 output[i].fZ = tempNorm.fZ; |
| 272 } else { |
| 273 output[i] = {0.0f, 0.0f, tempNorm.fZ}; |
| 274 output[i].normalize(); |
| 275 } |
| 276 |
| 277 SkASSERT(SkScalarNearlyEqual(output[i].length(), 1.0f)) |
| 247 } | 278 } |
| 248 | 279 |
| 249 output += n; | 280 output += n; |
| 250 x += n; | 281 x += n; |
| 251 count -= n; | 282 count -= n; |
| 252 } while (count > 0); | 283 } while (count > 0); |
| 253 } | 284 } |
| 254 | 285 |
| 255 //////////////////////////////////////////////////////////////////////////////// | 286 //////////////////////////////////////////////////////////////////////////////// |
| 256 | 287 |
| 257 sk_sp<SkFlattenable> NormalMapSourceImpl::CreateProc(SkReadBuffer& buf) { | 288 sk_sp<SkFlattenable> NormalMapSourceImpl::CreateProc(SkReadBuffer& buf) { |
| 258 | 289 |
| 259 sk_sp<SkShader> mapShader = buf.readFlattenable<SkShader>(); | 290 sk_sp<SkShader> mapShader = buf.readFlattenable<SkShader>(); |
| 260 | 291 |
| 261 SkVector normRotation = {1,0}; | 292 SkMatrix invCTM; |
| 262 if (!buf.isVersionLT(SkReadBuffer::kLightingShaderWritesInvNormRotation)) { | 293 buf.readMatrix(&invCTM); |
| 263 normRotation = buf.readPoint(); | |
| 264 } | |
| 265 | 294 |
| 266 return sk_make_sp<NormalMapSourceImpl>(std::move(mapShader), normRotation); | 295 return sk_make_sp<NormalMapSourceImpl>(std::move(mapShader), invCTM); |
| 267 } | 296 } |
| 268 | 297 |
| 269 void NormalMapSourceImpl::flatten(SkWriteBuffer& buf) const { | 298 void NormalMapSourceImpl::flatten(SkWriteBuffer& buf) const { |
| 270 this->INHERITED::flatten(buf); | 299 this->INHERITED::flatten(buf); |
| 271 | 300 |
| 272 buf.writeFlattenable(fMapShader.get()); | 301 buf.writeFlattenable(fMapShader.get()); |
| 273 buf.writePoint(fNormRotation); | 302 buf.writeMatrix(fInvCTM); |
| 274 } | 303 } |
| 275 | 304 |
| 276 //////////////////////////////////////////////////////////////////////////// | 305 //////////////////////////////////////////////////////////////////////////// |
| 277 | 306 |
| 278 sk_sp<SkNormalSource> SkNormalSource::MakeFromNormalMap(sk_sp<SkShader> map, | 307 sk_sp<SkNormalSource> SkNormalSource::MakeFromNormalMap(sk_sp<SkShader> map, con
st SkMatrix& ctm) { |
| 279 const SkVector &normRota
tion) { | 308 SkMatrix invCTM; |
| 280 SkASSERT(SkScalarNearlyEqual(normRotation.lengthSqd(), SK_Scalar1)); | 309 |
| 281 if (!map) { | 310 if (!ctm.invert(&invCTM) || !map) { |
| 282 return nullptr; | 311 return nullptr; |
| 283 } | 312 } |
| 284 | 313 |
| 285 return sk_make_sp<NormalMapSourceImpl>(std::move(map), normRotation); | 314 return sk_make_sp<NormalMapSourceImpl>(std::move(map), invCTM); |
| 286 } | 315 } |
| 287 | 316 |
| 288 //////////////////////////////////////////////////////////////////////////// | 317 //////////////////////////////////////////////////////////////////////////// |
| 289 | 318 |
| 290 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkNormalSource) | 319 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkNormalSource) |
| 291 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(NormalMapSourceImpl) | 320 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(NormalMapSourceImpl) |
| 292 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END | 321 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END |
| 293 | 322 |
| 294 //////////////////////////////////////////////////////////////////////////// | 323 //////////////////////////////////////////////////////////////////////////// |
| OLD | NEW |