babylon.standardMaterial.js 20 KB

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