pbrCustomMaterial.ts 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. import { Texture } from "babylonjs/Materials/Textures/texture";
  2. import { Effect } from "babylonjs/Materials/effect";
  3. import { MaterialDefines } from "babylonjs/Materials/materialDefines";
  4. import { PBRMaterial } from "babylonjs/Materials/PBR/pbrMaterial";
  5. import { Mesh } from "babylonjs/Meshes/mesh";
  6. import { Scene } from "babylonjs/scene";
  7. import { _TypeStore } from 'babylonjs/Misc/typeStore';
  8. export class ShaderAlebdoParts {
  9. constructor() { }
  10. public Fragment_Begin: string;
  11. public Fragment_Definitions: string;
  12. public Fragment_MainBegin: string;
  13. // albedoColor
  14. public Fragment_Custom_Albedo: string;
  15. // lights
  16. public Fragment_Before_Lights: string;
  17. // roughness
  18. public Fragment_Custom_MetallicRoughness: string;
  19. // microsurface
  20. public Fragment_Custom_MicroSurface: string;
  21. // fog
  22. public Fragment_Before_Fog: string;
  23. // alpha
  24. public Fragment_Custom_Alpha: string;
  25. public Fragment_Before_FragColor: string;
  26. public Vertex_Begin: string;
  27. public Vertex_Definitions: string;
  28. public Vertex_MainBegin: string;
  29. // positionUpdated
  30. public Vertex_Before_PositionUpdated: string;
  31. // normalUpdated
  32. public Vertex_Before_NormalUpdated: string;
  33. // worldPosComputed
  34. public Vertex_After_WorldPosComputed: string;
  35. // mainEnd
  36. public Vertex_MainEnd: string;
  37. }
  38. export class PBRCustomMaterial extends PBRMaterial {
  39. public static ShaderIndexer = 1;
  40. public CustomParts: ShaderAlebdoParts;
  41. _isCreatedShader: boolean;
  42. _createdShaderName: string;
  43. _customUniform: string[];
  44. _newUniforms: string[];
  45. _newUniformInstances: { [name: string]: any };
  46. _newSamplerInstances: { [name: string]: Texture };
  47. _customAttributes: string[];
  48. public FragmentShader: string;
  49. public VertexShader: string;
  50. public AttachAfterBind(mesh: Mesh, effect: Effect) {
  51. if (this._newUniformInstances) {
  52. for (let el in this._newUniformInstances) {
  53. const 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. }
  71. if (this._newSamplerInstances) {
  72. for (let el in this._newSamplerInstances) {
  73. const ea = el.toString().split('-');
  74. if (ea[0] == 'sampler2D' && this._newSamplerInstances[el].isReady && this._newSamplerInstances[el].isReady()) {
  75. effect.setTexture(ea[1], this._newSamplerInstances[el]);
  76. }
  77. }
  78. }
  79. }
  80. public ReviewUniform(name: string, arr: string[]): string[] {
  81. if (name == "uniform" && this._newUniforms) {
  82. for (var ind = 0; ind < this._newUniforms.length ; ind ++) {
  83. if (this._customUniform[ind].indexOf('sampler') == -1) {
  84. arr.push(this._newUniforms[ind]);
  85. }
  86. }
  87. }
  88. if (name == "sampler" && this._newUniforms) {
  89. for (var ind = 0; ind < this._newUniforms.length ; ind ++) {
  90. if (this._customUniform[ind].indexOf('sampler') != -1) {
  91. arr.push(this._newUniforms[ind]);
  92. }
  93. }
  94. }
  95. return arr;
  96. }
  97. public Builder(shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: MaterialDefines | string[], attributes?: string[], options?: BABYLON.ICustomShaderNameResolveOptions): string {
  98. if (options) {
  99. options.processFinalCode = (type: string, code: string) => {
  100. if (type === "vertex") {
  101. return code;
  102. }
  103. const sci = new BABYLON.ShaderCodeInliner(code);
  104. sci.inlineToken = "#define pbr_inline";
  105. sci.processCode();
  106. return sci.code;
  107. };
  108. }
  109. if (attributes && this._customAttributes && this._customAttributes.length > 0) {
  110. attributes.push(...this._customAttributes);
  111. }
  112. this.ReviewUniform("uniform", uniforms);
  113. this.ReviewUniform("sampler", samplers);
  114. if (this._isCreatedShader) {
  115. return this._createdShaderName;
  116. }
  117. this._isCreatedShader = false;
  118. PBRCustomMaterial.ShaderIndexer++;
  119. var name: string = "custom_" + PBRCustomMaterial.ShaderIndexer;
  120. var fn_afterBind = this._afterBind.bind(this);
  121. this._afterBind = (m, e) => {
  122. if (!e) {
  123. return;
  124. }
  125. this.AttachAfterBind(m, e);
  126. try { fn_afterBind(m, e); }
  127. catch (e) { }
  128. };
  129. Effect.ShadersStore[name + "VertexShader"] = this.VertexShader
  130. .replace('#define CUSTOM_VERTEX_BEGIN', (this.CustomParts.Vertex_Begin ? this.CustomParts.Vertex_Begin : ""))
  131. .replace('#define CUSTOM_VERTEX_DEFINITIONS', (this._customUniform ? this._customUniform.join("\n") : "") + (this.CustomParts.Vertex_Definitions ? this.CustomParts.Vertex_Definitions : ""))
  132. .replace('#define CUSTOM_VERTEX_MAIN_BEGIN', (this.CustomParts.Vertex_MainBegin ? this.CustomParts.Vertex_MainBegin : ""))
  133. .replace('#define CUSTOM_VERTEX_UPDATE_POSITION', (this.CustomParts.Vertex_Before_PositionUpdated ? this.CustomParts.Vertex_Before_PositionUpdated : ""))
  134. .replace('#define CUSTOM_VERTEX_UPDATE_NORMAL', (this.CustomParts.Vertex_Before_NormalUpdated ? this.CustomParts.Vertex_Before_NormalUpdated : ""))
  135. .replace('#define CUSTOM_VERTEX_MAIN_END', (this.CustomParts.Vertex_MainEnd ? this.CustomParts.Vertex_MainEnd : ""));
  136. if (this.CustomParts.Vertex_After_WorldPosComputed) {
  137. Effect.ShadersStore[name + "VertexShader"] = Effect.ShadersStore[name + "VertexShader"].replace('#define CUSTOM_VERTEX_UPDATE_WORLDPOS', this.CustomParts.Vertex_After_WorldPosComputed);
  138. }
  139. Effect.ShadersStore[name + "PixelShader"] = this.FragmentShader
  140. .replace('#define CUSTOM_FRAGMENT_BEGIN', (this.CustomParts.Fragment_Begin ? this.CustomParts.Fragment_Begin : ""))
  141. .replace('#define CUSTOM_FRAGMENT_MAIN_BEGIN', (this.CustomParts.Fragment_MainBegin ? this.CustomParts.Fragment_MainBegin : ""))
  142. .replace('#define CUSTOM_FRAGMENT_DEFINITIONS', (this._customUniform ? this._customUniform.join("\n") : "") + (this.CustomParts.Fragment_Definitions ? this.CustomParts.Fragment_Definitions : ""))
  143. .replace('#define CUSTOM_FRAGMENT_UPDATE_ALBEDO', (this.CustomParts.Fragment_Custom_Albedo ? this.CustomParts.Fragment_Custom_Albedo : ""))
  144. .replace('#define CUSTOM_FRAGMENT_UPDATE_ALPHA', (this.CustomParts.Fragment_Custom_Alpha ? this.CustomParts.Fragment_Custom_Alpha : ""))
  145. .replace('#define CUSTOM_FRAGMENT_BEFORE_LIGHTS', (this.CustomParts.Fragment_Before_Lights ? this.CustomParts.Fragment_Before_Lights : ""))
  146. .replace('#define CUSTOM_FRAGMENT_UPDATE_METALLICROUGHNESS', (this.CustomParts.Fragment_Custom_MetallicRoughness ? this.CustomParts.Fragment_Custom_MetallicRoughness : ""))
  147. .replace('#define CUSTOM_FRAGMENT_UPDATE_MICROSURFACE', (this.CustomParts.Fragment_Custom_MicroSurface ? this.CustomParts.Fragment_Custom_MicroSurface : ""))
  148. .replace('#define CUSTOM_FRAGMENT_BEFORE_FRAGCOLOR', (this.CustomParts.Fragment_Before_FragColor ? this.CustomParts.Fragment_Before_FragColor : ""));
  149. if (this.CustomParts.Fragment_Before_Fog) {
  150. Effect.ShadersStore[name + "PixelShader"] = Effect.ShadersStore[name + "PixelShader"].replace('#define CUSTOM_FRAGMENT_BEFORE_FOG', this.CustomParts.Fragment_Before_Fog);
  151. }
  152. this._isCreatedShader = true;
  153. this._createdShaderName = name;
  154. return name;
  155. }
  156. constructor(name: string, scene: Scene) {
  157. super(name, scene);
  158. this.CustomParts = new ShaderAlebdoParts();
  159. this.customShaderNameResolve = this.Builder;
  160. this.FragmentShader = Effect.ShadersStore["pbrPixelShader"];
  161. this.VertexShader = Effect.ShadersStore["pbrVertexShader"];
  162. this.FragmentShader = this.FragmentShader.replace(/#include<pbrBlockAlbedoOpacity>/g, Effect.IncludesShadersStore["pbrBlockAlbedoOpacity"]);
  163. this.FragmentShader = this.FragmentShader.replace(/#include<pbrBlockReflectivity>/g, Effect.IncludesShadersStore["pbrBlockReflectivity"]);
  164. this.FragmentShader = this.FragmentShader.replace(/#include<pbrBlockFinalColorComposition>/g, Effect.IncludesShadersStore["pbrBlockFinalColorComposition"]);
  165. }
  166. public AddUniform(name: string, kind: string, param: any): PBRCustomMaterial {
  167. if (!this._customUniform) {
  168. this._customUniform = new Array();
  169. this._newUniforms = new Array();
  170. this._newSamplerInstances = {};
  171. this._newUniformInstances = {};
  172. }
  173. if (param) {
  174. if (kind.indexOf("sampler") != -1) {
  175. (<any>this._newSamplerInstances)[kind + "-" + name] = param;
  176. }
  177. else {
  178. (<any>this._newUniformInstances)[kind + "-" + name] = param;
  179. }
  180. }
  181. this._customUniform.push("uniform " + kind + " " + name + ";");
  182. this._newUniforms.push(name);
  183. return this;
  184. }
  185. public AddAttribute(name: string): PBRCustomMaterial {
  186. if (!this._customAttributes) {
  187. this._customAttributes = [];
  188. }
  189. this._customAttributes.push(name);
  190. return this;
  191. }
  192. public Fragment_Begin(shaderPart: string): PBRCustomMaterial {
  193. this.CustomParts.Fragment_Begin = shaderPart;
  194. return this;
  195. }
  196. public Fragment_Definitions(shaderPart: string): PBRCustomMaterial {
  197. this.CustomParts.Fragment_Definitions = shaderPart;
  198. return this;
  199. }
  200. public Fragment_MainBegin(shaderPart: string): PBRCustomMaterial {
  201. this.CustomParts.Fragment_MainBegin = shaderPart;
  202. return this;
  203. }
  204. public Fragment_Custom_Albedo(shaderPart: string): PBRCustomMaterial {
  205. this.CustomParts.Fragment_Custom_Albedo = shaderPart.replace("result", "surfaceAlbedo");
  206. return this;
  207. }
  208. public Fragment_Custom_Alpha(shaderPart: string): PBRCustomMaterial {
  209. this.CustomParts.Fragment_Custom_Alpha = shaderPart.replace("result", "alpha");
  210. return this;
  211. }
  212. public Fragment_Before_Lights(shaderPart: string): PBRCustomMaterial {
  213. this.CustomParts.Fragment_Before_Lights = shaderPart;
  214. return this;
  215. }
  216. public Fragment_Custom_MetallicRoughness(shaderPart: string): PBRCustomMaterial {
  217. this.CustomParts.Fragment_Custom_MetallicRoughness = shaderPart;
  218. return this;
  219. }
  220. public Fragment_Custom_MicroSurface(shaderPart: string): PBRCustomMaterial {
  221. this.CustomParts.Fragment_Custom_MicroSurface = shaderPart;
  222. return this;
  223. }
  224. public Fragment_Before_Fog(shaderPart: string): PBRCustomMaterial {
  225. this.CustomParts.Fragment_Before_Fog = shaderPart;
  226. return this;
  227. }
  228. public Fragment_Before_FragColor(shaderPart: string): PBRCustomMaterial {
  229. this.CustomParts.Fragment_Before_FragColor = shaderPart.replace("result", "color");
  230. return this;
  231. }
  232. public Vertex_Begin(shaderPart: string): PBRCustomMaterial {
  233. this.CustomParts.Vertex_Begin = shaderPart;
  234. return this;
  235. }
  236. public Vertex_Definitions(shaderPart: string): PBRCustomMaterial {
  237. this.CustomParts.Vertex_Definitions = shaderPart;
  238. return this;
  239. }
  240. public Vertex_MainBegin(shaderPart: string): PBRCustomMaterial {
  241. this.CustomParts.Vertex_MainBegin = shaderPart;
  242. return this;
  243. }
  244. public Vertex_Before_PositionUpdated(shaderPart: string): PBRCustomMaterial {
  245. this.CustomParts.Vertex_Before_PositionUpdated = shaderPart.replace("result", "positionUpdated");
  246. return this;
  247. }
  248. public Vertex_Before_NormalUpdated(shaderPart: string): PBRCustomMaterial {
  249. this.CustomParts.Vertex_Before_NormalUpdated = shaderPart.replace("result", "normalUpdated");
  250. return this;
  251. }
  252. public Vertex_After_WorldPosComputed(shaderPart: string): PBRCustomMaterial {
  253. this.CustomParts.Vertex_After_WorldPosComputed = shaderPart;
  254. return this;
  255. }
  256. public Vertex_MainEnd(shaderPart: string): PBRCustomMaterial {
  257. this.CustomParts.Vertex_MainEnd = shaderPart;
  258. return this;
  259. }
  260. }
  261. _TypeStore.RegisteredTypes["BABYLON.PBRCustomMaterial"] = PBRCustomMaterial;