babylon.standardMaterial.js 21 KB

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