SkLightingShader.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. /*
  2. * Copyright 2015 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. #include "include/core/SkColor.h"
  8. #include "include/core/SkPoint3.h"
  9. #include "include/core/SkUnPreMultiply.h"
  10. #include "src/core/SkArenaAlloc.h"
  11. #include "src/core/SkBitmapProcState.h"
  12. #include "src/core/SkMathPriv.h"
  13. #include "src/core/SkNormalSource.h"
  14. #include "src/core/SkReadBuffer.h"
  15. #include "src/core/SkWriteBuffer.h"
  16. #include "src/shaders/SkBitmapProcShader.h"
  17. #include "src/shaders/SkEmptyShader.h"
  18. #include "src/shaders/SkLightingShader.h"
  19. #include "src/shaders/SkShaderBase.h"
  20. ////////////////////////////////////////////////////////////////////////////
  21. /*
  22. SkLightingShader TODOs:
  23. support different light types
  24. support multiple lights
  25. fix non-opaque diffuse textures
  26. To Test:
  27. A8 diffuse textures
  28. down & upsampled draws
  29. */
  30. /** \class SkLightingShaderImpl
  31. This subclass of shader applies lighting.
  32. */
  33. class SkLightingShaderImpl : public SkShaderBase {
  34. public:
  35. /** Create a new lighting shader that uses the provided normal map and
  36. lights to light the diffuse bitmap.
  37. @param diffuseShader the shader that provides the diffuse colors
  38. @param normalSource the source of normals for lighting computation
  39. @param lights the lights applied to the geometry
  40. */
  41. SkLightingShaderImpl(sk_sp<SkShader> diffuseShader,
  42. sk_sp<SkNormalSource> normalSource,
  43. sk_sp<SkLights> lights)
  44. : fDiffuseShader(std::move(diffuseShader))
  45. , fNormalSource(std::move(normalSource))
  46. , fLights(std::move(lights)) {}
  47. bool isOpaque() const override;
  48. #if SK_SUPPORT_GPU
  49. std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(const GrFPArgs&) const override;
  50. #endif
  51. class LightingShaderContext : public Context {
  52. public:
  53. // The context takes ownership of the context and provider. It will call their destructors
  54. // and then indirectly free their memory by calling free() on heapAllocated
  55. LightingShaderContext(const SkLightingShaderImpl&, const ContextRec&,
  56. SkShaderBase::Context* diffuseContext, SkNormalSource::Provider*,
  57. void* heapAllocated);
  58. void shadeSpan(int x, int y, SkPMColor[], int count) override;
  59. uint32_t getFlags() const override { return fFlags; }
  60. private:
  61. SkShaderBase::Context* fDiffuseContext;
  62. SkNormalSource::Provider* fNormalProvider;
  63. SkColor fPaintColor;
  64. uint32_t fFlags;
  65. typedef Context INHERITED;
  66. };
  67. protected:
  68. void flatten(SkWriteBuffer&) const override;
  69. #ifdef SK_ENABLE_LEGACY_SHADERCONTEXT
  70. Context* onMakeContext(const ContextRec&, SkArenaAlloc*) const override;
  71. #endif
  72. private:
  73. SK_FLATTENABLE_HOOKS(SkLightingShaderImpl)
  74. sk_sp<SkShader> fDiffuseShader;
  75. sk_sp<SkNormalSource> fNormalSource;
  76. sk_sp<SkLights> fLights;
  77. friend class SkLightingShader;
  78. typedef SkShaderBase INHERITED;
  79. };
  80. ////////////////////////////////////////////////////////////////////////////
  81. #if SK_SUPPORT_GPU
  82. #include "src/gpu/GrCoordTransform.h"
  83. #include "src/gpu/GrFragmentProcessor.h"
  84. #include "src/gpu/SkGr.h"
  85. #include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
  86. #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
  87. #include "src/gpu/glsl/GrGLSLProgramDataManager.h"
  88. #include "src/gpu/glsl/GrGLSLUniformHandler.h"
  89. // This FP expects a premul'd color input for its diffuse color. Premul'ing of the paint's color is
  90. // handled by the asFragmentProcessor() factory, but shaders providing diffuse color must output it
  91. // premul'd.
  92. class LightingFP : public GrFragmentProcessor {
  93. public:
  94. static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> normalFP,
  95. sk_sp<SkLights> lights) {
  96. return std::unique_ptr<GrFragmentProcessor>(new LightingFP(std::move(normalFP),
  97. std::move(lights)));
  98. }
  99. const char* name() const override { return "LightingFP"; }
  100. std::unique_ptr<GrFragmentProcessor> clone() const override {
  101. return std::unique_ptr<GrFragmentProcessor>(new LightingFP(*this));
  102. }
  103. const SkTArray<SkLights::Light>& directionalLights() const { return fDirectionalLights; }
  104. const SkColor3f& ambientColor() const { return fAmbientColor; }
  105. private:
  106. class GLSLLightingFP : public GrGLSLFragmentProcessor {
  107. public:
  108. GLSLLightingFP() {
  109. fAmbientColor.fX = 0.0f;
  110. }
  111. void emitCode(EmitArgs& args) override {
  112. GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
  113. GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
  114. const LightingFP& lightingFP = args.fFp.cast<LightingFP>();
  115. const char *lightDirsUniName = nullptr;
  116. const char *lightColorsUniName = nullptr;
  117. if (lightingFP.fDirectionalLights.count() != 0) {
  118. fLightDirsUni = uniformHandler->addUniformArray(
  119. kFragment_GrShaderFlag,
  120. kFloat3_GrSLType,
  121. "LightDir",
  122. lightingFP.fDirectionalLights.count(),
  123. &lightDirsUniName);
  124. fLightColorsUni = uniformHandler->addUniformArray(
  125. kFragment_GrShaderFlag,
  126. kFloat3_GrSLType,
  127. "LightColor",
  128. lightingFP.fDirectionalLights.count(),
  129. &lightColorsUniName);
  130. }
  131. const char* ambientColorUniName = nullptr;
  132. fAmbientColorUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kFloat3_GrSLType,
  133. "AmbientColor", &ambientColorUniName);
  134. fragBuilder->codeAppendf("half4 diffuseColor = %s;", args.fInputColor);
  135. SkString dstNormalName("dstNormal");
  136. this->emitChild(0, &dstNormalName, args);
  137. fragBuilder->codeAppendf("float3 normal = %s.xyz;", dstNormalName.c_str());
  138. fragBuilder->codeAppend( "half3 result = half3(0.0);");
  139. // diffuse light
  140. if (lightingFP.fDirectionalLights.count() != 0) {
  141. fragBuilder->codeAppendf("for (int i = 0; i < %d; i++) {",
  142. lightingFP.fDirectionalLights.count());
  143. // TODO: modulate the contribution from each light based on the shadow map
  144. fragBuilder->codeAppendf(" half NdotL = saturate(half(dot(normal, %s[i])));",
  145. lightDirsUniName);
  146. fragBuilder->codeAppendf(" result += half3(%s[i])*diffuseColor.rgb*NdotL;",
  147. lightColorsUniName);
  148. fragBuilder->codeAppend("}");
  149. }
  150. // ambient light
  151. fragBuilder->codeAppendf("result += half3(%s) * diffuseColor.rgb;",
  152. ambientColorUniName);
  153. // Clamping to alpha (equivalent to an unpremul'd clamp to 1.0)
  154. fragBuilder->codeAppendf("%s = half4(clamp(result.rgb, 0.0, diffuseColor.a), "
  155. "diffuseColor.a);", args.fOutputColor);
  156. }
  157. static void GenKey(const GrProcessor& proc, const GrShaderCaps&, GrProcessorKeyBuilder* b) {
  158. const LightingFP& lightingFP = proc.cast<LightingFP>();
  159. b->add32(lightingFP.fDirectionalLights.count());
  160. }
  161. protected:
  162. void onSetData(const GrGLSLProgramDataManager& pdman,
  163. const GrFragmentProcessor& proc) override {
  164. const LightingFP& lightingFP = proc.cast<LightingFP>();
  165. const SkTArray<SkLights::Light>& directionalLights = lightingFP.directionalLights();
  166. if (directionalLights != fDirectionalLights) {
  167. SkTArray<SkColor3f> lightDirs(directionalLights.count());
  168. SkTArray<SkVector3> lightColors(directionalLights.count());
  169. for (const SkLights::Light& light : directionalLights) {
  170. lightDirs.push_back(light.dir());
  171. lightColors.push_back(light.color());
  172. }
  173. pdman.set3fv(fLightDirsUni, directionalLights.count(), &(lightDirs[0].fX));
  174. pdman.set3fv(fLightColorsUni, directionalLights.count(), &(lightColors[0].fX));
  175. fDirectionalLights = directionalLights;
  176. }
  177. const SkColor3f& ambientColor = lightingFP.ambientColor();
  178. if (ambientColor != fAmbientColor) {
  179. pdman.set3fv(fAmbientColorUni, 1, &ambientColor.fX);
  180. fAmbientColor = ambientColor;
  181. }
  182. }
  183. private:
  184. SkTArray<SkLights::Light> fDirectionalLights;
  185. GrGLSLProgramDataManager::UniformHandle fLightDirsUni;
  186. GrGLSLProgramDataManager::UniformHandle fLightColorsUni;
  187. SkColor3f fAmbientColor;
  188. GrGLSLProgramDataManager::UniformHandle fAmbientColorUni;
  189. };
  190. void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
  191. GLSLLightingFP::GenKey(*this, caps, b);
  192. }
  193. LightingFP(std::unique_ptr<GrFragmentProcessor> normalFP, sk_sp<SkLights> lights)
  194. : INHERITED(kLightingFP_ClassID, kPreservesOpaqueInput_OptimizationFlag) {
  195. // fuse all ambient lights into a single one
  196. fAmbientColor = lights->ambientLightColor();
  197. for (int i = 0; i < lights->numLights(); ++i) {
  198. if (SkLights::Light::kDirectional_LightType == lights->light(i).type()) {
  199. fDirectionalLights.push_back(lights->light(i));
  200. // TODO get the handle to the shadow map if there is one
  201. } else {
  202. SkDEBUGFAIL("Unimplemented Light Type passed to LightingFP");
  203. }
  204. }
  205. this->registerChildProcessor(std::move(normalFP));
  206. }
  207. LightingFP(const LightingFP& that)
  208. : INHERITED(kLightingFP_ClassID, kPreservesOpaqueInput_OptimizationFlag)
  209. , fDirectionalLights(that.fDirectionalLights)
  210. , fAmbientColor(that.fAmbientColor) {
  211. this->registerChildProcessor(that.childProcessor(0).clone());
  212. }
  213. GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return new GLSLLightingFP; }
  214. bool onIsEqual(const GrFragmentProcessor& proc) const override {
  215. const LightingFP& lightingFP = proc.cast<LightingFP>();
  216. return fDirectionalLights == lightingFP.fDirectionalLights &&
  217. fAmbientColor == lightingFP.fAmbientColor;
  218. }
  219. SkTArray<SkLights::Light> fDirectionalLights;
  220. SkColor3f fAmbientColor;
  221. typedef GrFragmentProcessor INHERITED;
  222. };
  223. ////////////////////////////////////////////////////////////////////////////
  224. std::unique_ptr<GrFragmentProcessor> SkLightingShaderImpl::asFragmentProcessor(const GrFPArgs& args) const {
  225. std::unique_ptr<GrFragmentProcessor> normalFP(fNormalSource->asFragmentProcessor(args));
  226. if (!normalFP) {
  227. return nullptr;
  228. }
  229. if (fDiffuseShader) {
  230. std::unique_ptr<GrFragmentProcessor> fpPipeline[] = {
  231. as_SB(fDiffuseShader)->asFragmentProcessor(args),
  232. LightingFP::Make(std::move(normalFP), fLights)
  233. };
  234. if (!fpPipeline[0] || !fpPipeline[1]) {
  235. return nullptr;
  236. }
  237. std::unique_ptr<GrFragmentProcessor> innerLightFP = GrFragmentProcessor::RunInSeries(fpPipeline, 2);
  238. // FP is wrapped because paint's alpha needs to be applied to output
  239. return GrFragmentProcessor::MulChildByInputAlpha(std::move(innerLightFP));
  240. } else {
  241. // FP is wrapped because paint comes in unpremul'd to fragment shader, but LightingFP
  242. // expects premul'd color.
  243. return GrFragmentProcessor::PremulInput(LightingFP::Make(std::move(normalFP), fLights));
  244. }
  245. }
  246. #endif
  247. ////////////////////////////////////////////////////////////////////////////
  248. bool SkLightingShaderImpl::isOpaque() const {
  249. return (fDiffuseShader ? fDiffuseShader->isOpaque() : false);
  250. }
  251. SkLightingShaderImpl::LightingShaderContext::LightingShaderContext(
  252. const SkLightingShaderImpl& shader, const ContextRec& rec,
  253. SkShaderBase::Context* diffuseContext, SkNormalSource::Provider* normalProvider,
  254. void* heapAllocated)
  255. : INHERITED(shader, rec)
  256. , fDiffuseContext(diffuseContext)
  257. , fNormalProvider(normalProvider) {
  258. bool isOpaque = shader.isOpaque();
  259. // update fFlags
  260. uint32_t flags = 0;
  261. if (isOpaque && (255 == this->getPaintAlpha())) {
  262. flags |= kOpaqueAlpha_Flag;
  263. }
  264. fPaintColor = rec.fPaint->getColor();
  265. fFlags = flags;
  266. }
  267. static inline SkPMColor convert(SkColor3f color, U8CPU a) {
  268. if (color.fX <= 0.0f) {
  269. color.fX = 0.0f;
  270. } else if (color.fX >= 255.0f) {
  271. color.fX = 255.0f;
  272. }
  273. if (color.fY <= 0.0f) {
  274. color.fY = 0.0f;
  275. } else if (color.fY >= 255.0f) {
  276. color.fY = 255.0f;
  277. }
  278. if (color.fZ <= 0.0f) {
  279. color.fZ = 0.0f;
  280. } else if (color.fZ >= 255.0f) {
  281. color.fZ = 255.0f;
  282. }
  283. return SkPreMultiplyARGB(a, (int) color.fX, (int) color.fY, (int) color.fZ);
  284. }
  285. // larger is better (fewer times we have to loop), but we shouldn't
  286. // take up too much stack-space (each one here costs 16 bytes)
  287. #define BUFFER_MAX 16
  288. void SkLightingShaderImpl::LightingShaderContext::shadeSpan(int x, int y,
  289. SkPMColor result[], int count) {
  290. const SkLightingShaderImpl& lightShader = static_cast<const SkLightingShaderImpl&>(fShader);
  291. SkPMColor diffuse[BUFFER_MAX];
  292. SkPoint3 normals[BUFFER_MAX];
  293. SkColor diffColor = fPaintColor;
  294. do {
  295. int n = SkTMin(count, BUFFER_MAX);
  296. fNormalProvider->fillScanLine(x, y, normals, n);
  297. if (fDiffuseContext) {
  298. fDiffuseContext->shadeSpan(x, y, diffuse, n);
  299. }
  300. for (int i = 0; i < n; ++i) {
  301. if (fDiffuseContext) {
  302. diffColor = SkUnPreMultiply::PMColorToColor(diffuse[i]);
  303. }
  304. SkColor3f accum = SkColor3f::Make(0.0f, 0.0f, 0.0f);
  305. // Adding ambient light
  306. accum.fX += lightShader.fLights->ambientLightColor().fX * SkColorGetR(diffColor);
  307. accum.fY += lightShader.fLights->ambientLightColor().fY * SkColorGetG(diffColor);
  308. accum.fZ += lightShader.fLights->ambientLightColor().fZ * SkColorGetB(diffColor);
  309. // This is all done in linear unpremul color space (each component 0..255.0f though)
  310. for (int l = 0; l < lightShader.fLights->numLights(); ++l) {
  311. const SkLights::Light& light = lightShader.fLights->light(l);
  312. SkScalar illuminanceScalingFactor = 1.0f;
  313. if (SkLights::Light::kDirectional_LightType == light.type()) {
  314. illuminanceScalingFactor = normals[i].dot(light.dir());
  315. if (illuminanceScalingFactor < 0.0f) {
  316. illuminanceScalingFactor = 0.0f;
  317. }
  318. }
  319. accum.fX += light.color().fX * SkColorGetR(diffColor) * illuminanceScalingFactor;
  320. accum.fY += light.color().fY * SkColorGetG(diffColor) * illuminanceScalingFactor;
  321. accum.fZ += light.color().fZ * SkColorGetB(diffColor) * illuminanceScalingFactor;
  322. }
  323. // convert() premultiplies the accumulate color with alpha
  324. result[i] = convert(accum, SkColorGetA(diffColor));
  325. }
  326. result += n;
  327. x += n;
  328. count -= n;
  329. } while (count > 0);
  330. }
  331. ////////////////////////////////////////////////////////////////////////////
  332. sk_sp<SkFlattenable> SkLightingShaderImpl::CreateProc(SkReadBuffer& buf) {
  333. // Discarding SkShader flattenable params
  334. bool hasLocalMatrix = buf.readBool();
  335. if (hasLocalMatrix) {
  336. return nullptr;
  337. }
  338. sk_sp<SkLights> lights = SkLights::MakeFromBuffer(buf);
  339. sk_sp<SkNormalSource> normalSource(buf.readFlattenable<SkNormalSource>());
  340. bool hasDiffuse = buf.readBool();
  341. sk_sp<SkShader> diffuseShader = nullptr;
  342. if (hasDiffuse) {
  343. diffuseShader = buf.readFlattenable<SkShaderBase>();
  344. }
  345. return sk_make_sp<SkLightingShaderImpl>(std::move(diffuseShader), std::move(normalSource),
  346. std::move(lights));
  347. }
  348. void SkLightingShaderImpl::flatten(SkWriteBuffer& buf) const {
  349. this->INHERITED::flatten(buf);
  350. fLights->flatten(buf);
  351. buf.writeFlattenable(fNormalSource.get());
  352. buf.writeBool(static_cast<bool>(fDiffuseShader));
  353. if (fDiffuseShader) {
  354. buf.writeFlattenable(fDiffuseShader.get());
  355. }
  356. }
  357. #ifdef SK_ENABLE_LEGACY_SHADERCONTEXT
  358. SkShaderBase::Context* SkLightingShaderImpl::onMakeContext(
  359. const ContextRec& rec, SkArenaAlloc* alloc) const
  360. {
  361. SkShaderBase::Context *diffuseContext = nullptr;
  362. if (fDiffuseShader) {
  363. diffuseContext = as_SB(fDiffuseShader)->makeContext(rec, alloc);
  364. if (!diffuseContext) {
  365. return nullptr;
  366. }
  367. }
  368. SkNormalSource::Provider* normalProvider = fNormalSource->asProvider(rec, alloc);
  369. if (!normalProvider) {
  370. return nullptr;
  371. }
  372. // The diffuse shader can inspect the rec and make its decision about rec's colorspace.
  373. // What about the lighting shader? Is lighting sensitive to the rec's (device) colorspace?
  374. return alloc->make<LightingShaderContext>(*this, rec, diffuseContext, normalProvider, nullptr);
  375. }
  376. #endif
  377. ///////////////////////////////////////////////////////////////////////////////
  378. sk_sp<SkShader> SkLightingShader::Make(sk_sp<SkShader> diffuseShader,
  379. sk_sp<SkNormalSource> normalSource,
  380. sk_sp<SkLights> lights) {
  381. SkASSERT(lights);
  382. if (!normalSource) {
  383. normalSource = SkNormalSource::MakeFlat();
  384. }
  385. return sk_make_sp<SkLightingShaderImpl>(std::move(diffuseShader), std::move(normalSource),
  386. std::move(lights));
  387. }
  388. ///////////////////////////////////////////////////////////////////////////////
  389. void SkLightingShader::RegisterFlattenables() { SK_REGISTER_FLATTENABLE(SkLightingShaderImpl); }