make_material.ts 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. let make_material_default_scon: shader_context_t = null;
  2. let make_material_default_mcon: material_context_t = null;
  3. let make_material_height_used: bool = false;
  4. let make_material_emis_used: bool = false;
  5. let make_material_subs_used: bool = false;
  6. function make_material_get_mout(): bool {
  7. for (let i: i32 = 0; i < ui_nodes_get_canvas_material().nodes.length; ++i) {
  8. let n = ui_nodes_get_canvas_material().nodes[i];
  9. if (n.type == "OUTPUT_MATERIAL_PBR") {
  10. return true;
  11. }
  12. }
  13. return false;
  14. }
  15. function make_material_parse_mesh_material() {
  16. let m = project_materials[0].data;
  17. for (let i: i32 = 0; i < m._.shader._.contexts.length; ++i) {
  18. let c = m._.shader._.contexts[i];
  19. if (c.name == "mesh") {
  20. array_remove(m._.shader.contexts, c);
  21. array_remove(m._.shader._.contexts, c);
  22. make_material_delete_context(c);
  23. break;
  24. }
  25. }
  26. if (make_mesh_layer_pass_count > 1) {
  27. let i = 0;
  28. while (i < m._.shader._.contexts.length) {
  29. let c = m._.shader._.contexts[i];
  30. for (let j: i32 = 1; j < make_mesh_layer_pass_count; ++j) {
  31. if (c.name == "mesh" + j) {
  32. array_remove(m._.shader.contexts, c);
  33. array_remove(m._.shader._.contexts, c);
  34. make_material_delete_context(c);
  35. i--;
  36. break;
  37. }
  38. }
  39. i++;
  40. }
  41. i = 0;
  42. while (i < m.contexts.length) {
  43. let c = m.contexts[i];
  44. for (let j: i32 = 1; j < make_mesh_layer_pass_count; ++j) {
  45. if (c.name == "mesh" + j) {
  46. array_remove(m.contexts, c);
  47. array_remove(m._.contexts, c);
  48. i--;
  49. break;
  50. }
  51. }
  52. i++;
  53. }
  54. }
  55. let mm: material_t = { name: "Material", canvas: null };
  56. let con = make_mesh_run(mm);
  57. let scon: shader_context_t = shader_context_create(con.data);
  58. scon._.override_context = {};
  59. if (con.frag.shared_samplers.length > 0) {
  60. let sampler = con.frag.shared_samplers[0];
  61. scon._.override_context.shared_sampler = substring(sampler, string_last_index_of(sampler, " ") + 1, sampler.length);
  62. }
  63. if (!context_raw.texture_filter) {
  64. scon._.override_context.filter = "point";
  65. }
  66. array_push(m._.shader.contexts, scon);
  67. array_push(m._.shader._.contexts, scon);
  68. for (let i: i32 = 1; i < make_mesh_layer_pass_count; ++i) {
  69. let mm: material_t = { name: "Material", canvas: null };
  70. let con = make_mesh_run(mm, i);
  71. let scon: shader_context_t = shader_context_create(con.data);
  72. scon._.override_context = {};
  73. if (con.frag.shared_samplers.length > 0) {
  74. let sampler = con.frag.shared_samplers[0];
  75. scon._.override_context.shared_sampler = substring(sampler, string_last_index_of(sampler, " ") + 1, sampler.length);
  76. }
  77. if (!context_raw.texture_filter) {
  78. scon._.override_context.filter = "point";
  79. }
  80. array_push(m._.shader.contexts, scon);
  81. array_push(m._.shader._.contexts, scon);
  82. let mcon: material_context_t = material_context_create({ name: "mesh" + i, bind_textures: [] });
  83. array_push(m.contexts, mcon);
  84. array_push(m._.contexts, mcon);
  85. }
  86. context_raw.ddirty = 2;
  87. ///if arm_voxels
  88. make_material_make_voxel(m);
  89. ///end
  90. }
  91. function make_material_parse_particle_material() {
  92. let m = context_raw.particle_material;
  93. let sc: shader_context_t = null;
  94. for (let i: i32 = 0; i < m._.shader._.contexts.length; ++i) {
  95. let c = m._.shader._.contexts[i];
  96. if (c.name == "mesh") {
  97. sc = c;
  98. break;
  99. }
  100. }
  101. if (sc != null) {
  102. array_remove(m._.shader.contexts, sc);
  103. array_remove(m._.shader._.contexts, sc);
  104. }
  105. let con = make_particle_run({ name: "MaterialParticle", canvas: null });
  106. if (sc != null) {
  107. make_material_delete_context(sc);
  108. }
  109. sc = shader_context_create(con.data);
  110. array_push(m._.shader.contexts, sc);
  111. array_push(m._.shader._.contexts, sc);
  112. }
  113. function make_material_parse_mesh_preview_material() {
  114. if (!make_material_get_mout()) {
  115. return;
  116. }
  117. let m = project_materials[0].data;
  118. let scon: shader_context_t = null;
  119. for (let i: i32 = 0; i < m._.shader._.contexts.length; ++i) {
  120. let c = m._.shader._.contexts[i];
  121. if (c.name == "mesh") {
  122. scon = c;
  123. break;
  124. }
  125. }
  126. array_remove(m._.shader.contexts, scon);
  127. array_remove(m._.shader._.contexts, scon);
  128. let mcon: material_context_t = { name: "mesh", bind_textures: [] };
  129. let sd: material_t = { name: "Material", canvas: null };
  130. let con = make_mesh_preview_run(sd, mcon);
  131. for (let i: i32 = 0; i < m.contexts.length; ++i) {
  132. if (m.contexts[i].name == "mesh") {
  133. m.contexts[i] = material_context_create(mcon);
  134. break;
  135. }
  136. }
  137. if (scon != null) {
  138. make_material_delete_context(scon);
  139. }
  140. let compile_error = false;
  141. let _scon: shader_context_t = shader_context_create(con.data);
  142. if (_scon == null) {
  143. compile_error = true;
  144. }
  145. scon = _scon;
  146. if (compile_error) {
  147. return;
  148. }
  149. array_push(m._.shader.contexts, scon);
  150. array_push(m._.shader._.contexts, scon);
  151. }
  152. ///if arm_voxels
  153. function make_material_make_voxel(m: material_data_t) {
  154. let rebuild = make_material_height_used;
  155. if (config_raw.rp_gi != false && rebuild) {
  156. let scon: shader_context_t = null;
  157. for (let i: i32 = 0; i < m._.shader._.contexts.length; ++i) {
  158. let c = m._.shader._.contexts[i];
  159. if (c.name == "voxel") {
  160. scon = c;
  161. break;
  162. }
  163. }
  164. if (scon != null) {
  165. make_voxel_run(scon);
  166. }
  167. }
  168. }
  169. ///end
  170. function make_material_parse_paint_material(bake_previews: bool = true) {
  171. if (!make_material_get_mout()) {
  172. return;
  173. }
  174. if (bake_previews) {
  175. let current = _g2_current;
  176. let g2_in_use: bool = _g2_in_use;
  177. if (g2_in_use) g2_end();
  178. make_material_bake_node_previews();
  179. if (g2_in_use) g2_begin(current);
  180. }
  181. let m = project_materials[0].data;
  182. let scon: shader_context_t = null;
  183. let mcon: material_context_t = null;
  184. for (let i: i32 = 0; i < m._.shader._.contexts.length; ++i) {
  185. let c = m._.shader._.contexts[i];
  186. if (c.name == "paint") {
  187. array_remove(m._.shader.contexts, c);
  188. array_remove(m._.shader._.contexts, c);
  189. if (c != make_material_default_scon) {
  190. make_material_delete_context(c);
  191. }
  192. break;
  193. }
  194. }
  195. for (let i: i32 = 0; i < m.contexts.length; ++i) {
  196. let c = m.contexts[i];
  197. if (c.name == "paint") {
  198. array_remove(m.contexts, c);
  199. array_remove(m._.contexts, c);
  200. break;
  201. }
  202. }
  203. let sdata: material_t = { name: "Material", canvas: ui_nodes_get_canvas_material() };
  204. let mcon2: material_context_t = { name: "paint", bind_textures: [] };
  205. let con = make_sculpt_run(sdata, mcon2);
  206. let compile_error = false;
  207. let scon2: shader_context_t;
  208. let _scon: shader_context_t = shader_context_create(con.data);
  209. if (_scon == null) {
  210. compile_error = true;
  211. }
  212. scon2 = _scon;
  213. if (compile_error) {
  214. return;
  215. }
  216. scon2._.override_context = {};
  217. scon2._.override_context.addressing = "repeat";
  218. let mcon3: material_context_t = material_context_create(mcon2);
  219. array_push(m._.shader.contexts, scon2);
  220. array_push(m._.shader._.contexts, scon2);
  221. array_push(m.contexts, mcon3);
  222. array_push(m._.contexts, mcon3);
  223. if (make_material_default_scon == null) {
  224. make_material_default_scon = scon2;
  225. }
  226. if (make_material_default_mcon == null) {
  227. make_material_default_mcon = mcon3;
  228. }
  229. }
  230. function make_material_bake_node_previews() {
  231. context_raw.node_previews_used = [];
  232. if (context_raw.node_previews == null) {
  233. context_raw.node_previews = map_create();
  234. }
  235. make_material_traverse_nodes(ui_nodes_get_canvas_material().nodes, null, []);
  236. let keys: string[] = map_keys(context_raw.node_previews);
  237. for (let i: i32 = 0; i < keys.length; ++i) {
  238. let key: string = keys[i];
  239. if (array_index_of(context_raw.node_previews_used, key) == -1) {
  240. let image: image_t = map_get(context_raw.node_previews, key);
  241. app_notify_on_next_frame(function (image: image_t) {
  242. image_unload(image);
  243. }, image);
  244. map_delete(context_raw.node_previews, key);
  245. }
  246. }
  247. }
  248. function make_material_traverse_nodes(nodes: zui_node_t[], group: zui_node_canvas_t, parents: zui_node_t[]) {
  249. for (let i: i32 = 0; i < nodes.length; ++i) {
  250. let node = nodes[i];
  251. make_material_bake_node_preview(node, group, parents);
  252. if (node.type == "GROUP") {
  253. for (let j: i32 = 0; j < project_material_groups.length; ++j) {
  254. let g = project_material_groups[j];
  255. if (g.canvas.name == node.name) {
  256. array_push(parents, node);
  257. make_material_traverse_nodes(g.canvas.nodes, g.canvas, parents);
  258. parents.pop();
  259. break;
  260. }
  261. }
  262. }
  263. }
  264. }
  265. function make_material_bake_node_preview(node: zui_node_t, group: zui_node_canvas_t, parents: zui_node_t[]) {
  266. if (node.type == "BLUR") {
  267. let id = parser_material_node_name(node, parents);
  268. let image = map_get(context_raw.node_previews, id);
  269. array_push(context_raw.node_previews_used, id);
  270. let resX = math_floor(config_get_texture_res_x() / 4);
  271. let resY = math_floor(config_get_texture_res_y() / 4);
  272. if (image == null || image.width != resX || image.height != resY) {
  273. if (image != null) {
  274. image_unload(image);
  275. }
  276. image = image_create_render_target(resX, resY);
  277. map_set(context_raw.node_previews, id, image);
  278. }
  279. parser_material_blur_passthrough = true;
  280. util_render_make_node_preview(ui_nodes_get_canvas_material(), node, image, group, parents);
  281. parser_material_blur_passthrough = false;
  282. }
  283. else if (node.type == "DIRECT_WARP") {
  284. let id = parser_material_node_name(node, parents);
  285. let image = map_get(context_raw.node_previews, id);
  286. array_push(context_raw.node_previews_used, id);
  287. let resX = math_floor(config_get_texture_res_x());
  288. let resY = math_floor(config_get_texture_res_y());
  289. if (image == null || image.width != resX || image.height != resY) {
  290. if (image != null) {
  291. image_unload(image);
  292. }
  293. image = image_create_render_target(resX, resY);
  294. map_set(context_raw.node_previews, id, image);
  295. }
  296. parser_material_warp_passthrough = true;
  297. util_render_make_node_preview(ui_nodes_get_canvas_material(), node, image, group, parents);
  298. parser_material_warp_passthrough = false;
  299. }
  300. }
  301. function make_material_parse_node_preview_material(node: zui_node_t, group: zui_node_canvas_t = null, parents: zui_node_t[] = null): { scon: shader_context_t, mcon: material_context_t } {
  302. if (node.outputs.length == 0) {
  303. return null;
  304. }
  305. let sdata: material_t = { name: "Material", canvas: ui_nodes_get_canvas_material() };
  306. let mcon_raw: material_context_t = { name: "mesh", bind_textures: [] };
  307. let con = make_node_preview_run(sdata, mcon_raw, node, group, parents);
  308. let compile_error = false;
  309. let scon: shader_context_t;
  310. let _scon: shader_context_t = shader_context_create(con.data);
  311. if (_scon == null) {
  312. compile_error = true;
  313. }
  314. scon = _scon;
  315. if (compile_error) {
  316. return null;
  317. }
  318. let mcon: material_context_t = material_context_create(mcon_raw);
  319. return { scon: scon, mcon: mcon };
  320. }
  321. function make_material_parse_brush() {
  322. parser_logic_parse(context_raw.brush.canvas);
  323. }
  324. function make_material_get_displace_strength(): f32 {
  325. let sc = context_main_object().base.transform.scale.x;
  326. return config_raw.displace_strength * 0.02 * sc;
  327. }
  328. function make_material_voxelgi_half_extents(): string {
  329. let ext = context_raw.vxao_ext;
  330. return "const vec3 voxelgiHalfExtents = vec3(" + ext + ", " + ext + ", " + ext + ");";
  331. }
  332. function make_material_delete_context(c: shader_context_t) {
  333. app_notify_on_next_frame(function (c: shader_context_t) { // Ensure pipeline is no longer in use
  334. shader_context_delete(c);
  335. }, c);
  336. }