babylon.furMaterial.ts 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601
  1. /// <reference path="../../../dist/preview release/babylon.d.ts"/>
  2. module BABYLON {
  3. var maxSimultaneousLights = 4;
  4. class FurMaterialDefines extends MaterialDefines {
  5. public DIFFUSE = false;
  6. public HEIGHTMAP = false;
  7. public CLIPPLANE = false;
  8. public ALPHATEST = false;
  9. public POINTSIZE = false;
  10. public FOG = false;
  11. public LIGHT0 = false;
  12. public LIGHT1 = false;
  13. public LIGHT2 = false;
  14. public LIGHT3 = false;
  15. public SPOTLIGHT0 = false;
  16. public SPOTLIGHT1 = false;
  17. public SPOTLIGHT2 = false;
  18. public SPOTLIGHT3 = false;
  19. public HEMILIGHT0 = false;
  20. public HEMILIGHT1 = false;
  21. public HEMILIGHT2 = false;
  22. public HEMILIGHT3 = false;
  23. public DIRLIGHT0 = false;
  24. public DIRLIGHT1 = false;
  25. public DIRLIGHT2 = false;
  26. public DIRLIGHT3 = false;
  27. public POINTLIGHT0 = false;
  28. public POINTLIGHT1 = false;
  29. public POINTLIGHT2 = false;
  30. public POINTLIGHT3 = false;
  31. public SHADOW0 = false;
  32. public SHADOW1 = false;
  33. public SHADOW2 = false;
  34. public SHADOW3 = false;
  35. public SHADOWS = false;
  36. public SHADOWVSM0 = false;
  37. public SHADOWVSM1 = false;
  38. public SHADOWVSM2 = false;
  39. public SHADOWVSM3 = false;
  40. public SHADOWPCF0 = false;
  41. public SHADOWPCF1 = false;
  42. public SHADOWPCF2 = false;
  43. public SHADOWPCF3 = false;
  44. public NORMAL = false;
  45. public UV1 = false;
  46. public UV2 = false;
  47. public VERTEXCOLOR = false;
  48. public VERTEXALPHA = false;
  49. public BONES = false;
  50. public BONES4 = false;
  51. public BonesPerMesh = 0;
  52. public INSTANCES = false;
  53. constructor() {
  54. super();
  55. this._keys = Object.keys(this);
  56. }
  57. }
  58. export class FurMaterial extends Material {
  59. public diffuseTexture: BaseTexture;
  60. public heightTexture: BaseTexture;
  61. public diffuseColor = new Color3(1, 1, 1);
  62. public furLength: number = 1;
  63. public furAngle: number = 0;
  64. public furColor = new Color3(0.44,0.21,0.02);
  65. public disableLighting = false;
  66. private _worldViewProjectionMatrix = Matrix.Zero();
  67. private _scaledDiffuse = new Color3(1.,1.,1.);
  68. private _renderId: number;
  69. private _defines = new FurMaterialDefines();
  70. private _cachedDefines = new FurMaterialDefines();
  71. constructor(name: string, scene: Scene) {
  72. super(name, scene);
  73. this._cachedDefines.BonesPerMesh = -1;
  74. }
  75. public needAlphaBlending(): boolean {
  76. return (this.alpha < 1.0);
  77. }
  78. public needAlphaTesting(): boolean {
  79. return false;
  80. }
  81. public getAlphaTestTexture(): BaseTexture {
  82. return null;
  83. }
  84. // Methods
  85. private _checkCache(scene: Scene, mesh?: AbstractMesh, useInstances?: boolean): boolean {
  86. if (!mesh) {
  87. return true;
  88. }
  89. if (this._defines.INSTANCES !== useInstances) {
  90. return false;
  91. }
  92. if (mesh._materialDefines && mesh._materialDefines.isEqual(this._defines)) {
  93. return true;
  94. }
  95. return false;
  96. }
  97. public isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean {
  98. if (this.checkReadyOnlyOnce) {
  99. if (this._wasPreviouslyReady) {
  100. return true;
  101. }
  102. }
  103. var scene = this.getScene();
  104. if (!this.checkReadyOnEveryCall) {
  105. if (this._renderId === scene.getRenderId()) {
  106. if (this._checkCache(scene, mesh, useInstances)) {
  107. return true;
  108. }
  109. }
  110. }
  111. var engine = scene.getEngine();
  112. var needNormals = false;
  113. var needUVs = false;
  114. this._defines.reset();
  115. // Textures
  116. if (scene.texturesEnabled) {
  117. if (this.diffuseTexture && StandardMaterial.DiffuseTextureEnabled) {
  118. if (!this.diffuseTexture.isReady()) {
  119. return false;
  120. } else {
  121. needUVs = true;
  122. this._defines.DIFFUSE = true;
  123. }
  124. }
  125. if (this.heightTexture) {
  126. if (!this.heightTexture.isReady()) {
  127. return false;
  128. } else {
  129. needUVs = true;
  130. this._defines.HEIGHTMAP = true;
  131. }
  132. }
  133. }
  134. // Effect
  135. if (scene.clipPlane) {
  136. this._defines.CLIPPLANE = true;
  137. }
  138. if (engine.getAlphaTesting()) {
  139. this._defines.ALPHATEST = true;
  140. }
  141. // Point size
  142. if (this.pointsCloud || scene.forcePointsCloud) {
  143. this._defines.POINTSIZE = true;
  144. }
  145. // Fog
  146. if (scene.fogEnabled && mesh && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE && this.fogEnabled) {
  147. this._defines.FOG = true;
  148. }
  149. var lightIndex = 0;
  150. if (scene.lightsEnabled && !this.disableLighting) {
  151. for (var index = 0; index < scene.lights.length; index++) {
  152. var light = scene.lights[index];
  153. if (!light.isEnabled()) {
  154. continue;
  155. }
  156. // Excluded check
  157. if (light._excludedMeshesIds.length > 0) {
  158. for (var excludedIndex = 0; excludedIndex < light._excludedMeshesIds.length; excludedIndex++) {
  159. var excludedMesh = scene.getMeshByID(light._excludedMeshesIds[excludedIndex]);
  160. if (excludedMesh) {
  161. light.excludedMeshes.push(excludedMesh);
  162. }
  163. }
  164. light._excludedMeshesIds = [];
  165. }
  166. // Included check
  167. if (light._includedOnlyMeshesIds.length > 0) {
  168. for (var includedOnlyIndex = 0; includedOnlyIndex < light._includedOnlyMeshesIds.length; includedOnlyIndex++) {
  169. var includedOnlyMesh = scene.getMeshByID(light._includedOnlyMeshesIds[includedOnlyIndex]);
  170. if (includedOnlyMesh) {
  171. light.includedOnlyMeshes.push(includedOnlyMesh);
  172. }
  173. }
  174. light._includedOnlyMeshesIds = [];
  175. }
  176. if (!light.canAffectMesh(mesh)) {
  177. continue;
  178. }
  179. needNormals = true;
  180. this._defines["LIGHT" + lightIndex] = true;
  181. var type;
  182. if (light instanceof SpotLight) {
  183. type = "SPOTLIGHT" + lightIndex;
  184. } else if (light instanceof HemisphericLight) {
  185. type = "HEMILIGHT" + lightIndex;
  186. } else if (light instanceof PointLight) {
  187. type = "POINTLIGHT" + lightIndex;
  188. } else {
  189. type = "DIRLIGHT" + lightIndex;
  190. }
  191. this._defines[type] = true;
  192. // Shadows
  193. if (scene.shadowsEnabled) {
  194. var shadowGenerator = light.getShadowGenerator();
  195. if (mesh && mesh.receiveShadows && shadowGenerator) {
  196. this._defines["SHADOW" + lightIndex] = true;
  197. this._defines.SHADOWS = true;
  198. if (shadowGenerator.useVarianceShadowMap || shadowGenerator.useBlurVarianceShadowMap) {
  199. this._defines["SHADOWVSM" + lightIndex] = true;
  200. }
  201. if (shadowGenerator.usePoissonSampling) {
  202. this._defines["SHADOWPCF" + lightIndex] = true;
  203. }
  204. }
  205. }
  206. lightIndex++;
  207. if (lightIndex === maxSimultaneousLights)
  208. break;
  209. }
  210. }
  211. // Attribs
  212. if (mesh) {
  213. if (needNormals && mesh.isVerticesDataPresent(VertexBuffer.NormalKind)) {
  214. this._defines.NORMAL = true;
  215. }
  216. if (needUVs) {
  217. if (mesh.isVerticesDataPresent(VertexBuffer.UVKind)) {
  218. this._defines.UV1 = true;
  219. }
  220. if (mesh.isVerticesDataPresent(VertexBuffer.UV2Kind)) {
  221. this._defines.UV2 = true;
  222. }
  223. }
  224. if (mesh.useVertexColors && mesh.isVerticesDataPresent(VertexBuffer.ColorKind)) {
  225. this._defines.VERTEXCOLOR = true;
  226. if (mesh.hasVertexAlpha) {
  227. this._defines.VERTEXALPHA = true;
  228. }
  229. }
  230. if (mesh.useBones && mesh.computeBonesUsingShaders) {
  231. this._defines.BONES = true;
  232. this._defines.BonesPerMesh = (mesh.skeleton.bones.length + 1);
  233. this._defines.BONES4 = true;
  234. }
  235. // Instances
  236. if (useInstances) {
  237. this._defines.INSTANCES = true;
  238. }
  239. }
  240. // Get correct effect
  241. if (!this._defines.isEqual(this._cachedDefines)) {
  242. this._defines.cloneTo(this._cachedDefines);
  243. scene.resetCachedMaterial();
  244. // Fallbacks
  245. var fallbacks = new EffectFallbacks();
  246. if (this._defines.FOG) {
  247. fallbacks.addFallback(1, "FOG");
  248. }
  249. for (lightIndex = 0; lightIndex < maxSimultaneousLights; lightIndex++) {
  250. if (!this._defines["LIGHT" + lightIndex]) {
  251. continue;
  252. }
  253. if (lightIndex > 0) {
  254. fallbacks.addFallback(lightIndex, "LIGHT" + lightIndex);
  255. }
  256. if (this._defines["SHADOW" + lightIndex]) {
  257. fallbacks.addFallback(0, "SHADOW" + lightIndex);
  258. }
  259. if (this._defines["SHADOWPCF" + lightIndex]) {
  260. fallbacks.addFallback(0, "SHADOWPCF" + lightIndex);
  261. }
  262. if (this._defines["SHADOWVSM" + lightIndex]) {
  263. fallbacks.addFallback(0, "SHADOWVSM" + lightIndex);
  264. }
  265. }
  266. if (this._defines.BONES4) {
  267. fallbacks.addFallback(0, "BONES4");
  268. }
  269. //Attributes
  270. var attribs = [VertexBuffer.PositionKind];
  271. if (this._defines.NORMAL) {
  272. attribs.push(VertexBuffer.NormalKind);
  273. }
  274. if (this._defines.UV1) {
  275. attribs.push(VertexBuffer.UVKind);
  276. }
  277. if (this._defines.UV2) {
  278. attribs.push(VertexBuffer.UV2Kind);
  279. }
  280. if (this._defines.VERTEXCOLOR) {
  281. attribs.push(VertexBuffer.ColorKind);
  282. }
  283. if (this._defines.BONES) {
  284. attribs.push(VertexBuffer.MatricesIndicesKind);
  285. attribs.push(VertexBuffer.MatricesWeightsKind);
  286. }
  287. if (this._defines.INSTANCES) {
  288. attribs.push("world0");
  289. attribs.push("world1");
  290. attribs.push("world2");
  291. attribs.push("world3");
  292. }
  293. // Legacy browser patch
  294. var shaderName = "fur";
  295. var join = this._defines.toString();
  296. this._effect = scene.getEngine().createEffect(shaderName,
  297. attribs,
  298. ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vDiffuseColor",
  299. "vLightData0", "vLightDiffuse0", "vLightSpecular0", "vLightDirection0", "vLightGround0", "lightMatrix0",
  300. "vLightData1", "vLightDiffuse1", "vLightSpecular1", "vLightDirection1", "vLightGround1", "lightMatrix1",
  301. "vLightData2", "vLightDiffuse2", "vLightSpecular2", "vLightDirection2", "vLightGround2", "lightMatrix2",
  302. "vLightData3", "vLightDiffuse3", "vLightSpecular3", "vLightDirection3", "vLightGround3", "lightMatrix3",
  303. "vFogInfos", "vFogColor", "pointSize",
  304. "vDiffuseInfos",
  305. "mBones",
  306. "vClipPlane", "diffuseMatrix",
  307. "shadowsInfo0", "shadowsInfo1", "shadowsInfo2", "shadowsInfo3",
  308. "furLength", "furAngle", "furColor"
  309. ],
  310. ["diffuseSampler",
  311. "shadowSampler0", "shadowSampler1", "shadowSampler2", "shadowSampler3",
  312. "heightTexture"
  313. ],
  314. join, fallbacks, this.onCompiled, this.onError);
  315. }
  316. if (!this._effect.isReady()) {
  317. return false;
  318. }
  319. this._renderId = scene.getRenderId();
  320. this._wasPreviouslyReady = true;
  321. if (mesh) {
  322. if (!mesh._materialDefines) {
  323. mesh._materialDefines = new FurMaterialDefines();
  324. }
  325. this._defines.cloneTo(mesh._materialDefines);
  326. }
  327. return true;
  328. }
  329. public bindOnlyWorldMatrix(world: Matrix): void {
  330. this._effect.setMatrix("world", world);
  331. }
  332. public bind(world: Matrix, mesh?: Mesh): void {
  333. var scene = this.getScene();
  334. // Matrices
  335. this.bindOnlyWorldMatrix(world);
  336. this._effect.setMatrix("viewProjection", scene.getTransformMatrix());
  337. // Bones
  338. if (mesh && mesh.useBones && mesh.computeBonesUsingShaders) {
  339. this._effect.setMatrices("mBones", mesh.skeleton.getTransformMatrices());
  340. }
  341. if (scene.getCachedMaterial() !== this) {
  342. // Textures
  343. if (this.diffuseTexture && StandardMaterial.DiffuseTextureEnabled) {
  344. this._effect.setTexture("diffuseSampler", this.diffuseTexture);
  345. this._effect.setFloat2("vDiffuseInfos", this.diffuseTexture.coordinatesIndex, this.diffuseTexture.level);
  346. this._effect.setMatrix("diffuseMatrix", this.diffuseTexture.getTextureMatrix());
  347. }
  348. if (this.heightTexture) {
  349. this._effect.setTexture("heightTexture", this.heightTexture);
  350. }
  351. // Clip plane
  352. if (scene.clipPlane) {
  353. var clipPlane = scene.clipPlane;
  354. this._effect.setFloat4("vClipPlane", clipPlane.normal.x, clipPlane.normal.y, clipPlane.normal.z, clipPlane.d);
  355. }
  356. // Point size
  357. if (this.pointsCloud) {
  358. this._effect.setFloat("pointSize", this.pointSize);
  359. }
  360. this._effect.setVector3("vEyePosition", scene._mirroredCameraPosition ? scene._mirroredCameraPosition : scene.activeCamera.position);
  361. }
  362. this._effect.setColor4("vDiffuseColor", this._scaledDiffuse, this.alpha * mesh.visibility);
  363. if (scene.lightsEnabled && !this.disableLighting) {
  364. var lightIndex = 0;
  365. for (var index = 0; index < scene.lights.length; index++) {
  366. var light = scene.lights[index];
  367. if (!light.isEnabled()) {
  368. continue;
  369. }
  370. if (!light.canAffectMesh(mesh)) {
  371. continue;
  372. }
  373. if (light instanceof PointLight) {
  374. // Point Light
  375. light.transferToEffect(this._effect, "vLightData" + lightIndex);
  376. } else if (light instanceof DirectionalLight) {
  377. // Directional Light
  378. light.transferToEffect(this._effect, "vLightData" + lightIndex);
  379. } else if (light instanceof SpotLight) {
  380. // Spot Light
  381. light.transferToEffect(this._effect, "vLightData" + lightIndex, "vLightDirection" + lightIndex);
  382. } else if (light instanceof HemisphericLight) {
  383. // Hemispheric Light
  384. light.transferToEffect(this._effect, "vLightData" + lightIndex, "vLightGround" + lightIndex);
  385. }
  386. light.diffuse.scaleToRef(light.intensity, this._scaledDiffuse);
  387. this._effect.setColor4("vLightDiffuse" + lightIndex, this._scaledDiffuse, light.range);
  388. // Shadows
  389. if (scene.shadowsEnabled) {
  390. var shadowGenerator = light.getShadowGenerator();
  391. if (mesh.receiveShadows && shadowGenerator) {
  392. this._effect.setMatrix("lightMatrix" + lightIndex, shadowGenerator.getTransformMatrix());
  393. this._effect.setTexture("shadowSampler" + lightIndex, shadowGenerator.getShadowMapForRendering());
  394. this._effect.setFloat3("shadowsInfo" + lightIndex, shadowGenerator.getDarkness(), shadowGenerator.getShadowMap().getSize().width, shadowGenerator.bias);
  395. }
  396. }
  397. lightIndex++;
  398. if (lightIndex === maxSimultaneousLights)
  399. break;
  400. }
  401. }
  402. // View
  403. if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE) {
  404. this._effect.setMatrix("view", scene.getViewMatrix());
  405. }
  406. // Fog
  407. if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE) {
  408. this._effect.setFloat4("vFogInfos", scene.fogMode, scene.fogStart, scene.fogEnd, scene.fogDensity);
  409. this._effect.setColor3("vFogColor", scene.fogColor);
  410. }
  411. this._effect.setFloat("furLength", this.furLength);
  412. this._effect.setFloat("furAngle", this.furAngle);
  413. this._effect.setColor4("furColor", this.furColor, 1.0);
  414. super.bind(world, mesh);
  415. }
  416. public getAnimatables(): IAnimatable[] {
  417. var results = [];
  418. if (this.diffuseTexture && this.diffuseTexture.animations && this.diffuseTexture.animations.length > 0) {
  419. results.push(this.diffuseTexture);
  420. }
  421. if (this.heightTexture && this.heightTexture.animations && this.heightTexture.animations.length > 0) {
  422. results.push(this.heightTexture);
  423. }
  424. return results;
  425. }
  426. public dispose(forceDisposeEffect?: boolean): void {
  427. if (this.diffuseTexture) {
  428. this.diffuseTexture.dispose();
  429. }
  430. super.dispose(forceDisposeEffect);
  431. }
  432. public clone(name: string): FurMaterial {
  433. var newMaterial = new FurMaterial(name, this.getScene());
  434. // Base material
  435. this.copyTo(newMaterial);
  436. // Fur material
  437. if (this.diffuseTexture && this.diffuseTexture.clone) {
  438. newMaterial.diffuseTexture = this.diffuseTexture.clone();
  439. }
  440. if (this.heightTexture && this.heightTexture.clone) {
  441. newMaterial.heightTexture = this.heightTexture.clone();
  442. }
  443. if (this.diffuseColor && this.diffuseColor.clone) {
  444. newMaterial.diffuseColor = this.diffuseColor.clone();
  445. }
  446. return newMaterial;
  447. }
  448. public serialize(): any {
  449. var serializationObject = super.serialize();
  450. serializationObject.customType = "BABYLON.FurMaterial";
  451. serializationObject.diffuseColor = this.diffuseColor.asArray();
  452. serializationObject.disableLighting = this.disableLighting;
  453. serializationObject.furLength = this.furLength;
  454. serializationObject.furAngle = this.furAngle;
  455. serializationObject.furColor = this.furColor.asArray();
  456. if (this.diffuseTexture) {
  457. serializationObject.diffuseTexture = this.diffuseTexture.serialize();
  458. }
  459. if (this.heightTexture) {
  460. serializationObject.heightTexture = this.heightTexture.serialize();
  461. }
  462. return serializationObject;
  463. }
  464. public static Parse(source: any, scene: Scene, rootUrl: string): FurMaterial {
  465. var material = new FurMaterial(source.name, scene);
  466. material.diffuseColor = Color3.FromArray(source.diffuseColor);
  467. material.furLength = source.furLength;
  468. material.furAngle = source.furAngle;
  469. material.furColor = Color3.FromArray(source.furColor);
  470. material.disableLighting = source.disableLighting;
  471. material.alpha = source.alpha;
  472. material.id = source.id;
  473. Tags.AddTagsTo(material, source.tags);
  474. material.backFaceCulling = source.backFaceCulling;
  475. material.wireframe = source.wireframe;
  476. if (source.diffuseTexture) {
  477. material.diffuseTexture = Texture.Parse(source.diffuseTexture, scene, rootUrl);
  478. }
  479. if (source.heightTexture) {
  480. material.heightTexture = Texture.Parse(source.heightTexture, scene, rootUrl);
  481. }
  482. if (source.checkReadyOnlyOnce) {
  483. material.checkReadyOnlyOnce = source.checkReadyOnlyOnce;
  484. }
  485. return material;
  486. }
  487. }
  488. }