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

Side by Side Diff: samplecode/SampleLighting.cpp

Issue 1230603002: Revert of Add normal map sample (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 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 | « resources/brickwork_normal-map.jpg ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1
2 /*
3 * Copyright 2015 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8 #include "SampleCode.h"
9 #include "Resources.h"
10
11 #include "SkCanvas.h"
12 #include "SkErrorInternals.h"
13 #include "SkGr.h"
14 #include "SkReadBuffer.h"
15 #include "SkShader.h"
16 #include "SkWriteBuffer.h"
17
18 #include "GrFragmentProcessor.h"
19 #include "GrCoordTransform.h"
20 #include "gl/GrGLProcessor.h"
21 #include "gl/builders/GrGLProgramBuilder.h"
22
23 ///////////////////////////////////////////////////////////////////////////////
24
25 struct SkVector3 {
26 SkScalar fX, fY, fZ;
27
28 bool operator==(const SkVector3& other) const {
29 return fX == other.fX && fY == other.fY && fZ == other.fZ;
30 }
31
32 bool operator!=(const SkVector3& other) const {
33 return !(*this == other);
34 }
35 };
36
37 class LightingShader : public SkShader {
38 public:
39 struct Light {
40 SkVector3 fDirection;
41 SkColor fColor; // assumed to be linear color
42 };
43
44 LightingShader(const SkBitmap& diffuse, const SkBitmap& normal, const Light& light,
45 const SkColor ambient)
46 : fDiffuseMap(diffuse)
47 , fNormalMap(normal)
48 , fLight(light)
49 , fAmbientColor(ambient) {}
50
51 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(LightingShader);
52
53 void flatten(SkWriteBuffer& buf) const override {
54 buf.writeBitmap(fDiffuseMap);
55 buf.writeBitmap(fNormalMap);
56 buf.writeScalarArray(&fLight.fDirection.fX, 3);
57 buf.writeColor(fLight.fColor);
58 buf.writeColor(fAmbientColor);
59 }
60
61 bool asFragmentProcessor(GrContext*, const SkPaint& paint, const SkMatrix& v iewM,
62 const SkMatrix* localMatrix, GrColor* color,
63 GrShaderDataManager*, GrFragmentProcessor** fp) con st override;
64
65 SkShader::BitmapType asABitmap(SkBitmap* bitmap, SkMatrix* matrix,
66 SkShader::TileMode* xy) const override {
67 if (bitmap) {
68 *bitmap = fDiffuseMap;
69 }
70 if (matrix) {
71 matrix->reset();
72 }
73 if (xy) {
74 xy[0] = kClamp_TileMode;
75 xy[1] = kClamp_TileMode;
76 }
77 return kDefault_BitmapType;
78 }
79
80 #ifndef SK_IGNORE_TO_STRING
81 void toString(SkString* str) const override {
82 str->appendf("LightingShader: ()");
83 }
84 #endif
85
86 void setLight(const Light& light) { fLight = light; }
87
88 private:
89 SkBitmap fDiffuseMap;
90 SkBitmap fNormalMap;
91 Light fLight;
92 SkColor fAmbientColor;
93 };
94
95 SkFlattenable* LightingShader::CreateProc(SkReadBuffer& buf) {
96 SkBitmap diffuse;
97 if (!buf.readBitmap(&diffuse)) {
98 return NULL;
99 }
100 diffuse.setImmutable();
101
102 SkBitmap normal;
103 if (!buf.readBitmap(&normal)) {
104 return NULL;
105 }
106 normal.setImmutable();
107
108 Light light;
109 if (!buf.readScalarArray(&light.fDirection.fX, 3)) {
110 return NULL;
111 }
112 light.fColor = buf.readColor();
113
114 SkColor ambient = buf.readColor();
115
116 return SkNEW_ARGS(LightingShader, (diffuse, normal, light, ambient));
117 }
118
119 ////////////////////////////////////////////////////////////////////////////
120
121 class LightingFP : public GrFragmentProcessor {
122 public:
123 LightingFP(GrTexture* diffuse, GrTexture* normal, const SkMatrix& matrix,
124 SkVector3 lightDir, GrColor lightColor, GrColor ambientColor)
125 : fDeviceTransform(kDevice_GrCoordSet, matrix)
126 , fDiffuseTextureAccess(diffuse)
127 , fNormalTextureAccess(normal)
128 , fLightDir(lightDir)
129 , fLightColor(lightColor)
130 , fAmbientColor(ambientColor) {
131 this->addCoordTransform(&fDeviceTransform);
132 this->addTextureAccess(&fDiffuseTextureAccess);
133 this->addTextureAccess(&fNormalTextureAccess);
134
135 this->initClassID<LightingFP>();
136 }
137
138 class LightingGLFP : public GrGLFragmentProcessor {
139 public:
140 LightingGLFP() : fLightColor(GrColor_ILLEGAL) {
141 fLightDir.fX = 10000.0f;
142 }
143
144 void emitCode(GrGLFPBuilder* builder,
145 const GrFragmentProcessor& fp,
146 const char* outputColor,
147 const char* inputColor,
148 const TransformedCoordsArray& coords,
149 const TextureSamplerArray& samplers) override {
150
151 GrGLFragmentBuilder* fpb = builder->getFragmentShaderBuilder();
152
153 // add uniforms
154 const char* lightDirUniName = NULL;
155 fLightDirUni = builder->addUniform(GrGLProgramBuilder::kFragment_Vis ibility,
156 kVec3f_GrSLType, kDefault_GrSLPre cision,
157 "LightDir", &lightDirUniName);
158
159 const char* lightColorUniName = NULL;
160 fLightColorUni = builder->addUniform(GrGLProgramBuilder::kFragment_V isibility,
161 kVec4f_GrSLType, kDefault_GrSLP recision,
162 "LightColor", &lightColorUniNam e);
163
164 const char* ambientColorUniName = NULL;
165 fAmbientColorUni = builder->addUniform(GrGLProgramBuilder::kFragment _Visibility,
166 kVec4f_GrSLType, kDefault_GrS LPrecision,
167 "AmbientColor", &ambientColor UniName);
168
169 fpb->codeAppend("vec4 diffuseColor = ");
170 fpb->appendTextureLookupAndModulate(inputColor, samplers[0],
171 coords[0].c_str(), coords[0].get Type());
172 fpb->codeAppend(";");
173
174 fpb->codeAppend("vec4 normalColor = ");
175 fpb->appendTextureLookup(samplers[1], coords[0].c_str(), coords[0].g etType());
176 fpb->codeAppend(";");
177
178 fpb->codeAppend("vec3 normal = normalize(2.0*(normalColor.rgb - vec3 (0.5)));");
179 fpb->codeAppendf("vec3 lightDir = normalize(%s);", lightDirUniName);
180 fpb->codeAppend("float NdotL = dot(normal, lightDir);");
181 // diffuse light
182 fpb->codeAppendf("vec3 result = %s.rgb*diffuseColor.rgb*NdotL;", lig htColorUniName);
183 // ambient light
184 fpb->codeAppendf("result += %s.rgb;", ambientColorUniName);
185 fpb->codeAppendf("%s = vec4(result.rgb, diffuseColor.a);", outputCol or);
186 }
187
188 void setData(const GrGLProgramDataManager& pdman, const GrProcessor& pro c) override {
189 const LightingFP& lightingFP = proc.cast<LightingFP>();
190
191 SkVector3 lightDir = lightingFP.lightDir();
192 if (lightDir != fLightDir) {
193 pdman.set3fv(fLightDirUni, 1, &lightDir.fX);
194 fLightDir = lightDir;
195 }
196
197 GrColor lightColor = lightingFP.lightColor();
198 if (lightColor != fLightColor) {
199 GrGLfloat c[4];
200 GrColorToRGBAFloat(lightColor, c);
201 pdman.set4fv(fLightColorUni, 1, c);
202 fLightColor = lightColor;
203 }
204
205 GrColor ambientColor = lightingFP.ambientColor();
206 if (ambientColor != fAmbientColor) {
207 GrGLfloat c[4];
208 GrColorToRGBAFloat(ambientColor, c);
209 pdman.set4fv(fAmbientColorUni, 1, c);
210 fAmbientColor = ambientColor;
211 }
212 }
213
214 static void GenKey(const GrProcessor& proc, const GrGLSLCaps&,
215 GrProcessorKeyBuilder* b) {
216 // const LightingFP& lightingFP = proc.cast<LightingFP>();
217 // only one shader generated currently
218 b->add32(0x0);
219 }
220
221 private:
222 SkVector3 fLightDir;
223 GrGLProgramDataManager::UniformHandle fLightDirUni;
224
225 GrColor fLightColor;
226 GrGLProgramDataManager::UniformHandle fLightColorUni;
227
228 GrColor fAmbientColor;
229 GrGLProgramDataManager::UniformHandle fAmbientColorUni;
230 };
231
232 GrGLFragmentProcessor* createGLInstance() const override { return SkNEW(Ligh tingGLFP); }
233
234 void getGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) con st override {
235 LightingGLFP::GenKey(*this, caps, b);
236 }
237
238 const char* name() const override { return "LightingFP"; }
239
240 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
241 inout->mulByUnknownFourComponents();
242 }
243
244 SkVector3 lightDir() const { return fLightDir; }
245 GrColor lightColor() const { return fLightColor; }
246 GrColor ambientColor() const { return fAmbientColor; }
247
248 private:
249 bool onIsEqual(const GrFragmentProcessor& proc) const override {
250 const LightingFP& lightingFP = proc.cast<LightingFP>();
251 return fDeviceTransform == lightingFP.fDeviceTransform &&
252 fDiffuseTextureAccess == lightingFP.fDiffuseTextureAccess &&
253 fNormalTextureAccess == lightingFP.fNormalTextureAccess &&
254 fLightDir == lightingFP.fLightDir &&
255 fLightColor == lightingFP.fLightColor &&
256 fAmbientColor == lightingFP.fAmbientColor;
257 }
258
259 GrCoordTransform fDeviceTransform;
260 GrTextureAccess fDiffuseTextureAccess;
261 GrTextureAccess fNormalTextureAccess;
262 SkVector3 fLightDir;
263 GrColor fLightColor;
264 GrColor fAmbientColor;
265 };
266
267 bool LightingShader::asFragmentProcessor(GrContext* context, const SkPaint& pain t,
268 const SkMatrix& viewM, const SkMatrix* localMatrix,
269 GrColor* color, GrShaderDataManager*,
270 GrFragmentProcessor** fp) const {
271 // we assume diffuse and normal maps have same width and height
272 // TODO: support different sizes
273 SkASSERT(fDiffuseMap.width() == fNormalMap.width() &&
274 fDiffuseMap.height() == fNormalMap.height());
275 SkMatrix matrix;
276 matrix.setIDiv(fDiffuseMap.width(), fDiffuseMap.height());
277
278 SkMatrix lmInverse;
279 if (!this->getLocalMatrix().invert(&lmInverse)) {
280 return false;
281 }
282 if (localMatrix) {
283 SkMatrix inv;
284 if (!localMatrix->invert(&inv)) {
285 return false;
286 }
287 lmInverse.postConcat(inv);
288 }
289 matrix.preConcat(lmInverse);
290
291 // Must set wrap and filter on the sampler before requesting a texture. In t wo places below
292 // we check the matrix scale factors to determine how to interpret the filte r quality setting.
293 // This completely ignores the complexity of the drawVertices case where exp licit local coords
294 // are provided by the caller.
295 GrTextureParams::FilterMode textureFilterMode = GrTextureParams::kBilerp_Fil terMode;
296 switch (paint.getFilterQuality()) {
297 case kNone_SkFilterQuality:
298 textureFilterMode = GrTextureParams::kNone_FilterMode;
299 break;
300 case kLow_SkFilterQuality:
301 textureFilterMode = GrTextureParams::kBilerp_FilterMode;
302 break;
303 case kMedium_SkFilterQuality:{
304 SkMatrix matrix;
305 matrix.setConcat(viewM, this->getLocalMatrix());
306 if (matrix.getMinScale() < SK_Scalar1) {
307 textureFilterMode = GrTextureParams::kMipMap_FilterMode;
308 } else {
309 // Don't trigger MIP level generation unnecessarily.
310 textureFilterMode = GrTextureParams::kBilerp_FilterMode;
311 }
312 break;
313 }
314 case kHigh_SkFilterQuality:
315 default:
316 SkErrorInternals::SetError(kInvalidPaint_SkError,
317 "Sorry, I don't understand the filtering "
318 "mode you asked for. Falling back to "
319 "MIPMaps.");
320 textureFilterMode = GrTextureParams::kMipMap_FilterMode;
321 break;
322
323 }
324
325 // TODO: support other tile modes
326 GrTextureParams params(kClamp_TileMode, textureFilterMode);
327 SkAutoTUnref<GrTexture> diffuseTexture(GrRefCachedBitmapTexture(context, fDi ffuseMap, &params));
328 if (!diffuseTexture) {
329 SkErrorInternals::SetError(kInternalError_SkError,
330 "Couldn't convert bitmap to texture.");
331 return false;
332 }
333
334 SkAutoTUnref<GrTexture> normalTexture(GrRefCachedBitmapTexture(context, fNor malMap, &params));
335 if (!normalTexture) {
336 SkErrorInternals::SetError(kInternalError_SkError,
337 "Couldn't convert bitmap to texture.");
338 return false;
339 }
340
341 GrColor lightColor = GrColorPackRGBA(SkColorGetR(fLight.fColor), SkColorGetG (fLight.fColor),
342 SkColorGetB(fLight.fColor), SkColorGetA (fLight.fColor));
343 GrColor ambientColor = GrColorPackRGBA(SkColorGetR(fAmbientColor), SkColorGe tG(fAmbientColor),
344 SkColorGetB(fAmbientColor), SkColorGe tA(fAmbientColor));
345
346 *fp = SkNEW_ARGS(LightingFP, (diffuseTexture, normalTexture, matrix,
347 fLight.fDirection, lightColor, ambientColor));
348 *color = GrColorPackA4(paint.getAlpha());
349 return true;
350 }
351
352 ////////////////////////////////////////////////////////////////////////////
353
354 class LightingView : public SampleView {
355 public:
356 SkAutoTUnref<LightingShader> fShader;
357 SkBitmap fDiffuseBitmap;
358 SkBitmap fNormalBitmap;
359 SkScalar fLightAngle;
360 int fColorFactor;
361
362 LightingView() {
363 SkString diffusePath = GetResourcePath("brickwork-texture.jpg");
364 SkImageDecoder::DecodeFile(diffusePath.c_str(), &fDiffuseBitmap);
365 SkString normalPath = GetResourcePath("brickwork_normal-map.jpg");
366 SkImageDecoder::DecodeFile(normalPath.c_str(), &fNormalBitmap);
367
368 fLightAngle = 0.0f;
369 fColorFactor = 0;
370
371 LightingShader::Light light;
372 light.fColor = SkColorSetRGB(0xff, 0xff, 0xff);
373 light.fDirection.fX = SkScalarSin(fLightAngle)*SkScalarSin(SK_ScalarPI*0 .25f);
374 light.fDirection.fY = SkScalarCos(fLightAngle)*SkScalarSin(SK_ScalarPI*0 .25f);
375 light.fDirection.fZ = SkScalarCos(SK_ScalarPI*0.25f);
376
377 SkColor ambient = SkColorSetRGB(0x1f, 0x1f, 0x1f);
378
379 fShader.reset(SkNEW_ARGS(LightingShader, (fDiffuseBitmap, fNormalBitmap, light, ambient)));
380 }
381
382 virtual ~LightingView() {}
383
384 protected:
385 // overrides from SkEventSink
386 bool onQuery(SkEvent* evt) override {
387 if (SampleCode::TitleQ(*evt)) {
388 SampleCode::TitleR(evt, "Lighting");
389 return true;
390 }
391 return this->INHERITED::onQuery(evt);
392 }
393
394 void onDrawContent(SkCanvas* canvas) override {
395 fLightAngle += 0.015f;
396 fColorFactor++;
397
398 LightingShader::Light light;
399 light.fColor = SkColorSetRGB(0xff, 0xff, (fColorFactor >> 1) & 0xff);
400 light.fDirection.fX = SkScalarSin(fLightAngle)*SkScalarSin(SK_ScalarPI*0 .25f);
401 light.fDirection.fY = SkScalarCos(fLightAngle)*SkScalarSin(SK_ScalarPI*0 .25f);
402 light.fDirection.fZ = SkScalarCos(SK_ScalarPI*0.25f);
403
404 fShader.get()->setLight(light);
405
406 SkPaint paint;
407 paint.setShader(fShader);
408 paint.setColor(SK_ColorBLACK);
409
410 SkRect r = SkRect::MakeWH((SkScalar)fDiffuseBitmap.width(),
411 (SkScalar)fDiffuseBitmap.height());
412 canvas->drawRect(r, paint);
413
414 // so we're constantly updating
415 this->inval(NULL);
416 }
417
418 SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) ove rride {
419 this->inval(NULL);
420 return this->INHERITED::onFindClickHandler(x, y, modi);
421 }
422
423 private:
424 typedef SampleView INHERITED;
425 };
426
427 //////////////////////////////////////////////////////////////////////////////
428
429 static SkView* MyFactory() { return new LightingView; }
430 static SkViewRegister reg(MyFactory);
OLDNEW
« no previous file with comments | « resources/brickwork_normal-map.jpg ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698