babylon.shaderMaterial.ts 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. module BABYLON {
  2. export class ShaderMaterial extends Material {
  3. private _shaderPath: any;
  4. private _options: any;
  5. private _textures = new Array<Texture>();
  6. private _floats = new Array<number>();
  7. private _floatsArrays = {};
  8. private _colors3 = new Array<Color3>();
  9. private _colors4 = new Array<Color4>();
  10. private _vectors2 = new Array<Vector2>();
  11. private _vectors3 = new Array<Vector3>();
  12. private _matrices = new Array<Matrix>();
  13. private _cachedWorldViewMatrix = new BABYLON.Matrix();
  14. private _renderId: number;
  15. constructor(name: string, scene: Scene, shaderPath: any, options: any) {
  16. super(name, scene);
  17. this._shaderPath = shaderPath;
  18. options.needAlphaBlending = options.needAlphaBlending || false;
  19. options.needAlphaTesting = options.needAlphaTesting || false;
  20. options.attributes = options.attributes || ["position", "normal", "uv"];
  21. options.uniforms = options.uniforms || ["worldViewProjection"];
  22. options.samplers = options.samplers || [];
  23. this._options = options;
  24. }
  25. public needAlphaBlending(): boolean {
  26. return this._options.needAlphaBlending;
  27. }
  28. public needAlphaTesting(): boolean {
  29. return this._options.needAlphaTesting;
  30. }
  31. private _checkUniform(uniformName): void {
  32. if (this._options.uniforms.indexOf(uniformName) === -1) {
  33. this._options.uniforms.push(uniformName);
  34. }
  35. }
  36. public setTexture(name: string, texture: Texture): ShaderMaterial {
  37. if (this._options.samplers.indexOf(name) === -1) {
  38. this._options.samplers.push(name);
  39. }
  40. this._textures[name] = texture;
  41. return this;
  42. }
  43. public setFloat(name: string, value: number): ShaderMaterial {
  44. this._checkUniform(name);
  45. this._floats[name] = value;
  46. return this;
  47. }
  48. public setFloats(name: string, value: number[]): ShaderMaterial {
  49. this._checkUniform(name);
  50. this._floatsArrays[name] = value;
  51. return this;
  52. }
  53. public setColor3(name: string, value: Color3): ShaderMaterial {
  54. this._checkUniform(name);
  55. this._colors3[name] = value;
  56. return this;
  57. }
  58. public setColor4(name: string, value: Color4): ShaderMaterial {
  59. this._checkUniform(name);
  60. this._colors4[name] = value;
  61. return this;
  62. }
  63. public setVector2(name: string, value: Vector2): ShaderMaterial {
  64. this._checkUniform(name);
  65. this._vectors2[name] = value;
  66. return this;
  67. }
  68. public setVector3(name: string, value: Vector3): ShaderMaterial {
  69. this._checkUniform(name);
  70. this._vectors3[name] = value;
  71. return this;
  72. }
  73. public setMatrix(name: string, value: Matrix): ShaderMaterial {
  74. this._checkUniform(name);
  75. this._matrices[name] = value;
  76. return this;
  77. }
  78. public isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean {
  79. var scene = this.getScene();
  80. var engine = scene.getEngine();
  81. if (!this.checkReadyOnEveryCall) {
  82. if (this._renderId === scene.getRenderId()) {
  83. return true;
  84. }
  85. }
  86. // Instances
  87. var defines = [];
  88. var fallbacks = new EffectFallbacks();
  89. if (useInstances) {
  90. defines.push("#define INSTANCES");
  91. }
  92. // Bones
  93. if (mesh && mesh.useBones) {
  94. defines.push("#define BONES");
  95. defines.push("#define BonesPerMesh " + (mesh.skeleton.bones.length + 1));
  96. defines.push("#define BONES4");
  97. fallbacks.addFallback(0, "BONES4");
  98. }
  99. // Alpha test
  100. if (engine.getAlphaTesting()) {
  101. defines.push("#define ALPHATEST");
  102. }
  103. var previousEffect = this._effect;
  104. var join = defines.join("\n");
  105. this._effect = engine.createEffect(this._shaderPath,
  106. this._options.attributes,
  107. this._options.uniforms,
  108. this._options.samplers,
  109. join, fallbacks, this.onCompiled, this.onError);
  110. if (!this._effect.isReady()) {
  111. return false;
  112. }
  113. if (previousEffect !== this._effect) {
  114. scene.resetCachedMaterial();
  115. }
  116. this._renderId = scene.getRenderId();
  117. return true;
  118. }
  119. public bindOnlyWorldMatrix(world: Matrix): void {
  120. var scene = this.getScene();
  121. if (this._options.uniforms.indexOf("world") !== -1) {
  122. this._effect.setMatrix("world", world);
  123. }
  124. if (this._options.uniforms.indexOf("worldView") !== -1) {
  125. world.multiplyToRef(scene.getViewMatrix(), this._cachedWorldViewMatrix);
  126. this._effect.setMatrix("worldView", this._cachedWorldViewMatrix);
  127. }
  128. if (this._options.uniforms.indexOf("worldViewProjection") !== -1) {
  129. this._effect.setMatrix("worldViewProjection", world.multiply(scene.getTransformMatrix()));
  130. }
  131. }
  132. public bind(world: Matrix, mesh?: Mesh): void {
  133. // Std values
  134. this.bindOnlyWorldMatrix(world);
  135. if (this.getScene().getCachedMaterial() !== this) {
  136. if (this._options.uniforms.indexOf("view") !== -1) {
  137. this._effect.setMatrix("view", this.getScene().getViewMatrix());
  138. }
  139. if (this._options.uniforms.indexOf("projection") !== -1) {
  140. this._effect.setMatrix("projection", this.getScene().getProjectionMatrix());
  141. }
  142. if (this._options.uniforms.indexOf("viewProjection") !== -1) {
  143. this._effect.setMatrix("viewProjection", this.getScene().getTransformMatrix());
  144. }
  145. // Bones
  146. if (mesh.useBones) {
  147. this._effect.setMatrices("mBones", mesh.skeleton.getTransformMatrices());
  148. }
  149. // Texture
  150. for (var name in this._textures) {
  151. this._effect.setTexture(name, this._textures[name]);
  152. }
  153. // Float
  154. for (name in this._floats) {
  155. this._effect.setFloat(name, this._floats[name]);
  156. }
  157. // Float s
  158. for (name in this._floatsArrays) {
  159. this._effect.setArray(name, this._floatsArrays[name]);
  160. }
  161. // Color3
  162. for (name in this._colors3) {
  163. this._effect.setColor3(name, this._colors3[name]);
  164. }
  165. // Color4
  166. for (name in this._colors4) {
  167. var color = this._colors4[name];
  168. this._effect.setFloat4(name, color.r, color.g, color.b, color.a);
  169. }
  170. // Vector2
  171. for (name in this._vectors2) {
  172. this._effect.setVector2(name, this._vectors2[name]);
  173. }
  174. // Vector3
  175. for (name in this._vectors3) {
  176. this._effect.setVector3(name, this._vectors3[name]);
  177. }
  178. // Matrix
  179. for (name in this._matrices) {
  180. this._effect.setMatrix(name, this._matrices[name]);
  181. }
  182. }
  183. super.bind(world, mesh);
  184. }
  185. public dispose(forceDisposeEffect?: boolean): void {
  186. for (var name in this._textures) {
  187. this._textures[name].dispose();
  188. }
  189. this._textures = [];
  190. super.dispose(forceDisposeEffect);
  191. }
  192. }
  193. }