Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Side by Side Diff: src/core/SkNormalSource.cpp

Issue 2063793002: API change to allow for NormalSource selection at the user level. (Closed) Base URL: https://skia.googlesource.com/skia@dvonbeck-normal-factor-out
Patch Set: Addressed remaining patch 8 comments Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/core/SkNormalSource.h ('k') | tests/SerializationTest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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 ////////////////////////////////////////////////////////////////////////////
OLDNEW
« no previous file with comments | « src/core/SkNormalSource.h ('k') | tests/SerializationTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698