babylon.imageProcessingConfiguration.ts 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535
  1. module BABYLON {
  2. /**
  3. * Interface to follow in your material defines to integrate easily the
  4. * Image proccessing functions.
  5. */
  6. export interface IImageProcessingConfigurationDefines {
  7. IMAGEPROCESSING: boolean;
  8. VIGNETTE: boolean;
  9. VIGNETTEBLENDMODEMULTIPLY: boolean;
  10. VIGNETTEBLENDMODEOPAQUE: boolean;
  11. TONEMAPPING: boolean;
  12. CONTRAST: boolean;
  13. EXPOSURE: boolean;
  14. COLORCURVES: boolean;
  15. COLORGRADING: boolean;
  16. COLORGRADING3D: boolean;
  17. SAMPLER3DGREENDEPTH: boolean;
  18. SAMPLER3DBGRMAP: boolean;
  19. IMAGEPROCESSINGPOSTPROCESS: boolean;
  20. /**
  21. * If the grain should be performed in the image processing shader.
  22. */
  23. GRAIN: boolean;
  24. }
  25. /**
  26. * This groups together the common properties used for image processing either in direct forward pass
  27. * or through post processing effect depending on the use of the image processing pipeline in your scene
  28. * or not.
  29. */
  30. export class ImageProcessingConfiguration {
  31. /**
  32. * Color curves setup used in the effect if colorCurvesEnabled is set to true
  33. */
  34. @serializeAsColorCurves()
  35. public colorCurves: Nullable<ColorCurves> = new ColorCurves();
  36. @serialize()
  37. private _colorCurvesEnabled = false;
  38. /**
  39. * Gets wether the color curves effect is enabled.
  40. */
  41. public get colorCurvesEnabled(): boolean {
  42. return this._colorCurvesEnabled;
  43. }
  44. /**
  45. * Sets wether the color curves effect is enabled.
  46. */
  47. public set colorCurvesEnabled(value: boolean) {
  48. if (this._colorCurvesEnabled === value) {
  49. return;
  50. }
  51. this._colorCurvesEnabled = value;
  52. this._updateParameters();
  53. }
  54. /**
  55. * Color grading LUT texture used in the effect if colorGradingEnabled is set to true
  56. */
  57. @serializeAsTexture()
  58. public colorGradingTexture: Nullable<BaseTexture>;
  59. @serialize()
  60. private _colorGradingEnabled = false;
  61. /**
  62. * Gets wether the color grading effect is enabled.
  63. */
  64. public get colorGradingEnabled(): boolean {
  65. return this._colorGradingEnabled;
  66. }
  67. /**
  68. * Sets wether the color grading effect is enabled.
  69. */
  70. public set colorGradingEnabled(value: boolean) {
  71. if (this._colorGradingEnabled === value) {
  72. return;
  73. }
  74. this._colorGradingEnabled = value;
  75. this._updateParameters();
  76. }
  77. @serialize()
  78. private _colorGradingWithGreenDepth = true;
  79. /**
  80. * Gets wether the color grading effect is using a green depth for the 3d Texture.
  81. */
  82. public get colorGradingWithGreenDepth(): boolean {
  83. return this._colorGradingWithGreenDepth;
  84. }
  85. /**
  86. * Sets wether the color grading effect is using a green depth for the 3d Texture.
  87. */
  88. public set colorGradingWithGreenDepth(value: boolean) {
  89. if (this._colorGradingWithGreenDepth === value) {
  90. return;
  91. }
  92. this._colorGradingWithGreenDepth = value;
  93. this._updateParameters();
  94. }
  95. @serialize()
  96. private _colorGradingBGR = true;
  97. /**
  98. * Gets wether the color grading texture contains BGR values.
  99. */
  100. public get colorGradingBGR(): boolean {
  101. return this._colorGradingBGR;
  102. }
  103. /**
  104. * Sets wether the color grading texture contains BGR values.
  105. */
  106. public set colorGradingBGR(value: boolean) {
  107. if (this._colorGradingBGR === value) {
  108. return;
  109. }
  110. this._colorGradingBGR = value;
  111. this._updateParameters();
  112. }
  113. @serialize()
  114. public _exposure = 1.0;
  115. /**
  116. * Gets the Exposure used in the effect.
  117. */
  118. public get exposure(): number {
  119. return this._exposure;
  120. }
  121. /**
  122. * Sets the Exposure used in the effect.
  123. */
  124. public set exposure(value: number) {
  125. if (this._exposure === value) {
  126. return;
  127. }
  128. this._exposure = value;
  129. this._updateParameters();
  130. }
  131. @serialize()
  132. private _toneMappingEnabled = false;
  133. /**
  134. * Gets wether the tone mapping effect is enabled.
  135. */
  136. public get toneMappingEnabled(): boolean {
  137. return this._toneMappingEnabled;
  138. }
  139. /**
  140. * Sets wether the tone mapping effect is enabled.
  141. */
  142. public set toneMappingEnabled(value: boolean) {
  143. if (this._toneMappingEnabled === value) {
  144. return;
  145. }
  146. this._toneMappingEnabled = value;
  147. this._updateParameters();
  148. }
  149. @serialize()
  150. protected _contrast = 1.0;
  151. /**
  152. * Gets the contrast used in the effect.
  153. */
  154. public get contrast(): number {
  155. return this._contrast;
  156. }
  157. /**
  158. * Sets the contrast used in the effect.
  159. */
  160. public set contrast(value: number) {
  161. if (this._contrast === value) {
  162. return;
  163. }
  164. this._contrast = value;
  165. this._updateParameters();
  166. }
  167. /**
  168. * Vignette stretch size.
  169. */
  170. @serialize()
  171. public vignetteStretch = 0;
  172. /**
  173. * Vignette centre X Offset.
  174. */
  175. @serialize()
  176. public vignetteCentreX = 0;
  177. /**
  178. * Vignette centre Y Offset.
  179. */
  180. @serialize()
  181. public vignetteCentreY = 0;
  182. /**
  183. * Vignette weight or intensity of the vignette effect.
  184. */
  185. @serialize()
  186. public vignetteWeight = 1.5;
  187. /**
  188. * Color of the vignette applied on the screen through the chosen blend mode (vignetteBlendMode)
  189. * if vignetteEnabled is set to true.
  190. */
  191. @serializeAsColor4()
  192. public vignetteColor: Color4 = new Color4(0, 0, 0, 0);
  193. /**
  194. * Camera field of view used by the Vignette effect.
  195. */
  196. @serialize()
  197. public vignetteCameraFov = 0.5;
  198. @serialize()
  199. private _grainVarianceAmount = 0;
  200. /**
  201. * Amount of grain to be applied by the grain effect.
  202. */
  203. public get grainVarianceAmount(): number {
  204. return this._grainVarianceAmount;
  205. }
  206. public set grainVarianceAmount(value: number) {
  207. if (this._grainVarianceAmount === value) {
  208. return;
  209. }
  210. this._grainVarianceAmount = value;
  211. this._updateParameters();
  212. }
  213. @serialize()
  214. private _grainAnimated = false;
  215. /**
  216. * If the grain effect should be animated.
  217. */
  218. public get grainAnimated(): boolean {
  219. return this._grainAnimated;
  220. }
  221. public set grainAnimated(value: boolean) {
  222. if (this._grainAnimated === value) {
  223. return;
  224. }
  225. this._grainAnimated = value;
  226. this._updateParameters();
  227. }
  228. @serialize()
  229. private _vignetteBlendMode = ImageProcessingConfiguration.VIGNETTEMODE_MULTIPLY;
  230. /**
  231. * Gets the vignette blend mode allowing different kind of effect.
  232. */
  233. public get vignetteBlendMode(): number {
  234. return this._vignetteBlendMode;
  235. }
  236. /**
  237. * Sets the vignette blend mode allowing different kind of effect.
  238. */
  239. public set vignetteBlendMode(value: number) {
  240. if (this._vignetteBlendMode === value) {
  241. return;
  242. }
  243. this._vignetteBlendMode = value;
  244. this._updateParameters();
  245. }
  246. @serialize()
  247. private _vignetteEnabled = false;
  248. /**
  249. * Gets wether the vignette effect is enabled.
  250. */
  251. public get vignetteEnabled(): boolean {
  252. return this._vignetteEnabled;
  253. }
  254. /**
  255. * Sets wether the vignette effect is enabled.
  256. */
  257. public set vignetteEnabled(value: boolean) {
  258. if (this._vignetteEnabled === value) {
  259. return;
  260. }
  261. this._vignetteEnabled = value;
  262. this._updateParameters();
  263. }
  264. @serialize()
  265. private _applyByPostProcess = false;
  266. /**
  267. * Gets wether the image processing is applied through a post process or not.
  268. */
  269. public get applyByPostProcess(): boolean {
  270. return this._applyByPostProcess;
  271. }
  272. /**
  273. * Sets wether the image processing is applied through a post process or not.
  274. */
  275. public set applyByPostProcess(value: boolean) {
  276. if (this._applyByPostProcess === value) {
  277. return;
  278. }
  279. this._applyByPostProcess = value;
  280. this._updateParameters();
  281. }
  282. @serialize()
  283. private _isEnabled = true;
  284. /**
  285. * Gets wether the image processing is enabled or not.
  286. */
  287. public get isEnabled(): boolean {
  288. return this._isEnabled;
  289. }
  290. /**
  291. * Sets wether the image processing is enabled or not.
  292. */
  293. public set isEnabled(value: boolean) {
  294. if (this._isEnabled === value) {
  295. return;
  296. }
  297. this._isEnabled = value;
  298. this._updateParameters();
  299. }
  300. /**
  301. * An event triggered when the configuration changes and requires Shader to Update some parameters.
  302. * @type {BABYLON.Observable}
  303. */
  304. public onUpdateParameters = new Observable<ImageProcessingConfiguration>();
  305. /**
  306. * Method called each time the image processing information changes requires to recompile the effect.
  307. */
  308. protected _updateParameters(): void {
  309. this.onUpdateParameters.notifyObservers(this);
  310. }
  311. public getClassName(): string {
  312. return "ImageProcessingConfiguration";
  313. }
  314. /**
  315. * Prepare the list of uniforms associated with the Image Processing effects.
  316. * @param uniformsList The list of uniforms used in the effect
  317. * @param defines the list of defines currently in use
  318. */
  319. public static PrepareUniforms(uniforms: string[], defines: IImageProcessingConfigurationDefines): void {
  320. if (defines.EXPOSURE) {
  321. uniforms.push("exposureLinear");
  322. }
  323. if (defines.CONTRAST) {
  324. uniforms.push("contrast");
  325. }
  326. if (defines.COLORGRADING) {
  327. uniforms.push("colorTransformSettings");
  328. }
  329. if (defines.VIGNETTE) {
  330. uniforms.push("vInverseScreenSize");
  331. uniforms.push("vignetteSettings1");
  332. uniforms.push("vignetteSettings2");
  333. }
  334. if (defines.COLORCURVES) {
  335. ColorCurves.PrepareUniforms(uniforms);
  336. }
  337. if (defines.GRAIN){
  338. uniforms.push("grainVarianceAmount");
  339. uniforms.push("grainAnimatedSeed");
  340. }
  341. }
  342. /**
  343. * Prepare the list of samplers associated with the Image Processing effects.
  344. * @param uniformsList The list of uniforms used in the effect
  345. * @param defines the list of defines currently in use
  346. */
  347. public static PrepareSamplers(samplersList: string[], defines: IImageProcessingConfigurationDefines): void {
  348. if (defines.COLORGRADING) {
  349. samplersList.push("txColorTransform");
  350. }
  351. }
  352. /**
  353. * Prepare the list of defines associated to the shader.
  354. * @param defines the list of defines to complete
  355. */
  356. public prepareDefines(defines: IImageProcessingConfigurationDefines, forPostProcess: boolean = false): void {
  357. if (forPostProcess !== this.applyByPostProcess || !this._isEnabled) {
  358. defines.VIGNETTE = false;
  359. defines.TONEMAPPING = false;
  360. defines.CONTRAST = false;
  361. defines.EXPOSURE = false;
  362. defines.COLORCURVES = false;
  363. defines.COLORGRADING = false;
  364. defines.COLORGRADING3D = false;
  365. defines.IMAGEPROCESSING = false;
  366. defines.IMAGEPROCESSINGPOSTPROCESS = this.applyByPostProcess && this._isEnabled;
  367. return;
  368. }
  369. defines.VIGNETTE = this.vignetteEnabled;
  370. defines.VIGNETTEBLENDMODEMULTIPLY = (this.vignetteBlendMode === ImageProcessingConfiguration._VIGNETTEMODE_MULTIPLY);
  371. defines.VIGNETTEBLENDMODEOPAQUE = !defines.VIGNETTEBLENDMODEMULTIPLY;
  372. defines.TONEMAPPING = this.toneMappingEnabled;
  373. defines.CONTRAST = (this.contrast !== 1.0);
  374. defines.EXPOSURE = (this.exposure !== 1.0);
  375. defines.COLORCURVES = (this.colorCurvesEnabled && !!this.colorCurves);
  376. defines.COLORGRADING = (this.colorGradingEnabled && !!this.colorGradingTexture);
  377. if (defines.COLORGRADING) {
  378. defines.COLORGRADING3D = this.colorGradingTexture!.is3D;
  379. } else {
  380. defines.COLORGRADING3D = false;
  381. }
  382. defines.SAMPLER3DGREENDEPTH = this.colorGradingWithGreenDepth;
  383. defines.SAMPLER3DBGRMAP = this.colorGradingBGR;
  384. defines.IMAGEPROCESSINGPOSTPROCESS = this.applyByPostProcess;
  385. defines.IMAGEPROCESSING = defines.VIGNETTE || defines.TONEMAPPING || defines.CONTRAST || defines.EXPOSURE || defines.COLORCURVES || defines.COLORGRADING;
  386. defines.GRAIN = (this.grainVarianceAmount != 0.0);
  387. }
  388. /**
  389. * Returns true if all the image processing information are ready.
  390. */
  391. public isReady() {
  392. // Color Grading texure can not be none blocking.
  393. return !this.colorGradingEnabled || !this.colorGradingTexture || this.colorGradingTexture.isReady();
  394. }
  395. /**
  396. * Binds the image processing to the shader.
  397. * @param effect The effect to bind to
  398. */
  399. public bind(effect: Effect, aspectRatio = 1): void {
  400. // Color Curves
  401. if (this._colorCurvesEnabled && this.colorCurves) {
  402. ColorCurves.Bind(this.colorCurves, effect);
  403. }
  404. // Vignette
  405. if (this._vignetteEnabled) {
  406. var inverseWidth = 1 / effect.getEngine().getRenderWidth();
  407. var inverseHeight = 1 / effect.getEngine().getRenderHeight();
  408. effect.setFloat2("vInverseScreenSize", inverseWidth, inverseHeight);
  409. let vignetteScaleY = Math.tan(this.vignetteCameraFov * 0.5);
  410. let vignetteScaleX = vignetteScaleY * aspectRatio;
  411. let vignetteScaleGeometricMean = Math.sqrt(vignetteScaleX * vignetteScaleY);
  412. vignetteScaleX = Tools.Mix(vignetteScaleX, vignetteScaleGeometricMean, this.vignetteStretch);
  413. vignetteScaleY = Tools.Mix(vignetteScaleY, vignetteScaleGeometricMean, this.vignetteStretch);
  414. effect.setFloat4("vignetteSettings1", vignetteScaleX, vignetteScaleY, -vignetteScaleX * this.vignetteCentreX, -vignetteScaleY * this.vignetteCentreY);
  415. let vignettePower = -2.0 * this.vignetteWeight;
  416. effect.setFloat4("vignetteSettings2", this.vignetteColor.r, this.vignetteColor.g, this.vignetteColor.b, vignettePower);
  417. }
  418. // Exposure
  419. effect.setFloat("exposureLinear", this.exposure);
  420. // Contrast
  421. effect.setFloat("contrast", this.contrast);
  422. // Color transform settings
  423. if (this.colorGradingTexture) {
  424. effect.setTexture("txColorTransform", this.colorGradingTexture);
  425. let textureSize = this.colorGradingTexture.getSize().height;
  426. effect.setFloat4("colorTransformSettings",
  427. (textureSize - 1) / textureSize, // textureScale
  428. 0.5 / textureSize, // textureOffset
  429. textureSize, // textureSize
  430. this.colorGradingTexture.level // weight
  431. );
  432. }
  433. effect.setFloat("grainVarianceAmount", this.grainVarianceAmount);
  434. effect.setFloat("grainAnimatedSeed", this.grainAnimated ? Math.random() : 1);
  435. }
  436. /**
  437. * Clones the current image processing instance.
  438. * @return The cloned image processing
  439. */
  440. public clone(): ImageProcessingConfiguration {
  441. return SerializationHelper.Clone(() => new ImageProcessingConfiguration(), this);
  442. }
  443. /**
  444. * Serializes the current image processing instance to a json representation.
  445. * @return a JSON representation
  446. */
  447. public serialize(): any {
  448. return SerializationHelper.Serialize(this);
  449. }
  450. /**
  451. * Parses the image processing from a json representation.
  452. * @param source the JSON source to parse
  453. * @return The parsed image processing
  454. */
  455. public static Parse(source: any): ImageProcessingConfiguration {
  456. return SerializationHelper.Parse(() => new ImageProcessingConfiguration(), source, null, null);
  457. }
  458. // Static constants associated to the image processing.
  459. private static _VIGNETTEMODE_MULTIPLY = 0;
  460. private static _VIGNETTEMODE_OPAQUE = 1;
  461. /**
  462. * Used to apply the vignette as a mix with the pixel color.
  463. */
  464. public static get VIGNETTEMODE_MULTIPLY(): number {
  465. return this._VIGNETTEMODE_MULTIPLY;
  466. }
  467. /**
  468. * Used to apply the vignette as a replacement of the pixel color.
  469. */
  470. public static get VIGNETTEMODE_OPAQUE(): number {
  471. return this._VIGNETTEMODE_OPAQUE;
  472. }
  473. }
  474. }