customMaterial.ts 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. import { Texture } from "babylonjs/Materials/Textures/texture";
  2. import { Effect } from "babylonjs/Materials/effect";
  3. import { MaterialDefines } from "babylonjs/Materials/materialDefines";
  4. import { StandardMaterial } from "babylonjs/Materials/standardMaterial";
  5. import { Mesh } from "babylonjs/Meshes/mesh";
  6. import { Scene } from "babylonjs/scene";
  7. import { _TypeStore } from 'babylonjs/Misc/typeStore';
  8. export class CustomShaderStructure {
  9. public FragmentStore: string;
  10. public VertexStore: string;
  11. constructor() { }
  12. }
  13. export class ShaderSpecialParts {
  14. constructor() { }
  15. public Fragment_Begin: string;
  16. public Fragment_Definitions: string;
  17. public Fragment_MainBegin: string;
  18. // diffuseColor
  19. public Fragment_Custom_Diffuse: string;
  20. // lights
  21. public Fragment_Before_Lights: string;
  22. // fog
  23. public Fragment_Before_Fog: string;
  24. // alpha
  25. public Fragment_Custom_Alpha: string;
  26. public Fragment_Before_FragColor: string;
  27. public Vertex_Begin: string;
  28. public Vertex_Definitions: string;
  29. public Vertex_MainBegin: string;
  30. // positionUpdated
  31. public Vertex_Before_PositionUpdated: string;
  32. // normalUpdated
  33. public Vertex_Before_NormalUpdated: string;
  34. // worldPosComputed
  35. public Vertex_After_WorldPosComputed: string;
  36. // mainEnd
  37. public Vertex_MainEnd: string;
  38. }
  39. export class CustomMaterial extends StandardMaterial {
  40. public static ShaderIndexer = 1;
  41. public CustomParts: ShaderSpecialParts;
  42. _isCreatedShader: boolean;
  43. _createdShaderName: string;
  44. _customUniform: string[];
  45. _newUniforms: string[];
  46. _newUniformInstances: any[];
  47. _newSamplerInstances: Texture[];
  48. _customAttributes: string[];
  49. public FragmentShader: string;
  50. public VertexShader: string;
  51. public AttachAfterBind(mesh: Mesh, effect: Effect) {
  52. for (var el in this._newUniformInstances) {
  53. var ea = el.toString().split('-');
  54. if (ea[0] == 'vec2') {
  55. effect.setVector2(ea[1], this._newUniformInstances[el]);
  56. }
  57. else if (ea[0] == 'vec3') {
  58. effect.setVector3(ea[1], this._newUniformInstances[el]);
  59. }
  60. else if (ea[0] == 'vec4') {
  61. effect.setVector4(ea[1], this._newUniformInstances[el]);
  62. }
  63. else if (ea[0] == 'mat4') {
  64. effect.setMatrix(ea[1], this._newUniformInstances[el]);
  65. }
  66. else if (ea[0] == 'float') {
  67. effect.setFloat(ea[1], this._newUniformInstances[el]);
  68. }
  69. }
  70. for (var el in this._newSamplerInstances) {
  71. var ea = el.toString().split('-');
  72. if (ea[0] == 'sampler2D' && this._newSamplerInstances[el].isReady && this._newSamplerInstances[el].isReady()) {
  73. effect.setTexture(ea[1], this._newSamplerInstances[el]);
  74. }
  75. }
  76. }
  77. public ReviewUniform(name: string, arr: string[]): string[] {
  78. if (name == "uniform") {
  79. for (var ind = 0; ind < this._newUniforms.length ; ind ++) {
  80. if (this._customUniform[ind].indexOf('sampler') == -1) {
  81. arr.push(this._newUniforms[ind]);
  82. }
  83. }
  84. }
  85. if (name == "sampler") {
  86. for (var ind = 0; ind < this._newUniforms.length ; ind ++) {
  87. if (this._customUniform[ind].indexOf('sampler') != -1) {
  88. arr.push(this._newUniforms[ind]);
  89. }
  90. }
  91. }
  92. return arr;
  93. }
  94. public Builder(shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: MaterialDefines | string[], attributes?: string[]): string {
  95. if (attributes && this._customAttributes && this._customAttributes.length > 0) {
  96. attributes.push(...this._customAttributes);
  97. }
  98. this.ReviewUniform("uniform", uniforms);
  99. this.ReviewUniform("sampler", samplers);
  100. if (this._isCreatedShader) {
  101. return this._createdShaderName;
  102. }
  103. this._isCreatedShader = false;
  104. CustomMaterial.ShaderIndexer++;
  105. var name: string = "custom_" + CustomMaterial.ShaderIndexer;
  106. var fn_afterBind = this._afterBind.bind(this);
  107. this._afterBind = (m, e) => {
  108. if (!e) {
  109. return;
  110. }
  111. this.AttachAfterBind(m, e);
  112. try { fn_afterBind(m, e); }
  113. catch (e) { }
  114. };
  115. Effect.ShadersStore[name + "VertexShader"] = this.VertexShader
  116. .replace('#define CUSTOM_VERTEX_BEGIN', (this.CustomParts.Vertex_Begin ? this.CustomParts.Vertex_Begin : ""))
  117. .replace('#define CUSTOM_VERTEX_DEFINITIONS', (this._customUniform ? this._customUniform.join("\n") : "") + (this.CustomParts.Vertex_Definitions ? this.CustomParts.Vertex_Definitions : ""))
  118. .replace('#define CUSTOM_VERTEX_MAIN_BEGIN', (this.CustomParts.Vertex_MainBegin ? this.CustomParts.Vertex_MainBegin : ""))
  119. .replace('#define CUSTOM_VERTEX_UPDATE_POSITION', (this.CustomParts.Vertex_Before_PositionUpdated ? this.CustomParts.Vertex_Before_PositionUpdated : ""))
  120. .replace('#define CUSTOM_VERTEX_UPDATE_NORMAL', (this.CustomParts.Vertex_Before_NormalUpdated ? this.CustomParts.Vertex_Before_NormalUpdated : ""))
  121. .replace('#define CUSTOM_VERTEX_MAIN_END', (this.CustomParts.Vertex_MainEnd ? this.CustomParts.Vertex_MainEnd : ""));
  122. if (this.CustomParts.Vertex_After_WorldPosComputed) {
  123. Effect.ShadersStore[name + "VertexShader"] = Effect.ShadersStore[name + "VertexShader"].replace('#define CUSTOM_VERTEX_UPDATE_WORLDPOS', this.CustomParts.Vertex_After_WorldPosComputed);
  124. }
  125. Effect.ShadersStore[name + "PixelShader"] = this.FragmentShader
  126. .replace('#define CUSTOM_FRAGMENT_BEGIN', (this.CustomParts.Fragment_Begin ? this.CustomParts.Fragment_Begin : ""))
  127. .replace('#define CUSTOM_FRAGMENT_MAIN_BEGIN', (this.CustomParts.Fragment_MainBegin ? this.CustomParts.Fragment_MainBegin : ""))
  128. .replace('#define CUSTOM_FRAGMENT_DEFINITIONS', (this._customUniform ? this._customUniform.join("\n") : "") + (this.CustomParts.Fragment_Definitions ? this.CustomParts.Fragment_Definitions : ""))
  129. .replace('#define CUSTOM_FRAGMENT_UPDATE_DIFFUSE', (this.CustomParts.Fragment_Custom_Diffuse ? this.CustomParts.Fragment_Custom_Diffuse : ""))
  130. .replace('#define CUSTOM_FRAGMENT_UPDATE_ALPHA', (this.CustomParts.Fragment_Custom_Alpha ? this.CustomParts.Fragment_Custom_Alpha : ""))
  131. .replace('#define CUSTOM_FRAGMENT_BEFORE_LIGHTS', (this.CustomParts.Fragment_Before_Lights ? this.CustomParts.Fragment_Before_Lights : ""))
  132. .replace('#define CUSTOM_FRAGMENT_BEFORE_FOG', (this.CustomParts.Fragment_Before_Fog ? this.CustomParts.Fragment_Before_Fog : ""))
  133. .replace('#define CUSTOM_FRAGMENT_BEFORE_FRAGCOLOR', (this.CustomParts.Fragment_Before_FragColor ? this.CustomParts.Fragment_Before_FragColor : ""));
  134. this._isCreatedShader = true;
  135. this._createdShaderName = name;
  136. return name;
  137. }
  138. constructor(name: string, scene: Scene) {
  139. super(name, scene);
  140. this.CustomParts = new ShaderSpecialParts();
  141. this.customShaderNameResolve = this.Builder;
  142. this.FragmentShader = Effect.ShadersStore["defaultPixelShader"];
  143. this.VertexShader = Effect.ShadersStore["defaultVertexShader"];
  144. }
  145. public AddUniform(name: string, kind: string, param: any): CustomMaterial {
  146. if (!this._customUniform) {
  147. this._customUniform = new Array();
  148. this._newUniforms = new Array();
  149. this._newSamplerInstances = new Array();
  150. this._newUniformInstances = new Array();
  151. }
  152. if (param) {
  153. if (kind.indexOf("sampler") == -1) {
  154. (<any>this._newUniformInstances)[kind + "-" + name] = param;
  155. }
  156. else {
  157. (<any>this._newUniformInstances)[kind + "-" + name] = param;
  158. }
  159. }
  160. this._customUniform.push("uniform " + kind + " " + name + ";");
  161. this._newUniforms.push(name);
  162. return this;
  163. }
  164. public AddAttribute(name: string): CustomMaterial {
  165. if (!this._customAttributes) {
  166. this._customAttributes = [];
  167. }
  168. this._customAttributes.push(name);
  169. return this;
  170. }
  171. public Fragment_Begin(shaderPart: string): CustomMaterial {
  172. this.CustomParts.Fragment_Begin = shaderPart;
  173. return this;
  174. }
  175. public Fragment_Definitions(shaderPart: string): CustomMaterial {
  176. this.CustomParts.Fragment_Definitions = shaderPart;
  177. return this;
  178. }
  179. public Fragment_MainBegin(shaderPart: string): CustomMaterial {
  180. this.CustomParts.Fragment_MainBegin = shaderPart;
  181. return this;
  182. }
  183. public Fragment_Custom_Diffuse(shaderPart: string): CustomMaterial {
  184. this.CustomParts.Fragment_Custom_Diffuse = shaderPart.replace("result", "diffuseColor");
  185. return this;
  186. }
  187. public Fragment_Custom_Alpha(shaderPart: string): CustomMaterial {
  188. this.CustomParts.Fragment_Custom_Alpha = shaderPart.replace("result", "alpha");
  189. return this;
  190. }
  191. public Fragment_Before_Lights(shaderPart: string): CustomMaterial {
  192. this.CustomParts.Fragment_Before_Lights = shaderPart;
  193. return this;
  194. }
  195. public Fragment_Before_Fog(shaderPart: string): CustomMaterial {
  196. this.CustomParts.Fragment_Before_Fog = shaderPart;
  197. return this;
  198. }
  199. public Fragment_Before_FragColor(shaderPart: string): CustomMaterial {
  200. this.CustomParts.Fragment_Before_FragColor = shaderPart.replace("result", "color");
  201. return this;
  202. }
  203. public Vertex_Begin(shaderPart: string): CustomMaterial {
  204. this.CustomParts.Vertex_Begin = shaderPart;
  205. return this;
  206. }
  207. public Vertex_Definitions(shaderPart: string): CustomMaterial {
  208. this.CustomParts.Vertex_Definitions = shaderPart;
  209. return this;
  210. }
  211. public Vertex_MainBegin(shaderPart: string): CustomMaterial {
  212. this.CustomParts.Vertex_MainBegin = shaderPart;
  213. return this;
  214. }
  215. public Vertex_Before_PositionUpdated(shaderPart: string): CustomMaterial {
  216. this.CustomParts.Vertex_Before_PositionUpdated = shaderPart.replace("result", "positionUpdated");
  217. return this;
  218. }
  219. public Vertex_Before_NormalUpdated(shaderPart: string): CustomMaterial {
  220. this.CustomParts.Vertex_Before_NormalUpdated = shaderPart.replace("result", "normalUpdated");
  221. return this;
  222. }
  223. public Vertex_After_WorldPosComputed(shaderPart: string): CustomMaterial {
  224. this.CustomParts.Vertex_After_WorldPosComputed = shaderPart;
  225. return this;
  226. }
  227. public Vertex_MainEnd(shaderPart: string): CustomMaterial {
  228. this.CustomParts.Vertex_MainEnd = shaderPart;
  229. return this;
  230. }
  231. }
  232. _TypeStore.RegisteredTypes["BABYLON.CustomMaterial"] = CustomMaterial;