babylon.material.ts 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. module BABYLON {
  2. export class MaterialDefines {
  3. _keys: string[];
  4. public isEqual(other: MaterialDefines): boolean {
  5. for (var index = 0; index < this._keys.length; index++) {
  6. var prop = this._keys[index];
  7. if (this[prop] !== other[prop]) {
  8. return false;
  9. }
  10. }
  11. return true;
  12. }
  13. public cloneTo(other: MaterialDefines): void {
  14. for (var index = 0; index < this._keys.length; index++) {
  15. var prop = this._keys[index];
  16. other[prop] = this[prop];
  17. }
  18. }
  19. public reset(): void {
  20. for (var index = 0; index < this._keys.length; index++) {
  21. var prop = this._keys[index];
  22. if (typeof (this[prop]) === "number") {
  23. this[prop] = 0;
  24. } else {
  25. this[prop] = false;
  26. }
  27. }
  28. }
  29. public toString(): string {
  30. var result = "";
  31. for (var index = 0; index < this._keys.length; index++) {
  32. var prop = this._keys[index];
  33. if (typeof (this[prop]) === "number") {
  34. result += "#define " + prop + " " + this[prop] + "\n";
  35. } else if (this[prop]) {
  36. result += "#define " + prop + "\n";
  37. }
  38. }
  39. return result;
  40. }
  41. }
  42. export class Material {
  43. private static _TriangleFillMode = 0;
  44. private static _WireFrameFillMode = 1;
  45. private static _PointFillMode = 2;
  46. public static get TriangleFillMode(): number {
  47. return Material._TriangleFillMode;
  48. }
  49. public static get WireFrameFillMode(): number {
  50. return Material._WireFrameFillMode;
  51. }
  52. public static get PointFillMode(): number {
  53. return Material._PointFillMode;
  54. }
  55. private static _ClockWiseSideOrientation = 0;
  56. private static _CounterClockWiseSideOrientation = 1;
  57. public static get ClockWiseSideOrientation(): number {
  58. return Material._ClockWiseSideOrientation;
  59. }
  60. public static get CounterClockWiseSideOrientation(): number {
  61. return Material._CounterClockWiseSideOrientation;
  62. }
  63. public id: string;
  64. public checkReadyOnEveryCall = false;
  65. public checkReadyOnlyOnce = false;
  66. public state = "";
  67. public alpha = 1.0;
  68. public backFaceCulling = true;
  69. public sideOrientation = Material.CounterClockWiseSideOrientation;
  70. public onCompiled: (effect: Effect) => void;
  71. public onError: (effect: Effect, errors: string) => void;
  72. public onDispose: () => void;
  73. public onBind: (material: Material, mesh: Mesh) => void;
  74. public getRenderTargetTextures: () => SmartArray<RenderTargetTexture>;
  75. public alphaMode = Engine.ALPHA_COMBINE;
  76. public disableDepthWrite = false;
  77. public fogEnabled = true;
  78. public _effect: Effect;
  79. public _wasPreviouslyReady = false;
  80. private _scene: Scene;
  81. private _fillMode = Material.TriangleFillMode;
  82. private _cachedDepthWriteState: boolean;
  83. public pointSize = 1.0;
  84. public zOffset = 0;
  85. public get wireframe(): boolean {
  86. return this._fillMode === Material.WireFrameFillMode;
  87. }
  88. public set wireframe(value: boolean) {
  89. this._fillMode = (value ? Material.WireFrameFillMode : Material.TriangleFillMode);
  90. }
  91. public get pointsCloud(): boolean {
  92. return this._fillMode === Material.PointFillMode;
  93. }
  94. public set pointsCloud(value: boolean) {
  95. this._fillMode = (value ? Material.PointFillMode : Material.TriangleFillMode);
  96. }
  97. public get fillMode(): number {
  98. return this._fillMode;
  99. }
  100. public set fillMode(value: number) {
  101. this._fillMode = value;
  102. }
  103. constructor(public name: string, scene: Scene, doNotAdd?: boolean) {
  104. this.id = name;
  105. this._scene = scene;
  106. if (!doNotAdd) {
  107. scene.materials.push(this);
  108. }
  109. }
  110. public get isFrozen(): boolean {
  111. return this.checkReadyOnlyOnce;
  112. }
  113. public freeze(): void {
  114. this.checkReadyOnlyOnce = true;
  115. }
  116. public unfreeze(): void {
  117. this.checkReadyOnlyOnce = false;
  118. }
  119. public isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean {
  120. return true;
  121. }
  122. public getEffect(): Effect {
  123. return this._effect;
  124. }
  125. public getScene(): Scene {
  126. return this._scene;
  127. }
  128. public needAlphaBlending(): boolean {
  129. return (this.alpha < 1.0);
  130. }
  131. public needAlphaTesting(): boolean {
  132. return false;
  133. }
  134. public getAlphaTestTexture(): BaseTexture {
  135. return null;
  136. }
  137. public trackCreation(onCompiled: (effect: Effect) => void, onError: (effect: Effect, errors: string) => void) {
  138. }
  139. public markDirty(): void {
  140. this._wasPreviouslyReady = false;
  141. }
  142. public _preBind(): void {
  143. var engine = this._scene.getEngine();
  144. engine.enableEffect(this._effect);
  145. engine.setState(this.backFaceCulling, this.zOffset, false, this.sideOrientation === Material.ClockWiseSideOrientation);
  146. }
  147. public bind(world: Matrix, mesh?: Mesh): void {
  148. this._scene._cachedMaterial = this;
  149. if (this.onBind) {
  150. this.onBind(this, mesh);
  151. }
  152. if (this.disableDepthWrite) {
  153. var engine = this._scene.getEngine();
  154. this._cachedDepthWriteState = engine.getDepthWrite();
  155. engine.setDepthWrite(false);
  156. }
  157. }
  158. public bindOnlyWorldMatrix(world: Matrix): void {
  159. }
  160. public unbind(): void {
  161. if (this.disableDepthWrite) {
  162. var engine = this._scene.getEngine();
  163. engine.setDepthWrite(this._cachedDepthWriteState);
  164. }
  165. }
  166. public clone(name: string): Material {
  167. return null;
  168. }
  169. public getBindedMeshes(): AbstractMesh[] {
  170. var result = new Array<AbstractMesh>();
  171. for (var index = 0; index < this._scene.meshes.length; index++) {
  172. var mesh = this._scene.meshes[index];
  173. if (mesh.material === this) {
  174. result.push(mesh);
  175. }
  176. }
  177. return result;
  178. }
  179. public dispose(forceDisposeEffect?: boolean): void {
  180. // Animations
  181. this.getScene().stopAnimation(this);
  182. // Remove from scene
  183. var index = this._scene.materials.indexOf(this);
  184. if (index >= 0) {
  185. this._scene.materials.splice(index, 1);
  186. }
  187. // Shader are kept in cache for further use but we can get rid of this by using forceDisposeEffect
  188. if (forceDisposeEffect && this._effect) {
  189. this._scene.getEngine()._releaseEffect(this._effect);
  190. this._effect = null;
  191. }
  192. // Remove from meshes
  193. for (index = 0; index < this._scene.meshes.length; index++) {
  194. var mesh = this._scene.meshes[index];
  195. if (mesh.material === this) {
  196. mesh.material = null;
  197. }
  198. }
  199. // Callback
  200. if (this.onDispose) {
  201. this.onDispose();
  202. }
  203. }
  204. public copyTo(other: Material): void {
  205. other.checkReadyOnlyOnce = this.checkReadyOnlyOnce;
  206. other.checkReadyOnEveryCall = this.checkReadyOnEveryCall;
  207. other.alpha = this.alpha;
  208. other.fillMode = this.fillMode;
  209. other.backFaceCulling = this.backFaceCulling;
  210. other.fogEnabled = this.fogEnabled;
  211. other.wireframe = this.wireframe;
  212. other.zOffset = this.zOffset;
  213. other.alphaMode = this.alphaMode;
  214. other.sideOrientation = this.sideOrientation;
  215. other.disableDepthWrite = this.disableDepthWrite;
  216. other.pointSize = this.pointSize;
  217. other.pointsCloud = this.pointsCloud;
  218. }
  219. public serialize(): any {
  220. var serializationObject: any = {};
  221. serializationObject.name = this.name;
  222. serializationObject.alpha = this.alpha;
  223. serializationObject.id = this.id;
  224. serializationObject.tags = Tags.GetTags(this);
  225. serializationObject.backFaceCulling = this.backFaceCulling;
  226. serializationObject.checkReadyOnlyOnce = this.checkReadyOnlyOnce;
  227. serializationObject.disableDepthWrite = this.disableDepthWrite;
  228. return serializationObject;
  229. }
  230. public static ParseMultiMaterial(parsedMultiMaterial: any, scene: Scene): MultiMaterial {
  231. var multiMaterial = new BABYLON.MultiMaterial(parsedMultiMaterial.name, scene);
  232. multiMaterial.id = parsedMultiMaterial.id;
  233. Tags.AddTagsTo(multiMaterial, parsedMultiMaterial.tags);
  234. for (var matIndex = 0; matIndex < parsedMultiMaterial.materials.length; matIndex++) {
  235. var subMatId = parsedMultiMaterial.materials[matIndex];
  236. if (subMatId) {
  237. multiMaterial.subMaterials.push(scene.getMaterialByID(subMatId));
  238. } else {
  239. multiMaterial.subMaterials.push(null);
  240. }
  241. }
  242. return multiMaterial;
  243. }
  244. public static Parse(parsedMaterial: any, scene: Scene, rootUrl: string) {
  245. if (!parsedMaterial.customType) {
  246. return StandardMaterial.Parse(parsedMaterial, scene, rootUrl);
  247. }
  248. var materialType = Tools.Instantiate(parsedMaterial.customType);
  249. return materialType.Parse(parsedMaterial, scene, rootUrl);;
  250. }
  251. }
  252. }