RenderPathPaint.hx 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549
  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.RenderPath;
  7. import iron.Scene;
  8. import arm.util.ViewportUtil;
  9. import arm.ui.UITrait;
  10. import arm.ui.UIView2D;
  11. import arm.node.MaterialParser;
  12. import arm.Tool;
  13. #if arm_painter
  14. class RenderPathPaint {
  15. static var path: RenderPath;
  16. static var initVoxels = true; // Bake AO
  17. static var pushUndoLast: Bool;
  18. static var painto: MeshObject = null;
  19. static var planeo: MeshObject = null;
  20. static var visibles: Array<Bool> = null;
  21. static var mergedObjectVisible = false;
  22. static var savedFov = 0.0;
  23. static var dilated = true;
  24. static var baking = false;
  25. public static function init(_path: RenderPath) {
  26. path = _path;
  27. {
  28. var t = new RenderTargetRaw();
  29. t.name = "texpaint_blend0";
  30. t.width = Config.getTextureRes();
  31. t.height = Config.getTextureRes();
  32. t.format = "R8";
  33. path.createRenderTarget(t);
  34. }
  35. {
  36. var t = new RenderTargetRaw();
  37. t.name = "texpaint_blend1";
  38. t.width = Config.getTextureRes();
  39. t.height = Config.getTextureRes();
  40. t.format = "R8";
  41. path.createRenderTarget(t);
  42. }
  43. {
  44. var t = new RenderTargetRaw();
  45. t.name = "texpaint_colorid";
  46. t.width = 1;
  47. t.height = 1;
  48. t.format = "RGBA32";
  49. path.createRenderTarget(t);
  50. }
  51. {
  52. var t = new RenderTargetRaw();
  53. t.name = "texpaint_picker";
  54. t.width = 1;
  55. t.height = 1;
  56. t.format = "RGBA32";
  57. path.createRenderTarget(t);
  58. }
  59. {
  60. var t = new RenderTargetRaw();
  61. t.name = "texpaint_nor_picker";
  62. t.width = 1;
  63. t.height = 1;
  64. t.format = "RGBA32";
  65. path.createRenderTarget(t);
  66. }
  67. {
  68. var t = new RenderTargetRaw();
  69. t.name = "texpaint_pack_picker";
  70. t.width = 1;
  71. t.height = 1;
  72. t.format = "RGBA32";
  73. path.createRenderTarget(t);
  74. }
  75. path.loadShader("shader_datas/copy_mrt3_pass/copy_mrt3_pass");
  76. path.loadShader("shader_datas/dilate_pass/dilate_pass");
  77. }
  78. @:access(iron.RenderPath)
  79. public static function commandsPaint() {
  80. var tid = Context.layer.id;
  81. if (Context.pdirty > 0 && UITrait.inst.worktab.position != SpaceScene) {
  82. if (Context.tool == ToolParticle) {
  83. path.setTarget("texparticle");
  84. path.clearTarget(0x00000000);
  85. path.bindTarget("_main", "gbufferD");
  86. if ((UITrait.inst.xray || UITrait.inst.brushAngleReject) && UITrait.inst.brush3d) {
  87. path.bindTarget("gbuffer0", "gbuffer0");
  88. }
  89. var mo: MeshObject = cast Scene.active.getChild(".ParticleEmitter");
  90. mo.visible = true;
  91. mo.render(path.currentG, "mesh", @:privateAccess path.bindParams);
  92. mo.visible = false;
  93. mo = cast Scene.active.getChild(".Particle");
  94. mo.visible = true;
  95. mo.render(path.currentG, "mesh", @:privateAccess path.bindParams);
  96. mo.visible = false;
  97. @:privateAccess path.end();
  98. }
  99. if (Context.tool == ToolColorId) {
  100. path.setTarget("texpaint_colorid");
  101. path.clearTarget(0xff000000);
  102. path.bindTarget("gbuffer2", "gbuffer2");
  103. path.drawMeshes("paint");
  104. UITrait.inst.headerHandle.redraws = 2;
  105. }
  106. else if (Context.tool == ToolPicker) {
  107. path.setTarget("texpaint_picker", ["texpaint_nor_picker", "texpaint_pack_picker"]);
  108. path.clearTarget(0xff000000);
  109. path.bindTarget("gbuffer2", "gbuffer2");
  110. tid = Context.layer.id;
  111. path.bindTarget("texpaint" + tid, "texpaint");
  112. path.bindTarget("texpaint_nor" + tid, "texpaint_nor");
  113. path.bindTarget("texpaint_pack" + tid, "texpaint_pack");
  114. path.drawMeshes("paint");
  115. UITrait.inst.headerHandle.redraws = 2;
  116. var texpaint_picker = path.renderTargets.get("texpaint_picker").image;
  117. var texpaint_nor_picker = path.renderTargets.get("texpaint_nor_picker").image;
  118. var texpaint_pack_picker = path.renderTargets.get("texpaint_pack_picker").image;
  119. var a = texpaint_picker.getPixels();
  120. var b = texpaint_nor_picker.getPixels();
  121. var c = texpaint_pack_picker.getPixels();
  122. // Picked surface values
  123. UITrait.inst.baseRPicked = a.get(0) / 255;
  124. UITrait.inst.baseGPicked = a.get(1) / 255;
  125. UITrait.inst.baseBPicked = a.get(2) / 255;
  126. UITrait.inst.uvxPicked = a.get(3) / 255;
  127. UITrait.inst.normalRPicked = b.get(0) / 255;
  128. UITrait.inst.normalGPicked = b.get(1) / 255;
  129. UITrait.inst.normalBPicked = b.get(2) / 255;
  130. UITrait.inst.uvyPicked = c.get(3) / 255;
  131. UITrait.inst.occlusionPicked = c.get(0) / 255;
  132. UITrait.inst.roughnessPicked = c.get(1) / 255;
  133. UITrait.inst.metallicPicked = c.get(2) / 255;
  134. // Pick material
  135. if (UITrait.inst.pickerSelectMaterial) {
  136. var matid = b.get(3);
  137. for (m in Project.materials) {
  138. if (m.id == matid) {
  139. Context.setMaterial(m);
  140. UITrait.inst.materialIdPicked = matid;
  141. break;
  142. }
  143. }
  144. }
  145. }
  146. else {
  147. #if (!kha_direct3d12)
  148. if (Context.tool == ToolBake && UITrait.inst.bakeType == BakeAO) {
  149. if (initVoxels) {
  150. initVoxels = false;
  151. // Init voxel texture
  152. var rp_gi = Config.raw.rp_gi;
  153. Config.raw.rp_gi = true;
  154. #if rp_voxelao
  155. Inc.initGI();
  156. #end
  157. Config.raw.rp_gi = rp_gi;
  158. }
  159. path.clearImage("voxels", 0x00000000);
  160. path.setTarget("");
  161. path.setViewport(256, 256);
  162. path.bindTarget("voxels", "voxels");
  163. path.drawMeshes("voxel");
  164. path.generateMipmaps("voxels");
  165. }
  166. #end
  167. if (Context.tool == ToolBake && UITrait.inst.brushTime == iron.system.Time.delta) {
  168. // Clear to black on bake start
  169. path.setTarget("texpaint" + tid);
  170. path.clearTarget(0xff000000);
  171. }
  172. var blendA = "texpaint_blend0";
  173. var blendB = "texpaint_blend1";
  174. path.setTarget(blendB);
  175. path.bindTarget(blendA, "tex");
  176. path.drawShader("shader_datas/copy_pass/copy_pass");
  177. var isMask = Context.layerIsMask;
  178. var texpaint = isMask ? "texpaint_mask" + tid : "texpaint" + tid;
  179. path.setTarget(texpaint, ["texpaint_nor" + tid, "texpaint_pack" + tid, blendA]);
  180. path.bindTarget("_main", "gbufferD");
  181. if ((UITrait.inst.xray || UITrait.inst.brushAngleReject) && UITrait.inst.brush3d) {
  182. path.bindTarget("gbuffer0", "gbuffer0");
  183. }
  184. path.bindTarget(blendB, "paintmask");
  185. #if (!kha_direct3d12)
  186. if (Context.tool == ToolBake && UITrait.inst.bakeType == BakeAO) {
  187. path.bindTarget("voxels", "voxels");
  188. }
  189. #end
  190. if (UITrait.inst.colorIdPicked) {
  191. path.bindTarget("texpaint_colorid", "texpaint_colorid");
  192. }
  193. // Read texcoords from gbuffer
  194. var readTC = (Context.tool == ToolFill && UITrait.inst.fillTypeHandle.position == FillFace) ||
  195. Context.tool == ToolClone ||
  196. Context.tool == ToolBlur;
  197. if (readTC) {
  198. path.bindTarget("gbuffer2", "gbuffer2");
  199. }
  200. path.drawMeshes("paint");
  201. if (Context.tool == ToolBake && UITrait.inst.bakeType == BakeCurvature && UITrait.inst.bakeCurvSmooth > 0) {
  202. if (path.renderTargets.get("texpaint_blur") == null) {
  203. var t = new RenderTargetRaw();
  204. t.name = "texpaint_blur";
  205. t.width = Std.int(Config.getTextureRes() * 0.95);
  206. t.height = Std.int(Config.getTextureRes() * 0.95);
  207. t.format = "RGBA32";
  208. path.createRenderTarget(t);
  209. }
  210. var blurs = Math.round(UITrait.inst.bakeCurvSmooth);
  211. for (i in 0...blurs) {
  212. path.setTarget("texpaint_blur");
  213. path.bindTarget(texpaint, "tex");
  214. path.drawShader("shader_datas/copy_pass/copy_pass");
  215. path.setTarget(texpaint);
  216. path.bindTarget("texpaint_blur", "tex");
  217. path.drawShader("shader_datas/copy_pass/copy_pass");
  218. }
  219. }
  220. }
  221. }
  222. }
  223. @:access(iron.RenderPath)
  224. public static function commandsCursor() {
  225. var tool = Context.tool;
  226. if (tool != ToolBrush &&
  227. tool != ToolEraser &&
  228. tool != ToolClone &&
  229. tool != ToolBlur &&
  230. tool != ToolParticle) {
  231. // tool != ToolDecal &&
  232. // tool != ToolText) {
  233. return;
  234. }
  235. if (!App.uienabled ||
  236. UITrait.inst.worktab.position == SpaceScene) {
  237. return;
  238. }
  239. var plane = cast(Scene.active.getChild(".Plane"), MeshObject);
  240. var geom = plane.data.geom;
  241. var g = path.frameG;
  242. if (Layers.pipeCursor == null) Layers.makeCursorPipe();
  243. path.setTarget("");
  244. g.setPipeline(Layers.pipeCursor);
  245. var decal = Context.tool == ToolDecal || Context.tool == ToolText;
  246. var img = decal ? UITrait.inst.decalImage : Res.get("cursor.k");
  247. g.setTexture(Layers.cursorTex, img);
  248. var gbuffer0 = path.renderTargets.get("gbuffer0").image;
  249. g.setTextureDepth(Layers.cursorGbufferD, gbuffer0);
  250. g.setTexture(Layers.cursorGbuffer0, gbuffer0);
  251. var mx = Input.getMouse().viewX / iron.App.w();
  252. var my = 1.0 - (Input.getMouse().viewY / iron.App.h());
  253. if (UITrait.inst.brushLocked) {
  254. mx = (UITrait.inst.lockStartedX - iron.App.x()) / iron.App.w();
  255. my = 1.0 - (UITrait.inst.lockStartedY - iron.App.y()) / iron.App.h();
  256. }
  257. g.setFloat2(Layers.cursorMouse, mx, my);
  258. g.setFloat2(Layers.cursorStep, 2 / gbuffer0.width, 2 / gbuffer0.height);
  259. g.setFloat(Layers.cursorRadius, UITrait.inst.brushRadius / 3.4);
  260. g.setMatrix(Layers.cursorVP, Scene.active.camera.VP.self);
  261. var helpMat = iron.math.Mat4.identity();
  262. helpMat.getInverse(Scene.active.camera.VP);
  263. g.setMatrix(Layers.cursorInvVP, helpMat.self);
  264. g.setVertexBuffer(geom.vertexBuffer);
  265. g.setIndexBuffer(geom.indexBuffers[0]);
  266. g.drawIndexedVertices();
  267. g.disableScissor();
  268. path.end();
  269. }
  270. public static function begin() {
  271. pushUndoLast = History.pushUndo;
  272. if (History.pushUndo && History.undoLayers != null) {
  273. History.paint();
  274. }
  275. // 2D paint
  276. if (UITrait.inst.paint2d) {
  277. // Set plane mesh
  278. painto = Context.paintObject;
  279. visibles = [];
  280. for (p in Project.paintObjects) {
  281. visibles.push(p.visible);
  282. p.visible = false;
  283. }
  284. if (Context.mergedObject != null) {
  285. mergedObjectVisible = Context.mergedObject.visible;
  286. Context.mergedObject.visible = false;
  287. }
  288. var cam = Scene.active.camera;
  289. UITrait.inst.savedCamera.setFrom(cam.transform.local);
  290. savedFov = cam.data.raw.fov;
  291. ViewportUtil.updateCameraType(CameraPerspective);
  292. var m = Mat4.identity();
  293. m.translate(0, 0, 0.5);
  294. cam.transform.setMatrix(m);
  295. cam.data.raw.fov = 0.92;
  296. cam.buildProjection();
  297. cam.buildMatrix();
  298. var tw = 0.95 * UIView2D.inst.panScale;
  299. var tx = UIView2D.inst.panX / iron.App.w();
  300. var ty = UIView2D.inst.panY / iron.App.h();
  301. m.setIdentity();
  302. m.scale(new Vec4(tw, tw, 1));
  303. m.setLoc(new Vec4(tx, ty, 0));
  304. var m2 = Mat4.identity();
  305. m2.getInverse(Scene.active.camera.VP);
  306. m.multmat(m2);
  307. planeo = cast Scene.active.getChild(".Plane");
  308. planeo.visible = true;
  309. Context.paintObject = planeo;
  310. var v = new Vec4();
  311. var sx = v.set(m._00, m._01, m._02).length();
  312. planeo.transform.rot.fromEuler(-Math.PI / 2, 0, 0);
  313. planeo.transform.scale.set(sx, 1.0, sx);
  314. planeo.transform.loc.set(m._30, -m._31, 0.0);
  315. planeo.transform.buildMatrix();
  316. }
  317. }
  318. public static function end() {
  319. if (UITrait.inst.brush3d) RenderPathPaint.commandsCursor();
  320. Context.ddirty--;
  321. Context.pdirty--;
  322. Context.rdirty--;
  323. }
  324. public static function draw() {
  325. if (History.undoLayers != null) {
  326. // Symmetry
  327. if (UITrait.inst.symX || UITrait.inst.symY || UITrait.inst.symZ) {
  328. Context.ddirty = 2;
  329. var t = Context.paintObject.transform;
  330. var sx = t.scale.x;
  331. var sy = t.scale.y;
  332. var sz = t.scale.z;
  333. if (UITrait.inst.symX) {
  334. t.scale.set(-sx, sy, sz);
  335. t.buildMatrix();
  336. RenderPathPaint.commandsPaint();
  337. }
  338. if (UITrait.inst.symY) {
  339. t.scale.set(sx, -sy, sz);
  340. t.buildMatrix();
  341. RenderPathPaint.commandsPaint();
  342. }
  343. if (UITrait.inst.symZ) {
  344. t.scale.set(sx, sy, -sz);
  345. t.buildMatrix();
  346. RenderPathPaint.commandsPaint();
  347. }
  348. if (UITrait.inst.symX && UITrait.inst.symY) {
  349. t.scale.set(-sx, -sy, sz);
  350. t.buildMatrix();
  351. RenderPathPaint.commandsPaint();
  352. }
  353. if (UITrait.inst.symX && UITrait.inst.symZ) {
  354. t.scale.set(-sx, sy, -sz);
  355. t.buildMatrix();
  356. RenderPathPaint.commandsPaint();
  357. }
  358. if (UITrait.inst.symY && UITrait.inst.symZ) {
  359. t.scale.set(sx, -sy, -sz);
  360. t.buildMatrix();
  361. RenderPathPaint.commandsPaint();
  362. }
  363. if (UITrait.inst.symX && UITrait.inst.symY && UITrait.inst.symZ) {
  364. t.scale.set(-sx, -sy, -sz);
  365. t.buildMatrix();
  366. RenderPathPaint.commandsPaint();
  367. }
  368. t.scale.set(sx, sy, sz);
  369. t.buildMatrix();
  370. }
  371. if (Context.tool == ToolBake) {
  372. if (Context.pdirty > 0) dilated = false;
  373. if (UITrait.inst.bakeType == BakeNormal || UITrait.inst.bakeType == BakeHeight || UITrait.inst.bakeType == BakeDerivative) {
  374. if (!baking && Context.pdirty > 0) {
  375. baking = true;
  376. var _bakeType = UITrait.inst.bakeType;
  377. UITrait.inst.bakeType = UITrait.inst.bakeType == BakeNormal ? BakeNormalObject : BakePosition; // Bake high poly data
  378. MaterialParser.parsePaintMaterial();
  379. var _paintObject = Context.paintObject;
  380. var highPoly = Project.paintObjects[UITrait.inst.bakeHighPoly];
  381. var _visible = highPoly.visible;
  382. highPoly.visible = true;
  383. Context.selectPaintObject(highPoly);
  384. RenderPathPaint.commandsPaint();
  385. highPoly.visible = _visible;
  386. UITrait.inst.sub--;
  387. if (pushUndoLast) History.paint();
  388. Context.selectPaintObject(_paintObject);
  389. function _renderFinal(_) {
  390. UITrait.inst.bakeType = _bakeType;
  391. MaterialParser.parsePaintMaterial();
  392. Context.pdirty = 1;
  393. RenderPathPaint.commandsPaint();
  394. Context.pdirty = 0;
  395. iron.App.removeRender(_renderFinal);
  396. baking = false;
  397. }
  398. function _renderDeriv(_) {
  399. UITrait.inst.bakeType = BakeHeight;
  400. MaterialParser.parsePaintMaterial();
  401. Context.pdirty = 1;
  402. RenderPathPaint.commandsPaint();
  403. Context.pdirty = 0;
  404. UITrait.inst.sub--;
  405. if (pushUndoLast) History.paint();
  406. iron.App.removeRender(_renderDeriv);
  407. iron.App.notifyOnRender(_renderFinal);
  408. }
  409. iron.App.notifyOnRender(UITrait.inst.bakeType == BakeDerivative ? _renderDeriv : _renderFinal);
  410. }
  411. }
  412. else if (UITrait.inst.bakeType == BakeObjectID) {
  413. var _layerFilter = UITrait.inst.layerFilter;
  414. var _paintObject = Context.paintObject;
  415. var isMerged = Context.mergedObject != null;
  416. var _visible = isMerged && Context.mergedObject.visible;
  417. UITrait.inst.layerFilter = 1;
  418. if (isMerged) Context.mergedObject.visible = false;
  419. for (p in Project.paintObjects) {
  420. Context.selectPaintObject(p);
  421. RenderPathPaint.commandsPaint();
  422. }
  423. UITrait.inst.layerFilter = _layerFilter;
  424. Context.selectPaintObject(_paintObject);
  425. if (isMerged) Context.mergedObject.visible = _visible;
  426. }
  427. #if kha_direct3d12
  428. else if (UITrait.inst.bakeType == BakeAO ||
  429. UITrait.inst.bakeType == BakeLightmap ||
  430. UITrait.inst.bakeType == BakeBentNormal ||
  431. UITrait.inst.bakeType == BakeThickness) {
  432. RenderPathRaytrace.commandsBake();
  433. }
  434. #end
  435. else {
  436. RenderPathPaint.commandsPaint();
  437. }
  438. }
  439. else { // Paint
  440. RenderPathPaint.commandsPaint();
  441. }
  442. }
  443. //
  444. if (Context.brushBlendDirty) {
  445. Context.brushBlendDirty = false;
  446. path.setTarget("texpaint_blend0", ["texpaint_blend1"]);
  447. path.clearTarget(0x00000000);
  448. }
  449. if (UITrait.inst.paint2d) {
  450. // Restore paint mesh
  451. planeo.visible = false;
  452. for (i in 0...Project.paintObjects.length) {
  453. Project.paintObjects[i].visible = visibles[i];
  454. }
  455. if (Context.mergedObject != null) {
  456. Context.mergedObject.visible = mergedObjectVisible;
  457. }
  458. Context.paintObject = painto;
  459. Scene.active.camera.transform.setMatrix(UITrait.inst.savedCamera);
  460. Scene.active.camera.data.raw.fov = savedFov;
  461. ViewportUtil.updateCameraType(UITrait.inst.cameraType);
  462. Scene.active.camera.buildProjection();
  463. Scene.active.camera.buildMatrix();
  464. RenderPathDeferred.drawGbuffer();
  465. }
  466. }
  467. public static function bindLayers() {
  468. var tid = Project.layers[0].id;
  469. path.bindTarget("texpaint" + tid, "texpaint");
  470. path.bindTarget("texpaint_nor" + tid, "texpaint_nor");
  471. path.bindTarget("texpaint_pack" + tid, "texpaint_pack");
  472. for (i in 1...Project.layers.length) {
  473. var l = Project.layers[i];
  474. tid = l.id;
  475. path.bindTarget("texpaint" + tid, "texpaint" + tid);
  476. path.bindTarget("texpaint_nor" + tid, "texpaint_nor" + tid);
  477. path.bindTarget("texpaint_pack" + tid, "texpaint_pack" + tid);
  478. if (l.texpaint_mask != null) {
  479. path.bindTarget("texpaint_mask" + tid, "texpaint_mask" + tid);
  480. }
  481. }
  482. }
  483. public static function finishPaint() {
  484. if (Context.tool == ToolBake && !dilated && UITrait.inst.dilateRadius > 0) {
  485. Layers.makeTempImg();
  486. dilated = true;
  487. path.setTarget("temptex0");
  488. path.bindTarget("texpaint0", "tex");
  489. path.drawShader("shader_datas/copy_pass/copy_pass");
  490. path.setTarget("texpaint0");
  491. path.bindTarget("temptex0", "tex");
  492. path.drawShader("shader_datas/dilate_pass/dilate_pass");
  493. }
  494. // Brush stroke dilate
  495. // arm.util.UVUtil.cacheTriangleMap();
  496. // Layers.makeTempImg();
  497. // path.setTarget("temptex0");
  498. // path.bindTarget("texpaint0", "tex");
  499. // path.drawShader("shader_datas/copy_pass/copy_pass");
  500. // path.setTarget("texpaint0");
  501. // path.bindTarget("temptex0", "tex");
  502. // path.drawShader("shader_datas/dilate_pass/dilate_pass");
  503. }
  504. }
  505. #end