RenderPathPaint.hx 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857
  1. package arm.render;
  2. import iron.math.Mat4;
  3. import iron.math.Vec4;
  4. import iron.system.Input;
  5. import iron.object.MeshObject;
  6. import iron.data.SceneFormat;
  7. import iron.data.MeshData;
  8. import iron.RenderPath;
  9. import iron.Scene;
  10. import arm.Viewport;
  11. import arm.ui.UIView2D;
  12. import arm.ui.UIHeader;
  13. import arm.ui.UIStatus;
  14. import arm.node.MakeMaterial;
  15. import arm.Enums;
  16. class RenderPathPaint {
  17. public static var dilated = true;
  18. public static var liveLayer: arm.data.LayerSlot = null;
  19. public static var liveLayerDrawn = 0;
  20. public static var liveLayerLocked = false;
  21. static var path: RenderPath;
  22. static var initVoxels = true; // Bake AO
  23. static var pushUndoLast: Bool;
  24. static var painto: MeshObject = null;
  25. static var planeo: MeshObject = null;
  26. static var visibles: Array<Bool> = null;
  27. static var mergedObjectVisible = false;
  28. static var savedFov = 0.0;
  29. static var baking = false;
  30. static var _texpaint: RenderTarget;
  31. static var _texpaint_nor: RenderTarget;
  32. static var _texpaint_pack: RenderTarget;
  33. static var _texpaint_undo: RenderTarget;
  34. static var _texpaint_nor_undo: RenderTarget;
  35. static var _texpaint_pack_undo: RenderTarget;
  36. public static function init(_path: RenderPath) {
  37. path = _path;
  38. {
  39. var t = new RenderTargetRaw();
  40. t.name = "texpaint_blend0";
  41. t.width = Config.getTextureResX();
  42. t.height = Config.getTextureResY();
  43. t.format = "R8";
  44. path.createRenderTarget(t);
  45. }
  46. {
  47. var t = new RenderTargetRaw();
  48. t.name = "texpaint_blend1";
  49. t.width = Config.getTextureResX();
  50. t.height = Config.getTextureResY();
  51. t.format = "R8";
  52. path.createRenderTarget(t);
  53. }
  54. {
  55. var t = new RenderTargetRaw();
  56. t.name = "texpaint_colorid";
  57. t.width = 1;
  58. t.height = 1;
  59. t.format = "RGBA32";
  60. path.createRenderTarget(t);
  61. }
  62. {
  63. var t = new RenderTargetRaw();
  64. t.name = "texpaint_picker";
  65. t.width = 1;
  66. t.height = 1;
  67. t.format = "RGBA32";
  68. path.createRenderTarget(t);
  69. }
  70. {
  71. var t = new RenderTargetRaw();
  72. t.name = "texpaint_nor_picker";
  73. t.width = 1;
  74. t.height = 1;
  75. t.format = "RGBA32";
  76. path.createRenderTarget(t);
  77. }
  78. {
  79. var t = new RenderTargetRaw();
  80. t.name = "texpaint_pack_picker";
  81. t.width = 1;
  82. t.height = 1;
  83. t.format = "RGBA32";
  84. path.createRenderTarget(t);
  85. }
  86. {
  87. var t = new RenderTargetRaw();
  88. t.name = "texpaint_posnortex_picker0";
  89. t.width = 1;
  90. t.height = 1;
  91. t.format = "RGBA128";
  92. path.createRenderTarget(t);
  93. }
  94. {
  95. var t = new RenderTargetRaw();
  96. t.name = "texpaint_posnortex_picker1";
  97. t.width = 1;
  98. t.height = 1;
  99. t.format = "RGBA128";
  100. path.createRenderTarget(t);
  101. }
  102. path.loadShader("shader_datas/copy_mrt3_pass/copy_mrt3_pass");
  103. path.loadShader("shader_datas/dilate_pass/dilate_pass");
  104. }
  105. @:access(iron.RenderPath)
  106. public static function commandsPaint(dilation = true) {
  107. var tid = Context.layer.id;
  108. if (Context.pdirty > 0) {
  109. if (Context.tool == ToolParticle) {
  110. path.setTarget("texparticle");
  111. path.clearTarget(0x00000000);
  112. path.bindTarget("_main", "gbufferD");
  113. if ((Context.xray || Config.raw.brush_angle_reject) && Config.raw.brush_3d) {
  114. path.bindTarget("gbuffer0", "gbuffer0");
  115. }
  116. var mo: MeshObject = cast Scene.active.getChild(".ParticleEmitter");
  117. mo.visible = true;
  118. mo.render(path.currentG, "mesh", @:privateAccess path.bindParams);
  119. mo.visible = false;
  120. mo = cast Scene.active.getChild(".Particle");
  121. mo.visible = true;
  122. mo.render(path.currentG, "mesh", @:privateAccess path.bindParams);
  123. mo.visible = false;
  124. @:privateAccess path.end();
  125. }
  126. if (Context.tool == ToolColorId) {
  127. path.setTarget("texpaint_colorid");
  128. path.clearTarget(0xff000000);
  129. path.bindTarget("gbuffer2", "gbuffer2");
  130. path.drawMeshes("paint");
  131. UIHeader.inst.headerHandle.redraws = 2;
  132. }
  133. else if (Context.tool == ToolPicker) {
  134. if (Context.pickPosNorTex) {
  135. if (Context.paint2d) {
  136. path.setTarget("gbuffer0", ["gbuffer1", "gbuffer2"]);
  137. path.drawMeshes("mesh");
  138. }
  139. path.setTarget("texpaint_posnortex_picker0", ["texpaint_posnortex_picker1"]);
  140. path.bindTarget("gbuffer2", "gbuffer2");
  141. path.bindTarget("_main", "gbufferD");
  142. path.drawMeshes("paint");
  143. var texpaint_posnortex_picker0 = path.renderTargets.get("texpaint_posnortex_picker0").image;
  144. var texpaint_posnortex_picker1 = path.renderTargets.get("texpaint_posnortex_picker1").image;
  145. var a = texpaint_posnortex_picker0.getPixels();
  146. var b = texpaint_posnortex_picker1.getPixels();
  147. Context.posXPicked = a.getFloat(0);
  148. Context.posYPicked = a.getFloat(4);
  149. Context.posZPicked = a.getFloat(8);
  150. Context.uvxPicked = a.getFloat(12);
  151. Context.norXPicked = b.getFloat(0);
  152. Context.norYPicked = b.getFloat(4);
  153. Context.norZPicked = b.getFloat(8);
  154. Context.uvyPicked = b.getFloat(12);
  155. }
  156. else {
  157. #if kha_metal
  158. //path.setTarget("texpaint_picker");
  159. //path.clearTarget(0xff000000);
  160. //path.setTarget("texpaint_nor_picker");
  161. //path.clearTarget(0xff000000);
  162. //path.setTarget("texpaint_pack_picker");
  163. //path.clearTarget(0xff000000);
  164. path.setTarget("texpaint_picker", ["texpaint_nor_picker", "texpaint_pack_picker"]);
  165. #else
  166. path.setTarget("texpaint_picker", ["texpaint_nor_picker", "texpaint_pack_picker"]);
  167. //path.clearTarget(0xff000000);
  168. #end
  169. path.bindTarget("gbuffer2", "gbuffer2");
  170. tid = Context.layer.id;
  171. var useLiveLayer = arm.ui.UIHeader.inst.worktab.position == SpaceMaterial;
  172. if (useLiveLayer) RenderPathPaint.useLiveLayer(true);
  173. path.bindTarget("texpaint" + tid, "texpaint");
  174. path.bindTarget("texpaint_nor" + tid, "texpaint_nor");
  175. path.bindTarget("texpaint_pack" + tid, "texpaint_pack");
  176. path.drawMeshes("paint");
  177. if (useLiveLayer) RenderPathPaint.useLiveLayer(false);
  178. UIHeader.inst.headerHandle.redraws = 2;
  179. UIStatus.inst.statusHandle.redraws = 2;
  180. var texpaint_picker = path.renderTargets.get("texpaint_picker").image;
  181. var texpaint_nor_picker = path.renderTargets.get("texpaint_nor_picker").image;
  182. var texpaint_pack_picker = path.renderTargets.get("texpaint_pack_picker").image;
  183. var a = texpaint_picker.getPixels();
  184. var b = texpaint_nor_picker.getPixels();
  185. var c = texpaint_pack_picker.getPixels();
  186. // Picked surface values
  187. #if (kha_metal || kha_vulkan)
  188. Context.swatch.base.Rb = a.get(2);
  189. Context.swatch.base.Gb = a.get(1);
  190. Context.swatch.base.Bb = a.get(0);
  191. Context.swatch.normal.Rb = b.get(2);
  192. Context.swatch.normal.Gb = b.get(1);
  193. Context.swatch.normal.Bb = b.get(0);
  194. Context.swatch.occlusion = c.get(2) / 255;
  195. Context.swatch.roughness = c.get(1) / 255;
  196. Context.swatch.metallic = c.get(0) / 255;
  197. #else
  198. Context.swatch.base.Rb = a.get(0);
  199. Context.swatch.base.Gb = a.get(1);
  200. Context.swatch.base.Bb = a.get(2);
  201. Context.swatch.normal.Rb = b.get(0);
  202. Context.swatch.normal.Gb = b.get(1);
  203. Context.swatch.normal.Bb = b.get(2);
  204. Context.swatch.occlusion = c.get(0) / 255;
  205. Context.swatch.roughness = c.get(1) / 255;
  206. Context.swatch.metallic = c.get(2) / 255;
  207. #end
  208. Context.uvxPicked = a.get(3) / 255;
  209. Context.uvyPicked = c.get(3) / 255;
  210. // Pick material
  211. if (Context.pickerSelectMaterial) {
  212. // matid % 3 == 0 - normal, 1 - emission, 2 - subsurface
  213. var matid = Std.int((b.get(3) - (b.get(3) % 3)) / 3);
  214. for (m in Project.materials) {
  215. if (m.id == matid) {
  216. Context.setMaterial(m);
  217. Context.materialIdPicked = matid;
  218. break;
  219. }
  220. }
  221. }
  222. }
  223. }
  224. else {
  225. #if rp_voxelao
  226. if (Context.tool == ToolBake && Context.bakeType == BakeAO) {
  227. if (initVoxels) {
  228. initVoxels = false;
  229. // Init voxel texture
  230. var rp_gi = Config.raw.rp_gi;
  231. Config.raw.rp_gi = true;
  232. #if rp_voxelao
  233. Inc.initGI();
  234. #end
  235. Config.raw.rp_gi = rp_gi;
  236. }
  237. path.clearImage("voxels", 0x00000000);
  238. path.setTarget("");
  239. path.setViewport(256, 256);
  240. path.bindTarget("voxels", "voxels");
  241. path.drawMeshes("voxel");
  242. path.generateMipmaps("voxels");
  243. }
  244. #end
  245. var texpaint = "texpaint" + tid;
  246. if (Context.tool == ToolBake && Context.brushTime == iron.system.Time.delta) {
  247. // Clear to black on bake start
  248. path.setTarget(texpaint);
  249. path.clearTarget(0xff000000);
  250. }
  251. path.setTarget("texpaint_blend1");
  252. path.bindTarget("texpaint_blend0", "tex");
  253. path.drawShader("shader_datas/copy_pass/copyR8_pass");
  254. var isMask = Context.layer.isMask();
  255. if (isMask) {
  256. var ptid = Context.layer.parent.id;
  257. path.setTarget(texpaint, ["texpaint_nor" + ptid, "texpaint_pack" + ptid, "texpaint_blend0"]);
  258. }
  259. else {
  260. path.setTarget(texpaint, ["texpaint_nor" + tid, "texpaint_pack" + tid, "texpaint_blend0"]);
  261. }
  262. path.bindTarget("_main", "gbufferD");
  263. if ((Context.xray || Config.raw.brush_angle_reject) && Config.raw.brush_3d) {
  264. path.bindTarget("gbuffer0", "gbuffer0");
  265. }
  266. path.bindTarget("texpaint_blend1", "paintmask");
  267. #if rp_voxelao
  268. if (Context.tool == ToolBake && Context.bakeType == BakeAO) {
  269. path.bindTarget("voxels", "voxels");
  270. }
  271. #end
  272. if (Context.colorIdPicked) {
  273. path.bindTarget("texpaint_colorid", "texpaint_colorid");
  274. }
  275. // Read texcoords from gbuffer
  276. var readTC = (Context.tool == ToolFill && Context.fillTypeHandle.position == FillFace) ||
  277. Context.tool == ToolClone ||
  278. Context.tool == ToolBlur;
  279. if (readTC) {
  280. path.bindTarget("gbuffer2", "gbuffer2");
  281. }
  282. path.drawMeshes("paint");
  283. if (Context.tool == ToolBake && Context.bakeType == BakeCurvature && Context.bakeCurvSmooth > 0) {
  284. if (path.renderTargets.get("texpaint_blur") == null) {
  285. var t = new RenderTargetRaw();
  286. t.name = "texpaint_blur";
  287. t.width = Std.int(Config.getTextureResX() * 0.95);
  288. t.height = Std.int(Config.getTextureResY() * 0.95);
  289. t.format = "RGBA32";
  290. path.createRenderTarget(t);
  291. }
  292. var blurs = Math.round(Context.bakeCurvSmooth);
  293. for (i in 0...blurs) {
  294. path.setTarget("texpaint_blur");
  295. path.bindTarget(texpaint, "tex");
  296. path.drawShader("shader_datas/copy_pass/copy_pass");
  297. path.setTarget(texpaint);
  298. path.bindTarget("texpaint_blur", "tex");
  299. path.drawShader("shader_datas/copy_pass/copy_pass");
  300. }
  301. }
  302. if (dilation && Config.raw.dilate == DilateInstant) {
  303. dilate(true, false);
  304. }
  305. }
  306. }
  307. }
  308. public static function useLiveLayer(use: Bool) {
  309. var tid = Context.layer.id;
  310. var hid = History.undoI - 1 < 0 ? Config.raw.undo_steps - 1 : History.undoI - 1;
  311. if (use) {
  312. _texpaint = path.renderTargets.get("texpaint" + tid);
  313. _texpaint_undo = path.renderTargets.get("texpaint_undo" + hid);
  314. _texpaint_nor_undo = path.renderTargets.get("texpaint_nor_undo" + hid);
  315. _texpaint_pack_undo = path.renderTargets.get("texpaint_pack_undo" + hid);
  316. _texpaint_nor = path.renderTargets.get("texpaint_nor" + tid);
  317. _texpaint_pack = path.renderTargets.get("texpaint_pack" + tid);
  318. path.renderTargets.set("texpaint_undo" + hid, path.renderTargets.get("texpaint" + tid));
  319. path.renderTargets.set("texpaint" + tid, path.renderTargets.get("texpaint_live"));
  320. if (Context.layer.isLayer()) {
  321. path.renderTargets.set("texpaint_nor_undo" + hid, path.renderTargets.get("texpaint_nor" + tid));
  322. path.renderTargets.set("texpaint_pack_undo" + hid, path.renderTargets.get("texpaint_pack" + tid));
  323. path.renderTargets.set("texpaint_nor" + tid, path.renderTargets.get("texpaint_nor_live"));
  324. path.renderTargets.set("texpaint_pack" + tid, path.renderTargets.get("texpaint_pack_live"));
  325. }
  326. }
  327. else {
  328. path.renderTargets.set("texpaint" + tid, _texpaint);
  329. path.renderTargets.set("texpaint_undo" + hid, _texpaint_undo);
  330. if (Context.layer.isLayer()) {
  331. path.renderTargets.set("texpaint_nor_undo" + hid, _texpaint_nor_undo);
  332. path.renderTargets.set("texpaint_pack_undo" + hid, _texpaint_pack_undo);
  333. path.renderTargets.set("texpaint_nor" + tid, _texpaint_nor);
  334. path.renderTargets.set("texpaint_pack" + tid, _texpaint_pack);
  335. }
  336. }
  337. liveLayerLocked = use;
  338. }
  339. static function commandsLiveBrush() {
  340. var tool = Context.tool;
  341. if (tool != ToolBrush &&
  342. tool != ToolEraser &&
  343. tool != ToolClone &&
  344. tool != ToolDecal &&
  345. tool != ToolText &&
  346. tool != ToolBlur) {
  347. return;
  348. }
  349. if (liveLayerLocked) return;
  350. if (liveLayer == null) {
  351. liveLayer = new arm.data.LayerSlot("_live");
  352. }
  353. var tid = Context.layer.id;
  354. if (Context.layer.isMask()) {
  355. path.setTarget("texpaint_live");
  356. path.bindTarget("texpaint" + tid, "tex");
  357. path.drawShader("shader_datas/copy_pass/copy_pass");
  358. }
  359. else {
  360. path.setTarget("texpaint_live", ["texpaint_nor_live", "texpaint_pack_live"]);
  361. path.bindTarget("texpaint" + tid, "tex0");
  362. path.bindTarget("texpaint_nor" + tid, "tex1");
  363. path.bindTarget("texpaint_pack" + tid, "tex2");
  364. path.drawShader("shader_datas/copy_mrt3_pass/copy_mrt3_pass");
  365. }
  366. useLiveLayer(true);
  367. liveLayerDrawn = 2;
  368. UIView2D.inst.hwnd.redraws = 2;
  369. var _x = Context.paintVec.x;
  370. var _y = Context.paintVec.y;
  371. if (Context.brushLocked) {
  372. Context.paintVec.x = (Context.lockStartedX - iron.App.x()) / iron.App.w();
  373. Context.paintVec.y = (Context.lockStartedY - iron.App.y()) / iron.App.h();
  374. }
  375. var _lastX = Context.lastPaintVecX;
  376. var _lastY = Context.lastPaintVecY;
  377. var _pdirty = Context.pdirty;
  378. Context.lastPaintVecX = Context.paintVec.x;
  379. Context.lastPaintVecY = Context.paintVec.y;
  380. if (Operator.shortcut(Config.keymap.brush_ruler)) {
  381. Context.lastPaintVecX = Context.lastPaintX;
  382. Context.lastPaintVecY = Context.lastPaintY;
  383. }
  384. Context.pdirty = 2;
  385. commandsSymmetry();
  386. commandsPaint();
  387. useLiveLayer(false);
  388. Context.paintVec.x = _x;
  389. Context.paintVec.y = _y;
  390. Context.lastPaintVecX = _lastX;
  391. Context.lastPaintVecY = _lastY;
  392. Context.pdirty = _pdirty;
  393. Context.brushBlendDirty = true;
  394. }
  395. public static function commandsCursor() {
  396. var decal = Context.tool == ToolDecal || Context.tool == ToolText;
  397. var decalMask = decal && Operator.shortcut(Config.keymap.decal_mask, ShortcutDown);
  398. var tool = Context.tool;
  399. if (tool != ToolBrush &&
  400. tool != ToolEraser &&
  401. tool != ToolClone &&
  402. tool != ToolBlur &&
  403. tool != ToolParticle &&
  404. !decalMask) {
  405. return;
  406. }
  407. var fillLayer = Context.layer.fill_layer != null;
  408. var groupLayer = Context.layer.isGroup();
  409. if (!App.uiEnabled || App.isDragging || fillLayer || groupLayer) {
  410. return;
  411. }
  412. var mx = Context.paintVec.x;
  413. var my = 1.0 - Context.paintVec.y;
  414. if (Context.brushLocked) {
  415. mx = (Context.lockStartedX - iron.App.x()) / iron.App.w();
  416. my = 1.0 - (Context.lockStartedY - iron.App.y()) / iron.App.h();
  417. }
  418. var radius = decalMask ? Context.brushDecalMaskRadius : Context.brushRadius;
  419. drawCursor(mx, my, Context.brushNodesRadius * radius / 3.4);
  420. // if (Context.brushLazyRadius > 0 && (Context.tool == ToolBrush || Context.tool == ToolEraser)) {
  421. // var _brushRadius = Context.brushRadius;
  422. // Context.brushRadius = Context.brushLazyRadius;
  423. // mx = Context.brushLazyX;
  424. // my = 1.0 - Context.brushLazyY;
  425. // if (Context.brushLocked) {
  426. // mx = (Context.lockStartedX - iron.App.x()) / iron.App.w();
  427. // my = 1.0 - (Context.lockStartedY - iron.App.y()) / iron.App.h();
  428. // }
  429. // drawCursor(mx, my, 0.2, 0.2, 0.2);
  430. // Context.brushRadius -= Context.brushLazyRadius;
  431. // }
  432. }
  433. @:access(iron.RenderPath)
  434. static function drawCursor(mx: Float, my: Float, radius: Float, tintR = 1.0, tintG = 1.0, tintB = 1.0) {
  435. var plane = cast(Scene.active.getChild(".Plane"), MeshObject);
  436. var geom = plane.data.geom;
  437. var g = path.frameG;
  438. if (Layers.pipeCursor == null) Layers.makeCursorPipe();
  439. path.setTarget("");
  440. g.setPipeline(Layers.pipeCursor);
  441. var decal = Context.tool == ToolDecal || Context.tool == ToolText;
  442. var decalMask = decal && Operator.shortcut(Config.keymap.decal_mask, ShortcutDown);
  443. var img = (decal && !decalMask) ? Context.decalImage : Res.get("cursor.k");
  444. g.setTexture(Layers.cursorTex, img);
  445. var gbuffer0 = path.renderTargets.get("gbuffer0").image;
  446. g.setTextureDepth(Layers.cursorGbufferD, gbuffer0);
  447. g.setFloat2(Layers.cursorMouse, mx, my);
  448. g.setFloat2(Layers.cursorTexStep, 1 / gbuffer0.width, 1 / gbuffer0.height);
  449. g.setFloat(Layers.cursorRadius, radius);
  450. var right = Scene.active.camera.rightWorld().normalize();
  451. g.setFloat3(Layers.cursorCameraRight, right.x, right.y, right.z);
  452. g.setFloat3(Layers.cursorTint, tintR, tintG, tintB);
  453. g.setMatrix(Layers.cursorVP, Scene.active.camera.VP.self);
  454. var helpMat = iron.math.Mat4.identity();
  455. helpMat.getInverse(Scene.active.camera.VP);
  456. g.setMatrix(Layers.cursorInvVP, helpMat.self);
  457. #if (kha_metal || kha_vulkan)
  458. g.setVertexBuffer(geom.get([{name: "tex", data: "short2norm"}]));
  459. #else
  460. g.setVertexBuffer(geom.vertexBuffer);
  461. #end
  462. g.setIndexBuffer(geom.indexBuffers[0]);
  463. g.drawIndexedVertices();
  464. g.disableScissor();
  465. path.end();
  466. }
  467. static function commandsSymmetry() {
  468. if (Context.symX || Context.symY || Context.symZ) {
  469. Context.ddirty = 2;
  470. var t = Context.paintObject.transform;
  471. var sx = t.scale.x;
  472. var sy = t.scale.y;
  473. var sz = t.scale.z;
  474. if (Context.symX) {
  475. t.scale.set(-sx, sy, sz);
  476. t.buildMatrix();
  477. commandsPaint(false);
  478. }
  479. if (Context.symY) {
  480. t.scale.set(sx, -sy, sz);
  481. t.buildMatrix();
  482. commandsPaint(false);
  483. }
  484. if (Context.symZ) {
  485. t.scale.set(sx, sy, -sz);
  486. t.buildMatrix();
  487. commandsPaint(false);
  488. }
  489. if (Context.symX && Context.symY) {
  490. t.scale.set(-sx, -sy, sz);
  491. t.buildMatrix();
  492. commandsPaint(false);
  493. }
  494. if (Context.symX && Context.symZ) {
  495. t.scale.set(-sx, sy, -sz);
  496. t.buildMatrix();
  497. commandsPaint(false);
  498. }
  499. if (Context.symY && Context.symZ) {
  500. t.scale.set(sx, -sy, -sz);
  501. t.buildMatrix();
  502. commandsPaint(false);
  503. }
  504. if (Context.symX && Context.symY && Context.symZ) {
  505. t.scale.set(-sx, -sy, -sz);
  506. t.buildMatrix();
  507. commandsPaint(false);
  508. }
  509. t.scale.set(sx, sy, sz);
  510. t.buildMatrix();
  511. }
  512. }
  513. static function paintEnabled(): Bool {
  514. var fillLayer = Context.layer.fill_layer != null && Context.tool != ToolPicker && Context.tool != ToolColorId;
  515. var groupLayer = Context.layer.isGroup();
  516. return !fillLayer && !groupLayer && !Context.foregroundEvent;
  517. }
  518. public static function begin() {
  519. if (!paintEnabled()) return;
  520. pushUndoLast = History.pushUndo;
  521. if (History.pushUndo && History.undoLayers != null) {
  522. History.paint();
  523. }
  524. if (Context.paint2d) {
  525. setPlaneMesh();
  526. }
  527. if (liveLayerDrawn > 0) liveLayerDrawn--;
  528. if (Config.raw.brush_live && Context.pdirty <= 0 && Context.ddirty <= 0 && Context.brushTime == 0) {
  529. // Depth is unchanged, draw before gbuffer gets updated
  530. commandsLiveBrush();
  531. }
  532. }
  533. public static function end() {
  534. if (Config.raw.brush_3d) commandsCursor();
  535. Context.ddirty--;
  536. Context.rdirty--;
  537. if (!paintEnabled()) return;
  538. Context.pdirty--;
  539. }
  540. public static function draw() {
  541. if (!paintEnabled()) return;
  542. if (Config.raw.brush_live && Context.pdirty <= 0 && Context.ddirty > 0 && Context.brushTime == 0) {
  543. // gbuffer has been updated now but brush will lag 1 frame
  544. commandsLiveBrush();
  545. }
  546. if (History.undoLayers != null) {
  547. commandsSymmetry();
  548. if (Context.pdirty > 0) dilated = false;
  549. if (Context.tool == ToolBake) {
  550. if (Context.bakeType == BakeNormal || Context.bakeType == BakeHeight || Context.bakeType == BakeDerivative) {
  551. if (!baking && Context.pdirty > 0) {
  552. baking = true;
  553. var _bakeType = Context.bakeType;
  554. Context.bakeType = Context.bakeType == BakeNormal ? BakeNormalObject : BakePosition; // Bake high poly data
  555. MakeMaterial.parsePaintMaterial();
  556. var _paintObject = Context.paintObject;
  557. var highPoly = Project.paintObjects[Context.bakeHighPoly];
  558. var _visible = highPoly.visible;
  559. highPoly.visible = true;
  560. Context.selectPaintObject(highPoly);
  561. commandsPaint();
  562. highPoly.visible = _visible;
  563. if (pushUndoLast) History.paint();
  564. Context.selectPaintObject(_paintObject);
  565. function _renderFinal() {
  566. Context.bakeType = _bakeType;
  567. MakeMaterial.parsePaintMaterial();
  568. Context.pdirty = 1;
  569. commandsPaint();
  570. Context.pdirty = 0;
  571. baking = false;
  572. }
  573. function _renderDeriv() {
  574. Context.bakeType = BakeHeight;
  575. MakeMaterial.parsePaintMaterial();
  576. Context.pdirty = 1;
  577. commandsPaint();
  578. Context.pdirty = 0;
  579. if (pushUndoLast) History.paint();
  580. iron.App.notifyOnInit(_renderFinal);
  581. }
  582. iron.App.notifyOnInit(Context.bakeType == BakeDerivative ? _renderDeriv : _renderFinal);
  583. }
  584. }
  585. else if (Context.bakeType == BakeObjectID) {
  586. var _layerFilter = Context.layerFilter;
  587. var _paintObject = Context.paintObject;
  588. var isMerged = Context.mergedObject != null;
  589. var _visible = isMerged && Context.mergedObject.visible;
  590. Context.layerFilter = 1;
  591. if (isMerged) Context.mergedObject.visible = false;
  592. for (p in Project.paintObjects) {
  593. Context.selectPaintObject(p);
  594. commandsPaint();
  595. }
  596. Context.layerFilter = _layerFilter;
  597. Context.selectPaintObject(_paintObject);
  598. if (isMerged) Context.mergedObject.visible = _visible;
  599. }
  600. #if (kha_direct3d12 || kha_vulkan)
  601. else if (Context.bakeType == BakeAO ||
  602. Context.bakeType == BakeLightmap ||
  603. Context.bakeType == BakeBentNormal ||
  604. Context.bakeType == BakeThickness) {
  605. var dirty = RenderPathRaytraceBake.commands(MakeMaterial.parsePaintMaterial);
  606. if (dirty) UIHeader.inst.headerHandle.redraws = 2;
  607. if (Config.raw.dilate == DilateInstant) { // && Context.pdirty == 1
  608. dilate(true, false);
  609. }
  610. }
  611. #end
  612. else {
  613. commandsPaint();
  614. }
  615. }
  616. else { // Paint
  617. commandsPaint();
  618. }
  619. }
  620. //
  621. if (Context.brushBlendDirty) {
  622. Context.brushBlendDirty = false;
  623. #if kha_metal
  624. path.setTarget("texpaint_blend0");
  625. path.clearTarget(0x00000000);
  626. path.setTarget("texpaint_blend1");
  627. path.clearTarget(0x00000000);
  628. #else
  629. path.setTarget("texpaint_blend0", ["texpaint_blend1"]);
  630. path.clearTarget(0x00000000);
  631. #end
  632. }
  633. if (Context.paint2d) {
  634. restorePlaneMesh();
  635. }
  636. }
  637. public static function setPlaneMesh() {
  638. Context.paint2dView = true;
  639. // Set plane mesh
  640. painto = Context.paintObject;
  641. visibles = [];
  642. for (p in Project.paintObjects) {
  643. visibles.push(p.visible);
  644. p.visible = false;
  645. }
  646. if (Context.mergedObject != null) {
  647. mergedObjectVisible = Context.mergedObject.visible;
  648. Context.mergedObject.visible = false;
  649. }
  650. var cam = Scene.active.camera;
  651. Context.savedCamera.setFrom(cam.transform.local);
  652. savedFov = cam.data.raw.fov;
  653. Viewport.updateCameraType(CameraPerspective);
  654. var m = Mat4.identity();
  655. m.translate(0, 0, 0.5);
  656. cam.transform.setMatrix(m);
  657. cam.data.raw.fov = 0.92;
  658. cam.buildProjection();
  659. cam.buildMatrix();
  660. var tw = 0.95 * UIView2D.inst.panScale;
  661. var tx = UIView2D.inst.panX / UIView2D.inst.ww;
  662. var ty = UIView2D.inst.panY / iron.App.h();
  663. m.setIdentity();
  664. m.scale(new Vec4(tw, tw, 1));
  665. m.setLoc(new Vec4(tx, ty, 0));
  666. var m2 = Mat4.identity();
  667. m2.getInverse(Scene.active.camera.VP);
  668. m.multmat(m2);
  669. var tiled = UIView2D.inst.tiledShow;
  670. if (tiled && Scene.active.getChild(".PlaneTiled") == null) {
  671. // 3x3 planes
  672. var posa = [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];
  673. var nora = [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];
  674. var texa = [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];
  675. var inda = [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];
  676. var raw: TMeshData = {
  677. name: ".PlaneTiled",
  678. vertex_arrays: [
  679. { attrib: "pos", values: i16(posa), data: "short4norm" },
  680. { attrib: "nor", values: i16(nora), data: "short2norm" },
  681. { attrib: "tex", values: i16(texa), data: "short2norm" }
  682. ],
  683. index_arrays: [
  684. { values: u32(inda), material: 0 }
  685. ],
  686. scale_pos: 1.5,
  687. scale_tex: 1.0
  688. };
  689. new MeshData(raw, function(md: MeshData) {
  690. var materials = cast(Scene.active.getChild(".Plane"), MeshObject).materials;
  691. var o = Scene.active.addMeshObject(md, materials);
  692. o.name = ".PlaneTiled";
  693. });
  694. }
  695. planeo = cast Scene.active.getChild(tiled ? ".PlaneTiled" : ".Plane");
  696. planeo.visible = true;
  697. Context.paintObject = planeo;
  698. var v = new Vec4();
  699. var sx = v.set(m._00, m._01, m._02).length();
  700. planeo.transform.rot.fromEuler(-Math.PI / 2, 0, 0);
  701. planeo.transform.scale.set(sx, 1.0, sx);
  702. planeo.transform.scale.z *= Config.getTextureResY() / Config.getTextureResX();
  703. planeo.transform.loc.set(m._30, -m._31, 0.0);
  704. planeo.transform.buildMatrix();
  705. }
  706. public static function restorePlaneMesh() {
  707. Context.paint2dView = false;
  708. // Restore paint mesh
  709. planeo.visible = false;
  710. planeo.transform.loc.set(0.0, 0.0, 0.0);
  711. for (i in 0...Project.paintObjects.length) {
  712. Project.paintObjects[i].visible = visibles[i];
  713. }
  714. if (Context.mergedObject != null) {
  715. Context.mergedObject.visible = mergedObjectVisible;
  716. }
  717. Context.paintObject = painto;
  718. Scene.active.camera.transform.setMatrix(Context.savedCamera);
  719. Scene.active.camera.data.raw.fov = savedFov;
  720. Viewport.updateCameraType(Context.cameraType);
  721. Scene.active.camera.buildProjection();
  722. Scene.active.camera.buildMatrix();
  723. RenderPathDeferred.drawGbuffer();
  724. }
  725. public static function bindLayers() {
  726. var isLive = Config.raw.brush_live && liveLayerDrawn > 0;
  727. var isMaterialSpace = UIHeader.inst.worktab.position == SpaceMaterial;
  728. if (isLive || isMaterialSpace) useLiveLayer(true);
  729. for (i in 0...Project.layers.length) {
  730. var l = Project.layers[i];
  731. path.bindTarget("texpaint" + l.id, "texpaint" + l.id);
  732. if (l.isLayer()) {
  733. path.bindTarget("texpaint_nor" + l.id, "texpaint_nor" + l.id);
  734. path.bindTarget("texpaint_pack" + l.id, "texpaint_pack" + l.id);
  735. }
  736. }
  737. }
  738. public static function unbindLayers() {
  739. var isLive = Config.raw.brush_live && liveLayerDrawn > 0;
  740. var isMaterialSpace = UIHeader.inst.worktab.position == SpaceMaterial;
  741. if (isLive || isMaterialSpace) useLiveLayer(false);
  742. }
  743. public static function dilate(base: Bool, nor_pack: Bool) {
  744. if (Config.raw.dilate_radius > 0 && !Context.paint2d) {
  745. arm.util.UVUtil.cacheDilateMap();
  746. Layers.makeTempImg();
  747. var tid = Context.layer.id;
  748. if (base) {
  749. var texpaint = "texpaint";
  750. path.setTarget("temptex0");
  751. path.bindTarget(texpaint + tid, "tex");
  752. path.drawShader("shader_datas/copy_pass/copy_pass");
  753. path.setTarget(texpaint + tid);
  754. path.bindTarget("temptex0", "tex");
  755. path.drawShader("shader_datas/dilate_pass/dilate_pass");
  756. }
  757. if (nor_pack && !Context.layer.isMask()) {
  758. path.setTarget("temptex0");
  759. path.bindTarget("texpaint_nor" + tid, "tex");
  760. path.drawShader("shader_datas/copy_pass/copy_pass");
  761. path.setTarget("texpaint_nor" + tid);
  762. path.bindTarget("temptex0", "tex");
  763. path.drawShader("shader_datas/dilate_pass/dilate_pass");
  764. path.setTarget("temptex0");
  765. path.bindTarget("texpaint_pack" + tid, "tex");
  766. path.drawShader("shader_datas/copy_pass/copy_pass");
  767. path.setTarget("texpaint_pack" + tid);
  768. path.bindTarget("temptex0", "tex");
  769. path.drawShader("shader_datas/dilate_pass/dilate_pass");
  770. }
  771. }
  772. }
  773. static function u32(ar: Array<Int>): kha.arrays.Uint32Array {
  774. var res = new kha.arrays.Uint32Array(ar.length);
  775. for (i in 0...ar.length) res[i] = ar[i];
  776. return res;
  777. }
  778. static function i16(ar: Array<Int>): kha.arrays.Int16Array {
  779. var res = new kha.arrays.Int16Array(ar.length);
  780. for (i in 0...ar.length) res[i] = ar[i];
  781. return res;
  782. }
  783. }