babylon.standardMaterial.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  1. "use strict";
  2. var BABYLON = BABYLON || {};
  3. (function () {
  4. BABYLON.StandardMaterial = function (name, scene) {
  5. BABYLON.Material.call(this, name, scene);
  6. this.diffuseTexture = null;
  7. this.ambientTexture = null;
  8. this.opacityTexture = null;
  9. this.reflectionTexture = null;
  10. this.emissiveTexture = null;
  11. this.specularTexture = null;
  12. this.bumpTexture = null;
  13. this.ambientColor = new BABYLON.Color3(0, 0, 0);
  14. this.diffuseColor = new BABYLON.Color3(1, 1, 1);
  15. this.specularColor = new BABYLON.Color3(1, 1, 1);
  16. this.specularPower = 64;
  17. this.emissiveColor = new BABYLON.Color3(0, 0, 0);
  18. this._cachedDefines = null;
  19. this._renderTargets = new BABYLON.Tools.SmartArray(16);
  20. // Internals
  21. this._worldViewProjectionMatrix = BABYLON.Matrix.Zero();
  22. this._lightMatrix = BABYLON.Matrix.Zero();
  23. this._globalAmbientColor = new BABYLON.Color3(0, 0, 0);
  24. this._baseColor = new BABYLON.Color3();
  25. this._scaledDiffuse = new BABYLON.Color3();
  26. this._scaledSpecular = new BABYLON.Color3();
  27. };
  28. BABYLON.StandardMaterial.prototype = Object.create(BABYLON.Material.prototype);
  29. // Properties
  30. BABYLON.StandardMaterial.prototype.needAlphaBlending = function () {
  31. return (this.alpha < 1.0) || (this.opacityTexture != null);
  32. };
  33. BABYLON.StandardMaterial.prototype.needAlphaTesting = function () {
  34. return this.diffuseTexture != null && this.diffuseTexture.hasAlpha;
  35. };
  36. // Methods
  37. BABYLON.StandardMaterial.prototype.isReady = function (mesh) {
  38. if (this.checkReadyOnlyOnce) {
  39. if (this._wasPreviouslyReady) {
  40. return true;
  41. }
  42. }
  43. if (!this.checkReadyOnEveryCall) {
  44. if (this._renderId === this._scene.getRenderId()) {
  45. return true;
  46. }
  47. }
  48. var engine = this._scene.getEngine();
  49. var defines = [];
  50. var optionalDefines = [];
  51. // Textures
  52. if (this._scene.texturesEnabled) {
  53. if (this.diffuseTexture) {
  54. if (!this.diffuseTexture.isReady()) {
  55. return false;
  56. } else {
  57. defines.push("#define DIFFUSE");
  58. }
  59. }
  60. if (this.ambientTexture) {
  61. if (!this.ambientTexture.isReady()) {
  62. return false;
  63. } else {
  64. defines.push("#define AMBIENT");
  65. }
  66. }
  67. if (this.opacityTexture) {
  68. if (!this.opacityTexture.isReady()) {
  69. return false;
  70. } else {
  71. defines.push("#define OPACITY");
  72. }
  73. }
  74. if (this.reflectionTexture) {
  75. if (!this.reflectionTexture.isReady()) {
  76. return false;
  77. } else {
  78. defines.push("#define REFLECTION");
  79. }
  80. }
  81. if (this.emissiveTexture) {
  82. if (!this.emissiveTexture.isReady()) {
  83. return false;
  84. } else {
  85. defines.push("#define EMISSIVE");
  86. }
  87. }
  88. if (this.specularTexture) {
  89. if (!this.specularTexture.isReady()) {
  90. return false;
  91. } else {
  92. defines.push("#define SPECULAR");
  93. optionalDefines.push(defines[defines.length - 1]);
  94. }
  95. }
  96. }
  97. if (this._scene.getEngine().getCaps().standardDerivatives && this.bumpTexture) {
  98. if (!this.bumpTexture.isReady()) {
  99. return false;
  100. } else {
  101. defines.push("#define BUMP");
  102. optionalDefines.push(defines[defines.length - 1]);
  103. }
  104. }
  105. // Effect
  106. if (BABYLON.clipPlane) {
  107. defines.push("#define CLIPPLANE");
  108. }
  109. if (engine.getAlphaTesting()) {
  110. defines.push("#define ALPHATEST");
  111. }
  112. // Fog
  113. if (this._scene.fogMode !== BABYLON.Scene.FOGMODE_NONE) {
  114. defines.push("#define FOG");
  115. optionalDefines.push(defines[defines.length - 1]);
  116. }
  117. var shadowsActivated = false;
  118. var lightIndex = 0;
  119. if (this._scene.lightsEnabled) {
  120. for (var index = 0; index < this._scene.lights.length; index++) {
  121. var light = this._scene.lights[index];
  122. if (!light.isEnabled()) {
  123. continue;
  124. }
  125. if (mesh && light.excludedMeshes.indexOf(mesh) !== -1) {
  126. continue;
  127. }
  128. defines.push("#define LIGHT" + lightIndex);
  129. if (lightIndex > 0) {
  130. optionalDefines.push(defines[defines.length - 1]);
  131. }
  132. var type;
  133. if (light instanceof BABYLON.SpotLight) {
  134. type = "#define SPOTLIGHT" + lightIndex;
  135. } else if (light instanceof BABYLON.HemisphericLight) {
  136. type = "#define HEMILIGHT" + lightIndex;
  137. } else {
  138. type = "#define POINTDIRLIGHT" + lightIndex;
  139. }
  140. defines.push(type);
  141. if (lightIndex > 0) {
  142. optionalDefines.push(defines[defines.length - 1]);
  143. }
  144. // Shadows
  145. var shadowGenerator = light.getShadowGenerator();
  146. if (mesh && mesh.receiveShadows && shadowGenerator) {
  147. defines.push("#define SHADOW" + lightIndex);
  148. if (lightIndex > 0) {
  149. optionalDefines.push(defines[defines.length - 1]);
  150. }
  151. if (!shadowsActivated) {
  152. defines.push("#define SHADOWS");
  153. shadowsActivated = true;
  154. }
  155. if (shadowGenerator.useVarianceShadowMap) {
  156. defines.push("#define SHADOWVSM" + lightIndex);
  157. if (lightIndex > 0) {
  158. optionalDefines.push(defines[defines.length - 1]);
  159. }
  160. }
  161. }
  162. lightIndex++;
  163. if (lightIndex == 4)
  164. break;
  165. }
  166. }
  167. var attribs = [BABYLON.VertexBuffer.PositionKind, BABYLON.VertexBuffer.NormalKind];
  168. if (mesh) {
  169. if (mesh.isVerticesDataPresent(BABYLON.VertexBuffer.UVKind)) {
  170. attribs.push(BABYLON.VertexBuffer.UVKind);
  171. defines.push("#define UV1");
  172. }
  173. if (mesh.isVerticesDataPresent(BABYLON.VertexBuffer.UV2Kind)) {
  174. attribs.push(BABYLON.VertexBuffer.UV2Kind);
  175. defines.push("#define UV2");
  176. }
  177. if (mesh.isVerticesDataPresent(BABYLON.VertexBuffer.ColorKind)) {
  178. attribs.push(BABYLON.VertexBuffer.ColorKind);
  179. defines.push("#define VERTEXCOLOR");
  180. }
  181. if (mesh.skeleton && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind) && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind)) {
  182. attribs.push(BABYLON.VertexBuffer.MatricesIndicesKind);
  183. attribs.push(BABYLON.VertexBuffer.MatricesWeightsKind);
  184. defines.push("#define BONES");
  185. defines.push("#define BonesPerMesh " + mesh.skeleton.bones.length);
  186. defines.push("#define BONES4");
  187. optionalDefines.push(defines[defines.length - 1]);
  188. }
  189. }
  190. // Get correct effect
  191. var join = defines.join("\n");
  192. if (this._cachedDefines != join) {
  193. this._cachedDefines = join;
  194. // IE patch
  195. var shaderName = "default";
  196. if (BABYLON.Tools.isIE()) {
  197. shaderName = "iedefault";
  198. }
  199. this._effect = this._scene.getEngine().createEffect(shaderName,
  200. attribs,
  201. ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vAmbientColor", "vDiffuseColor", "vSpecularColor", "vEmissiveColor",
  202. "vLightData0", "vLightDiffuse0", "vLightSpecular0", "vLightDirection0", "vLightGround0", "lightMatrix0",
  203. "vLightData1", "vLightDiffuse1", "vLightSpecular1", "vLightDirection1", "vLightGround1", "lightMatrix1",
  204. "vLightData2", "vLightDiffuse2", "vLightSpecular2", "vLightDirection2", "vLightGround2", "lightMatrix2",
  205. "vLightData3", "vLightDiffuse3", "vLightSpecular3", "vLightDirection3", "vLightGround3", "lightMatrix3",
  206. "vFogInfos", "vFogColor",
  207. "vDiffuseInfos", "vAmbientInfos", "vOpacityInfos", "vReflectionInfos", "vEmissiveInfos", "vSpecularInfos", "vBumpInfos",
  208. "mBones",
  209. "vClipPlane", "diffuseMatrix", "ambientMatrix", "opacityMatrix", "reflectionMatrix", "emissiveMatrix", "specularMatrix", "bumpMatrix"],
  210. ["diffuseSampler", "ambientSampler", "opacitySampler", "reflectionCubeSampler", "reflection2DSampler", "emissiveSampler", "specularSampler", "bumpSampler",
  211. "shadowSampler0", "shadowSampler1", "shadowSampler2", "shadowSampler3"
  212. ],
  213. join, optionalDefines);
  214. }
  215. if (!this._effect.isReady()) {
  216. return false;
  217. }
  218. this._renderId = this._scene.getRenderId();
  219. this._wasPreviouslyReady = true;
  220. return true;
  221. };
  222. BABYLON.StandardMaterial.prototype.getRenderTargetTextures = function () {
  223. this._renderTargets.reset();
  224. if (this.reflectionTexture && this.reflectionTexture.isRenderTarget) {
  225. this._renderTargets.push(this.reflectionTexture);
  226. }
  227. return this._renderTargets;
  228. };
  229. BABYLON.StandardMaterial.prototype.unbind = function () {
  230. if (this.reflectionTexture && this.reflectionTexture.isRenderTarget) {
  231. this._effect.setTexture("reflection2DSampler", null);
  232. }
  233. };
  234. BABYLON.StandardMaterial.prototype.bind = function (world, mesh) {
  235. this._baseColor.copyFrom(this.diffuseColor);
  236. // Matrices
  237. this._effect.setMatrix("world", world);
  238. this._effect.setMatrix("viewProjection", this._scene.getTransformMatrix());
  239. // Bones
  240. if (mesh.skeleton && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesIndicesKind) && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.MatricesWeightsKind)) {
  241. this._effect.setMatrices("mBones", mesh.skeleton.getTransformMatrices());
  242. }
  243. // Textures
  244. if (this.diffuseTexture) {
  245. this._effect.setTexture("diffuseSampler", this.diffuseTexture);
  246. this._effect.setFloat2("vDiffuseInfos", this.diffuseTexture.coordinatesIndex, this.diffuseTexture.level);
  247. this._effect.setMatrix("diffuseMatrix", this.diffuseTexture._computeTextureMatrix());
  248. this._baseColor.copyFromFloats(1, 1, 1);
  249. }
  250. if (this.ambientTexture) {
  251. this._effect.setTexture("ambientSampler", this.ambientTexture);
  252. this._effect.setFloat2("vAmbientInfos", this.ambientTexture.coordinatesIndex, this.ambientTexture.level);
  253. this._effect.setMatrix("ambientMatrix", this.ambientTexture._computeTextureMatrix());
  254. }
  255. if (this.opacityTexture) {
  256. this._effect.setTexture("opacitySampler", this.opacityTexture);
  257. this._effect.setFloat2("vOpacityInfos", this.opacityTexture.coordinatesIndex, this.opacityTexture.level);
  258. this._effect.setMatrix("opacityMatrix", this.opacityTexture._computeTextureMatrix());
  259. }
  260. if (this.reflectionTexture) {
  261. if (this.reflectionTexture.isCube) {
  262. this._effect.setTexture("reflectionCubeSampler", this.reflectionTexture);
  263. } else {
  264. this._effect.setTexture("reflection2DSampler", this.reflectionTexture);
  265. }
  266. this._effect.setMatrix("reflectionMatrix", this.reflectionTexture._computeReflectionTextureMatrix());
  267. this._effect.setFloat3("vReflectionInfos", this.reflectionTexture.coordinatesMode, this.reflectionTexture.level, this.reflectionTexture.isCube ? 1 : 0);
  268. }
  269. if (this.emissiveTexture) {
  270. this._effect.setTexture("emissiveSampler", this.emissiveTexture);
  271. this._effect.setFloat2("vEmissiveInfos", this.emissiveTexture.coordinatesIndex, this.emissiveTexture.level);
  272. this._effect.setMatrix("emissiveMatrix", this.emissiveTexture._computeTextureMatrix());
  273. }
  274. if (this.specularTexture) {
  275. this._effect.setTexture("specularSampler", this.specularTexture);
  276. this._effect.setFloat2("vSpecularInfos", this.specularTexture.coordinatesIndex, this.specularTexture.level);
  277. this._effect.setMatrix("specularMatrix", this.specularTexture._computeTextureMatrix());
  278. }
  279. if (this.bumpTexture && this._scene.getEngine().getCaps().standardDerivatives) {
  280. this._effect.setTexture("bumpSampler", this.bumpTexture);
  281. this._effect.setFloat2("vBumpInfos", this.bumpTexture.coordinatesIndex, this.bumpTexture.level);
  282. this._effect.setMatrix("bumpMatrix", this.bumpTexture._computeTextureMatrix());
  283. }
  284. // Colors
  285. this._scene.ambientColor.multiplyToRef(this.ambientColor, this._globalAmbientColor);
  286. this._effect.setVector3("vEyePosition", this._scene.activeCamera.position);
  287. this._effect.setColor3("vAmbientColor", this._globalAmbientColor);
  288. this._effect.setColor4("vDiffuseColor", this._baseColor, this.alpha * mesh.visibility);
  289. this._effect.setColor4("vSpecularColor", this.specularColor, this.specularPower);
  290. this._effect.setColor3("vEmissiveColor", this.emissiveColor);
  291. if (this._scene.lightsEnabled) {
  292. var lightIndex = 0;
  293. for (var index = 0; index < this._scene.lights.length; index++) {
  294. var light = this._scene.lights[index];
  295. if (!light.isEnabled()) {
  296. continue;
  297. }
  298. if (mesh && light.excludedMeshes.indexOf(mesh) !== -1) {
  299. continue;
  300. }
  301. if (light instanceof BABYLON.PointLight) {
  302. // Point Light
  303. light.transferToEffect(this._effect, "vLightData" + lightIndex);
  304. } else if (light instanceof BABYLON.DirectionalLight) {
  305. // Directional Light
  306. light.transferToEffect(this._effect, "vLightData" + lightIndex);
  307. } else if (light instanceof BABYLON.SpotLight) {
  308. // Spot Light
  309. light.transferToEffect(this._effect, "vLightData" + lightIndex, "vLightDirection" + lightIndex);
  310. } else if (light instanceof BABYLON.HemisphericLight) {
  311. // Hemispheric Light
  312. light.transferToEffect(this._effect, "vLightData" + lightIndex, "vLightGround" + lightIndex);
  313. }
  314. light.diffuse.scaleToRef(light.intensity, this._scaledDiffuse);
  315. light.specular.scaleToRef(light.intensity, this._scaledSpecular);
  316. this._effect.setColor3("vLightDiffuse" + lightIndex, this._scaledDiffuse);
  317. this._effect.setColor3("vLightSpecular" + lightIndex, this._scaledSpecular);
  318. // Shadows
  319. var shadowGenerator = light.getShadowGenerator();
  320. if (mesh.receiveShadows && shadowGenerator) {
  321. world.multiplyToRef(shadowGenerator.getTransformMatrix(), this._lightMatrix);
  322. this._effect.setMatrix("lightMatrix" + lightIndex, this._lightMatrix);
  323. this._effect.setTexture("shadowSampler" + lightIndex, shadowGenerator.getShadowMap());
  324. }
  325. lightIndex++;
  326. if (lightIndex == 4)
  327. break;
  328. }
  329. }
  330. if (BABYLON.clipPlane) {
  331. this._effect.setFloat4("vClipPlane", BABYLON.clipPlane.normal.x, BABYLON.clipPlane.normal.y, BABYLON.clipPlane.normal.z, BABYLON.clipPlane.d);
  332. }
  333. // View
  334. if (this._scene.fogMode !== BABYLON.Scene.FOGMODE_NONE || this.reflectionTexture) {
  335. this._effect.setMatrix("view", this._scene.getViewMatrix());
  336. }
  337. // Fog
  338. if (this._scene.fogMode !== BABYLON.Scene.FOGMODE_NONE) {
  339. this._effect.setFloat4("vFogInfos", this._scene.fogMode, this._scene.fogStart, this._scene.fogEnd, this._scene.fogDensity);
  340. this._effect.setColor3("vFogColor", this._scene.fogColor);
  341. }
  342. };
  343. BABYLON.StandardMaterial.prototype.getAnimatables = function () {
  344. var results = [];
  345. if (this.diffuseTexture && this.diffuseTexture.animations && this.diffuseTexture.animations.length > 0) {
  346. results.push(this.diffuseTexture);
  347. }
  348. if (this.ambientTexture && this.ambientTexture.animations && this.ambientTexture.animations.length > 0) {
  349. results.push(this.ambientTexture);
  350. }
  351. if (this.opacityTexture && this.opacityTexture.animations && this.opacityTexture.animations.length > 0) {
  352. results.push(this.opacityTexture);
  353. }
  354. if (this.reflectionTexture && this.reflectionTexture.animations && this.reflectionTexture.animations.length > 0) {
  355. results.push(this.reflectionTexture);
  356. }
  357. if (this.emissiveTexture && this.emissiveTexture.animations && this.emissiveTexture.animations.length > 0) {
  358. results.push(this.emissiveTexture);
  359. }
  360. if (this.specularTexture && this.specularTexture.animations && this.specularTexture.animations.length > 0) {
  361. results.push(this.specularTexture);
  362. }
  363. if (this.bumpTexture && this.bumpTexture.animations && this.bumpTexture.animations.length > 0) {
  364. results.push(this.bumpTexture);
  365. }
  366. return results;
  367. };
  368. BABYLON.StandardMaterial.prototype.dispose = function () {
  369. if (this.diffuseTexture) {
  370. this.diffuseTexture.dispose();
  371. }
  372. if (this.ambientTexture) {
  373. this.ambientTexture.dispose();
  374. }
  375. if (this.opacityTexture) {
  376. this.opacityTexture.dispose();
  377. }
  378. if (this.reflectionTexture) {
  379. this.reflectionTexture.dispose();
  380. }
  381. if (this.emissiveTexture) {
  382. this.emissiveTexture.dispose();
  383. }
  384. if (this.specularTexture) {
  385. this.specularTexture.dispose();
  386. }
  387. if (this.bumpTexture) {
  388. this.bumpTexture.dispose();
  389. }
  390. this.baseDispose();
  391. };
  392. BABYLON.StandardMaterial.prototype.clone = function (name) {
  393. var newStandardMaterial = new BABYLON.StandardMaterial(name, this._scene);
  394. // Base material
  395. newStandardMaterial.checkReadyOnEveryCall = this.checkReadyOnEveryCall;
  396. newStandardMaterial.alpha = this.alpha;
  397. newStandardMaterial.wireframe = this.wireframe;
  398. newStandardMaterial.backFaceCulling = this.backFaceCulling;
  399. // Standard material
  400. if (this.diffuseTexture && this.diffuseTexture.clone) {
  401. newStandardMaterial.diffuseTexture = this.diffuseTexture.clone();
  402. }
  403. if (this.ambientTexture && this.ambientTexture.clone) {
  404. newStandardMaterial.ambientTexture = this.ambientTexture.clone();
  405. }
  406. if (this.opacityTexture && this.opacityTexture.clone) {
  407. newStandardMaterial.opacityTexture = this.opacityTexture.clone();
  408. }
  409. if (this.reflectionTexture && this.reflectionTexture.clone) {
  410. newStandardMaterial.reflectionTexture = this.reflectionTexture.clone();
  411. }
  412. if (this.emissiveTexture && this.emissiveTexture.clone) {
  413. newStandardMaterial.emissiveTexture = this.emissiveTexture.clone();
  414. }
  415. if (this.specularTexture && this.specularTexture.clone) {
  416. newStandardMaterial.specularTexture = this.specularTexture.clone();
  417. }
  418. if (this.bumpTexture && this.bumpTexture.clone) {
  419. newStandardMaterial.bumpTexture = this.bumpTexture.clone();
  420. }
  421. newStandardMaterial.ambientColor = this.ambientColor.clone();
  422. newStandardMaterial.diffuseColor = this.diffuseColor.clone();
  423. newStandardMaterial.specularColor = this.specularColor.clone();
  424. newStandardMaterial.specularPower = this.specularPower;
  425. newStandardMaterial.emissiveColor = this.emissiveColor.clone();
  426. return newStandardMaterial;
  427. };
  428. })();