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 "SkNormalSourceImpl.h" | |
9 #include "SkShader.h" | |
10 | |
11 class NormalMapFP : public GrFragmentProcessor { | |
12 public: | |
13 NormalMapFP(GrTexture* normal, const SkMatrix& normMatrix, const GrTexturePa rams& normParams, | |
14 const SkVector& invNormRotation) | |
15 : fNormDeviceTransform(kLocal_GrCoordSet, normMatrix, normal, normPa rams.filterMode()) | |
egdaniel
2016/06/09 16:56:38
Skia's style has these initiliazers only tabbed in
dvonbeck
2016/06/09 18:51:29
Done.
| |
16 , fNormalTextureAccess(normal, normParams) | |
17 , fInvNormRotation(invNormRotation) { | |
18 this->addCoordTransform(&fNormDeviceTransform); | |
19 this->addTextureAccess(&fNormalTextureAccess); | |
20 | |
21 this->initClassID<NormalMapFP>(); | |
22 } | |
23 | |
24 class NormalMapGLFP : public GrGLSLFragmentProcessor { | |
egdaniel
2016/06/09 16:56:38
Usually we put the GL in front of the class name,
dvonbeck
2016/06/09 18:51:29
Done.
| |
25 public: | |
26 NormalMapGLFP() { | |
27 fInvNormRotation.set(0.0f, 0.0f); | |
28 } | |
29 | |
30 void emitCode(EmitArgs& args) override { | |
31 | |
32 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder; | |
33 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; | |
34 | |
35 // add uniform | |
36 const char* xformUniName = nullptr; | |
37 fXformUni = uniformHandler->addUniform(kFragment_GrShaderFlag, | |
38 kVec2f_GrSLType, kDefault_GrS LPrecision, | |
39 "Xform", &xformUniName); | |
40 | |
41 fragBuilder->codeAppend("vec4 normalColor = "); | |
42 fragBuilder->appendTextureLookup(args.fTexSamplers[0], | |
43 args.fCoords[0].c_str(), | |
44 args.fCoords[0].getType()); | |
45 fragBuilder->codeAppend(";"); | |
46 | |
47 fragBuilder->codeAppend("vec3 normal = normalColor.rgb - vec3(0.5);" ); | |
48 | |
49 // TODO: inverse map the light direction vectors in the vertex shade r rather than | |
50 // transforming all the normals here! | |
51 fragBuilder->codeAppendf( | |
52 "mat3 m = mat3(%s.x, -%s.y, 0.0, %s.y, %s.x, 0.0, 0.0, 0.0, 1.0);", | |
53 xformUniName, xformUniName, xformUniName, xformUniName); | |
54 | |
55 fragBuilder->codeAppend("normal = normalize(m*normal);"); | |
56 fragBuilder->codeAppendf("%s = vec4(normal, 0);", args.fOutputColor) ; | |
57 } | |
58 | |
59 // TODO does this need changing now? | |
60 static void GenKey(const GrProcessor& proc, const GrGLSLCaps&, | |
61 GrProcessorKeyBuilder* b) { | |
62 // const LightingFP& lightingFP = proc.cast<LightingFP>(); | |
63 // only one shader generated currently | |
64 b->add32(0x0); | |
egdaniel
2016/06/09 16:56:38
This should be fine outputing zero. Clean up the c
dvonbeck
2016/06/09 18:51:29
Done.
| |
65 } | |
66 | |
67 protected: | |
68 void onSetData(const GrGLSLProgramDataManager& pdman, const GrProcessor& proc) override { | |
69 const NormalMapFP& normalMapFP = proc.cast<NormalMapFP>(); | |
70 | |
71 const SkVector& invNormRotation = normalMapFP.invNormRotation(); | |
72 if (invNormRotation != fInvNormRotation) { | |
73 pdman.set2fv(fXformUni, 1, &invNormRotation.fX); | |
74 fInvNormRotation = invNormRotation; | |
75 } | |
76 } | |
77 | |
78 private: | |
79 SkVector fInvNormRotation; | |
80 GrGLSLProgramDataManager::UniformHandle fXformUni; | |
81 }; | |
82 | |
83 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override { | |
84 NormalMapGLFP::GenKey(*this, caps, b); | |
85 } | |
86 | |
87 const char* name() const override { return "NormalMapFP"; } | |
88 | |
89 // TODO what is this? keep? delete? | |
90 void onComputeInvariantOutput(GrInvariantOutput* inout) const override { | |
91 inout->mulByUnknownFourComponents(); | |
egdaniel
2016/06/09 16:56:38
Since this guy doesn't actually use his input, and
dvonbeck
2016/06/09 18:51:29
The object doesn't have a setUnknownFourComponents
egdaniel
2016/06/10 14:23:27
Sorry that was the function on the inner struct. T
dvonbeck
2016/06/10 15:22:28
Done.
| |
92 } | |
93 | |
94 const SkVector& invNormRotation() const { return fInvNormRotation; } | |
95 | |
96 private: | |
97 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return new NormalMapGLFP; } | |
98 | |
99 bool onIsEqual(const GrFragmentProcessor& proc) const override { | |
100 const NormalMapFP& normalMapFP = proc.cast<NormalMapFP>(); | |
101 return fNormDeviceTransform == normalMapFP.fNormDeviceTransform && | |
102 fNormalTextureAccess == normalMapFP.fNormalTextureAccess && | |
103 fInvNormRotation == normalMapFP.fInvNormRotation; | |
104 } | |
105 | |
106 GrCoordTransform fNormDeviceTransform; | |
107 GrTextureAccess fNormalTextureAccess; | |
108 | |
109 SkVector fInvNormRotation; | |
110 }; | |
111 | |
112 // TODO same code at SkLightingShader.cpp. Refactor to common source! | |
113 static bool make_mat(const SkBitmap& bm, | |
114 const SkMatrix& localMatrix1, | |
115 const SkMatrix* localMatrix2, | |
116 SkMatrix* result) { | |
117 | |
118 result->setIDiv(bm.width(), bm.height()); | |
119 | |
120 SkMatrix lmInverse; | |
121 if (!localMatrix1.invert(&lmInverse)) { | |
122 return false; | |
123 } | |
124 if (localMatrix2) { | |
125 SkMatrix inv; | |
126 if (!localMatrix2->invert(&inv)) { | |
127 return false; | |
128 } | |
129 lmInverse.postConcat(inv); | |
130 } | |
131 result->preConcat(lmInverse); | |
132 | |
133 return true; | |
134 } | |
135 | |
136 class NormalMapSourceImpl : public NormalSource { | |
137 public: | |
138 NormalMapSourceImpl(const SkBitmap &normal, const SkVector &invNormRotation, | |
139 const SkMatrix *normLocalM) | |
egdaniel
2016/06/09 16:56:38
alight with other parameters
dvonbeck
2016/06/09 18:51:29
Done.
| |
140 : fNormalMap(normal) | |
egdaniel
2016/06/09 16:56:38
again remove one tab
dvonbeck
2016/06/09 18:51:29
Done.
| |
141 , fInvNormRotation(invNormRotation) { | |
142 | |
143 if (normLocalM) { | |
144 fNormLocalMatrix = *normLocalM; | |
145 } else { | |
146 fNormLocalMatrix.reset(); | |
147 } | |
148 // Pre-cache so future calls to fNormLocalMatrix.getType() are threadsaf e. | |
149 (void)fNormLocalMatrix.getType(); | |
150 } | |
151 | |
152 const GrFragmentProcessor* asFragmentProcessor( | |
153 GrContext* context, | |
154 const SkMatrix& viewM, | |
155 const SkMatrix* localMatrix, | |
156 SkFilterQuality filterQuality, | |
157 SkSourceGammaTreatment gammaTreatme nt) const override; | |
158 | |
159 private: | |
160 SkBitmap fNormalMap; | |
161 SkMatrix fNormLocalMatrix; | |
162 SkVector fInvNormRotation; | |
163 }; | |
164 | |
165 const GrFragmentProcessor* NormalMapSourceImpl::asFragmentProcessor( | |
166 GrContext *context, | |
167 const SkMatrix &viewM, | |
168 const SkMatrix *localMatrix , | |
169 SkFilterQuality filterQuali ty, | |
170 SkSourceGammaTreatment gamm aTreatment) const { | |
171 | |
172 // TODO Here, the old code was checking that diffuse map and normal map are same size, that | |
egdaniel
2016/06/09 16:56:38
We should really have a way so that the diffuse bi
dvonbeck
2016/06/09 18:51:29
Acknowledged.
| |
173 // TODO needs to happen somewhere again! | |
174 | |
175 SkMatrix normM; | |
176 if (!make_mat(fNormalMap, fNormLocalMatrix, localMatrix, &normM)) { | |
177 return nullptr; | |
178 } | |
179 | |
180 bool doBicubic; | |
181 GrTextureParams::FilterMode normFilterMode = GrSkFilterQualityToGrFilterMode ( | |
182 SkTMin(filterQuality, kMedium_SkFilterQuality), | |
183 viewM, | |
184 fNormLocalMatrix, | |
185 &doBicubic); | |
186 SkASSERT(!doBicubic); | |
187 | |
188 // TODO: support other tile modes | |
189 GrTextureParams normParams(SkShader::kClamp_TileMode, normFilterMode); | |
190 SkAutoTUnref<GrTexture> normalTexture(GrRefCachedBitmapTexture(context, | |
191 fNormalMap, | |
192 normParams, | |
193 gammaTreatmen t)); | |
194 if (!normalTexture) { | |
195 SkErrorInternals::SetError(kInternalError_SkError, "Couldn't convert bit map to texture."); | |
196 return nullptr; | |
197 } | |
198 | |
199 // TODO is this correct memory handling? | |
egdaniel
2016/06/09 16:56:38
yes this is fine here. It is the callers responsib
dvonbeck
2016/06/09 18:51:29
Done.
| |
200 return new NormalMapFP(normalTexture, normM, normParams, fInvNormRotation); | |
201 } | |
202 | |
203 // TODO This function is also in SkLightingShader. Refactor to common source? | |
204 // TODO what does it mean for the funciton to be static | |
205 static bool bitmap_is_too_big(const SkBitmap& bm) { | |
206 // SkBitmapProcShader stores bitmap coordinates in a 16bit buffer, as it | |
207 // communicates between its matrix-proc and its sampler-proc. Until we can | |
208 // widen that, we have to reject bitmaps that are larger. | |
209 // | |
210 static const int kMaxSize = 65535; | |
211 | |
212 return bm.width() > kMaxSize || bm.height() > kMaxSize; | |
213 } | |
214 | |
215 sk_sp<NormalSource> NormalMapSource::Make(const SkBitmap &normal, const SkVector &invNormRotation, | |
216 const SkMatrix *normLocalM) { | |
217 | |
218 // TODO not checking normal and diffuse maps to be same size | |
219 if (normal.isNull() || bitmap_is_too_big(normal)) { | |
220 return nullptr; | |
221 } | |
222 | |
223 SkASSERT(SkScalarNearlyEqual(invNormRotation.lengthSqd(), SK_Scalar1)); | |
224 | |
225 return sk_make_sp<NormalMapSourceImpl>(normal, invNormRotation, normLocalM); | |
226 } | |
OLD | NEW |