OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright 2016 Google Inc. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license that can be | |
5 * found in the LICENSE file. | |
6 */ | |
7 | |
8 #include "SkBitmapProcShader.h" | |
9 #include "SkError.h" | |
10 #include "SkErrorInternals.h" | |
11 #include "SkLightingShader.h" | |
12 #include "SkReadBuffer.h" | |
13 #include "SkWriteBuffer.h" | |
14 | |
15 SkLightingShader::NormalSource::~NormalSource(){} | |
16 | |
17 /////////////////////////////////////////////////////////////////////////////// | |
18 | |
19 class SK_API NormalMapSourceImpl : public SkLightingShader::NormalSource { | |
20 public: | |
21 NormalMapSourceImpl(const SkBitmap &normal, const SkVector &invNormRotation, | |
22 const SkMatrix *normLocalM) | |
23 : fNormalMap(normal) | |
24 , fInvNormRotation(invNormRotation) { | |
25 | |
26 if (normLocalM) { | |
27 fNormLocalMatrix = *normLocalM; | |
28 } else { | |
29 fNormLocalMatrix.reset(); | |
30 } | |
31 // Pre-cache so future calls to fNormLocalMatrix.getType() are threadsaf e. | |
32 (void)fNormLocalMatrix.getType(); | |
33 } | |
34 | |
35 #if SK_SUPPORT_GPU | |
36 sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*, | |
37 const SkMatrix& viewM, | |
38 const SkMatrix* localMatrix, | |
39 SkFilterQuality, | |
40 SkSourceGammaTreatment) const override; | |
41 #endif | |
42 | |
43 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(NormalMapSourceImpl) | |
dvonbeck
2016/06/10 18:31:22
FLATTENABLE: Macro
| |
44 | |
45 protected: | |
46 void flatten(SkWriteBuffer& buf) const override; | |
47 | |
48 private: | |
49 SkBitmap fNormalMap; | |
50 SkMatrix fNormLocalMatrix; | |
51 SkVector fInvNormRotation; | |
52 | |
53 friend class SkLightingShader::NormalMapSource; | |
54 | |
55 typedef SkLightingShader::NormalSource INHERITED; | |
56 }; | |
57 | |
58 //////////////////////////////////////////////////////////////////////////// | |
59 | |
60 #if SK_SUPPORT_GPU | |
61 | |
62 #include "GrCoordTransform.h" | |
63 #include "GrInvariantOutput.h" | |
64 #include "GrTextureParams.h" | |
65 #include "glsl/GrGLSLFragmentProcessor.h" | |
66 #include "glsl/GrGLSLFragmentShaderBuilder.h" | |
67 #include "SkGr.h" | |
68 | |
69 class NormalMapFP : public GrFragmentProcessor { | |
70 public: | |
71 NormalMapFP(GrTexture* normal, const SkMatrix& normMatrix, const GrTexturePa rams& normParams, | |
72 const SkVector& invNormRotation) | |
73 : fNormDeviceTransform(kLocal_GrCoordSet, normMatrix, normal, normParams .filterMode()) | |
74 , fNormalTextureAccess(normal, normParams) | |
75 , fInvNormRotation(invNormRotation) { | |
76 this->addCoordTransform(&fNormDeviceTransform); | |
77 this->addTextureAccess(&fNormalTextureAccess); | |
78 | |
79 this->initClassID<NormalMapFP>(); | |
80 } | |
81 | |
82 class GLSLNormalMapFP : public GrGLSLFragmentProcessor { | |
83 public: | |
84 GLSLNormalMapFP() { | |
85 fInvNormRotation.set(0.0f, 0.0f); | |
86 } | |
87 | |
88 void emitCode(EmitArgs& args) override { | |
89 | |
90 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder; | |
91 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; | |
92 | |
93 // add uniform | |
94 const char* xformUniName = nullptr; | |
95 fXformUni = uniformHandler->addUniform(kFragment_GrShaderFlag, | |
96 kVec2f_GrSLType, kDefault_GrS LPrecision, | |
97 "Xform", &xformUniName); | |
98 | |
99 fragBuilder->codeAppend("vec4 normalColor = "); | |
100 fragBuilder->appendTextureLookup(args.fTexSamplers[0], | |
101 args.fCoords[0].c_str(), | |
102 args.fCoords[0].getType()); | |
103 fragBuilder->codeAppend(";"); | |
104 | |
105 fragBuilder->codeAppend("vec3 normal = normalColor.rgb - vec3(0.5);" ); | |
106 | |
107 // TODO: inverse map the light direction vectors in the vertex shade r rather than | |
108 // transforming all the normals here! | |
109 fragBuilder->codeAppendf( | |
110 "mat3 m = mat3(%s.x, -%s.y, 0.0, %s.y, %s.x, 0.0, 0.0, 0.0, 1.0);", | |
111 xformUniName, xformUniName, xformUniName, xformUniName); | |
112 | |
113 fragBuilder->codeAppend("normal = normalize(m*normal);"); | |
114 fragBuilder->codeAppendf("%s = vec4(normal, 0);", args.fOutputColor) ; | |
115 } | |
116 | |
117 static void GenKey(const GrProcessor& proc, const GrGLSLCaps&, | |
118 GrProcessorKeyBuilder* b) { | |
119 b->add32(0x0); | |
120 } | |
121 | |
122 protected: | |
123 void onSetData(const GrGLSLProgramDataManager& pdman, const GrProcessor& proc) override { | |
124 const NormalMapFP& normalMapFP = proc.cast<NormalMapFP>(); | |
125 | |
126 const SkVector& invNormRotation = normalMapFP.invNormRotation(); | |
127 if (invNormRotation != fInvNormRotation) { | |
128 pdman.set2fv(fXformUni, 1, &invNormRotation.fX); | |
129 fInvNormRotation = invNormRotation; | |
130 } | |
131 } | |
132 | |
133 private: | |
134 SkVector fInvNormRotation; | |
135 GrGLSLProgramDataManager::UniformHandle fXformUni; | |
136 }; | |
137 | |
138 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override { | |
139 GLSLNormalMapFP::GenKey(*this, caps, b); | |
140 } | |
141 | |
142 const char* name() const override { return "NormalMapFP"; } | |
143 | |
144 // TODO what is this? keep? delete? | |
145 void onComputeInvariantOutput(GrInvariantOutput* inout) const override { | |
146 inout->setToUnknown(GrInvariantOutput::ReadInput::kWillNot_ReadInput); | |
147 } | |
148 | |
149 const SkVector& invNormRotation() const { return fInvNormRotation; } | |
150 | |
151 private: | |
152 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return new GLSLNormalMapFP; } | |
153 | |
154 bool onIsEqual(const GrFragmentProcessor& proc) const override { | |
155 const NormalMapFP& normalMapFP = proc.cast<NormalMapFP>(); | |
156 return fNormDeviceTransform == normalMapFP.fNormDeviceTransform && | |
157 fNormalTextureAccess == normalMapFP.fNormalTextureAccess && | |
158 fInvNormRotation == normalMapFP.fInvNormRotation; | |
159 } | |
160 | |
161 GrCoordTransform fNormDeviceTransform; | |
162 GrTextureAccess fNormalTextureAccess; | |
163 | |
164 SkVector fInvNormRotation; | |
165 }; | |
166 | |
167 // TODO same code at SkLightingShader.cpp. Refactor to common source! | |
168 static bool make_mat(const SkBitmap& bm, | |
169 const SkMatrix& localMatrix1, | |
170 const SkMatrix* localMatrix2, | |
171 SkMatrix* result) { | |
172 | |
173 result->setIDiv(bm.width(), bm.height()); | |
174 | |
175 SkMatrix lmInverse; | |
176 if (!localMatrix1.invert(&lmInverse)) { | |
177 return false; | |
178 } | |
179 if (localMatrix2) { | |
180 SkMatrix inv; | |
181 if (!localMatrix2->invert(&inv)) { | |
182 return false; | |
183 } | |
184 lmInverse.postConcat(inv); | |
185 } | |
186 result->preConcat(lmInverse); | |
187 | |
188 return true; | |
189 } | |
190 | |
191 sk_sp<GrFragmentProcessor> NormalMapSourceImpl::asFragmentProcessor( | |
192 GrContext *context, | |
193 const SkMatrix &viewM, | |
194 const SkMatrix *localMatrix , | |
195 SkFilterQuality filterQuali ty, | |
196 SkSourceGammaTreatment gamm aTreatment) const { | |
197 | |
198 // TODO Here, the old code was checking that diffuse map and normal map are same size, that | |
199 // will be addressed when diffuse maps are factored out of SkLightingSh ader in a future CL | |
200 | |
201 SkMatrix normM; | |
202 if (!make_mat(fNormalMap, fNormLocalMatrix, localMatrix, &normM)) { | |
203 return nullptr; | |
204 } | |
205 | |
206 bool doBicubic; | |
207 GrTextureParams::FilterMode normFilterMode = GrSkFilterQualityToGrFilterMode ( | |
208 SkTMin(filterQuality, kMedium_SkFilterQuality), | |
209 viewM, | |
210 fNormLocalMatrix, | |
211 &doBicubic); | |
212 SkASSERT(!doBicubic); | |
213 | |
214 // TODO: support other tile modes | |
215 GrTextureParams normParams(SkShader::kClamp_TileMode, normFilterMode); | |
216 SkAutoTUnref<GrTexture> normalTexture(GrRefCachedBitmapTexture(context, | |
217 fNormalMap, | |
218 normParams, | |
219 gammaTreatmen t)); | |
220 if (!normalTexture) { | |
221 SkErrorInternals::SetError(kInternalError_SkError, "Couldn't convert bit map to texture."); | |
222 return nullptr; | |
223 } | |
224 | |
225 return sk_make_sp<NormalMapFP>(normalTexture, normM, normParams, fInvNormRot ation); | |
226 } | |
227 | |
228 #endif // SK_SUPPORT_GPU | |
229 | |
230 //////////////////////////////////////////////////////////////////////////// | |
231 | |
232 sk_sp<SkFlattenable> NormalMapSourceImpl::CreateProc(SkReadBuffer& buf) { | |
dvonbeck
2016/06/10 18:31:21
FLATTENABLE: Reading NormalMapSourceImpl from buff
| |
233 | |
234 SkMatrix normLocalM; | |
235 bool hasNormLocalM = buf.readBool(); | |
236 if (hasNormLocalM) { | |
237 buf.readMatrix(&normLocalM); | |
238 } else { | |
239 normLocalM.reset(); | |
240 } | |
241 | |
242 SkBitmap normal; | |
243 if (!buf.readBitmap(&normal)) { | |
244 return nullptr; | |
245 } | |
246 normal.setImmutable(); | |
247 | |
248 SkVector invNormRotation = {1,0}; | |
249 if (!buf.isVersionLT(SkReadBuffer::kLightingShaderWritesInvNormRotation)) { | |
250 invNormRotation = buf.readPoint(); | |
251 } | |
252 | |
253 return sk_make_sp<NormalMapSourceImpl>(normal, invNormRotation, &normLocalM) ; | |
254 } | |
255 | |
256 void NormalMapSourceImpl::flatten(SkWriteBuffer& buf) const { | |
dvonbeck
2016/06/10 18:31:22
FLATTENABLE: Flattening NormalMapSourceImpl
| |
257 this->INHERITED::flatten(buf); | |
258 | |
259 bool hasNormLocalM = !fNormLocalMatrix.isIdentity(); | |
260 buf.writeBool(hasNormLocalM); | |
261 if (hasNormLocalM) { | |
262 buf.writeMatrix(fNormLocalMatrix); | |
263 } | |
264 | |
265 buf.writeBitmap(fNormalMap); | |
266 buf.writePoint(fInvNormRotation); | |
267 } | |
268 | |
269 //////////////////////////////////////////////////////////////////////////// | |
270 | |
271 sk_sp<SkLightingShader::NormalSource> SkLightingShader::NormalMapSource::Make( | |
272 const SkBitmap &normal, const SkVector &invNormRotation, const SkMatrix *normLocalM) { | |
273 | |
274 // TODO not checking normal and diffuse maps to be same size, will be addres sed when diffuse | |
275 // maps are factored out of SkLightingShader in a future CL | |
276 if (normal.isNull() || SkBitmapProcShader::bitmapIsTooBig(normal)) { | |
277 return nullptr; | |
278 } | |
279 | |
280 SkASSERT(SkScalarNearlyEqual(invNormRotation.lengthSqd(), SK_Scalar1)); | |
281 | |
282 return sk_make_sp<NormalMapSourceImpl>(normal, invNormRotation, normLocalM); | |
283 } | |
284 | |
285 //////////////////////////////////////////////////////////////////////////// | |
286 | |
287 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkLightingShader::NormalMapSource) | |
288 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(NormalMapSourceImpl) | |
289 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END | |
290 | |
291 //////////////////////////////////////////////////////////////////////////// | |
OLD | NEW |