render_path_paint.ts 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873
  1. let render_path_paint_live_layer: slot_layer_t = null;
  2. let render_path_paint_live_layer_drawn: i32 = 0;
  3. let render_path_paint_live_layer_locked: bool = false;
  4. let render_path_paint_dilated: bool = true;
  5. let render_path_paint_push_undo_last: bool;
  6. let render_path_paint_painto: mesh_object_t = null;
  7. let render_path_paint_planeo: mesh_object_t = null;
  8. let render_path_paint_visibles: bool[] = null;
  9. let render_path_paint_merged_object_visible: bool = false;
  10. let render_path_paint_saved_fov: f32 = 0.0;
  11. let render_path_paint_baking: bool = false;
  12. let _render_path_paint_texpaint: render_target_t;
  13. let _render_path_paint_texpaint_nor: render_target_t;
  14. let _render_path_paint_texpaint_pack: render_target_t;
  15. let _render_path_paint_texpaint_undo: render_target_t;
  16. let _render_path_paint_texpaint_nor_undo: render_target_t;
  17. let _render_path_paint_texpaint_pack_undo: render_target_t;
  18. let render_path_paint_last_x: f32 = -1.0;
  19. let render_path_paint_last_y: f32 = -1.0;
  20. function render_path_paint_init() {
  21. {
  22. let t: render_target_t = render_target_create();
  23. t.name = "texpaint_blend0";
  24. t.width = config_get_texture_res_x();
  25. t.height = config_get_texture_res_y();
  26. t.format = "R8";
  27. render_path_create_render_target(t);
  28. }
  29. {
  30. let t: render_target_t = render_target_create();
  31. t.name = "texpaint_blend1";
  32. t.width = config_get_texture_res_x();
  33. t.height = config_get_texture_res_y();
  34. t.format = "R8";
  35. render_path_create_render_target(t);
  36. }
  37. {
  38. let t: render_target_t = render_target_create();
  39. t.name = "texpaint_colorid";
  40. t.width = 1;
  41. t.height = 1;
  42. t.format = "RGBA32";
  43. render_path_create_render_target(t);
  44. }
  45. {
  46. let t: render_target_t = render_target_create();
  47. t.name = "texpaint_picker";
  48. t.width = 1;
  49. t.height = 1;
  50. t.format = "RGBA32";
  51. render_path_create_render_target(t);
  52. }
  53. {
  54. let t: render_target_t = render_target_create();
  55. t.name = "texpaint_nor_picker";
  56. t.width = 1;
  57. t.height = 1;
  58. t.format = "RGBA32";
  59. render_path_create_render_target(t);
  60. }
  61. {
  62. let t: render_target_t = render_target_create();
  63. t.name = "texpaint_pack_picker";
  64. t.width = 1;
  65. t.height = 1;
  66. t.format = "RGBA32";
  67. render_path_create_render_target(t);
  68. }
  69. {
  70. let t: render_target_t = render_target_create();
  71. t.name = "texpaint_uv_picker";
  72. t.width = 1;
  73. t.height = 1;
  74. t.format = "RGBA32";
  75. render_path_create_render_target(t);
  76. }
  77. {
  78. let t: render_target_t = render_target_create();
  79. t.name = "texpaint_posnortex_picker0";
  80. t.width = 1;
  81. t.height = 1;
  82. t.format = "RGBA128";
  83. render_path_create_render_target(t);
  84. }
  85. {
  86. let t: render_target_t = render_target_create();
  87. t.name = "texpaint_posnortex_picker1";
  88. t.width = 1;
  89. t.height = 1;
  90. t.format = "RGBA128";
  91. render_path_create_render_target(t);
  92. }
  93. render_path_load_shader("shader_datas/copy_mrt3_pass/copy_mrt3_pass");
  94. render_path_load_shader("shader_datas/copy_mrt3_pass/copy_mrt3RGBA64_pass");
  95. render_path_load_shader("shader_datas/copy_mrt3_pass/copy_mrt3RGBA128_pass");
  96. render_path_load_shader("shader_datas/dilate_pass/dilate_pass");
  97. render_path_load_shader("shader_datas/dilate_pass/dilateRGBA64_pass");
  98. render_path_load_shader("shader_datas/dilate_pass/dilateRGBA128_pass");
  99. }
  100. function render_path_paint_draw_fullscreen_triangle(context: string) {
  101. // Note that vertices are mangled in vertex shader to form a fullscreen triangle,
  102. // so plane transform does not matter
  103. let plane: mesh_object_t = scene_get_child(".Plane").ext;
  104. let _visible: bool = plane.base.visible;
  105. plane.base.visible = true;
  106. mesh_object_render(plane, context, _render_path_bind_params);
  107. plane.base.visible = _visible;
  108. render_path_end();
  109. }
  110. function render_path_paint_commands_paint(dilation: bool = true) {
  111. let tid: i32 = context_raw.layer.id;
  112. if (context_raw.pdirty > 0) {
  113. if (context_raw.tool == workspace_tool_t.COLORID) {
  114. render_path_set_target("texpaint_colorid", null, null, clear_flag_t.COLOR, 0xff000000);
  115. render_path_bind_target("gbuffer2", "gbuffer2");
  116. render_path_paint_draw_fullscreen_triangle("paint");
  117. ui_header_handle.redraws = 2;
  118. }
  119. else if (context_raw.tool == workspace_tool_t.PICKER || context_raw.tool == workspace_tool_t.MATERIAL) {
  120. if (context_raw.pick_pos_nor_tex) {
  121. if (context_raw.paint2d) {
  122. let additional: string[] = ["gbuffer1", "gbuffer2"];
  123. render_path_set_target("gbuffer0", additional, "main");
  124. render_path_draw_meshes("mesh");
  125. }
  126. let additional: string[] = ["texpaint_posnortex_picker1"];
  127. render_path_set_target("texpaint_posnortex_picker0", additional);
  128. render_path_bind_target("gbuffer2", "gbuffer2");
  129. render_path_bind_target("main", "gbufferD");
  130. render_path_draw_meshes("paint");
  131. let picker0: render_target_t = map_get(render_path_render_targets, "texpaint_posnortex_picker0");
  132. let picker1: render_target_t = map_get(render_path_render_targets, "texpaint_posnortex_picker1");
  133. let texpaint_posnortex_picker0: gpu_texture_t = picker0._image;
  134. let texpaint_posnortex_picker1: gpu_texture_t = picker1._image;
  135. let a: buffer_t = gpu_get_texture_pixels(texpaint_posnortex_picker0);
  136. let b: buffer_t = gpu_get_texture_pixels(texpaint_posnortex_picker1);
  137. context_raw.posx_picked = buffer_get_f32(a, 0);
  138. context_raw.posy_picked = buffer_get_f32(a, 4);
  139. context_raw.posz_picked = buffer_get_f32(a, 8);
  140. context_raw.uvx_picked = buffer_get_f32(a, 12);
  141. context_raw.norx_picked = buffer_get_f32(b, 0);
  142. context_raw.nory_picked = buffer_get_f32(b, 4);
  143. context_raw.norz_picked = buffer_get_f32(b, 8);
  144. context_raw.uvy_picked = buffer_get_f32(b, 12);
  145. }
  146. else {
  147. let additional: string[] = ["texpaint_nor_picker", "texpaint_pack_picker", "texpaint_uv_picker"];
  148. render_path_set_target("texpaint_picker", additional);
  149. render_path_bind_target("gbuffer2", "gbuffer2");
  150. tid = context_raw.layer.id;
  151. let use_live_layer: bool = context_raw.tool == workspace_tool_t.MATERIAL;
  152. if (use_live_layer) {
  153. render_path_paint_use_live_layer(true);
  154. }
  155. render_path_bind_target("texpaint" + tid, "texpaint");
  156. render_path_bind_target("texpaint_nor" + tid, "texpaint_nor");
  157. render_path_bind_target("texpaint_pack" + tid, "texpaint_pack");
  158. render_path_paint_draw_fullscreen_triangle("paint");
  159. if (use_live_layer) {
  160. render_path_paint_use_live_layer(false);
  161. }
  162. ui_header_handle.redraws = 2;
  163. ui_base_hwnds[2].redraws = 2;
  164. let texpaint_picker: render_target_t = map_get(render_path_render_targets, "texpaint_picker");
  165. let texpaint_nor_picker: render_target_t = map_get(render_path_render_targets, "texpaint_nor_picker");
  166. let texpaint_pack_picker: render_target_t = map_get(render_path_render_targets, "texpaint_pack_picker");
  167. let texpaint_uv_picker: render_target_t = map_get(render_path_render_targets, "texpaint_uv_picker");
  168. let a: buffer_t = gpu_get_texture_pixels(texpaint_picker._image);
  169. let b: buffer_t = gpu_get_texture_pixels(texpaint_nor_picker._image);
  170. let c: buffer_t = gpu_get_texture_pixels(texpaint_pack_picker._image);
  171. let d: buffer_t = gpu_get_texture_pixels(texpaint_uv_picker._image);
  172. if (context_raw.color_picker_callback != null) {
  173. context_raw.color_picker_callback(context_raw.picked_color);
  174. }
  175. // Picked surface values
  176. ///if (arm_metal || arm_vulkan)
  177. let i0: i32 = 2;
  178. let i1: i32 = 1;
  179. let i2: i32 = 0;
  180. ///else
  181. let i0: i32 = 0;
  182. let i1: i32 = 1;
  183. let i2: i32 = 2;
  184. ///end
  185. let i3: i32 = 3;
  186. context_raw.picked_color.base = color_set_rb(context_raw.picked_color.base, buffer_get_u8(a, i0));
  187. context_raw.picked_color.base = color_set_gb(context_raw.picked_color.base, buffer_get_u8(a, i1));
  188. context_raw.picked_color.base = color_set_bb(context_raw.picked_color.base, buffer_get_u8(a, i2));
  189. context_raw.picked_color.normal = color_set_rb(context_raw.picked_color.normal, buffer_get_u8(b, i0));
  190. context_raw.picked_color.normal = color_set_gb(context_raw.picked_color.normal, buffer_get_u8(b, i1));
  191. context_raw.picked_color.normal = color_set_bb(context_raw.picked_color.normal, buffer_get_u8(b, i2));
  192. context_raw.picked_color.occlusion = buffer_get_u8(c, i0) / 255;
  193. context_raw.picked_color.roughness = buffer_get_u8(c, i1) / 255;
  194. context_raw.picked_color.metallic = buffer_get_u8(c, i2) / 255;
  195. context_raw.picked_color.height = buffer_get_u8(c, i3) / 255;
  196. context_raw.picked_color.opacity = buffer_get_u8(a, i3) / 255;
  197. context_raw.uvx_picked = buffer_get_u8(d, i0) / 255;
  198. context_raw.uvy_picked = buffer_get_u8(d, i1) / 255;
  199. // Pick material
  200. if (context_raw.picker_select_material && context_raw.color_picker_callback == null) {
  201. // matid % 3 == 0 - normal, 1 - emission, 2 - subsurface
  202. let id: i32 = buffer_get_u8(b, 3);
  203. let matid: i32 = math_floor((id - (id % 3)) / 3);
  204. for (let i: i32 = 0; i < project_materials.length; ++i) {
  205. let m: slot_material_t = project_materials[i];
  206. if (m.id == matid) {
  207. context_set_material(m);
  208. context_raw.materialid_picked = matid;
  209. break;
  210. }
  211. }
  212. }
  213. }
  214. }
  215. else {
  216. let texpaint: string = "texpaint" + tid;
  217. if (context_raw.tool == workspace_tool_t.BAKE && context_raw.brush_time == sys_delta()) {
  218. // Clear to black on bake start
  219. render_path_set_target(texpaint, null, null, clear_flag_t.COLOR, 0xff000000);
  220. }
  221. render_path_set_target("texpaint_blend1");
  222. render_path_bind_target("texpaint_blend0", "tex");
  223. render_path_draw_shader("shader_datas/copy_pass/copyR8_pass");
  224. let is_mask: bool = slot_layer_is_mask(context_raw.layer);
  225. if (is_mask) {
  226. let ptid: i32 = context_raw.layer.parent.id;
  227. if (slot_layer_is_group(context_raw.layer.parent)) { // Group mask
  228. for (let i: i32 = 0; i < slot_layer_get_children(context_raw.layer.parent).length; ++i) {
  229. let c: slot_layer_t = slot_layer_get_children(context_raw.layer.parent)[i];
  230. ptid = c.id;
  231. break;
  232. }
  233. }
  234. let additional: string[] = ["texpaint_nor" + ptid, "texpaint_pack" + ptid, "texpaint_blend0"];
  235. render_path_set_target(texpaint, additional);
  236. }
  237. else {
  238. let additional: string[] = ["texpaint_nor" + tid, "texpaint_pack" + tid, "texpaint_blend0"];
  239. render_path_set_target(texpaint, additional);
  240. }
  241. render_path_bind_target("main", "gbufferD");
  242. if ((context_raw.xray || config_raw.brush_angle_reject) && config_raw.brush_3d) {
  243. render_path_bind_target("gbuffer0", "gbuffer0");
  244. }
  245. render_path_bind_target("texpaint_blend1", "paintmask");
  246. if (context_raw.colorid_picked) {
  247. render_path_bind_target("texpaint_colorid", "texpaint_colorid");
  248. }
  249. // Read texcoords from gbuffer
  250. let read_tc: bool = (context_raw.tool == workspace_tool_t.FILL && context_raw.fill_type_handle.position == fill_type_t.FACE) ||
  251. context_raw.tool == workspace_tool_t.CLONE ||
  252. context_raw.tool == workspace_tool_t.BLUR ||
  253. context_raw.tool == workspace_tool_t.SMUDGE;
  254. if (read_tc) {
  255. render_path_bind_target("gbuffer2", "gbuffer2");
  256. }
  257. render_path_draw_meshes("paint");
  258. if (context_raw.tool == workspace_tool_t.BAKE && context_raw.bake_type == bake_type_t.CURVATURE && context_raw.bake_curv_smooth > 0) {
  259. if (map_get(render_path_render_targets, "texpaint_blur") == null) {
  260. let t: render_target_t = render_target_create();
  261. t.name = "texpaint_blur";
  262. t.width = math_floor(config_get_texture_res_x() * 0.95);
  263. t.height = math_floor(config_get_texture_res_y() * 0.95);
  264. t.format = "RGBA32";
  265. render_path_create_render_target(t);
  266. }
  267. let blurs: i32 = math_round(context_raw.bake_curv_smooth);
  268. for (let i: i32 = 0; i < blurs; ++i) {
  269. render_path_set_target("texpaint_blur");
  270. render_path_bind_target(texpaint, "tex");
  271. render_path_draw_shader("shader_datas/copy_pass/copy_pass");
  272. render_path_set_target(texpaint);
  273. render_path_bind_target("texpaint_blur", "tex");
  274. render_path_draw_shader("shader_datas/copy_pass/copy_pass");
  275. }
  276. }
  277. if (dilation && config_raw.dilate == dilate_type_t.INSTANT) {
  278. render_path_paint_dilate(true, false);
  279. }
  280. }
  281. }
  282. }
  283. function render_path_paint_use_live_layer(use: bool) {
  284. let tid: i32 = context_raw.layer.id;
  285. let hid: i32 = history_undo_i - 1 < 0 ? config_raw.undo_steps - 1 : history_undo_i - 1;
  286. if (use) {
  287. _render_path_paint_texpaint = map_get(render_path_render_targets, "texpaint" + tid);
  288. _render_path_paint_texpaint_undo = map_get(render_path_render_targets, "texpaint_undo" + hid);
  289. _render_path_paint_texpaint_nor_undo = map_get(render_path_render_targets, "texpaint_nor_undo" + hid);
  290. _render_path_paint_texpaint_pack_undo = map_get(render_path_render_targets, "texpaint_pack_undo" + hid);
  291. _render_path_paint_texpaint_nor = map_get(render_path_render_targets, "texpaint_nor" + tid);
  292. _render_path_paint_texpaint_pack = map_get(render_path_render_targets, "texpaint_pack" + tid);
  293. map_set(render_path_render_targets, "texpaint_undo" + hid, map_get(render_path_render_targets, "texpaint" + tid));
  294. map_set(render_path_render_targets, "texpaint" + tid, map_get(render_path_render_targets, "texpaint_live"));
  295. if (slot_layer_is_layer(context_raw.layer)) {
  296. map_set(render_path_render_targets, "texpaint_nor_undo" + hid, map_get(render_path_render_targets, "texpaint_nor" + tid));
  297. map_set(render_path_render_targets, "texpaint_pack_undo" + hid, map_get(render_path_render_targets, "texpaint_pack" + tid));
  298. map_set(render_path_render_targets, "texpaint_nor" + tid, map_get(render_path_render_targets, "texpaint_nor_live"));
  299. map_set(render_path_render_targets, "texpaint_pack" + tid, map_get(render_path_render_targets, "texpaint_pack_live"));
  300. }
  301. }
  302. else {
  303. map_set(render_path_render_targets, "texpaint" + tid, _render_path_paint_texpaint);
  304. map_set(render_path_render_targets, "texpaint_undo" + hid, _render_path_paint_texpaint_undo);
  305. if (slot_layer_is_layer(context_raw.layer)) {
  306. map_set(render_path_render_targets, "texpaint_nor_undo" + hid, _render_path_paint_texpaint_nor_undo);
  307. map_set(render_path_render_targets, "texpaint_pack_undo" + hid, _render_path_paint_texpaint_pack_undo);
  308. map_set(render_path_render_targets, "texpaint_nor" + tid, _render_path_paint_texpaint_nor);
  309. map_set(render_path_render_targets, "texpaint_pack" + tid, _render_path_paint_texpaint_pack);
  310. }
  311. }
  312. render_path_paint_live_layer_locked = use;
  313. }
  314. function render_path_paint_commands_live_brush() {
  315. let tool: workspace_tool_t = context_raw.tool;
  316. if (tool != workspace_tool_t.BRUSH &&
  317. tool != workspace_tool_t.ERASER &&
  318. tool != workspace_tool_t.CLONE &&
  319. tool != workspace_tool_t.DECAL &&
  320. tool != workspace_tool_t.TEXT &&
  321. tool != workspace_tool_t.BLUR &&
  322. tool != workspace_tool_t.SMUDGE) {
  323. return;
  324. }
  325. if (render_path_paint_live_layer_locked) {
  326. return;
  327. }
  328. if (render_path_paint_live_layer == null) {
  329. render_path_paint_live_layer = slot_layer_create("_live");
  330. }
  331. let tid: i32 = context_raw.layer.id;
  332. if (slot_layer_is_mask(context_raw.layer)) {
  333. render_path_set_target("texpaint_live");
  334. render_path_bind_target("texpaint" + tid, "tex");
  335. render_path_draw_shader("shader_datas/copy_pass/copy_pass");
  336. }
  337. else {
  338. let additional: string[] = ["texpaint_nor_live", "texpaint_pack_live"];
  339. render_path_set_target("texpaint_live", additional);
  340. render_path_bind_target("texpaint" + tid, "tex0");
  341. render_path_bind_target("texpaint_nor" + tid, "tex1");
  342. render_path_bind_target("texpaint_pack" + tid, "tex2");
  343. render_path_draw_shader("shader_datas/copy_mrt3_pass/copy_mrt3_pass");
  344. }
  345. render_path_paint_use_live_layer(true);
  346. render_path_paint_live_layer_drawn = 2;
  347. ui_view2d_hwnd.redraws = 2;
  348. let _x: f32 = context_raw.paint_vec.x;
  349. let _y: f32 = context_raw.paint_vec.y;
  350. if (context_raw.brush_locked) {
  351. context_raw.paint_vec.x = (context_raw.lock_started_x - sys_x()) / sys_w();
  352. context_raw.paint_vec.y = (context_raw.lock_started_y - sys_y()) / sys_h();
  353. }
  354. let _last_x: f32 = context_raw.last_paint_vec_x;
  355. let _last_y: f32 = context_raw.last_paint_vec_y;
  356. let _pdirty: i32 = context_raw.pdirty;
  357. context_raw.last_paint_vec_x = context_raw.paint_vec.x;
  358. context_raw.last_paint_vec_y = context_raw.paint_vec.y;
  359. if (operator_shortcut(map_get(config_keymap, "brush_ruler"))) {
  360. context_raw.last_paint_vec_x = context_raw.last_paint_x;
  361. context_raw.last_paint_vec_y = context_raw.last_paint_y;
  362. }
  363. context_raw.pdirty = 2;
  364. render_path_paint_commands_symmetry();
  365. render_path_paint_commands_paint();
  366. render_path_paint_use_live_layer(false);
  367. context_raw.paint_vec.x = _x;
  368. context_raw.paint_vec.y = _y;
  369. context_raw.last_paint_vec_x = _last_x;
  370. context_raw.last_paint_vec_y = _last_y;
  371. context_raw.pdirty = _pdirty;
  372. context_raw.brush_blend_dirty = true;
  373. }
  374. function render_path_paint_commands_cursor() {
  375. if (!config_raw.brush_3d) {
  376. return;
  377. }
  378. let decal_mask: bool = context_is_decal_mask();
  379. let tool: workspace_tool_t = context_raw.tool;
  380. if (tool != workspace_tool_t.BRUSH &&
  381. tool != workspace_tool_t.ERASER &&
  382. tool != workspace_tool_t.CLONE &&
  383. tool != workspace_tool_t.BLUR &&
  384. tool != workspace_tool_t.SMUDGE &&
  385. tool != workspace_tool_t.PARTICLE &&
  386. !decal_mask) {
  387. return;
  388. }
  389. let fill_layer: bool = context_raw.layer.fill_layer != null;
  390. let group_layer: bool = slot_layer_is_group(context_raw.layer);
  391. if (!base_ui_enabled || base_is_dragging || fill_layer || group_layer) {
  392. return;
  393. }
  394. let mx: f32 = context_raw.paint_vec.x;
  395. let my: f32 = 1.0 - context_raw.paint_vec.y;
  396. if (context_raw.brush_locked) {
  397. mx = (context_raw.lock_started_x - sys_x()) / sys_w();
  398. my = 1.0 - (context_raw.lock_started_y - sys_y()) / sys_h();
  399. }
  400. let radius: f32 = decal_mask ? context_raw.brush_decal_mask_radius : context_raw.brush_radius;
  401. render_path_paint_draw_cursor(mx, my, context_raw.brush_nodes_radius * radius / 3.4);
  402. }
  403. function render_path_paint_draw_cursor(mx: f32, my: f32, radius: f32, tint_r: f32 = 1.0, tint_g: f32 = 1.0, tint_b: f32 = 1.0) {
  404. let plane: mesh_object_t = scene_get_child(".Plane").ext;
  405. let geom: mesh_data_t = plane.data;
  406. render_path_set_target("");
  407. gpu_set_pipeline(pipes_cursor);
  408. let rt: render_target_t = map_get(render_path_render_targets, "main");
  409. let main: gpu_texture_t = rt._image;
  410. gpu_set_texture(pipes_cursor_gbufferd, main);
  411. gpu_set_float2(pipes_cursor_mouse, mx, my);
  412. gpu_set_float2(pipes_cursor_tex_step, 1 / main.width, 1 / main.height);
  413. gpu_set_float(pipes_cursor_radius, radius);
  414. let right: vec4_t = vec4_norm(camera_object_right_world(scene_camera));
  415. gpu_set_float3(pipes_cursor_camera_right, right.x, right.y, right.z);
  416. gpu_set_float3(pipes_cursor_tint, tint_r, tint_g, tint_b);
  417. gpu_set_matrix4(pipes_cursor_vp, scene_camera.vp);
  418. let inv_vp: mat4_t = mat4_inv(scene_camera.vp);
  419. gpu_set_matrix4(pipes_cursor_inv_vp, inv_vp);
  420. gpu_set_vertex_buffer(geom._.vertex_buffer);
  421. gpu_set_index_buffer(geom._.index_buffers[0]);
  422. gpu_draw();
  423. render_path_end();
  424. }
  425. function render_path_paint_commands_symmetry() {
  426. if (context_raw.sym_x || context_raw.sym_y || context_raw.sym_z) {
  427. context_raw.ddirty = 2;
  428. let t: transform_t = context_raw.paint_object.base.transform;
  429. let sx: f32 = t.scale.x;
  430. let sy: f32 = t.scale.y;
  431. let sz: f32 = t.scale.z;
  432. if (context_raw.sym_x) {
  433. t.scale = vec4_create(-sx, sy, sz);
  434. transform_build_matrix(t);
  435. render_path_paint_commands_paint(false);
  436. }
  437. if (context_raw.sym_y) {
  438. t.scale = vec4_create(sx, -sy, sz);
  439. transform_build_matrix(t);
  440. render_path_paint_commands_paint(false);
  441. }
  442. if (context_raw.sym_z) {
  443. t.scale = vec4_create(sx, sy, -sz);
  444. transform_build_matrix(t);
  445. render_path_paint_commands_paint(false);
  446. }
  447. if (context_raw.sym_x && context_raw.sym_y) {
  448. t.scale = vec4_create(-sx, -sy, sz);
  449. transform_build_matrix(t);
  450. render_path_paint_commands_paint(false);
  451. }
  452. if (context_raw.sym_x && context_raw.sym_z) {
  453. t.scale = vec4_create(-sx, sy, -sz);
  454. transform_build_matrix(t);
  455. render_path_paint_commands_paint(false);
  456. }
  457. if (context_raw.sym_y && context_raw.sym_z) {
  458. t.scale = vec4_create(sx, -sy, -sz);
  459. transform_build_matrix(t);
  460. render_path_paint_commands_paint(false);
  461. }
  462. if (context_raw.sym_x && context_raw.sym_y && context_raw.sym_z) {
  463. t.scale = vec4_create(-sx, -sy, -sz);
  464. transform_build_matrix(t);
  465. render_path_paint_commands_paint(false);
  466. }
  467. t.scale = vec4_create(sx, sy, sz);
  468. transform_build_matrix(t);
  469. }
  470. }
  471. function render_path_paint_paint_enabled(): bool {
  472. let fill_layer: bool = context_raw.layer.fill_layer != null && context_raw.tool != workspace_tool_t.PICKER && context_raw.tool != workspace_tool_t.MATERIAL && context_raw.tool != workspace_tool_t.COLORID;
  473. let group_layer: bool = slot_layer_is_group(context_raw.layer);
  474. let gizmo: bool = context_raw.tool == workspace_tool_t.GIZMO;
  475. return !fill_layer && !group_layer && !context_raw.foreground_event && !gizmo;
  476. }
  477. function render_path_paint_live_brush_dirty() {
  478. let mx: f32 = render_path_paint_last_x;
  479. let my: f32 = render_path_paint_last_y;
  480. render_path_paint_last_x = mouse_view_x();
  481. render_path_paint_last_y = mouse_view_y();
  482. if (config_raw.brush_live && context_raw.pdirty <= 0) {
  483. let moved: bool = (mx != render_path_paint_last_x || my != render_path_paint_last_y) && (context_in_viewport() || context_in_2d_view());
  484. if (moved || context_raw.brush_locked) {
  485. context_raw.rdirty = 2;
  486. }
  487. }
  488. }
  489. function render_path_paint_begin() {
  490. if (!render_path_paint_dilated) {
  491. render_path_paint_dilate(config_raw.dilate == dilate_type_t.DELAYED, true);
  492. render_path_paint_dilated = true;
  493. }
  494. if (!render_path_paint_paint_enabled()) {
  495. return;
  496. }
  497. render_path_paint_push_undo_last = history_push_undo;
  498. if (history_push_undo && history_undo_layers != null) {
  499. history_paint();
  500. }
  501. if (context_raw.paint2d) {
  502. render_path_paint_set_plane_mesh();
  503. }
  504. if (render_path_paint_live_layer_drawn > 0) {
  505. render_path_paint_live_layer_drawn--;
  506. }
  507. if (config_raw.brush_live && context_raw.pdirty <= 0 && context_raw.ddirty <= 0 && context_raw.brush_time == 0) {
  508. // Depth is unchanged, draw before gbuffer gets updated
  509. render_path_paint_commands_live_brush();
  510. }
  511. }
  512. function render_path_paint_end() {
  513. context_raw.ddirty--;
  514. context_raw.rdirty--;
  515. if (!render_path_paint_paint_enabled()) {
  516. return;
  517. }
  518. context_raw.pdirty--;
  519. }
  520. let _render_path_paint_bake_type: bake_type_t;
  521. function _render_path_paint_final() {
  522. context_raw.bake_type = _render_path_paint_bake_type;
  523. make_material_parse_paint_material();
  524. context_raw.pdirty = 1;
  525. render_path_paint_commands_paint();
  526. context_raw.pdirty = 0;
  527. render_path_paint_baking = false;
  528. }
  529. function _render_path_paint_deriv() {
  530. context_raw.bake_type = bake_type_t.HEIGHT;
  531. make_material_parse_paint_material();
  532. context_raw.pdirty = 1;
  533. render_path_paint_commands_paint();
  534. context_raw.pdirty = 0;
  535. if (render_path_paint_push_undo_last) {
  536. history_paint();
  537. }
  538. sys_notify_on_init(_render_path_paint_final);
  539. }
  540. function render_path_paint_is_rt_bake(): bool {
  541. return (context_raw.bake_type == bake_type_t.AO ||
  542. context_raw.bake_type == bake_type_t.LIGHTMAP ||
  543. context_raw.bake_type == bake_type_t.BENT_NORMAL ||
  544. context_raw.bake_type == bake_type_t.THICKNESS);
  545. }
  546. function render_path_paint_update_bake_layer(bits: texture_bits_t) {
  547. // Use RGBA128 texture format for high poly to low poly baking to prevent artifacts
  548. // Existing undo layers are used during the baking process for now
  549. if (base_bits_handle.position != texture_bits_t.BITS32) {
  550. base_bits_handle.position = bits;
  551. slot_layer_resize_and_set_bits(context_raw.layer);
  552. for (let i: i32 = 0; i < history_undo_layers.length; ++i) {
  553. let l: slot_layer_t = history_undo_layers[i];
  554. slot_layer_resize_and_set_bits(l);
  555. }
  556. base_bits_handle.position = texture_bits_t.BITS8;
  557. }
  558. }
  559. function render_path_paint_draw() {
  560. if (!render_path_paint_paint_enabled()) {
  561. return;
  562. }
  563. ///if (!arm_ios) // No hover on iPad, decals are painted by pen release
  564. if (config_raw.brush_live && context_raw.pdirty <= 0 && context_raw.ddirty > 0 && context_raw.brush_time == 0) {
  565. // gbuffer has been updated now but brush will lag 1 frame
  566. render_path_paint_commands_live_brush();
  567. }
  568. ///end
  569. if (history_undo_layers != null) {
  570. render_path_paint_commands_symmetry();
  571. if (context_raw.pdirty > 0) {
  572. render_path_paint_dilated = false;
  573. }
  574. if (context_raw.tool == workspace_tool_t.BAKE) {
  575. if (context_raw.bake_type == bake_type_t.NORMAL || context_raw.bake_type == bake_type_t.HEIGHT || context_raw.bake_type == bake_type_t.DERIVATIVE) {
  576. if (!render_path_paint_baking && context_raw.pdirty > 0) {
  577. render_path_paint_update_bake_layer(texture_bits_t.BITS32);
  578. render_path_paint_baking = true;
  579. _render_path_paint_bake_type = context_raw.bake_type;
  580. context_raw.bake_type = context_raw.bake_type == bake_type_t.NORMAL ? bake_type_t.NORMAL_OBJECT : bake_type_t.POSITION; // Bake high poly data
  581. make_material_parse_paint_material();
  582. let _paint_object: mesh_object_t = context_raw.paint_object;
  583. let high_poly: mesh_object_t = project_paint_objects[context_raw.bake_high_poly];
  584. let _visible: bool = high_poly.base.visible;
  585. high_poly.base.visible = true;
  586. context_select_paint_object(high_poly);
  587. render_path_paint_commands_paint();
  588. high_poly.base.visible = _visible;
  589. if (render_path_paint_push_undo_last) {
  590. history_paint();
  591. }
  592. context_select_paint_object(_paint_object);
  593. if (context_raw.bake_type == bake_type_t.DERIVATIVE) {
  594. sys_notify_on_init(_render_path_paint_deriv);
  595. }
  596. else {
  597. sys_notify_on_init(_render_path_paint_final);
  598. }
  599. }
  600. }
  601. else if (context_raw.bake_type == bake_type_t.OBJECTID) {
  602. let _layer_filter: i32 = context_raw.layer_filter;
  603. let _paint_object: mesh_object_t = context_raw.paint_object;
  604. let is_merged: bool = context_raw.merged_object != null;
  605. let _visible: bool = is_merged && context_raw.merged_object.base.visible;
  606. context_raw.layer_filter = 1;
  607. if (is_merged) {
  608. context_raw.merged_object.base.visible = false;
  609. }
  610. for (let i: i32 = 0; i < project_paint_objects.length; ++i) {
  611. let p: mesh_object_t = project_paint_objects[i];
  612. context_select_paint_object(p);
  613. render_path_paint_commands_paint();
  614. }
  615. context_raw.layer_filter = _layer_filter;
  616. context_select_paint_object(_paint_object);
  617. if (is_merged) context_raw.merged_object.base.visible = _visible;
  618. }
  619. else if (render_path_paint_is_rt_bake()) {
  620. let dirty: bool = render_path_raytrace_bake_commands(make_material_parse_paint_material);
  621. if (dirty) ui_header_handle.redraws = 2;
  622. if (config_raw.dilate == dilate_type_t.INSTANT) { // && raw.pdirty == 1
  623. render_path_paint_dilate(true, false);
  624. }
  625. }
  626. else {
  627. render_path_paint_commands_paint();
  628. }
  629. }
  630. else { // Paint
  631. render_path_paint_commands_paint();
  632. }
  633. }
  634. if (context_raw.brush_blend_dirty) {
  635. context_raw.brush_blend_dirty = false;
  636. render_path_set_target("texpaint_blend0", null, null, clear_flag_t.COLOR, 0x00000000);
  637. render_path_set_target("texpaint_blend1", null, null, clear_flag_t.COLOR, 0x00000000);
  638. render_path_end();
  639. }
  640. if (context_raw.paint2d) {
  641. render_path_paint_restore_plane_mesh();
  642. }
  643. }
  644. function render_path_paint_set_plane_mesh() {
  645. context_raw.paint2d_view = true;
  646. render_path_paint_painto = context_raw.paint_object;
  647. render_path_paint_visibles = [];
  648. for (let i: i32 = 0; i < project_paint_objects.length; ++i) {
  649. let p: mesh_object_t = project_paint_objects[i];
  650. array_push(render_path_paint_visibles, p.base.visible);
  651. p.base.visible = false;
  652. }
  653. if (context_raw.merged_object != null) {
  654. render_path_paint_merged_object_visible = context_raw.merged_object.base.visible;
  655. context_raw.merged_object.base.visible = false;
  656. }
  657. let cam: camera_object_t = scene_camera;
  658. context_raw.saved_camera = mat4_clone(cam.base.transform.local);
  659. render_path_paint_saved_fov = cam.data.fov;
  660. viewport_update_camera_type(camera_type_t.PERSPECTIVE);
  661. let m: mat4_t = mat4_identity();
  662. m = mat4_translate(m, 0, 0, 0.5);
  663. transform_set_matrix(cam.base.transform, m);
  664. cam.data.fov = base_default_fov;
  665. camera_object_build_proj(cam);
  666. camera_object_build_mat(cam);
  667. let tw: f32 = 0.95 * ui_view2d_pan_scale;
  668. let tx: f32 = ui_view2d_pan_x / ui_view2d_ww;
  669. let ty: f32 = ui_view2d_pan_y / sys_h();
  670. m = mat4_identity();
  671. m = mat4_scale(m, vec4_create(tw, tw, 1));
  672. m = mat4_set_loc(m, vec4_create(tx, ty, 0));
  673. let m2: mat4_t = mat4_identity();
  674. m2 = mat4_inv(scene_camera.vp);
  675. m = mat4_mult_mat(m, m2);
  676. let tiled: bool = ui_view2d_tiled_show;
  677. if (tiled && scene_get_child(".PlaneTiled") == null) {
  678. // 3x3 planes
  679. let posa: i16[] = [32767,0,-32767,0,10922,0,-10922,0,10922,0,-32767,0,10922,0,-10922,0,-10922,0,10922,0,-10922,0,-10922,0,-10922,0,10922,0,-32767,0,32767,0,-32767,0,10922,0,10922,0,10922,0,-10922,0,32767,0,-10922,0,10922,0,32767,0,10922,0,10922,0,32767,0,10922,0,10922,0,-10922,0,-10922,0,-32767,0,10922,0,-32767,0,-10922,0,32767,0,-10922,0,10922,0,10922,0,10922,0,-10922,0,-10922,0,-32767,0,-32767,0,-10922,0,-32767,0,-32767,0,10922,0,-32767,0,-10922,0,-10922,0,-10922,0,-32767,0,32767,0,-32767,0,32767,0,-10922,0,10922,0,-10922,0,10922,0,-10922,0,10922,0,10922,0,-10922,0,10922,0,-10922,0,10922,0,-10922,0,32767,0,-32767,0,32767,0,10922,0,10922,0,10922,0,32767,0,-10922,0,32767,0,32767,0,10922,0,32767,0,32767,0,10922,0,32767,0,-10922,0,-10922,0,-10922,0,10922,0,-32767,0,10922,0,32767,0,-10922,0,32767,0,10922,0,10922,0,10922,0,-10922,0,-32767,0,-10922,0,-10922,0,-32767,0,-10922,0,10922,0,-32767,0,10922,0,-10922,0,-10922,0,-10922,0];
  680. let nora: i16[] = [0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767,0,-32767];
  681. let texa: i16[] = [32767,32767,0,0,0,32767,32767,32767,0,0,0,32767,32767,32767,0,0,0,32767,32767,32767,0,0,0,32767,32767,32767,0,0,0,32767,32767,32767,0,0,0,32767,32767,32767,0,0,0,32767,32767,32767,0,0,0,32767,32767,32767,0,0,0,32767,32767,32767,32767,0,0,0,32767,32767,32767,0,0,0,32767,32767,32767,0,0,0,32767,32767,32767,0,0,0,32767,32767,32767,0,0,0,32767,32767,32767,0,0,0,32767,32767,32767,0,0,0,32767,32767,32767,0,0,0,32767,32767,32767,0,0,0];
  682. let inda: u32[] = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53];
  683. let raw: mesh_data_t = {
  684. name: ".PlaneTiled",
  685. vertex_arrays: [
  686. { attrib: "pos", values: i16_array_create_from_array(posa), data: "short4norm" },
  687. { attrib: "nor", values: i16_array_create_from_array(nora), data: "short2norm" },
  688. { attrib: "tex", values: i16_array_create_from_array(texa), data: "short2norm" }
  689. ],
  690. index_arrays: [
  691. { values: u32_array_create_from_array(inda), material: 0 }
  692. ],
  693. scale_pos: 1.5,
  694. scale_tex: 1.0
  695. };
  696. let md: mesh_data_t = mesh_data_create(raw);
  697. let mo: mesh_object_t = scene_get_child(".Plane").ext;
  698. let materials: material_data_t[] = mo.materials;
  699. let o: mesh_object_t = scene_add_mesh_object(md, materials);
  700. o.base.name = ".PlaneTiled";
  701. }
  702. render_path_paint_planeo = scene_get_child(tiled ? ".PlaneTiled" : ".Plane").ext;
  703. render_path_paint_planeo.base.visible = true;
  704. context_raw.paint_object = render_path_paint_planeo;
  705. let v: vec4_t = vec4_create();
  706. v = vec4_create(m.m00, m.m01, m.m02);
  707. let sx: f32 = vec4_len(v);
  708. render_path_paint_planeo.base.transform.rot = quat_from_euler(-math_pi() / 2, 0, 0);
  709. render_path_paint_planeo.base.transform.scale = vec4_create(sx, 1.0, sx);
  710. render_path_paint_planeo.base.transform.scale.z *= config_get_texture_res_y() / config_get_texture_res_x();
  711. render_path_paint_planeo.base.transform.loc = vec4_create(m.m30, -m.m31, 0.0);
  712. transform_build_matrix(render_path_paint_planeo.base.transform);
  713. }
  714. function render_path_paint_restore_plane_mesh() {
  715. context_raw.paint2d_view = false;
  716. render_path_paint_planeo.base.visible = false;
  717. render_path_paint_planeo.base.transform.loc = vec4_create(0.0, 0.0, 0.0);
  718. for (let i: i32 = 0; i < project_paint_objects.length; ++i) {
  719. project_paint_objects[i].base.visible = render_path_paint_visibles[i];
  720. }
  721. if (context_raw.merged_object != null) {
  722. context_raw.merged_object.base.visible = render_path_paint_merged_object_visible;
  723. }
  724. context_raw.paint_object = render_path_paint_painto;
  725. transform_set_matrix(scene_camera.base.transform, context_raw.saved_camera);
  726. scene_camera.data.fov = render_path_paint_saved_fov;
  727. viewport_update_camera_type(context_raw.camera_type);
  728. camera_object_build_proj(scene_camera);
  729. camera_object_build_mat(scene_camera);
  730. render_path_base_draw_gbuffer();
  731. }
  732. function render_path_paint_bind_layers() {
  733. let is_live: bool = config_raw.brush_live && render_path_paint_live_layer_drawn > 0;
  734. let is_material_tool: bool = context_raw.tool == workspace_tool_t.MATERIAL;
  735. if (is_live || is_material_tool) {
  736. render_path_paint_use_live_layer(true);
  737. }
  738. for (let i: i32 = 0; i < project_layers.length; ++i) {
  739. let l: slot_layer_t = project_layers[i];
  740. render_path_bind_target("texpaint" + l.id, "texpaint" + l.id);
  741. if (slot_layer_is_layer(l)) {
  742. render_path_bind_target("texpaint_nor" + l.id, "texpaint_nor" + l.id);
  743. render_path_bind_target("texpaint_pack" + l.id, "texpaint_pack" + l.id);
  744. }
  745. }
  746. }
  747. function render_path_paint_unbind_layers() {
  748. let is_live: bool = config_raw.brush_live && render_path_paint_live_layer_drawn > 0;
  749. let is_material_tool: bool = context_raw.tool == workspace_tool_t.MATERIAL;
  750. if (is_live || is_material_tool) {
  751. render_path_paint_use_live_layer(false);
  752. }
  753. }
  754. function render_path_paint_dilate(base: bool, nor_pack: bool) {
  755. if (config_raw.dilate_radius > 0 && !context_raw.paint2d) {
  756. util_uv_cache_dilate_map();
  757. layers_make_temp_img();
  758. let tid: i32 = context_raw.layer.id;
  759. let format: string = base_bits_handle.position == texture_bits_t.BITS8 ? "RGBA32" :
  760. base_bits_handle.position == texture_bits_t.BITS16 ? "RGBA64" :
  761. "RGBA128";
  762. let copy_pass: string = format == "RGBA64" ? "copyRGBA64_pass" :
  763. format == "RGBA128" ? "copyRGBA128_pass" :
  764. "copy_pass";
  765. let dilate_pass: string = format == "RGBA64" ? "dilateRGBA64_pass" :
  766. format == "RGBA128" ? "dilateRGBA128_pass" :
  767. "dilate_pass";
  768. if (base) {
  769. let texpaint: string = "texpaint";
  770. render_path_set_target("temptex0");
  771. render_path_bind_target(texpaint + tid, "tex");
  772. render_path_draw_shader("shader_datas/copy_pass/" + copy_pass);
  773. render_path_set_target(texpaint + tid);
  774. render_path_bind_target("temptex0", "tex");
  775. render_path_draw_shader("shader_datas/dilate_pass/" + dilate_pass);
  776. }
  777. if (nor_pack && !slot_layer_is_mask(context_raw.layer)) {
  778. render_path_set_target("temptex0");
  779. render_path_bind_target("texpaint_nor" + tid, "tex");
  780. render_path_draw_shader("shader_datas/copy_pass/" + copy_pass);
  781. render_path_set_target("texpaint_nor" + tid);
  782. render_path_bind_target("temptex0", "tex");
  783. render_path_draw_shader("shader_datas/dilate_pass/" + dilate_pass);
  784. render_path_set_target("temptex0");
  785. render_path_bind_target("texpaint_pack" + tid, "tex");
  786. render_path_draw_shader("shader_datas/copy_pass/" + copy_pass);
  787. render_path_set_target("texpaint_pack" + tid);
  788. render_path_bind_target("temptex0", "tex");
  789. render_path_draw_shader("shader_datas/dilate_pass/" + dilate_pass);
  790. }
  791. }
  792. }