babylon.backgroundMaterial.ts 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142
  1. module BABYLON {
  2. /**
  3. * Background material defines definition.
  4. * @hidden Mainly internal Use
  5. */
  6. class BackgroundMaterialDefines extends MaterialDefines implements IImageProcessingConfigurationDefines {
  7. /**
  8. * True if the diffuse texture is in use.
  9. */
  10. public DIFFUSE = false;
  11. /**
  12. * The direct UV channel to use.
  13. */
  14. public DIFFUSEDIRECTUV = 0;
  15. /**
  16. * True if the diffuse texture is in gamma space.
  17. */
  18. public GAMMADIFFUSE = false;
  19. /**
  20. * True if the diffuse texture has opacity in the alpha channel.
  21. */
  22. public DIFFUSEHASALPHA = false;
  23. /**
  24. * True if you want the material to fade to transparent at grazing angle.
  25. */
  26. public OPACITYFRESNEL = false;
  27. /**
  28. * True if an extra blur needs to be added in the reflection.
  29. */
  30. public REFLECTIONBLUR = false;
  31. /**
  32. * True if you want the material to fade to reflection at grazing angle.
  33. */
  34. public REFLECTIONFRESNEL = false;
  35. /**
  36. * True if you want the material to falloff as far as you move away from the scene center.
  37. */
  38. public REFLECTIONFALLOFF = false;
  39. /**
  40. * False if the current Webgl implementation does not support the texture lod extension.
  41. */
  42. public TEXTURELODSUPPORT = false;
  43. /**
  44. * True to ensure the data are premultiplied.
  45. */
  46. public PREMULTIPLYALPHA = false;
  47. /**
  48. * True if the texture contains cooked RGB values and not gray scaled multipliers.
  49. */
  50. public USERGBCOLOR = false;
  51. /**
  52. * True if highlight and shadow levels have been specified. It can help ensuring the main perceived color
  53. * stays aligned with the desired configuration.
  54. */
  55. public USEHIGHLIGHTANDSHADOWCOLORS = false;
  56. /**
  57. * True to add noise in order to reduce the banding effect.
  58. */
  59. public NOISE = false;
  60. /**
  61. * is the reflection texture in BGR color scheme?
  62. * Mainly used to solve a bug in ios10 video tag
  63. */
  64. public REFLECTIONBGR = false;
  65. public IMAGEPROCESSING = false;
  66. public VIGNETTE = false;
  67. public VIGNETTEBLENDMODEMULTIPLY = false;
  68. public VIGNETTEBLENDMODEOPAQUE = false;
  69. public TONEMAPPING = false;
  70. public CONTRAST = false;
  71. public COLORCURVES = false;
  72. public COLORGRADING = false;
  73. public COLORGRADING3D = false;
  74. public SAMPLER3DGREENDEPTH = false;
  75. public SAMPLER3DBGRMAP = false;
  76. public IMAGEPROCESSINGPOSTPROCESS = false;
  77. public EXPOSURE = false;
  78. // Reflection.
  79. public REFLECTION = false;
  80. public REFLECTIONMAP_3D = false;
  81. public REFLECTIONMAP_SPHERICAL = false;
  82. public REFLECTIONMAP_PLANAR = false;
  83. public REFLECTIONMAP_CUBIC = false;
  84. public REFLECTIONMAP_PROJECTION = false;
  85. public REFLECTIONMAP_SKYBOX = false;
  86. public REFLECTIONMAP_EXPLICIT = false;
  87. public REFLECTIONMAP_EQUIRECTANGULAR = false;
  88. public REFLECTIONMAP_EQUIRECTANGULAR_FIXED = false;
  89. public REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED = false;
  90. public INVERTCUBICMAP = false;
  91. public REFLECTIONMAP_OPPOSITEZ = false;
  92. public LODINREFLECTIONALPHA = false;
  93. public GAMMAREFLECTION = false;
  94. public EQUIRECTANGULAR_RELFECTION_FOV = false;
  95. // Default BJS.
  96. public MAINUV1 = false;
  97. public MAINUV2 = false;
  98. public UV1 = false;
  99. public UV2 = false;
  100. public CLIPPLANE = false;
  101. public POINTSIZE = false;
  102. public FOG = false;
  103. public NORMAL = false;
  104. public NUM_BONE_INFLUENCERS = 0;
  105. public BonesPerMesh = 0;
  106. public INSTANCES = false;
  107. public SHADOWFLOAT = false;
  108. /**
  109. * Constructor of the defines.
  110. */
  111. constructor() {
  112. super();
  113. this.rebuild();
  114. }
  115. }
  116. /**
  117. * Background material used to create an efficient environement around your scene.
  118. */
  119. export class BackgroundMaterial extends PushMaterial {
  120. /**
  121. * Standard reflectance value at parallel view angle.
  122. */
  123. public static StandardReflectance0 = 0.05;
  124. /**
  125. * Standard reflectance value at grazing angle.
  126. */
  127. public static StandardReflectance90 = 0.5;
  128. @serializeAsColor3()
  129. protected _primaryColor: Color3;
  130. /**
  131. * Key light Color (multiply against the environement texture)
  132. */
  133. @expandToProperty("_markAllSubMeshesAsLightsDirty")
  134. public primaryColor = Color3.White();
  135. @serializeAsColor3()
  136. protected __perceptualColor: Nullable<Color3>;
  137. /**
  138. * Experimental Internal Use Only.
  139. *
  140. * Key light Color in "perceptual value" meaning the color you would like to see on screen.
  141. * This acts as a helper to set the primary color to a more "human friendly" value.
  142. * Conversion to linear space as well as exposure and tone mapping correction will be applied to keep the
  143. * output color as close as possible from the chosen value.
  144. * (This does not account for contrast color grading and color curves as they are considered post effect and not directly
  145. * part of lighting setup.)
  146. */
  147. public get _perceptualColor(): Nullable<Color3> {
  148. return this.__perceptualColor;
  149. }
  150. public set _perceptualColor(value: Nullable<Color3>) {
  151. this.__perceptualColor = value;
  152. this._computePrimaryColorFromPerceptualColor();
  153. this._markAllSubMeshesAsLightsDirty();
  154. }
  155. @serialize()
  156. protected _primaryColorShadowLevel: float = 0;
  157. /**
  158. * Defines the level of the shadows (dark area of the reflection map) in order to help scaling the colors.
  159. * The color opposite to the primary color is used at the level chosen to define what the black area would look.
  160. */
  161. public get primaryColorShadowLevel(): float {
  162. return this._primaryColorShadowLevel;
  163. }
  164. public set primaryColorShadowLevel(value: float) {
  165. this._primaryColorShadowLevel = value;
  166. this._computePrimaryColors();
  167. this._markAllSubMeshesAsLightsDirty();
  168. }
  169. @serialize()
  170. protected _primaryColorHighlightLevel: float = 0;
  171. /**
  172. * Defines the level of the highliights (highlight area of the reflection map) in order to help scaling the colors.
  173. * The primary color is used at the level chosen to define what the white area would look.
  174. */
  175. @expandToProperty("_markAllSubMeshesAsLightsDirty")
  176. public get primaryColorHighlightLevel(): float {
  177. return this._primaryColorHighlightLevel;
  178. }
  179. public set primaryColorHighlightLevel(value: float) {
  180. this._primaryColorHighlightLevel = value;
  181. this._computePrimaryColors();
  182. this._markAllSubMeshesAsLightsDirty();
  183. }
  184. @serializeAsTexture()
  185. protected _reflectionTexture: Nullable<BaseTexture>;
  186. /**
  187. * Reflection Texture used in the material.
  188. * Should be author in a specific way for the best result (refer to the documentation).
  189. */
  190. @expandToProperty("_markAllSubMeshesAsTexturesDirty")
  191. public reflectionTexture: Nullable<BaseTexture> = null;
  192. @serialize()
  193. protected _reflectionBlur: float;
  194. /**
  195. * Reflection Texture level of blur.
  196. *
  197. * Can be use to reuse an existing HDR Texture and target a specific LOD to prevent authoring the
  198. * texture twice.
  199. */
  200. @expandToProperty("_markAllSubMeshesAsTexturesDirty")
  201. public reflectionBlur: float = 0;
  202. @serializeAsTexture()
  203. protected _diffuseTexture: Nullable<BaseTexture>;
  204. /**
  205. * Diffuse Texture used in the material.
  206. * Should be author in a specific way for the best result (refer to the documentation).
  207. */
  208. @expandToProperty("_markAllSubMeshesAsTexturesDirty")
  209. public diffuseTexture: Nullable<BaseTexture> = null;
  210. protected _shadowLights: Nullable<IShadowLight[]> = null;
  211. /**
  212. * Specify the list of lights casting shadow on the material.
  213. * All scene shadow lights will be included if null.
  214. */
  215. @expandToProperty("_markAllSubMeshesAsTexturesDirty")
  216. public shadowLights: Nullable<IShadowLight[]> = null;
  217. @serialize()
  218. protected _shadowLevel: float;
  219. /**
  220. * Helps adjusting the shadow to a softer level if required.
  221. * 0 means black shadows and 1 means no shadows.
  222. */
  223. @expandToProperty("_markAllSubMeshesAsTexturesDirty")
  224. public shadowLevel: float = 0;
  225. @serializeAsVector3()
  226. protected _sceneCenter: Vector3;
  227. /**
  228. * In case of opacity Fresnel or reflection falloff, this is use as a scene center.
  229. * It is usually zero but might be interesting to modify according to your setup.
  230. */
  231. @expandToProperty("_markAllSubMeshesAsTexturesDirty")
  232. public sceneCenter: Vector3 = Vector3.Zero();
  233. @serialize()
  234. protected _opacityFresnel: boolean;
  235. /**
  236. * This helps specifying that the material is falling off to the sky box at grazing angle.
  237. * This helps ensuring a nice transition when the camera goes under the ground.
  238. */
  239. @expandToProperty("_markAllSubMeshesAsTexturesDirty")
  240. public opacityFresnel: boolean = true;
  241. @serialize()
  242. protected _reflectionFresnel: boolean;
  243. /**
  244. * This helps specifying that the material is falling off from diffuse to the reflection texture at grazing angle.
  245. * This helps adding a mirror texture on the ground.
  246. */
  247. @expandToProperty("_markAllSubMeshesAsTexturesDirty")
  248. public reflectionFresnel: boolean = false;
  249. @serialize()
  250. protected _reflectionFalloffDistance: number;
  251. /**
  252. * This helps specifying the falloff radius off the reflection texture from the sceneCenter.
  253. * This helps adding a nice falloff effect to the reflection if used as a mirror for instance.
  254. */
  255. @expandToProperty("_markAllSubMeshesAsTexturesDirty")
  256. public reflectionFalloffDistance: number = 0.0;
  257. @serialize()
  258. protected _reflectionAmount: number;
  259. /**
  260. * This specifies the weight of the reflection against the background in case of reflection Fresnel.
  261. */
  262. @expandToProperty("_markAllSubMeshesAsTexturesDirty")
  263. public reflectionAmount: number = 1.0;
  264. @serialize()
  265. protected _reflectionReflectance0: number;
  266. /**
  267. * This specifies the weight of the reflection at grazing angle.
  268. */
  269. @expandToProperty("_markAllSubMeshesAsTexturesDirty")
  270. public reflectionReflectance0: number = 0.05;
  271. @serialize()
  272. protected _reflectionReflectance90: number;
  273. /**
  274. * This specifies the weight of the reflection at a perpendicular point of view.
  275. */
  276. @expandToProperty("_markAllSubMeshesAsTexturesDirty")
  277. public reflectionReflectance90: number = 0.5;
  278. /**
  279. * Sets the reflection reflectance fresnel values according to the default standard
  280. * empirically know to work well :-)
  281. */
  282. public set reflectionStandardFresnelWeight(value: number) {
  283. let reflectionWeight = value;
  284. if (reflectionWeight < 0.5) {
  285. reflectionWeight = reflectionWeight * 2.0;
  286. this.reflectionReflectance0 = BackgroundMaterial.StandardReflectance0 * reflectionWeight;
  287. this.reflectionReflectance90 = BackgroundMaterial.StandardReflectance90 * reflectionWeight;
  288. } else {
  289. reflectionWeight = reflectionWeight * 2.0 - 1.0;
  290. this.reflectionReflectance0 = BackgroundMaterial.StandardReflectance0 + (1.0 - BackgroundMaterial.StandardReflectance0) * reflectionWeight;
  291. this.reflectionReflectance90 = BackgroundMaterial.StandardReflectance90 + (1.0 - BackgroundMaterial.StandardReflectance90) * reflectionWeight;
  292. }
  293. }
  294. @serialize()
  295. protected _useRGBColor: boolean;
  296. /**
  297. * Helps to directly use the maps channels instead of their level.
  298. */
  299. @expandToProperty("_markAllSubMeshesAsTexturesDirty")
  300. public useRGBColor: boolean = true;
  301. @serialize()
  302. protected _enableNoise: boolean;
  303. /**
  304. * This helps reducing the banding effect that could occur on the background.
  305. */
  306. @expandToProperty("_markAllSubMeshesAsTexturesDirty")
  307. public enableNoise: boolean = false;
  308. /**
  309. * The current fov(field of view) multiplier, 0.0 - 2.0. Defaults to 1.0. Lower values "zoom in" and higher values "zoom out".
  310. * Best used when trying to implement visual zoom effects like fish-eye or binoculars while not adjusting camera fov.
  311. * Recommended to be keep at 1.0 except for special cases.
  312. */
  313. public get fovMultiplier(): number {
  314. return this._fovMultiplier;
  315. }
  316. public set fovMultiplier(value: number) {
  317. if (isNaN(value)) {
  318. value = 1.0;
  319. }
  320. this._fovMultiplier = Math.max(0.0, Math.min(2.0, value));
  321. }
  322. private _fovMultiplier: float = 1.0;
  323. /**
  324. * Enable the FOV adjustment feature controlled by fovMultiplier.
  325. */
  326. public useEquirectangularFOV: boolean = false;
  327. @serialize()
  328. private _maxSimultaneousLights: int = 4;
  329. /**
  330. * Number of Simultaneous lights allowed on the material.
  331. */
  332. @expandToProperty("_markAllSubMeshesAsTexturesDirty")
  333. public maxSimultaneousLights: int = 4;
  334. /**
  335. * Default configuration related to image processing available in the Background Material.
  336. */
  337. @serializeAsImageProcessingConfiguration()
  338. protected _imageProcessingConfiguration: ImageProcessingConfiguration;
  339. /**
  340. * Keep track of the image processing observer to allow dispose and replace.
  341. */
  342. private _imageProcessingObserver: Nullable<Observer<ImageProcessingConfiguration>> = null;
  343. /**
  344. * Attaches a new image processing configuration to the PBR Material.
  345. * @param configuration (if null the scene configuration will be use)
  346. */
  347. protected _attachImageProcessingConfiguration(configuration: Nullable<ImageProcessingConfiguration>): void {
  348. if (configuration === this._imageProcessingConfiguration) {
  349. return;
  350. }
  351. // Detaches observer.
  352. if (this._imageProcessingConfiguration && this._imageProcessingObserver) {
  353. this._imageProcessingConfiguration.onUpdateParameters.remove(this._imageProcessingObserver);
  354. }
  355. // Pick the scene configuration if needed.
  356. if (!configuration) {
  357. this._imageProcessingConfiguration = this.getScene().imageProcessingConfiguration;
  358. }
  359. else {
  360. this._imageProcessingConfiguration = configuration;
  361. }
  362. // Attaches observer.
  363. this._imageProcessingObserver = this._imageProcessingConfiguration.onUpdateParameters.add(conf => {
  364. this._computePrimaryColorFromPerceptualColor();
  365. this._markAllSubMeshesAsImageProcessingDirty();
  366. });
  367. }
  368. /**
  369. * Gets the image processing configuration used either in this material.
  370. */
  371. public get imageProcessingConfiguration(): Nullable<ImageProcessingConfiguration> {
  372. return this._imageProcessingConfiguration;
  373. }
  374. /**
  375. * Sets the Default image processing configuration used either in the this material.
  376. *
  377. * If sets to null, the scene one is in use.
  378. */
  379. public set imageProcessingConfiguration(value: Nullable<ImageProcessingConfiguration>) {
  380. this._attachImageProcessingConfiguration(value);
  381. // Ensure the effect will be rebuilt.
  382. this._markAllSubMeshesAsTexturesDirty();
  383. }
  384. /**
  385. * Gets wether the color curves effect is enabled.
  386. */
  387. public get cameraColorCurvesEnabled(): boolean {
  388. return (<ImageProcessingConfiguration>this.imageProcessingConfiguration).colorCurvesEnabled;
  389. }
  390. /**
  391. * Sets wether the color curves effect is enabled.
  392. */
  393. public set cameraColorCurvesEnabled(value: boolean) {
  394. (<ImageProcessingConfiguration>this.imageProcessingConfiguration).colorCurvesEnabled = value;
  395. }
  396. /**
  397. * Gets wether the color grading effect is enabled.
  398. */
  399. public get cameraColorGradingEnabled(): boolean {
  400. return (<ImageProcessingConfiguration>this.imageProcessingConfiguration).colorGradingEnabled;
  401. }
  402. /**
  403. * Gets wether the color grading effect is enabled.
  404. */
  405. public set cameraColorGradingEnabled(value: boolean) {
  406. (<ImageProcessingConfiguration>this.imageProcessingConfiguration).colorGradingEnabled = value;
  407. }
  408. /**
  409. * Gets wether tonemapping is enabled or not.
  410. */
  411. public get cameraToneMappingEnabled(): boolean {
  412. return this._imageProcessingConfiguration.toneMappingEnabled;
  413. };
  414. /**
  415. * Sets wether tonemapping is enabled or not
  416. */
  417. public set cameraToneMappingEnabled(value: boolean) {
  418. this._imageProcessingConfiguration.toneMappingEnabled = value;
  419. };
  420. /**
  421. * The camera exposure used on this material.
  422. * This property is here and not in the camera to allow controlling exposure without full screen post process.
  423. * This corresponds to a photographic exposure.
  424. */
  425. public get cameraExposure(): float {
  426. return this._imageProcessingConfiguration.exposure;
  427. };
  428. /**
  429. * The camera exposure used on this material.
  430. * This property is here and not in the camera to allow controlling exposure without full screen post process.
  431. * This corresponds to a photographic exposure.
  432. */
  433. public set cameraExposure(value: float) {
  434. this._imageProcessingConfiguration.exposure = value;
  435. };
  436. /**
  437. * Gets The camera contrast used on this material.
  438. */
  439. public get cameraContrast(): float {
  440. return this._imageProcessingConfiguration.contrast;
  441. }
  442. /**
  443. * Sets The camera contrast used on this material.
  444. */
  445. public set cameraContrast(value: float) {
  446. this._imageProcessingConfiguration.contrast = value;
  447. }
  448. /**
  449. * Gets the Color Grading 2D Lookup Texture.
  450. */
  451. public get cameraColorGradingTexture(): Nullable<BaseTexture> {
  452. return this._imageProcessingConfiguration.colorGradingTexture;
  453. }
  454. /**
  455. * Sets the Color Grading 2D Lookup Texture.
  456. */
  457. public set cameraColorGradingTexture(value: Nullable<BaseTexture>) {
  458. (<ImageProcessingConfiguration>this.imageProcessingConfiguration).colorGradingTexture = value;
  459. }
  460. /**
  461. * The color grading curves provide additional color adjustmnent that is applied after any color grading transform (3D LUT).
  462. * They allow basic adjustment of saturation and small exposure adjustments, along with color filter tinting to provide white balance adjustment or more stylistic effects.
  463. * These are similar to controls found in many professional imaging or colorist software. The global controls are applied to the entire image. For advanced tuning, extra controls are provided to adjust the shadow, midtone and highlight areas of the image;
  464. * corresponding to low luminance, medium luminance, and high luminance areas respectively.
  465. */
  466. public get cameraColorCurves(): Nullable<ColorCurves> {
  467. return (<ImageProcessingConfiguration>this.imageProcessingConfiguration).colorCurves;
  468. }
  469. /**
  470. * The color grading curves provide additional color adjustmnent that is applied after any color grading transform (3D LUT).
  471. * They allow basic adjustment of saturation and small exposure adjustments, along with color filter tinting to provide white balance adjustment or more stylistic effects.
  472. * These are similar to controls found in many professional imaging or colorist software. The global controls are applied to the entire image. For advanced tuning, extra controls are provided to adjust the shadow, midtone and highlight areas of the image;
  473. * corresponding to low luminance, medium luminance, and high luminance areas respectively.
  474. */
  475. public set cameraColorCurves(value: Nullable<ColorCurves>) {
  476. (<ImageProcessingConfiguration>this.imageProcessingConfiguration).colorCurves = value;
  477. }
  478. /**
  479. * Due to a bug in iOS10, video tags (which are using the background material) are in BGR and not RGB.
  480. * Setting this flag to true (not done automatically!) will convert it back to RGB.
  481. */
  482. public switchToBGR: boolean = false;
  483. // Temp values kept as cache in the material.
  484. private _renderTargets = new SmartArray<RenderTargetTexture>(16);
  485. private _reflectionControls = Vector4.Zero();
  486. private _white = Color3.White();
  487. private _primaryShadowColor = Color3.Black();
  488. private _primaryHighlightColor = Color3.Black();
  489. /**
  490. * Instantiates a Background Material in the given scene
  491. * @param name The friendly name of the material
  492. * @param scene The scene to add the material to
  493. */
  494. constructor(name: string, scene: Scene) {
  495. super(name, scene);
  496. // Setup the default processing configuration to the scene.
  497. this._attachImageProcessingConfiguration(null);
  498. this.getRenderTargetTextures = (): SmartArray<RenderTargetTexture> => {
  499. this._renderTargets.reset();
  500. if (this._diffuseTexture && this._diffuseTexture.isRenderTarget) {
  501. this._renderTargets.push(this._diffuseTexture as RenderTargetTexture);
  502. }
  503. if (this._reflectionTexture && this._reflectionTexture.isRenderTarget) {
  504. this._renderTargets.push(this._reflectionTexture as RenderTargetTexture);
  505. }
  506. return this._renderTargets;
  507. }
  508. }
  509. /**
  510. * The entire material has been created in order to prevent overdraw.
  511. * @returns false
  512. */
  513. public needAlphaTesting(): boolean {
  514. return true;
  515. }
  516. /**
  517. * The entire material has been created in order to prevent overdraw.
  518. * @returns true if blending is enable
  519. */
  520. public needAlphaBlending(): boolean {
  521. return ((this.alpha < 0) || (this._diffuseTexture != null && this._diffuseTexture.hasAlpha));
  522. }
  523. /**
  524. * Checks wether the material is ready to be rendered for a given mesh.
  525. * @param mesh The mesh to render
  526. * @param subMesh The submesh to check against
  527. * @param useInstances Specify wether or not the material is used with instances
  528. * @returns true if all the dependencies are ready (Textures, Effects...)
  529. */
  530. public isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances: boolean = false): boolean {
  531. if (subMesh.effect && this.isFrozen) {
  532. if (this._wasPreviouslyReady) {
  533. return true;
  534. }
  535. }
  536. if (!subMesh._materialDefines) {
  537. subMesh._materialDefines = new BackgroundMaterialDefines();
  538. }
  539. var scene = this.getScene();
  540. var defines = <BackgroundMaterialDefines>subMesh._materialDefines;
  541. if (!this.checkReadyOnEveryCall && subMesh.effect) {
  542. if (defines._renderId === scene.getRenderId()) {
  543. return true;
  544. }
  545. }
  546. var engine = scene.getEngine();
  547. // Lights
  548. MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights);
  549. defines._needNormals = true;
  550. // Textures
  551. if (defines._areTexturesDirty) {
  552. defines._needUVs = false;
  553. if (scene.texturesEnabled) {
  554. if (scene.getEngine().getCaps().textureLOD) {
  555. defines.TEXTURELODSUPPORT = true;
  556. }
  557. if (this._diffuseTexture && StandardMaterial.DiffuseTextureEnabled) {
  558. if (!this._diffuseTexture.isReadyOrNotBlocking()) {
  559. return false;
  560. }
  561. MaterialHelper.PrepareDefinesForMergedUV(this._diffuseTexture, defines, "DIFFUSE");
  562. defines.DIFFUSEHASALPHA = this._diffuseTexture.hasAlpha;
  563. defines.GAMMADIFFUSE = this._diffuseTexture.gammaSpace;
  564. defines.OPACITYFRESNEL = this._opacityFresnel;
  565. } else {
  566. defines.DIFFUSE = false;
  567. defines.DIFFUSEHASALPHA = false;
  568. defines.GAMMADIFFUSE = false;
  569. defines.OPACITYFRESNEL = false;
  570. }
  571. var reflectionTexture = this._reflectionTexture;
  572. if (reflectionTexture && StandardMaterial.ReflectionTextureEnabled) {
  573. if (!reflectionTexture.isReadyOrNotBlocking()) {
  574. return false;
  575. }
  576. defines.REFLECTION = true;
  577. defines.GAMMAREFLECTION = reflectionTexture.gammaSpace;
  578. defines.REFLECTIONBLUR = this._reflectionBlur > 0;
  579. defines.REFLECTIONMAP_OPPOSITEZ = this.getScene().useRightHandedSystem ? !reflectionTexture.invertZ : reflectionTexture.invertZ;
  580. defines.LODINREFLECTIONALPHA = reflectionTexture.lodLevelInAlpha;
  581. defines.EQUIRECTANGULAR_RELFECTION_FOV = this.useEquirectangularFOV;
  582. defines.REFLECTIONBGR = this.switchToBGR;
  583. if (reflectionTexture.coordinatesMode === Texture.INVCUBIC_MODE) {
  584. defines.INVERTCUBICMAP = true;
  585. }
  586. defines.REFLECTIONMAP_3D = reflectionTexture.isCube;
  587. switch (reflectionTexture.coordinatesMode) {
  588. case Texture.CUBIC_MODE:
  589. case Texture.INVCUBIC_MODE:
  590. defines.REFLECTIONMAP_CUBIC = true;
  591. break;
  592. case Texture.EXPLICIT_MODE:
  593. defines.REFLECTIONMAP_EXPLICIT = true;
  594. break;
  595. case Texture.PLANAR_MODE:
  596. defines.REFLECTIONMAP_PLANAR = true;
  597. break;
  598. case Texture.PROJECTION_MODE:
  599. defines.REFLECTIONMAP_PROJECTION = true;
  600. break;
  601. case Texture.SKYBOX_MODE:
  602. defines.REFLECTIONMAP_SKYBOX = true;
  603. break;
  604. case Texture.SPHERICAL_MODE:
  605. defines.REFLECTIONMAP_SPHERICAL = true;
  606. break;
  607. case Texture.EQUIRECTANGULAR_MODE:
  608. defines.REFLECTIONMAP_EQUIRECTANGULAR = true;
  609. break;
  610. case Texture.FIXED_EQUIRECTANGULAR_MODE:
  611. defines.REFLECTIONMAP_EQUIRECTANGULAR_FIXED = true;
  612. break;
  613. case Texture.FIXED_EQUIRECTANGULAR_MIRRORED_MODE:
  614. defines.REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED = true;
  615. break;
  616. }
  617. if (this.reflectionFresnel) {
  618. defines.REFLECTIONFRESNEL = true;
  619. defines.REFLECTIONFALLOFF = this.reflectionFalloffDistance > 0;
  620. this._reflectionControls.x = this.reflectionAmount;
  621. this._reflectionControls.y = this.reflectionReflectance0;
  622. this._reflectionControls.z = this.reflectionReflectance90;
  623. this._reflectionControls.w = 1 / this.reflectionFalloffDistance;
  624. }
  625. else {
  626. defines.REFLECTIONFRESNEL = false;
  627. defines.REFLECTIONFALLOFF = false;
  628. }
  629. } else {
  630. defines.REFLECTION = false;
  631. defines.REFLECTIONFRESNEL = false;
  632. defines.REFLECTIONFALLOFF = false;
  633. defines.REFLECTIONBLUR = false;
  634. defines.REFLECTIONMAP_3D = false;
  635. defines.REFLECTIONMAP_SPHERICAL = false;
  636. defines.REFLECTIONMAP_PLANAR = false;
  637. defines.REFLECTIONMAP_CUBIC = false;
  638. defines.REFLECTIONMAP_PROJECTION = false;
  639. defines.REFLECTIONMAP_SKYBOX = false;
  640. defines.REFLECTIONMAP_EXPLICIT = false;
  641. defines.REFLECTIONMAP_EQUIRECTANGULAR = false;
  642. defines.REFLECTIONMAP_EQUIRECTANGULAR_FIXED = false;
  643. defines.REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED = false;
  644. defines.INVERTCUBICMAP = false;
  645. defines.REFLECTIONMAP_OPPOSITEZ = false;
  646. defines.LODINREFLECTIONALPHA = false;
  647. defines.GAMMAREFLECTION = false;
  648. }
  649. }
  650. defines.PREMULTIPLYALPHA = (this.alphaMode === Engine.ALPHA_PREMULTIPLIED || this.alphaMode === Engine.ALPHA_PREMULTIPLIED_PORTERDUFF);
  651. defines.USERGBCOLOR = this._useRGBColor;
  652. defines.NOISE = this._enableNoise;
  653. }
  654. if (defines._areLightsDirty) {
  655. defines.USEHIGHLIGHTANDSHADOWCOLORS = !this._useRGBColor && (this._primaryColorShadowLevel !== 0 || this._primaryColorHighlightLevel !== 0);
  656. }
  657. if (defines._areImageProcessingDirty) {
  658. if (!this._imageProcessingConfiguration.isReady()) {
  659. return false;
  660. }
  661. this._imageProcessingConfiguration.prepareDefines(defines);
  662. }
  663. // Misc.
  664. MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, this.pointsCloud, this.fogEnabled, this._shouldTurnAlphaTestOn(mesh), defines);
  665. // Values that need to be evaluated on every frame
  666. MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances);
  667. // Attribs
  668. if (MaterialHelper.PrepareDefinesForAttributes(mesh, defines, false, true, false)) {
  669. if (mesh) {
  670. if (!scene.getEngine().getCaps().standardDerivatives && !mesh.isVerticesDataPresent(VertexBuffer.NormalKind)) {
  671. mesh.createNormals(true);
  672. Tools.Warn("BackgroundMaterial: Normals have been created for the mesh: " + mesh.name);
  673. }
  674. }
  675. }
  676. // Get correct effect
  677. if (defines.isDirty) {
  678. defines.markAsProcessed();
  679. scene.resetCachedMaterial();
  680. // Fallbacks
  681. var fallbacks = new EffectFallbacks();
  682. if (defines.FOG) {
  683. fallbacks.addFallback(0, "FOG");
  684. }
  685. if (defines.POINTSIZE) {
  686. fallbacks.addFallback(1, "POINTSIZE");
  687. }
  688. MaterialHelper.HandleFallbacksForShadows(defines, fallbacks, this._maxSimultaneousLights);
  689. if (defines.NUM_BONE_INFLUENCERS > 0) {
  690. fallbacks.addCPUSkinningFallback(0, mesh);
  691. }
  692. //Attributes
  693. var attribs = [VertexBuffer.PositionKind];
  694. if (defines.NORMAL) {
  695. attribs.push(VertexBuffer.NormalKind);
  696. }
  697. if (defines.UV1) {
  698. attribs.push(VertexBuffer.UVKind);
  699. }
  700. if (defines.UV2) {
  701. attribs.push(VertexBuffer.UV2Kind);
  702. }
  703. MaterialHelper.PrepareAttributesForBones(attribs, mesh, defines, fallbacks);
  704. MaterialHelper.PrepareAttributesForInstances(attribs, defines);
  705. var uniforms = ["world", "view", "viewProjection", "vEyePosition", "vLightsType",
  706. "vFogInfos", "vFogColor", "pointSize",
  707. "vClipPlane", "mBones",
  708. "vPrimaryColor", "vPrimaryColorShadow",
  709. "vReflectionInfos", "reflectionMatrix", "vReflectionMicrosurfaceInfos", "fFovMultiplier",
  710. "shadowLevel", "alpha",
  711. "vBackgroundCenter", "vReflectionControl",
  712. "vDiffuseInfos", "diffuseMatrix",
  713. ];
  714. var samplers = ["diffuseSampler", "reflectionSampler", "reflectionSamplerLow", "reflectionSamplerHigh"];
  715. var uniformBuffers = ["Material", "Scene"];
  716. ImageProcessingConfiguration.PrepareUniforms(uniforms, defines);
  717. ImageProcessingConfiguration.PrepareSamplers(samplers, defines);
  718. MaterialHelper.PrepareUniformsAndSamplersList(<EffectCreationOptions>{
  719. uniformsNames: uniforms,
  720. uniformBuffersNames: uniformBuffers,
  721. samplers: samplers,
  722. defines: defines,
  723. maxSimultaneousLights: this._maxSimultaneousLights
  724. });
  725. var onCompiled = (effect: Effect) => {
  726. if (this.onCompiled) {
  727. this.onCompiled(effect);
  728. }
  729. this.bindSceneUniformBuffer(effect, scene.getSceneUniformBuffer());
  730. };
  731. var join = defines.toString();
  732. subMesh.setEffect(scene.getEngine().createEffect("background", <EffectCreationOptions>{
  733. attributes: attribs,
  734. uniformsNames: uniforms,
  735. uniformBuffersNames: uniformBuffers,
  736. samplers: samplers,
  737. defines: join,
  738. fallbacks: fallbacks,
  739. onCompiled: onCompiled,
  740. onError: this.onError,
  741. indexParameters: { maxSimultaneousLights: this._maxSimultaneousLights }
  742. }, engine), defines);
  743. this.buildUniformLayout();
  744. }
  745. if (!subMesh.effect || !subMesh.effect.isReady()) {
  746. return false;
  747. }
  748. defines._renderId = scene.getRenderId();
  749. this._wasPreviouslyReady = true;
  750. return true;
  751. }
  752. /**
  753. * Compute the primary color according to the chosen perceptual color.
  754. */
  755. private _computePrimaryColorFromPerceptualColor(): void {
  756. if (!this.__perceptualColor) {
  757. return;
  758. }
  759. this._primaryColor.copyFrom(this.__perceptualColor);
  760. // Revert gamma space.
  761. this._primaryColor.toLinearSpaceToRef(this._primaryColor);
  762. // Revert image processing configuration.
  763. if (this._imageProcessingConfiguration) {
  764. // Revert Exposure.
  765. this._primaryColor.scaleToRef(1 / this._imageProcessingConfiguration.exposure, this._primaryColor);
  766. }
  767. this._computePrimaryColors();
  768. }
  769. /**
  770. * Compute the highlights and shadow colors according to their chosen levels.
  771. */
  772. private _computePrimaryColors(): void {
  773. if (this._primaryColorShadowLevel === 0 && this._primaryColorHighlightLevel === 0) {
  774. return;
  775. }
  776. // Find the highlight color based on the configuration.
  777. this._primaryColor.scaleToRef(this._primaryColorShadowLevel, this._primaryShadowColor);
  778. this._primaryColor.subtractToRef(this._primaryShadowColor, this._primaryShadowColor);
  779. // Find the shadow color based on the configuration.
  780. this._white.subtractToRef(this._primaryColor, this._primaryHighlightColor);
  781. this._primaryHighlightColor.scaleToRef(this._primaryColorHighlightLevel, this._primaryHighlightColor);
  782. this._primaryColor.addToRef(this._primaryHighlightColor, this._primaryHighlightColor);
  783. }
  784. /**
  785. * Build the uniform buffer used in the material.
  786. */
  787. public buildUniformLayout(): void {
  788. // Order is important !
  789. this._uniformBuffer.addUniform("vPrimaryColor", 4);
  790. this._uniformBuffer.addUniform("vPrimaryColorShadow", 4);
  791. this._uniformBuffer.addUniform("vDiffuseInfos", 2);
  792. this._uniformBuffer.addUniform("vReflectionInfos", 2);
  793. this._uniformBuffer.addUniform("diffuseMatrix", 16);
  794. this._uniformBuffer.addUniform("reflectionMatrix", 16);
  795. this._uniformBuffer.addUniform("vReflectionMicrosurfaceInfos", 3);
  796. this._uniformBuffer.addUniform("fFovMultiplier", 1);
  797. this._uniformBuffer.addUniform("pointSize", 1);
  798. this._uniformBuffer.addUniform("shadowLevel", 1);
  799. this._uniformBuffer.addUniform("alpha", 1);
  800. this._uniformBuffer.addUniform("vBackgroundCenter", 3);
  801. this._uniformBuffer.addUniform("vReflectionControl", 4);
  802. this._uniformBuffer.create();
  803. }
  804. /**
  805. * Unbind the material.
  806. */
  807. public unbind(): void {
  808. if (this._diffuseTexture && this._diffuseTexture.isRenderTarget) {
  809. this._uniformBuffer.setTexture("diffuseSampler", null);
  810. }
  811. if (this._reflectionTexture && this._reflectionTexture.isRenderTarget) {
  812. this._uniformBuffer.setTexture("reflectionSampler", null);
  813. }
  814. super.unbind();
  815. }
  816. /**
  817. * Bind only the world matrix to the material.
  818. * @param world The world matrix to bind.
  819. */
  820. public bindOnlyWorldMatrix(world: Matrix): void {
  821. this._activeEffect.setMatrix("world", world);
  822. }
  823. /**
  824. * Bind the material for a dedicated submeh (every used meshes will be considered opaque).
  825. * @param world The world matrix to bind.
  826. * @param subMesh The submesh to bind for.
  827. */
  828. public bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void {
  829. var scene = this.getScene();
  830. var defines = <BackgroundMaterialDefines>subMesh._materialDefines;
  831. if (!defines) {
  832. return;
  833. }
  834. var effect = subMesh.effect;
  835. if (!effect) {
  836. return;
  837. }
  838. this._activeEffect = effect;
  839. // Matrices
  840. this.bindOnlyWorldMatrix(world);
  841. // Bones
  842. MaterialHelper.BindBonesParameters(mesh, this._activeEffect);
  843. let mustRebind = this._mustRebind(scene, effect, mesh.visibility);
  844. if (mustRebind) {
  845. this._uniformBuffer.bindToEffect(effect, "Material");
  846. this.bindViewProjection(effect);
  847. let reflectionTexture = this._reflectionTexture;
  848. if (!this._uniformBuffer.useUbo || !this.isFrozen || !this._uniformBuffer.isSync) {
  849. // Texture uniforms
  850. if (scene.texturesEnabled) {
  851. if (this._diffuseTexture && StandardMaterial.DiffuseTextureEnabled) {
  852. this._uniformBuffer.updateFloat2("vDiffuseInfos", this._diffuseTexture.coordinatesIndex, this._diffuseTexture.level);
  853. MaterialHelper.BindTextureMatrix(this._diffuseTexture, this._uniformBuffer, "diffuse");
  854. }
  855. if (reflectionTexture && StandardMaterial.ReflectionTextureEnabled) {
  856. this._uniformBuffer.updateMatrix("reflectionMatrix", reflectionTexture.getReflectionTextureMatrix());
  857. this._uniformBuffer.updateFloat2("vReflectionInfos", reflectionTexture.level, this._reflectionBlur);
  858. this._uniformBuffer.updateFloat3("vReflectionMicrosurfaceInfos",
  859. reflectionTexture.getSize().width,
  860. reflectionTexture.lodGenerationScale,
  861. reflectionTexture.lodGenerationOffset);
  862. }
  863. }
  864. if (this.shadowLevel > 0) {
  865. this._uniformBuffer.updateFloat("shadowLevel", this.shadowLevel);
  866. }
  867. this._uniformBuffer.updateFloat("alpha", this.alpha);
  868. // Point size
  869. if (this.pointsCloud) {
  870. this._uniformBuffer.updateFloat("pointSize", this.pointSize);
  871. }
  872. if (defines.USEHIGHLIGHTANDSHADOWCOLORS) {
  873. this._uniformBuffer.updateColor4("vPrimaryColor", this._primaryHighlightColor, 1.0);
  874. this._uniformBuffer.updateColor4("vPrimaryColorShadow", this._primaryShadowColor, 1.0);
  875. }
  876. else {
  877. this._uniformBuffer.updateColor4("vPrimaryColor", this._primaryColor, 1.0);
  878. }
  879. }
  880. this._uniformBuffer.updateFloat("fFovMultiplier", this._fovMultiplier);
  881. // Textures
  882. if (scene.texturesEnabled) {
  883. if (this._diffuseTexture && StandardMaterial.DiffuseTextureEnabled) {
  884. this._uniformBuffer.setTexture("diffuseSampler", this._diffuseTexture);
  885. }
  886. if (reflectionTexture && StandardMaterial.ReflectionTextureEnabled) {
  887. if (defines.REFLECTIONBLUR && defines.TEXTURELODSUPPORT) {
  888. this._uniformBuffer.setTexture("reflectionSampler", reflectionTexture);
  889. }
  890. else if (!defines.REFLECTIONBLUR) {
  891. this._uniformBuffer.setTexture("reflectionSampler", reflectionTexture);
  892. }
  893. else {
  894. this._uniformBuffer.setTexture("reflectionSampler", reflectionTexture._lodTextureMid || reflectionTexture);
  895. this._uniformBuffer.setTexture("reflectionSamplerLow", reflectionTexture._lodTextureLow || reflectionTexture);
  896. this._uniformBuffer.setTexture("reflectionSamplerHigh", reflectionTexture._lodTextureHigh || reflectionTexture);
  897. }
  898. if (defines.REFLECTIONFRESNEL) {
  899. this._uniformBuffer.updateFloat3("vBackgroundCenter", this.sceneCenter.x, this.sceneCenter.y, this.sceneCenter.z);
  900. this._uniformBuffer.updateFloat4("vReflectionControl", this._reflectionControls.x, this._reflectionControls.y, this._reflectionControls.z, this._reflectionControls.w);
  901. }
  902. }
  903. }
  904. // Clip plane
  905. MaterialHelper.BindClipPlane(this._activeEffect, scene);
  906. MaterialHelper.BindEyePosition(effect, scene);
  907. }
  908. if (mustRebind || !this.isFrozen) {
  909. if (scene.lightsEnabled) {
  910. MaterialHelper.BindLights(scene, mesh, this._activeEffect, defines, this._maxSimultaneousLights, false);
  911. }
  912. // View
  913. this.bindView(effect);
  914. // Fog
  915. MaterialHelper.BindFogParameters(scene, mesh, this._activeEffect);
  916. // image processing
  917. this._imageProcessingConfiguration.bind(this._activeEffect);
  918. }
  919. this._uniformBuffer.update();
  920. this._afterBind(mesh);
  921. }
  922. /**
  923. * Dispose the material.
  924. * @param forceDisposeEffect Force disposal of the associated effect.
  925. * @param forceDisposeTextures Force disposal of the associated textures.
  926. */
  927. public dispose(forceDisposeEffect: boolean = false, forceDisposeTextures: boolean = false): void {
  928. if (forceDisposeTextures) {
  929. if (this.diffuseTexture) {
  930. this.diffuseTexture.dispose();
  931. }
  932. if (this.reflectionTexture) {
  933. this.reflectionTexture.dispose();
  934. }
  935. }
  936. this._renderTargets.dispose();
  937. if (this._imageProcessingConfiguration && this._imageProcessingObserver) {
  938. this._imageProcessingConfiguration.onUpdateParameters.remove(this._imageProcessingObserver);
  939. }
  940. super.dispose(forceDisposeEffect);
  941. }
  942. /**
  943. * Clones the material.
  944. * @param name The cloned name.
  945. * @returns The cloned material.
  946. */
  947. public clone(name: string): BackgroundMaterial {
  948. return SerializationHelper.Clone(() => new BackgroundMaterial(name, this.getScene()), this);
  949. }
  950. /**
  951. * Serializes the current material to its JSON representation.
  952. * @returns The JSON representation.
  953. */
  954. public serialize(): any {
  955. var serializationObject = SerializationHelper.Serialize(this);
  956. serializationObject.customType = "BABYLON.BackgroundMaterial";
  957. return serializationObject;
  958. }
  959. /**
  960. * Gets the class name of the material
  961. * @returns "BackgroundMaterial"
  962. */
  963. public getClassName(): string {
  964. return "BackgroundMaterial";
  965. }
  966. /**
  967. * Parse a JSON input to create back a background material.
  968. * @param source The JSON data to parse
  969. * @param scene The scene to create the parsed material in
  970. * @param rootUrl The root url of the assets the material depends upon
  971. * @returns the instantiated BackgroundMaterial.
  972. */
  973. public static Parse(source: any, scene: Scene, rootUrl: string): BackgroundMaterial {
  974. return SerializationHelper.Parse(() => new BackgroundMaterial(source.name, scene), source, scene, rootUrl);
  975. }
  976. }
  977. }