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

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

Issue 2080993002: Added API for Bevel NormalSource. (Closed) Base URL: https://skia.googlesource.com/skia@dvonbeck-diffuse-api-change
Patch Set: Addressed patch 7 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
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 "SkNormalBevelSource.h"
9 #include "SkErrorInternals.h" 9 #include "SkNormalFlatSource.h"
10 #include "SkLightingShader.h" 10 #include "SkNormalMapSource.h"
11 #include "SkMatrix.h"
12 #include "SkNormalSource.h" 11 #include "SkNormalSource.h"
13 #include "SkPM4f.h"
14 #include "SkReadBuffer.h"
15 #include "SkWriteBuffer.h"
16 12
17 // Genretating vtable 13 // Generating vtable
18 SkNormalSource::~SkNormalSource() {} 14 SkNormalSource::~SkNormalSource() {}
19 15
20 ///////////////////////////////////////////////////////////////////////////////
21
22 class NormalMapSourceImpl : public SkNormalSource {
23 public:
24 NormalMapSourceImpl(sk_sp<SkShader> mapShader, const SkMatrix& invCTM)
25 : fMapShader(std::move(mapShader))
26 , fInvCTM(invCTM) {}
27
28 #if SK_SUPPORT_GPU
29 sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*,
30 const SkMatrix& viewM,
31 const SkMatrix* localMatrix,
32 SkFilterQuality,
33 SkSourceGammaTreatment) const override;
34 #endif
35
36 SkNormalSource::Provider* asProvider(const SkShader::ContextRec& rec,
37 void* storage) const ov erride;
38
39 size_t providerSize(const SkShader::ContextRec& rec) const override;
40 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(NormalMapSourceImpl)
41
42 protected:
43 void flatten(SkWriteBuffer& buf) const override;
44
45 bool computeNormTotalInverse(const SkShader::ContextRec& rec, SkMatrix* norm TotalInverse) const;
46
47 private:
48 class Provider : public SkNormalSource::Provider {
49 public:
50 Provider(const NormalMapSourceImpl& source, SkShader::Context* mapContex t,
51 SkPaint* overridePaint);
52
53 virtual ~Provider() override;
54
55 void fillScanLine(int x, int y, SkPoint3 output[], int count) const over ride;
56
57 private:
58 const NormalMapSourceImpl& fSource;
59 SkShader::Context* fMapContext;
60
61 SkPaint* fOverridePaint;
62
63 typedef SkNormalSource::Provider INHERITED;
64 };
65
66 sk_sp<SkShader> fMapShader;
67 SkMatrix fInvCTM; // Inverse of the canvas total matrix, used for rot ating normals.
68
69 friend class SkNormalSource;
70
71 typedef SkNormalSource INHERITED;
72 };
73
74 ////////////////////////////////////////////////////////////////////////////
75
76 #if SK_SUPPORT_GPU
77
78 #include "GrCoordTransform.h"
79 #include "GrInvariantOutput.h"
80 #include "GrTextureParams.h"
81 #include "glsl/GrGLSLFragmentProcessor.h"
82 #include "glsl/GrGLSLFragmentShaderBuilder.h"
83 #include "SkGr.h"
84
85 class NormalMapFP : public GrFragmentProcessor {
86 public:
87 NormalMapFP(sk_sp<GrFragmentProcessor> mapFP, const SkMatrix& invCTM)
88 : fInvCTM(invCTM) {
89 this->registerChildProcessor(mapFP);
90
91 this->initClassID<NormalMapFP>();
92 }
93
94 class GLSLNormalMapFP : public GrGLSLFragmentProcessor {
95 public:
96 GLSLNormalMapFP()
97 : fColumnMajorInvCTM22{0.0f} {}
98
99 void emitCode(EmitArgs& args) override {
100 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
101 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
102
103 // add uniform
104 const char* xformUniName = nullptr;
105 fXformUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kMat2 2f_GrSLType,
106 kDefault_GrSLPrecision, "Xfor m", &xformUniName);
107
108 SkString dstNormalColorName("dstNormalColor");
109 this->emitChild(0, nullptr, &dstNormalColorName, args);
110 fragBuilder->codeAppendf("vec3 normal = normalize(%s.rgb - vec3(0.5) );",
111 dstNormalColorName.c_str());
112
113 // If there's no x & y components, return (0, 0, +/- 1) instead to a void division by 0
114 fragBuilder->codeAppend( "if (abs(normal.z) > 0.999) {");
115 fragBuilder->codeAppendf(" %s = normalize(vec4(0.0, 0.0, normal.z , 0.0));",
116 args.fOutputColor);
117 // Else, Normalizing the transformed X and Y, while keeping constant both Z and the
118 // vector's angle in the XY plane. This maintains the "slope" for th e surface while
119 // appropriately rotating the normal regardless of any anisotropic s caling that occurs.
120 // Here, we call 'scaling factor' the number that must divide the tr ansformed X and Y so
121 // that the normal's length remains equal to 1.
122 fragBuilder->codeAppend( "} else {");
123 fragBuilder->codeAppendf(" vec2 transformed = %s * normal.xy;",
124 xformUniName);
125 fragBuilder->codeAppend( " float scalingFactorSquared = "
126 "( (transformed.x * transformed .x) "
127 "+ (transformed.y * transform ed.y) )"
128 "/(1.0 - (normal.z * normal.z)) ;");
129 fragBuilder->codeAppendf(" %s = vec4(transformed*inversesqrt(scal ingFactorSquared),"
130 "normal.z, 0.0);",
131 args.fOutputColor);
132 fragBuilder->codeAppend( "}");
133 }
134
135 static void GenKey(const GrProcessor& proc, const GrGLSLCaps&,
136 GrProcessorKeyBuilder* b) {
137 b->add32(0x0);
138 }
139
140 protected:
141 void onSetData(const GrGLSLProgramDataManager& pdman, const GrProcessor& proc) override {
142 const NormalMapFP& normalMapFP = proc.cast<NormalMapFP>();
143
144 const SkMatrix& invCTM = normalMapFP.invCTM();
145 fColumnMajorInvCTM22[0] = invCTM.get(SkMatrix::kMScaleX);
146 fColumnMajorInvCTM22[1] = invCTM.get(SkMatrix::kMSkewY);
147 fColumnMajorInvCTM22[2] = invCTM.get(SkMatrix::kMSkewX);
148 fColumnMajorInvCTM22[3] = invCTM.get(SkMatrix::kMScaleY);
149 pdman.setMatrix2f(fXformUni, fColumnMajorInvCTM22);
150 }
151
152 private:
153 float fColumnMajorInvCTM22[4];
154 GrGLSLProgramDataManager::UniformHandle fXformUni;
155 };
156
157 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override {
158 GLSLNormalMapFP::GenKey(*this, caps, b);
159 }
160
161 const char* name() const override { return "NormalMapFP"; }
162
163 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
164 inout->setToUnknown(GrInvariantOutput::ReadInput::kWillNot_ReadInput);
165 }
166
167 const SkMatrix& invCTM() const { return fInvCTM; }
168
169 private:
170 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return new GLSLNormalMapFP; }
171
172 bool onIsEqual(const GrFragmentProcessor& proc) const override {
173 const NormalMapFP& normalMapFP = proc.cast<NormalMapFP>();
174 return fInvCTM == normalMapFP.fInvCTM;
175 }
176
177 SkMatrix fInvCTM;
178 };
179
180 sk_sp<GrFragmentProcessor> NormalMapSourceImpl::asFragmentProcessor(
181 GrContext *context,
182 const SkMatrix &viewM,
183 const SkMatrix *localMatrix ,
184 SkFilterQuality filterQuali ty,
185 SkSourceGammaTreatment gamm aTreatment) const {
186 sk_sp<GrFragmentProcessor> mapFP = fMapShader->asFragmentProcessor(context, viewM,
187 localMatrix, filterQuality, gammaTreatment);
188 if (!mapFP) {
189 return nullptr;
190 }
191
192 return sk_make_sp<NormalMapFP>(std::move(mapFP), fInvCTM);
193 }
194
195 #endif // SK_SUPPORT_GPU
196
197 ////////////////////////////////////////////////////////////////////////////
198
199 NormalMapSourceImpl::Provider::Provider(const NormalMapSourceImpl& source,
200 SkShader::Context* mapContext,
201 SkPaint* overridePaint)
202 : fSource(source)
203 , fMapContext(mapContext)
204 , fOverridePaint(overridePaint) {}
205
206 NormalMapSourceImpl::Provider::~Provider() {
207 fMapContext->~Context();
208 fOverridePaint->~SkPaint();
209 }
210
211 SkNormalSource::Provider* NormalMapSourceImpl::asProvider(
212 const SkShader::ContextRec &rec, void *storage) const {
213 SkMatrix normTotalInv;
214 if (!this->computeNormTotalInverse(rec, &normTotalInv)) {
215 return nullptr;
216 }
217
218 // Overriding paint's alpha because we need the normal map's RGB channels to be unpremul'd
219 void* paintStorage = (char*)storage + sizeof(Provider);
220 SkPaint* overridePaint = new (paintStorage) SkPaint(*(rec.fPaint));
221 overridePaint->setAlpha(0xFF);
222 SkShader::ContextRec overrideRec(*overridePaint, *(rec.fMatrix), rec.fLocalM atrix,
223 rec.fPreferredDstType);
224
225 void* mapContextStorage = (char*) paintStorage + sizeof(SkPaint);
226 SkShader::Context* context = fMapShader->createContext(overrideRec, mapConte xtStorage);
227 if (!context) {
228 return nullptr;
229 }
230
231 return new (storage) Provider(*this, context, overridePaint);
232 }
233
234 size_t NormalMapSourceImpl::providerSize(const SkShader::ContextRec& rec) const {
235 return sizeof(Provider) + sizeof(SkPaint) + fMapShader->contextSize(rec);
236 }
237
238 bool NormalMapSourceImpl::computeNormTotalInverse(const SkShader::ContextRec& re c,
239 SkMatrix* normTotalInverse) co nst {
240 SkMatrix total;
241 total.setConcat(*rec.fMatrix, fMapShader->getLocalMatrix());
242
243 const SkMatrix* m = &total;
244 if (rec.fLocalMatrix) {
245 total.setConcat(*m, *rec.fLocalMatrix);
246 m = &total;
247 }
248 return m->invert(normTotalInverse);
249 }
250
251 #define BUFFER_MAX 16
252 void NormalMapSourceImpl::Provider::fillScanLine(int x, int y, SkPoint3 output[] ,
253 int count) const {
254 SkPMColor tmpNormalColors[BUFFER_MAX];
255
256 do {
257 int n = SkTMin(count, BUFFER_MAX);
258
259 fMapContext->shadeSpan(x, y, tmpNormalColors, n);
260
261 for (int i = 0; i < n; i++) {
262 SkPoint3 tempNorm;
263
264 tempNorm.set(SkIntToScalar(SkGetPackedR32(tmpNormalColors[i])) - 127 .0f,
265 SkIntToScalar(SkGetPackedG32(tmpNormalColors[i])) - 127 .0f,
266 SkIntToScalar(SkGetPackedB32(tmpNormalColors[i])) - 127 .0f);
267
268 tempNorm.normalize();
269
270
271 if (!SkScalarNearlyEqual(SkScalarAbs(tempNorm.fZ), 1.0f)) {
272 SkVector transformed = fSource.fInvCTM.mapVector(tempNorm.fX, te mpNorm.fY);
273
274 // Normalizing the transformed X and Y, while keeping constant b oth Z and the
275 // vector's angle in the XY plane. This maintains the "slope" fo r the surface while
276 // appropriately rotating the normal for any anisotropic scaling that occurs.
277 // Here, we call scaling factor the number that must divide the transformed X and Y
278 // so that the normal's length remains equal to 1.
279 SkScalar scalingFactorSquared =
280 (SkScalarSquare(transformed.fX) + SkScalarSquare(transfo rmed.fY))
281 / (1.0f - SkScalarSquare(tempNorm.fZ));
282 SkScalar invScalingFactor = SkScalarInvert(SkScalarSqrt(scalingF actorSquared));
283
284 output[i].fX = transformed.fX * invScalingFactor;
285 output[i].fY = transformed.fY * invScalingFactor;
286 output[i].fZ = tempNorm.fZ;
287 } else {
288 output[i] = {0.0f, 0.0f, tempNorm.fZ};
289 output[i].normalize();
290 }
291
292 SkASSERT(SkScalarNearlyEqual(output[i].length(), 1.0f))
293 }
294
295 output += n;
296 x += n;
297 count -= n;
298 } while (count > 0);
299 }
300
301 ////////////////////////////////////////////////////////////////////////////////
302
303 sk_sp<SkFlattenable> NormalMapSourceImpl::CreateProc(SkReadBuffer& buf) {
304
305 sk_sp<SkShader> mapShader = buf.readFlattenable<SkShader>();
306
307 SkMatrix invCTM;
308 buf.readMatrix(&invCTM);
309
310 return sk_make_sp<NormalMapSourceImpl>(std::move(mapShader), invCTM);
311 }
312
313 void NormalMapSourceImpl::flatten(SkWriteBuffer& buf) const {
314 this->INHERITED::flatten(buf);
315
316 buf.writeFlattenable(fMapShader.get());
317 buf.writeMatrix(fInvCTM);
318 }
319
320 ////////////////////////////////////////////////////////////////////////////
321
322 sk_sp<SkNormalSource> SkNormalSource::MakeFromNormalMap(sk_sp<SkShader> map, con st SkMatrix& ctm) {
323 SkMatrix invCTM;
324
325 if (!ctm.invert(&invCTM) || !map) {
326 return nullptr;
327 }
328
329 return sk_make_sp<NormalMapSourceImpl>(std::move(map), invCTM);
330 }
331
332 ///////////////////////////////////////////////////////////////////////////////
333
334 class SK_API NormalFlatSourceImpl : public SkNormalSource {
335 public:
336 NormalFlatSourceImpl(){}
337
338 #if SK_SUPPORT_GPU
339 sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*,
340 const SkMatrix& viewM,
341 const SkMatrix* localMatrix,
342 SkFilterQuality,
343 SkSourceGammaTreatment) const override;
344 #endif
345
346 SkNormalSource::Provider* asProvider(const SkShader::ContextRec& rec,
347 void* storage) const override;
348 size_t providerSize(const SkShader::ContextRec& rec) const override;
349
350 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(NormalFlatSourceImpl)
351
352 protected:
353 void flatten(SkWriteBuffer& buf) const override;
354
355 private:
356 class Provider : public SkNormalSource::Provider {
357 public:
358 Provider();
359
360 virtual ~Provider();
361
362 void fillScanLine(int x, int y, SkPoint3 output[], int count) const over ride;
363
364 private:
365 typedef SkNormalSource::Provider INHERITED;
366 };
367
368 friend class SkNormalSource;
369
370 typedef SkNormalSource INHERITED;
371 };
372
373 ////////////////////////////////////////////////////////////////////////////
374
375 #if SK_SUPPORT_GPU
376
377 class NormalFlatFP : public GrFragmentProcessor {
378 public:
379 NormalFlatFP() {
380 this->initClassID<NormalFlatFP>();
381 }
382
383 class GLSLNormalFlatFP : public GrGLSLFragmentProcessor {
384 public:
385 GLSLNormalFlatFP() {}
386
387 void emitCode(EmitArgs& args) override {
388 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
389
390 fragBuilder->codeAppendf("%s = vec4(0, 0, 1, 0);", args.fOutputColor );
391 }
392
393 static void GenKey(const GrProcessor& proc, const GrGLSLCaps&,
394 GrProcessorKeyBuilder* b) {
395 b->add32(0x0);
396 }
397
398 protected:
399 void onSetData(const GrGLSLProgramDataManager& pdman, const GrProcessor& proc) override {}
400 };
401
402 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override {
403 GLSLNormalFlatFP::GenKey(*this, caps, b);
404 }
405
406 const char* name() const override { return "NormalFlatFP"; }
407
408 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
409 inout->setToUnknown(GrInvariantOutput::ReadInput::kWillNot_ReadInput);
410 }
411
412 private:
413 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return new GLSLNormalFlatFP; }
414
415 bool onIsEqual(const GrFragmentProcessor& proc) const override {
416 return true;
417 }
418 };
419
420 sk_sp<GrFragmentProcessor> NormalFlatSourceImpl::asFragmentProcessor(
421 GrContext *context,
422 const SkMatrix &viewM,
423 const SkMatrix *localMatrix ,
424 SkFilterQuality filterQuali ty,
425 SkSourceGammaTreatment gamm aTreatment) const {
426
427 return sk_make_sp<NormalFlatFP>();
428 }
429
430 #endif // SK_SUPPORT_GPU
431
432 ////////////////////////////////////////////////////////////////////////////
433
434 NormalFlatSourceImpl::Provider::Provider() {}
435
436 NormalFlatSourceImpl::Provider::~Provider() {}
437
438 SkNormalSource::Provider* NormalFlatSourceImpl::asProvider(const SkShader::Conte xtRec &rec,
439 void *storage) const {
440 return new (storage) Provider();
441 }
442
443 size_t NormalFlatSourceImpl::providerSize(const SkShader::ContextRec&) const {
444 return sizeof(Provider);
445 }
446
447 void NormalFlatSourceImpl::Provider::fillScanLine(int x, int y, SkPoint3 output[ ],
448 int count) const {
449 for (int i = 0; i < count; i++) {
450 output[i] = {0.0f, 0.0f, 1.0f};
451 }
452 }
453
454 ////////////////////////////////////////////////////////////////////////////////
455
456 sk_sp<SkFlattenable> NormalFlatSourceImpl::CreateProc(SkReadBuffer& buf) {
457 return sk_make_sp<NormalFlatSourceImpl>();
458 }
459
460 void NormalFlatSourceImpl::flatten(SkWriteBuffer& buf) const {
461 this->INHERITED::flatten(buf);
462 }
463
464 ////////////////////////////////////////////////////////////////////////////
465
466 sk_sp<SkNormalSource> SkNormalSource::MakeFlat() {
467 return sk_make_sp<NormalFlatSourceImpl>();
468 }
469
470 ////////////////////////////////////////////////////////////////////////////
471
472 //////////////////////////////////////////////////////////////////////////// 16 ////////////////////////////////////////////////////////////////////////////
473 17
474 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkNormalSource) 18 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkNormalSource)
475 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(NormalMapSourceImpl) 19 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkNormalMapSourceImpl)
476 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(NormalFlatSourceImpl) 20 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkNormalFlatSourceImpl)
21 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkNormalBevelSourceImpl)
477 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END 22 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
478 23
479 //////////////////////////////////////////////////////////////////////////// 24 ////////////////////////////////////////////////////////////////////////////
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698