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 |