waterMaterial.ts 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780
  1. import { Nullable } from "babylonjs/types";
  2. import { serializeAsVector2, serializeAsTexture, serialize, expandToProperty, serializeAsColor3, SerializationHelper } from "babylonjs/Misc/decorators";
  3. import { Matrix, Vector2, Vector3 } from "babylonjs/Maths/math.vector";
  4. import { Color3 } from "babylonjs/Maths/math.color";
  5. import { Plane } from 'babylonjs/Maths/math.plane';
  6. import { IAnimatable } from 'babylonjs/Animations/animatable.interface';
  7. import { Constants } from "babylonjs/Engines/constants";
  8. import { SmartArray } from "babylonjs/Misc/smartArray";
  9. import { Observer } from 'babylonjs/Misc/observable';
  10. import { BaseTexture } from "babylonjs/Materials/Textures/baseTexture";
  11. import { RenderTargetTexture } from "babylonjs/Materials/Textures/renderTargetTexture";
  12. import { IEffectCreationOptions } from "babylonjs/Materials/effect";
  13. import { MaterialDefines } from "babylonjs/Materials/materialDefines";
  14. import { IImageProcessingConfigurationDefines, ImageProcessingConfiguration } from "babylonjs/Materials/imageProcessingConfiguration";
  15. import { MaterialHelper } from "babylonjs/Materials/materialHelper";
  16. import { PushMaterial } from "babylonjs/Materials/pushMaterial";
  17. import { MaterialFlags } from "babylonjs/Materials/materialFlags";
  18. import { VertexBuffer } from "babylonjs/Meshes/buffer";
  19. import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
  20. import { SubMesh } from "babylonjs/Meshes/subMesh";
  21. import { Mesh } from "babylonjs/Meshes/mesh";
  22. import { Camera } from "babylonjs/Cameras/camera";
  23. import { Scene } from "babylonjs/scene";
  24. import { _TypeStore } from 'babylonjs/Misc/typeStore';
  25. import "./water.fragment";
  26. import "./water.vertex";
  27. import { EffectFallbacks } from 'babylonjs/Materials/effectFallbacks';
  28. class WaterMaterialDefines extends MaterialDefines implements IImageProcessingConfigurationDefines {
  29. public BUMP = false;
  30. public REFLECTION = false;
  31. public CLIPPLANE = false;
  32. public CLIPPLANE2 = false;
  33. public CLIPPLANE3 = false;
  34. public CLIPPLANE4 = false;
  35. public CLIPPLANE5 = false;
  36. public CLIPPLANE6 = false;
  37. public ALPHATEST = false;
  38. public DEPTHPREPASS = false;
  39. public POINTSIZE = false;
  40. public FOG = false;
  41. public NORMAL = false;
  42. public UV1 = false;
  43. public UV2 = false;
  44. public VERTEXCOLOR = false;
  45. public VERTEXALPHA = false;
  46. public NUM_BONE_INFLUENCERS = 0;
  47. public BonesPerMesh = 0;
  48. public INSTANCES = false;
  49. public SPECULARTERM = false;
  50. public LOGARITHMICDEPTH = false;
  51. public FRESNELSEPARATE = false;
  52. public BUMPSUPERIMPOSE = false;
  53. public BUMPAFFECTSREFLECTION = false;
  54. public IMAGEPROCESSING = false;
  55. public VIGNETTE = false;
  56. public VIGNETTEBLENDMODEMULTIPLY = false;
  57. public VIGNETTEBLENDMODEOPAQUE = false;
  58. public TONEMAPPING = false;
  59. public TONEMAPPING_ACES = false;
  60. public CONTRAST = false;
  61. public EXPOSURE = false;
  62. public COLORCURVES = false;
  63. public COLORGRADING = false;
  64. public COLORGRADING3D = false;
  65. public SAMPLER3DGREENDEPTH = false;
  66. public SAMPLER3DBGRMAP = false;
  67. public IMAGEPROCESSINGPOSTPROCESS = false;
  68. constructor() {
  69. super();
  70. this.rebuild();
  71. }
  72. }
  73. export class WaterMaterial extends PushMaterial {
  74. /*
  75. * Public members
  76. */
  77. @serializeAsTexture("bumpTexture")
  78. private _bumpTexture: BaseTexture;
  79. @expandToProperty("_markAllSubMeshesAsTexturesDirty")
  80. public bumpTexture: BaseTexture;
  81. @serializeAsColor3()
  82. public diffuseColor = new Color3(1, 1, 1);
  83. @serializeAsColor3()
  84. public specularColor = new Color3(0, 0, 0);
  85. @serialize()
  86. public specularPower = 64;
  87. @serialize("disableLighting")
  88. private _disableLighting = false;
  89. @expandToProperty("_markAllSubMeshesAsLightsDirty")
  90. public disableLighting: boolean;
  91. @serialize("maxSimultaneousLights")
  92. private _maxSimultaneousLights = 4;
  93. @expandToProperty("_markAllSubMeshesAsLightsDirty")
  94. public maxSimultaneousLights: number;
  95. /**
  96. * Defines the wind force.
  97. */
  98. @serialize()
  99. public windForce: number = 6;
  100. /**
  101. * Defines the direction of the wind in the plane (X, Z).
  102. */
  103. @serializeAsVector2()
  104. public windDirection: Vector2 = new Vector2(0, 1);
  105. /**
  106. * Defines the height of the waves.
  107. */
  108. @serialize()
  109. public waveHeight: number = 0.4;
  110. /**
  111. * Defines the bump height related to the bump map.
  112. */
  113. @serialize()
  114. public bumpHeight: number = 0.4;
  115. /**
  116. * Defines wether or not: to add a smaller moving bump to less steady waves.
  117. */
  118. @serialize("bumpSuperimpose")
  119. private _bumpSuperimpose = false;
  120. @expandToProperty("_markAllSubMeshesAsMiscDirty")
  121. public bumpSuperimpose: boolean;
  122. /**
  123. * Defines wether or not color refraction and reflection differently with .waterColor2 and .colorBlendFactor2. Non-linear (physically correct) fresnel.
  124. */
  125. @serialize("fresnelSeparate")
  126. private _fresnelSeparate = false;
  127. @expandToProperty("_markAllSubMeshesAsMiscDirty")
  128. public fresnelSeparate: boolean;
  129. /**
  130. * Defines wether or not bump Wwves modify the reflection.
  131. */
  132. @serialize("bumpAffectsReflection")
  133. private _bumpAffectsReflection = false;
  134. @expandToProperty("_markAllSubMeshesAsMiscDirty")
  135. public bumpAffectsReflection: boolean;
  136. /**
  137. * Defines the water color blended with the refraction (near).
  138. */
  139. @serializeAsColor3()
  140. public waterColor: Color3 = new Color3(0.1, 0.1, 0.6);
  141. /**
  142. * Defines the blend factor related to the water color.
  143. */
  144. @serialize()
  145. public colorBlendFactor: number = 0.2;
  146. /**
  147. * Defines the water color blended with the reflection (far).
  148. */
  149. @serializeAsColor3()
  150. public waterColor2: Color3 = new Color3(0.1, 0.1, 0.6);
  151. /**
  152. * Defines the blend factor related to the water color (reflection, far).
  153. */
  154. @serialize()
  155. public colorBlendFactor2: number = 0.2;
  156. /**
  157. * Defines the maximum length of a wave.
  158. */
  159. @serialize()
  160. public waveLength: number = 0.1;
  161. /**
  162. * Defines the waves speed.
  163. */
  164. @serialize()
  165. public waveSpeed: number = 1.0;
  166. /**
  167. * Defines the number of times waves are repeated. This is typically used to adjust waves count according to the ground's size where the material is applied on.
  168. */
  169. @serialize()
  170. public waveCount: number = 20;
  171. /**
  172. * Sets or gets whether or not automatic clipping should be enabled or not. Setting to true will save performances and
  173. * will avoid calculating useless pixels in the pixel shader of the water material.
  174. */
  175. @serialize()
  176. public disableClipPlane: boolean = false;
  177. protected _renderTargets = new SmartArray<RenderTargetTexture>(16);
  178. /*
  179. * Private members
  180. */
  181. private _mesh: Nullable<AbstractMesh> = null;
  182. private _refractionRTT: Nullable<RenderTargetTexture>;
  183. private _reflectionRTT: Nullable<RenderTargetTexture>;
  184. private _reflectionTransform: Matrix = Matrix.Zero();
  185. private _lastTime: number = 0;
  186. private _lastDeltaTime: number = 0;
  187. private _useLogarithmicDepth: boolean;
  188. private _waitingRenderList: Nullable<string[]>;
  189. private _imageProcessingConfiguration: Nullable<ImageProcessingConfiguration>;
  190. private _imageProcessingObserver: Nullable<Observer<ImageProcessingConfiguration>>;
  191. /**
  192. * Gets a boolean indicating that current material needs to register RTT
  193. */
  194. public get hasRenderTargetTextures(): boolean {
  195. return true;
  196. }
  197. /**
  198. * Constructor
  199. */
  200. constructor(name: string, scene: Scene, public renderTargetSize: Vector2 = new Vector2(512, 512)) {
  201. super(name, scene);
  202. this._createRenderTargets(scene, renderTargetSize);
  203. // Create render targets
  204. this.getRenderTargetTextures = (): SmartArray<RenderTargetTexture> => {
  205. this._renderTargets.reset();
  206. this._renderTargets.push(<RenderTargetTexture>this._reflectionRTT);
  207. this._renderTargets.push(<RenderTargetTexture>this._refractionRTT);
  208. return this._renderTargets;
  209. };
  210. this._imageProcessingConfiguration = this.getScene().imageProcessingConfiguration;
  211. if (this._imageProcessingConfiguration) {
  212. this._imageProcessingObserver = this._imageProcessingConfiguration.onUpdateParameters.add(() => {
  213. this._markAllSubMeshesAsImageProcessingDirty();
  214. });
  215. }
  216. }
  217. @serialize()
  218. public get useLogarithmicDepth(): boolean {
  219. return this._useLogarithmicDepth;
  220. }
  221. public set useLogarithmicDepth(value: boolean) {
  222. this._useLogarithmicDepth = value && this.getScene().getEngine().getCaps().fragmentDepthSupported;
  223. this._markAllSubMeshesAsMiscDirty();
  224. }
  225. // Get / Set
  226. public get refractionTexture(): Nullable<RenderTargetTexture> {
  227. return this._refractionRTT;
  228. }
  229. public get reflectionTexture(): Nullable<RenderTargetTexture> {
  230. return this._reflectionRTT;
  231. }
  232. // Methods
  233. public addToRenderList(node: any): void {
  234. if (this._refractionRTT && this._refractionRTT.renderList) {
  235. this._refractionRTT.renderList.push(node);
  236. }
  237. if (this._reflectionRTT && this._reflectionRTT.renderList) {
  238. this._reflectionRTT.renderList.push(node);
  239. }
  240. }
  241. public enableRenderTargets(enable: boolean): void {
  242. var refreshRate = enable ? 1 : 0;
  243. if (this._refractionRTT) {
  244. this._refractionRTT.refreshRate = refreshRate;
  245. }
  246. if (this._reflectionRTT) {
  247. this._reflectionRTT.refreshRate = refreshRate;
  248. }
  249. }
  250. public getRenderList(): Nullable<AbstractMesh[]> {
  251. return this._refractionRTT ? this._refractionRTT.renderList : [];
  252. }
  253. public get renderTargetsEnabled(): boolean {
  254. return !(this._refractionRTT && this._refractionRTT.refreshRate === 0);
  255. }
  256. public needAlphaBlending(): boolean {
  257. return (this.alpha < 1.0);
  258. }
  259. public needAlphaTesting(): boolean {
  260. return false;
  261. }
  262. public getAlphaTestTexture(): Nullable<BaseTexture> {
  263. return null;
  264. }
  265. public isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean {
  266. if (this.isFrozen) {
  267. if (subMesh.effect && subMesh.effect._wasPreviouslyReady) {
  268. return true;
  269. }
  270. }
  271. if (!subMesh._materialDefines) {
  272. subMesh._materialDefines = new WaterMaterialDefines();
  273. }
  274. var defines = <WaterMaterialDefines>subMesh._materialDefines;
  275. var scene = this.getScene();
  276. if (this._isReadyForSubMesh(subMesh)) {
  277. return true;
  278. }
  279. var engine = scene.getEngine();
  280. // Textures
  281. if (defines._areTexturesDirty) {
  282. defines._needUVs = false;
  283. if (scene.texturesEnabled) {
  284. if (this.bumpTexture && MaterialFlags.BumpTextureEnabled) {
  285. if (!this.bumpTexture.isReady()) {
  286. return false;
  287. } else {
  288. defines._needUVs = true;
  289. defines.BUMP = true;
  290. }
  291. }
  292. if (MaterialFlags.ReflectionTextureEnabled) {
  293. defines.REFLECTION = true;
  294. }
  295. }
  296. }
  297. MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false);
  298. MaterialHelper.PrepareDefinesForMisc(mesh, scene, this._useLogarithmicDepth, this.pointsCloud, this.fogEnabled, this._shouldTurnAlphaTestOn(mesh), defines);
  299. if (defines._areMiscDirty) {
  300. if (this._fresnelSeparate) {
  301. defines.FRESNELSEPARATE = true;
  302. }
  303. if (this._bumpSuperimpose) {
  304. defines.BUMPSUPERIMPOSE = true;
  305. }
  306. if (this._bumpAffectsReflection) {
  307. defines.BUMPAFFECTSREFLECTION = true;
  308. }
  309. }
  310. // Lights
  311. defines._needNormals = MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, true, this._maxSimultaneousLights, this._disableLighting);
  312. // Image processing
  313. if (defines._areImageProcessingDirty && this._imageProcessingConfiguration) {
  314. if (!this._imageProcessingConfiguration.isReady()) {
  315. return false;
  316. }
  317. this._imageProcessingConfiguration.prepareDefines(defines);
  318. defines.IS_REFLECTION_LINEAR = (this.reflectionTexture != null && !this.reflectionTexture.gammaSpace);
  319. defines.IS_REFRACTION_LINEAR = (this.refractionTexture != null && !this.refractionTexture.gammaSpace);
  320. }
  321. // Attribs
  322. MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true);
  323. // Configure this
  324. this._mesh = mesh;
  325. if (this._waitingRenderList) {
  326. for (var i = 0; i < this._waitingRenderList.length; i++) {
  327. this.addToRenderList(scene.getNodeByID(this._waitingRenderList[i]));
  328. }
  329. this._waitingRenderList = null;
  330. }
  331. // Get correct effect
  332. if (defines.isDirty) {
  333. defines.markAsProcessed();
  334. scene.resetCachedMaterial();
  335. // Fallbacks
  336. var fallbacks = new EffectFallbacks();
  337. if (defines.FOG) {
  338. fallbacks.addFallback(1, "FOG");
  339. }
  340. if (defines.LOGARITHMICDEPTH) {
  341. fallbacks.addFallback(0, "LOGARITHMICDEPTH");
  342. }
  343. MaterialHelper.HandleFallbacksForShadows(defines, fallbacks, this.maxSimultaneousLights);
  344. if (defines.NUM_BONE_INFLUENCERS > 0) {
  345. fallbacks.addCPUSkinningFallback(0, mesh);
  346. }
  347. //Attributes
  348. var attribs = [VertexBuffer.PositionKind];
  349. if (defines.NORMAL) {
  350. attribs.push(VertexBuffer.NormalKind);
  351. }
  352. if (defines.UV1) {
  353. attribs.push(VertexBuffer.UVKind);
  354. }
  355. if (defines.UV2) {
  356. attribs.push(VertexBuffer.UV2Kind);
  357. }
  358. if (defines.VERTEXCOLOR) {
  359. attribs.push(VertexBuffer.ColorKind);
  360. }
  361. MaterialHelper.PrepareAttributesForBones(attribs, mesh, defines, fallbacks);
  362. MaterialHelper.PrepareAttributesForInstances(attribs, defines);
  363. // Legacy browser patch
  364. var shaderName = "water";
  365. var join = defines.toString();
  366. var uniforms = ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vDiffuseColor", "vSpecularColor",
  367. "vFogInfos", "vFogColor", "pointSize",
  368. "vNormalInfos",
  369. "mBones",
  370. "vClipPlane", "vClipPlane2", "vClipPlane3", "vClipPlane4", "vClipPlane5", "vClipPlane6", "normalMatrix",
  371. "logarithmicDepthConstant",
  372. // Water
  373. "worldReflectionViewProjection", "windDirection", "waveLength", "time", "windForce",
  374. "cameraPosition", "bumpHeight", "waveHeight", "waterColor", "waterColor2", "colorBlendFactor", "colorBlendFactor2", "waveSpeed",
  375. "waveCount"
  376. ];
  377. var samplers = ["normalSampler",
  378. // Water
  379. "refractionSampler", "reflectionSampler"
  380. ];
  381. var uniformBuffers = new Array<string>();
  382. if (ImageProcessingConfiguration) {
  383. ImageProcessingConfiguration.PrepareUniforms(uniforms, defines);
  384. ImageProcessingConfiguration.PrepareSamplers(samplers, defines);
  385. }
  386. MaterialHelper.PrepareUniformsAndSamplersList(<IEffectCreationOptions>{
  387. uniformsNames: uniforms,
  388. uniformBuffersNames: uniformBuffers,
  389. samplers: samplers,
  390. defines: defines,
  391. maxSimultaneousLights: this.maxSimultaneousLights
  392. });
  393. subMesh.setEffect(scene.getEngine().createEffect(shaderName,
  394. <IEffectCreationOptions>{
  395. attributes: attribs,
  396. uniformsNames: uniforms,
  397. uniformBuffersNames: uniformBuffers,
  398. samplers: samplers,
  399. defines: join,
  400. fallbacks: fallbacks,
  401. onCompiled: this.onCompiled,
  402. onError: this.onError,
  403. indexParameters: { maxSimultaneousLights: this._maxSimultaneousLights }
  404. }, engine), defines);
  405. }
  406. if (!subMesh.effect || !subMesh.effect.isReady()) {
  407. return false;
  408. }
  409. defines._renderId = scene.getRenderId();
  410. subMesh.effect._wasPreviouslyReady = true;
  411. return true;
  412. }
  413. public bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void {
  414. var scene = this.getScene();
  415. var defines = <WaterMaterialDefines>subMesh._materialDefines;
  416. if (!defines) {
  417. return;
  418. }
  419. var effect = subMesh.effect;
  420. if (!effect || !this._mesh) {
  421. return;
  422. }
  423. this._activeEffect = effect;
  424. // Matrices
  425. this.bindOnlyWorldMatrix(world);
  426. this._activeEffect.setMatrix("viewProjection", scene.getTransformMatrix());
  427. // Bones
  428. MaterialHelper.BindBonesParameters(mesh, this._activeEffect);
  429. if (this._mustRebind(scene, effect)) {
  430. // Textures
  431. if (this.bumpTexture && MaterialFlags.BumpTextureEnabled) {
  432. this._activeEffect.setTexture("normalSampler", this.bumpTexture);
  433. this._activeEffect.setFloat2("vNormalInfos", this.bumpTexture.coordinatesIndex, this.bumpTexture.level);
  434. this._activeEffect.setMatrix("normalMatrix", this.bumpTexture.getTextureMatrix());
  435. }
  436. // Clip plane
  437. MaterialHelper.BindClipPlane(this._activeEffect, scene);
  438. // Point size
  439. if (this.pointsCloud) {
  440. this._activeEffect.setFloat("pointSize", this.pointSize);
  441. }
  442. MaterialHelper.BindEyePosition(effect, scene);
  443. }
  444. this._activeEffect.setColor4("vDiffuseColor", this.diffuseColor, this.alpha * mesh.visibility);
  445. if (defines.SPECULARTERM) {
  446. this._activeEffect.setColor4("vSpecularColor", this.specularColor, this.specularPower);
  447. }
  448. if (scene.lightsEnabled && !this.disableLighting) {
  449. MaterialHelper.BindLights(scene, mesh, this._activeEffect, defines, this.maxSimultaneousLights);
  450. }
  451. // View
  452. if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE) {
  453. this._activeEffect.setMatrix("view", scene.getViewMatrix());
  454. }
  455. // Fog
  456. MaterialHelper.BindFogParameters(scene, mesh, this._activeEffect);
  457. // Log. depth
  458. MaterialHelper.BindLogDepth(defines, this._activeEffect, scene);
  459. // Water
  460. if (MaterialFlags.ReflectionTextureEnabled) {
  461. this._activeEffect.setTexture("refractionSampler", this._refractionRTT);
  462. this._activeEffect.setTexture("reflectionSampler", this._reflectionRTT);
  463. }
  464. var wrvp = this._mesh.getWorldMatrix().multiply(this._reflectionTransform).multiply(scene.getProjectionMatrix());
  465. // Add delta time. Prevent adding delta time if it hasn't changed.
  466. let deltaTime = scene.getEngine().getDeltaTime();
  467. if (deltaTime !== this._lastDeltaTime) {
  468. this._lastDeltaTime = deltaTime;
  469. this._lastTime += this._lastDeltaTime;
  470. }
  471. this._activeEffect.setMatrix("worldReflectionViewProjection", wrvp);
  472. this._activeEffect.setVector2("windDirection", this.windDirection);
  473. this._activeEffect.setFloat("waveLength", this.waveLength);
  474. this._activeEffect.setFloat("time", this._lastTime / 100000);
  475. this._activeEffect.setFloat("windForce", this.windForce);
  476. this._activeEffect.setFloat("waveHeight", this.waveHeight);
  477. this._activeEffect.setFloat("bumpHeight", this.bumpHeight);
  478. this._activeEffect.setColor4("waterColor", this.waterColor, 1.0);
  479. this._activeEffect.setFloat("colorBlendFactor", this.colorBlendFactor);
  480. this._activeEffect.setColor4("waterColor2", this.waterColor2, 1.0);
  481. this._activeEffect.setFloat("colorBlendFactor2", this.colorBlendFactor2);
  482. this._activeEffect.setFloat("waveSpeed", this.waveSpeed);
  483. this._activeEffect.setFloat("waveCount", this.waveCount);
  484. // image processing
  485. if (this._imageProcessingConfiguration && !this._imageProcessingConfiguration.applyByPostProcess) {
  486. this._imageProcessingConfiguration.bind(this._activeEffect);
  487. }
  488. this._afterBind(mesh, this._activeEffect);
  489. }
  490. private _createRenderTargets(scene: Scene, renderTargetSize: Vector2): void {
  491. // Render targets
  492. this._refractionRTT = new RenderTargetTexture(name + "_refraction", { width: renderTargetSize.x, height: renderTargetSize.y }, scene, false, true);
  493. this._refractionRTT.wrapU = Constants.TEXTURE_MIRROR_ADDRESSMODE;
  494. this._refractionRTT.wrapV = Constants.TEXTURE_MIRROR_ADDRESSMODE;
  495. this._refractionRTT.ignoreCameraViewport = true;
  496. this._reflectionRTT = new RenderTargetTexture(name + "_reflection", { width: renderTargetSize.x, height: renderTargetSize.y }, scene, false, true);
  497. this._reflectionRTT.wrapU = Constants.TEXTURE_MIRROR_ADDRESSMODE;
  498. this._reflectionRTT.wrapV = Constants.TEXTURE_MIRROR_ADDRESSMODE;
  499. this._reflectionRTT.ignoreCameraViewport = true;
  500. var isVisible: boolean;
  501. var clipPlane: Nullable<Plane> = null;
  502. var savedViewMatrix: Matrix;
  503. var mirrorMatrix = Matrix.Zero();
  504. this._refractionRTT.onBeforeRender = () => {
  505. if (this._mesh) {
  506. isVisible = this._mesh.isVisible;
  507. this._mesh.isVisible = false;
  508. }
  509. // Clip plane
  510. if (!this.disableClipPlane) {
  511. clipPlane = scene.clipPlane;
  512. var positiony = this._mesh ? this._mesh.position.y : 0.0;
  513. scene.clipPlane = Plane.FromPositionAndNormal(new Vector3(0, positiony + 0.05, 0), new Vector3(0, 1, 0));
  514. }
  515. };
  516. this._refractionRTT.onAfterRender = () => {
  517. if (this._mesh) {
  518. this._mesh.isVisible = isVisible;
  519. }
  520. // Clip plane
  521. if (!this.disableClipPlane) {
  522. scene.clipPlane = clipPlane;
  523. }
  524. };
  525. this._reflectionRTT.onBeforeRender = () => {
  526. if (this._mesh) {
  527. isVisible = this._mesh.isVisible;
  528. this._mesh.isVisible = false;
  529. }
  530. // Clip plane
  531. if (!this.disableClipPlane) {
  532. clipPlane = scene.clipPlane;
  533. var positiony = this._mesh ? this._mesh.position.y : 0.0;
  534. scene.clipPlane = Plane.FromPositionAndNormal(new Vector3(0, positiony - 0.05, 0), new Vector3(0, -1, 0));
  535. Matrix.ReflectionToRef(scene.clipPlane, mirrorMatrix);
  536. }
  537. // Transform
  538. savedViewMatrix = scene.getViewMatrix();
  539. mirrorMatrix.multiplyToRef(savedViewMatrix, this._reflectionTransform);
  540. scene.setTransformMatrix(this._reflectionTransform, scene.getProjectionMatrix());
  541. scene.getEngine().cullBackFaces = false;
  542. scene._mirroredCameraPosition = Vector3.TransformCoordinates((<Camera>scene.activeCamera).position, mirrorMatrix);
  543. };
  544. this._reflectionRTT.onAfterRender = () => {
  545. if (this._mesh) {
  546. this._mesh.isVisible = isVisible;
  547. }
  548. // Clip plane
  549. scene.clipPlane = clipPlane;
  550. // Transform
  551. scene.setTransformMatrix(savedViewMatrix, scene.getProjectionMatrix());
  552. scene.getEngine().cullBackFaces = true;
  553. scene._mirroredCameraPosition = null;
  554. };
  555. }
  556. public getAnimatables(): IAnimatable[] {
  557. var results = [];
  558. if (this.bumpTexture && this.bumpTexture.animations && this.bumpTexture.animations.length > 0) {
  559. results.push(this.bumpTexture);
  560. }
  561. if (this._reflectionRTT && this._reflectionRTT.animations && this._reflectionRTT.animations.length > 0) {
  562. results.push(this._reflectionRTT);
  563. }
  564. if (this._refractionRTT && this._refractionRTT.animations && this._refractionRTT.animations.length > 0) {
  565. results.push(this._refractionRTT);
  566. }
  567. return results;
  568. }
  569. public getActiveTextures(): BaseTexture[] {
  570. var activeTextures = super.getActiveTextures();
  571. if (this._bumpTexture) {
  572. activeTextures.push(this._bumpTexture);
  573. }
  574. return activeTextures;
  575. }
  576. public hasTexture(texture: BaseTexture): boolean {
  577. if (super.hasTexture(texture)) {
  578. return true;
  579. }
  580. if (this._bumpTexture === texture) {
  581. return true;
  582. }
  583. return false;
  584. }
  585. public dispose(forceDisposeEffect?: boolean): void {
  586. if (this.bumpTexture) {
  587. this.bumpTexture.dispose();
  588. }
  589. var index = this.getScene().customRenderTargets.indexOf(<RenderTargetTexture>this._refractionRTT);
  590. if (index != -1) {
  591. this.getScene().customRenderTargets.splice(index, 1);
  592. }
  593. index = -1;
  594. index = this.getScene().customRenderTargets.indexOf(<RenderTargetTexture>this._reflectionRTT);
  595. if (index != -1) {
  596. this.getScene().customRenderTargets.splice(index, 1);
  597. }
  598. if (this._reflectionRTT) {
  599. this._reflectionRTT.dispose();
  600. }
  601. if (this._refractionRTT) {
  602. this._refractionRTT.dispose();
  603. }
  604. // Remove image-processing observer
  605. if (this._imageProcessingConfiguration && this._imageProcessingObserver) {
  606. this._imageProcessingConfiguration.onUpdateParameters.remove(this._imageProcessingObserver);
  607. }
  608. super.dispose(forceDisposeEffect);
  609. }
  610. public clone(name: string): WaterMaterial {
  611. return SerializationHelper.Clone(() => new WaterMaterial(name, this.getScene()), this);
  612. }
  613. public serialize(): any {
  614. var serializationObject = SerializationHelper.Serialize(this);
  615. serializationObject.customType = "BABYLON.WaterMaterial";
  616. serializationObject.renderList = [];
  617. if (this._refractionRTT && this._refractionRTT.renderList) {
  618. for (var i = 0; i < this._refractionRTT.renderList.length; i++) {
  619. serializationObject.renderList.push(this._refractionRTT.renderList[i].id);
  620. }
  621. }
  622. return serializationObject;
  623. }
  624. public getClassName(): string {
  625. return "WaterMaterial";
  626. }
  627. // Statics
  628. public static Parse(source: any, scene: Scene, rootUrl: string): WaterMaterial {
  629. var mat = SerializationHelper.Parse(() => new WaterMaterial(source.name, scene), source, scene, rootUrl);
  630. mat._waitingRenderList = source.renderList;
  631. return mat;
  632. }
  633. public static CreateDefaultMesh(name: string, scene: Scene): Mesh {
  634. var mesh = Mesh.CreateGround(name, 512, 512, 32, scene, false);
  635. return mesh;
  636. }
  637. }
  638. _TypeStore.RegisteredTypes["BABYLON.WaterMaterial"] = WaterMaterial;