make_paint.ts 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  1. ///if is_paint
  2. function make_paint_is_raytraced_bake(): bool {
  3. return context_raw.bake_type == bake_type_t.INIT;
  4. }
  5. function make_paint_color_attachments(): string[] {
  6. if (context_raw.tool == tool_type_t.COLORID) {
  7. let res: string[] = ["RGBA32"];
  8. return res;
  9. }
  10. if (context_raw.tool == tool_type_t.PICKER && context_raw.pick_pos_nor_tex) {
  11. let res: string[] = ["RGBA128", "RGBA128"];
  12. return res;
  13. }
  14. if (context_raw.tool == tool_type_t.PICKER || context_raw.tool == tool_type_t.MATERIAL) {
  15. let res: string[] = ["RGBA32", "RGBA32", "RGBA32", "RGBA32"];
  16. return res;
  17. }
  18. if (context_raw.tool == tool_type_t.BAKE && make_paint_is_raytraced_bake()) {
  19. let res: string[] = ["RGBA64", "RGBA64"];
  20. return res;
  21. }
  22. let format: tex_format_t =
  23. base_bits_handle.position == texture_bits_t.BITS8 ? tex_format_t.RGBA32 :
  24. base_bits_handle.position == texture_bits_t.BITS16 ? tex_format_t.RGBA64 :
  25. tex_format_t.RGBA128;
  26. if (format == tex_format_t.RGBA64) {
  27. let res: string[] = ["RGBA64", "RGBA64", "RGBA64", "R8"];
  28. return res;
  29. }
  30. if (format == tex_format_t.RGBA128) {
  31. let res: string[] = ["RGBA128", "RGBA128", "RGBA128", "R8"];
  32. return res;
  33. }
  34. let res: string[] = ["RGBA32", "RGBA32", "RGBA32", "R8"];
  35. return res;
  36. }
  37. function make_paint_run(data: material_t, matcon: material_context_t): node_shader_context_t {
  38. let context_id: string = "paint";
  39. let props: shader_context_t = {
  40. name: context_id,
  41. depth_write: false,
  42. compare_mode: "always",
  43. cull_mode: "none",
  44. vertex_elements: [
  45. {
  46. name: "pos",
  47. data: "short4norm"
  48. },
  49. {
  50. name: "nor",
  51. data: "short2norm"
  52. },
  53. {
  54. name: "tex",
  55. data: "short2norm"
  56. }
  57. ],
  58. color_attachments: make_paint_color_attachments()
  59. };
  60. let con_paint: node_shader_context_t = node_shader_context_create(data, props);
  61. con_paint.data.color_writes_red = [true, true, true, true];
  62. con_paint.data.color_writes_green = [true, true, true, true];
  63. con_paint.data.color_writes_blue = [true, true, true, true];
  64. con_paint.data.color_writes_alpha = [true, true, true, true];
  65. con_paint.allow_vcols = mesh_data_get_vertex_array(context_raw.paint_object.data, "col") != null;
  66. let kong: node_shader_t = node_shader_context_make_kong(con_paint);
  67. if (context_raw.tool == tool_type_t.BAKE && context_raw.bake_type == bake_type_t.INIT) {
  68. // Init raytraced bake
  69. make_bake_position_normal(kong);
  70. con_paint.data.shader_from_source = true;
  71. gpu_create_shaders_from_kong(node_shader_get(kong), ADDRESS(con_paint.data.vertex_shader), ADDRESS(con_paint.data.fragment_shader), ADDRESS(con_paint.data._.vertex_shader_size), ADDRESS(con_paint.data._.fragment_shader_size));
  72. return con_paint;
  73. }
  74. if (context_raw.tool == tool_type_t.BAKE) {
  75. make_bake_set_color_writes(con_paint);
  76. }
  77. if (context_raw.tool == tool_type_t.COLORID || context_raw.tool == tool_type_t.PICKER || context_raw.tool == tool_type_t.MATERIAL) {
  78. make_colorid_picker_run(kong);
  79. con_paint.data.shader_from_source = true;
  80. gpu_create_shaders_from_kong(node_shader_get(kong), ADDRESS(con_paint.data.vertex_shader), ADDRESS(con_paint.data.fragment_shader), ADDRESS(con_paint.data._.vertex_shader_size), ADDRESS(con_paint.data._.fragment_shader_size));
  81. return con_paint;
  82. }
  83. let face_fill: bool = context_raw.tool == tool_type_t.FILL && context_raw.fill_type_handle.position == fill_type_t.FACE;
  84. let uv_island_fill: bool = context_raw.tool == tool_type_t.FILL && context_raw.fill_type_handle.position == fill_type_t.UV_ISLAND;
  85. let decal: bool = context_is_decal();
  86. node_shader_write_vert(kong, "var tpos: float2 = float2(input.tex.x * 2.0 - 1.0, (1.0 - input.tex.y) * 2.0 - 1.0);");
  87. node_shader_write_vert(kong, "output.pos = float4(tpos, 0.0, 1.0);");
  88. let decal_layer: bool = context_raw.layer.fill_layer != null && context_raw.layer.uv_type == uv_type_t.PROJECT;
  89. if (decal_layer) {
  90. node_shader_add_constant(kong, "WVP: float4x4", "_decal_layer_matrix");
  91. }
  92. else {
  93. node_shader_add_constant(kong, "WVP: float4x4", "_world_view_proj_matrix");
  94. }
  95. node_shader_add_out(kong, "ndc: float4");
  96. node_shader_write_attrib_vert(kong, "output.ndc = constants.WVP * float4(input.pos.xyz, 1.0);");
  97. node_shader_write_attrib_frag(kong, "var sp: float3 = (input.ndc.xyz / input.ndc.w) * 0.5 + 0.5;");
  98. node_shader_write_attrib_frag(kong, "sp.y = 1.0 - sp.y;");
  99. node_shader_write_attrib_frag(kong, "sp.z -= 0.0001;"); // small bias
  100. let uv_type: uv_type_t = context_raw.layer.fill_layer != null ? context_raw.layer.uv_type : context_raw.brush_paint;
  101. if (uv_type == uv_type_t.PROJECT) {
  102. kong.frag_ndcpos = true;
  103. }
  104. node_shader_add_constant(kong, "inp: float4", "_input_brush");
  105. node_shader_add_constant(kong, "inplast: float4", "_input_brush_last");
  106. node_shader_add_constant(kong, "aspect_ratio: float", "_aspect_ratio_window");
  107. node_shader_write_frag(kong, "var bsp: float2 = sp.xy * 2.0 - 1.0;");
  108. node_shader_write_frag(kong, "bsp.x *= constants.aspect_ratio;");
  109. node_shader_write_frag(kong, "bsp = bsp * 0.5 + 0.5;");
  110. node_shader_add_texture(kong, "gbufferD");
  111. kong.frag_out = "float4[4]";
  112. node_shader_add_constant(kong, "brush_radius: float", "_brush_radius");
  113. node_shader_add_constant(kong, "brush_opacity: float", "_brush_opacity");
  114. node_shader_add_constant(kong, "brush_hardness: float", "_brush_hardness");
  115. if (context_raw.tool == tool_type_t.BRUSH ||
  116. context_raw.tool == tool_type_t.ERASER ||
  117. context_raw.tool == tool_type_t.CLONE ||
  118. context_raw.tool == tool_type_t.BLUR ||
  119. context_raw.tool == tool_type_t.SMUDGE ||
  120. context_raw.tool == tool_type_t.PARTICLE ||
  121. decal) {
  122. let depth_reject: bool = !context_raw.xray;
  123. if (config_raw.brush_3d && !config_raw.brush_depth_reject) {
  124. depth_reject = false;
  125. }
  126. // TODO: sp.z needs to take height channel into account
  127. let particle: bool = context_raw.tool == tool_type_t.PARTICLE;
  128. if (config_raw.brush_3d && !decal && !particle) {
  129. if (make_material_height_used || context_raw.sym_x || context_raw.sym_y || context_raw.sym_z) {
  130. depth_reject = false;
  131. }
  132. }
  133. if (depth_reject) {
  134. node_shader_write_frag(kong, "if (sp.z > sample_lod(gbufferD, sampler_linear, sp.xy, 0.0).r - 0.00008) { discard; }");
  135. }
  136. make_brush_run(kong);
  137. }
  138. else { // Fill, Bake
  139. node_shader_write_frag(kong, "var dist: float = 0.0;");
  140. let angle_fill: bool = context_raw.tool == tool_type_t.FILL && context_raw.fill_type_handle.position == fill_type_t.ANGLE;
  141. if (angle_fill) {
  142. node_shader_add_function(kong, str_octahedron_wrap);
  143. node_shader_add_texture(kong, "gbuffer0");
  144. node_shader_write_frag(kong, "var g0: float2 = sample_lod(gbuffer0, sampler_linear, constants.inp.xy, 0.0).rg;");
  145. node_shader_write_frag(kong, "var wn: float3;");
  146. node_shader_write_frag(kong, "wn.z = 1.0 - abs(g0.x) - abs(g0.y);");
  147. // node_shader_write_frag(kong, "wn.xy = wn.z >= 0.0 ? g0.xy : octahedron_wrap(g0.xy);");
  148. node_shader_write_frag(kong, "if (wn.z >= 0.0) { wn.x = g0.x; wn.y = g0.y; } else { var f2: float2 = octahedron_wrap(g0.xy); wn.x = f2.x; wn.y = f2.y; }");
  149. node_shader_write_frag(kong, "wn = normalize(wn);");
  150. kong.frag_n = true;
  151. let angle: f32 = context_raw.brush_angle_reject_dot;
  152. node_shader_write_frag(kong, "if (dot(wn, n) < " + angle + ") { discard; }");
  153. }
  154. let stencil_fill: bool = context_raw.tool == tool_type_t.FILL && context_raw.brush_stencil_image != null;
  155. if (stencil_fill) {
  156. node_shader_write_frag(kong, "if (sp.z > sample_lod(gbufferD, sampler_linear, sp.xy, 0.0).r - 0.00005) { discard; }");
  157. }
  158. }
  159. if (context_raw.colorid_picked || face_fill || uv_island_fill) {
  160. node_shader_add_out(kong, "tex_coord_pick: float2");
  161. node_shader_write_vert(kong, "output.tex_coord_pick = input.tex;");
  162. if (context_raw.colorid_picked) {
  163. make_discard_color_id(kong);
  164. }
  165. if (face_fill) {
  166. make_discard_face(kong);
  167. }
  168. else if (uv_island_fill) {
  169. make_discard_uv_island(kong);
  170. }
  171. }
  172. if (context_raw.picker_mask_handle.position == picker_mask_t.MATERIAL) {
  173. make_discard_material_id(kong);
  174. }
  175. make_texcoord_run(kong);
  176. if (context_raw.tool == tool_type_t.CLONE || context_raw.tool == tool_type_t.BLUR || context_raw.tool == tool_type_t.SMUDGE) {
  177. node_shader_add_texture(kong, "gbuffer2");
  178. node_shader_add_constant(kong, "gbuffer_size: float2", "_gbuffer_size");
  179. node_shader_add_texture(kong, "texpaint_undo", "_texpaint_undo");
  180. node_shader_add_texture(kong, "texpaint_nor_undo", "_texpaint_nor_undo");
  181. node_shader_add_texture(kong, "texpaint_pack_undo", "_texpaint_pack_undo");
  182. if (context_raw.tool == tool_type_t.CLONE) {
  183. make_clone_run(kong);
  184. }
  185. else { // Blur, Smudge
  186. make_blur_run(kong);
  187. }
  188. }
  189. else {
  190. parser_material_parse_emission = context_raw.material.paint_emis;
  191. parser_material_parse_subsurface = context_raw.material.paint_subs;
  192. parser_material_parse_height = context_raw.material.paint_height;
  193. parser_material_parse_height_as_channel = true;
  194. let uv_type: uv_type_t = context_raw.layer.fill_layer != null ? context_raw.layer.uv_type : context_raw.brush_paint;
  195. parser_material_triplanar = uv_type == uv_type_t.TRIPLANAR && !decal;
  196. parser_material_sample_keep_aspect = decal;
  197. parser_material_sample_uv_scale = "constants.brush_scale";
  198. let sout: shader_out_t = parser_material_parse(ui_nodes_get_canvas_material(), con_paint, kong, matcon);
  199. parser_material_parse_emission = false;
  200. parser_material_parse_subsurface = false;
  201. parser_material_parse_height_as_channel = false;
  202. parser_material_parse_height = false;
  203. let base: string = sout.out_basecol;
  204. let rough: string = sout.out_roughness;
  205. let met: string = sout.out_metallic;
  206. let occ: string = sout.out_occlusion;
  207. let nortan: string = parser_material_out_normaltan;
  208. let height: string = sout.out_height;
  209. let opac: string = sout.out_opacity;
  210. let emis: string = sout.out_emission;
  211. let subs: string = sout.out_subsurface;
  212. node_shader_write_frag(kong, "var basecol: float3 = " + base + ";");
  213. node_shader_write_frag(kong, "var roughness: float = " + rough + ";");
  214. node_shader_write_frag(kong, "var metallic: float = " + met + ";");
  215. node_shader_write_frag(kong, "var occlusion: float = " + occ + ";");
  216. node_shader_write_frag(kong, "var nortan: float3 = " + nortan + ";");
  217. node_shader_write_frag(kong, "var height: float = " + height + ";");
  218. node_shader_write_frag(kong, "var mat_opacity: float = " + opac + ";");
  219. node_shader_write_frag(kong, "var opacity: float = mat_opacity;");
  220. if (context_raw.tool == tool_type_t.GIZMO) {
  221. node_shader_write_frag(kong, "opacity = 1.0;");
  222. }
  223. else {
  224. if (context_raw.layer.fill_layer == null) {
  225. node_shader_write_frag(kong, "opacity *= constants.brush_opacity;");
  226. }
  227. }
  228. if (context_raw.material.paint_emis) {
  229. node_shader_write_frag(kong, "var emis: float = " + emis + ";");
  230. }
  231. if (context_raw.material.paint_subs) {
  232. node_shader_write_frag(kong, "var subs: float = " + subs + ";");
  233. }
  234. if (!make_material_height_used && parse_float(height) != 0.0) {
  235. make_material_height_used = true;
  236. // Height used for the first time, also rebuild vertex shader
  237. return make_paint_run(data, matcon);
  238. }
  239. make_material_emis_used = parse_float(emis) != 0.0;
  240. make_material_subs_used = parse_float(subs) != 0.0;
  241. }
  242. if (context_raw.brush_mask_image != null && context_raw.tool == tool_type_t.DECAL) {
  243. node_shader_add_texture(kong, "texbrushmask", "_texbrushmask");
  244. node_shader_write_frag(kong, "var mask_sample: float4 = sample_lod(texbrushmask, sampler_linear, uvsp, 0.0);");
  245. if (context_raw.brush_mask_image_is_alpha) {
  246. node_shader_write_frag(kong, "opacity *= mask_sample.a;");
  247. }
  248. else {
  249. node_shader_write_frag(kong, "opacity *= mask_sample.r * mask_sample.a;");
  250. }
  251. }
  252. else if (context_raw.tool == tool_type_t.TEXT) {
  253. node_shader_add_texture(kong, "textexttool", "_textexttool");
  254. node_shader_write_frag(kong, "opacity *= sample_lod(textexttool, sampler_linear, uvsp, 0.0).r;");
  255. }
  256. if (context_raw.brush_stencil_image != null && (
  257. context_raw.tool == tool_type_t.BRUSH ||
  258. context_raw.tool == tool_type_t.ERASER ||
  259. context_raw.tool == tool_type_t.FILL ||
  260. context_raw.tool == tool_type_t.CLONE ||
  261. context_raw.tool == tool_type_t.BLUR ||
  262. context_raw.tool == tool_type_t.SMUDGE ||
  263. context_raw.tool == tool_type_t.PARTICLE ||
  264. decal)) {
  265. node_shader_add_texture(kong, "texbrushstencil", "_texbrushstencil");
  266. node_shader_add_constant(kong, "texbrushstencil_size: float2", "_size(_texbrushstencil)");
  267. node_shader_add_constant(kong, "stencil_transform: float4", "_stencil_transform");
  268. node_shader_write_frag(kong, "var stencil_uv: float2 = (sp.xy - constants.stencil_transform.xy) / constants.stencil_transform.z * float2(constants.aspect_ratio, 1.0);");
  269. node_shader_write_frag(kong, "var stencil_size: float2 = constants.texbrushstencil_size;");
  270. node_shader_write_frag(kong, "var stencil_ratio: float = stencil_size.y / stencil_size.x;");
  271. node_shader_write_frag(kong, "stencil_uv -= float2(0.5 / stencil_ratio, 0.5);");
  272. node_shader_write_frag(kong, "stencil_uv = float2(stencil_uv.x * cos(constants.stencil_transform.w) - stencil_uv.y * sin(constants.stencil_transform.w),\
  273. stencil_uv.x * sin(constants.stencil_transform.w) + stencil_uv.y * cos(constants.stencil_transform.w));");
  274. node_shader_write_frag(kong, "stencil_uv += float2(0.5 / stencil_ratio, 0.5);");
  275. node_shader_write_frag(kong, "stencil_uv.x *= stencil_ratio;");
  276. node_shader_write_frag(kong, "if (stencil_uv.x < 0.0 || stencil_uv.x > 1.0 || stencil_uv.y < 0.0 || stencil_uv.y > 1.0) { discard; }");
  277. node_shader_write_frag(kong, "var texbrushstencil_sample: float4 = sample_lod(texbrushstencil, sampler_linear, stencil_uv, 0.0);");
  278. if (context_raw.brush_stencil_image_is_alpha) {
  279. node_shader_write_frag(kong, "opacity *= texbrushstencil_sample.a;");
  280. }
  281. else {
  282. node_shader_write_frag(kong, "opacity *= texbrushstencil_sample.r * texbrushstencil_sample.a;");
  283. }
  284. }
  285. if (context_raw.brush_mask_image != null && (context_raw.tool == tool_type_t.BRUSH || context_raw.tool == tool_type_t.ERASER)) {
  286. node_shader_add_texture(kong, "texbrushmask", "_texbrushmask");
  287. node_shader_write_frag(kong, "var binp_mask: float2 = constants.inp.xy * 2.0 - 1.0;");
  288. node_shader_write_frag(kong, "binp_mask.x *= constants.aspect_ratio;");
  289. node_shader_write_frag(kong, "binp_mask = binp_mask * 0.5 + 0.5;");
  290. node_shader_write_frag(kong, "var pa_mask: float2 = bsp.xy - binp_mask.xy;");
  291. if (context_raw.brush_directional) {
  292. node_shader_add_constant(kong, "brush_direction: float3", "_brush_direction");
  293. node_shader_write_frag(kong, "if (constants.brush_direction.z == 0.0) { discard; }");
  294. node_shader_write_frag(kong, "pa_mask = float2(pa_mask.x * constants.brush_direction.x - pa_mask.y * constants.brush_direction.y, pa_mask.x * constants.brush_direction.y + pa_mask.y * constants.brush_direction.x);");
  295. }
  296. let angle: f32 = context_raw.brush_angle + context_raw.brush_nodes_angle;
  297. if (angle != 0.0) {
  298. node_shader_add_constant(kong, "brush_angle: float2", "_brush_angle");
  299. node_shader_write_frag(kong, "pa_mask.xy = float2(pa_mask.x * constants.brush_angle.x - pa_mask.y * constants.brush_angle.y, pa_mask.x * constants.brush_angle.y + pa_mask.y * constants.brush_angle.x);");
  300. }
  301. node_shader_write_frag(kong, "pa_mask = pa_mask / constants.brush_radius;");
  302. if (config_raw.brush_3d) {
  303. node_shader_add_constant(kong, "eye: float3", "_camera_pos");
  304. node_shader_write_frag(kong, "pa_mask = pa_mask * (distance(constants.eye, winp.xyz) / 1.5);");
  305. }
  306. node_shader_write_frag(kong, "pa_mask = pa_mask.xy * 0.5 + 0.5;");
  307. node_shader_write_frag(kong, "var mask_sample: float4 = sample_lod(texbrushmask, sampler_linear, pa_mask, 0.0);");
  308. if (context_raw.brush_mask_image_is_alpha) {
  309. node_shader_write_frag(kong, "opacity *= mask_sample.a;");
  310. }
  311. else {
  312. node_shader_write_frag(kong, "opacity *= mask_sample.r * mask_sample.a;");
  313. }
  314. }
  315. node_shader_write_frag(kong, "if (opacity == 0.0) { discard; }");
  316. if (context_raw.tool == tool_type_t.PARTICLE) { // Particle mask
  317. make_particle_mask(kong);
  318. }
  319. else { // Brush cursor mask
  320. node_shader_write_frag(kong, "var str: float = clamp((constants.brush_radius - dist) * constants.brush_hardness * 400.0, 0.0, 1.0) * opacity;");
  321. // node_shader_write_frag(kong, "var str: float = pow(clamp(1.0 - (dist / constants.brush_radius), 0.0, 1.0), 1.0 - constants.brush_hardness) * opacity;");
  322. // node_shader_write_frag(kong, "var t: float = clamp(dist / constants.brush_radius, 0.0, 1.0); var falloff: float = 1.0 - smoothstep(0.0, 1.0, t); var str: float = pow(falloff, 1.0 / max(constants.brush_hardness, 0.01)) * opacity;");
  323. }
  324. // Manual blending to preserve memory
  325. kong.frag_wvpposition = true;
  326. node_shader_write_frag(kong, "var sample_tc: float2 = float2(input.wvpposition.x / input.wvpposition.w, input.wvpposition.y / input.wvpposition.w) * 0.5 + 0.5;");
  327. node_shader_write_frag(kong, "sample_tc.y = 1.0 - sample_tc.y;");
  328. node_shader_add_texture(kong, "paintmask");
  329. node_shader_write_frag(kong, "var sample_mask: float = sample_lod(paintmask, sampler_linear, sample_tc, 0.0).r;");
  330. node_shader_write_frag(kong, "str = max(str, sample_mask);");
  331. // write(frag, "str = clamp(str + sample_mask, 0.0, 1.0);");
  332. node_shader_add_texture(kong, "texpaint_undo", "_texpaint_undo");
  333. node_shader_write_frag(kong, "var sample_undo: float4 = sample_lod(texpaint_undo, sampler_linear, sample_tc, 0.0);");
  334. let matid: f32 = context_raw.material.id / 255;
  335. if (context_raw.picker_mask_handle.position == picker_mask_t.MATERIAL) {
  336. matid = context_raw.materialid_picked / 255; // Keep existing material id in place when mask is set
  337. }
  338. let matid_string: string = parser_material_vec1(matid * 3.0);
  339. node_shader_write_frag(kong, "var matid: float = " + matid_string + ";");
  340. // matid % 3 == 0 - normal, 1 - emission, 2 - subsurface
  341. if (context_raw.material.paint_emis && make_material_emis_used) {
  342. node_shader_write_frag(kong, "if (emis > 0.0) {");
  343. node_shader_write_frag(kong, " matid += 1.0 / 255.0;");
  344. node_shader_write_frag(kong, " if (str == 0.0) { discard; }");
  345. node_shader_write_frag(kong, "}");
  346. }
  347. else if (context_raw.material.paint_subs && make_material_subs_used) {
  348. node_shader_write_frag(kong, "if (subs > 0.0) {");
  349. node_shader_write_frag(kong, " matid += 2.0 / 255.0;");
  350. node_shader_write_frag(kong, " if (str == 0.0) { discard; }");
  351. node_shader_write_frag(kong, "}");
  352. }
  353. let is_mask: bool = slot_layer_is_mask(context_raw.layer);
  354. let layered: bool = context_raw.layer != project_layers[0];
  355. if (layered && !is_mask) {
  356. if (context_raw.tool == tool_type_t.ERASER) {
  357. node_shader_write_frag(kong, "output[0] = float4(lerp3(sample_undo.rgb, float3(0.0, 0.0, 0.0), str), sample_undo.a - str);");
  358. node_shader_write_frag(kong, "nortan = float3(0.5, 0.5, 1.0);");
  359. node_shader_write_frag(kong, "occlusion = 1.0;");
  360. node_shader_write_frag(kong, "roughness = 0.0;");
  361. node_shader_write_frag(kong, "metallic = 0.0;");
  362. node_shader_write_frag(kong, "matid = 0.0;");
  363. }
  364. else if (context_raw.tool == tool_type_t.PARTICLE || decal || context_raw.brush_mask_image != null) {
  365. node_shader_write_frag(kong, "output[0] = float4(" + make_material_blend_mode(kong, context_raw.brush_blending, "sample_undo.rgb", "basecol", "str") + ", max(str, sample_undo.a));");
  366. }
  367. else {
  368. if (context_raw.layer.fill_layer != null) {
  369. node_shader_write_frag(kong, "output[0] = float4(" + make_material_blend_mode(kong, context_raw.brush_blending, "sample_undo.rgb", "basecol", "opacity") + ", mat_opacity);");
  370. }
  371. else {
  372. node_shader_write_frag(kong, "output[0] = float4(" + make_material_blend_mode(kong, context_raw.brush_blending, "sample_undo.rgb", "basecol", "opacity") + ", max(str, sample_undo.a));");
  373. }
  374. }
  375. node_shader_write_frag(kong, "output[1] = float4(nortan, matid);");
  376. let height: string = "0.0";
  377. if (context_raw.material.paint_height && make_material_height_used) {
  378. height = "height";
  379. }
  380. if (decal) {
  381. node_shader_add_texture(kong, "texpaint_pack_undo", "_texpaint_pack_undo");
  382. node_shader_write_frag(kong, "var sample_pack_undo: float4 = sample_lod(texpaint_pack_undo, sampler_linear, sample_tc, 0.0);");
  383. node_shader_write_frag(kong, "output[2] = lerp4(sample_pack_undo, float4(occlusion, roughness, metallic, " + height + "), str);");
  384. }
  385. else {
  386. node_shader_write_frag(kong, "output[2] = float4(occlusion, roughness, metallic, " + height + ");");
  387. }
  388. }
  389. else {
  390. if (context_raw.tool == tool_type_t.ERASER) {
  391. node_shader_write_frag(kong, "output[0] = float4(lerp3(sample_undo.rgb, float3(0.0, 0.0, 0.0), str), sample_undo.a - str);");
  392. node_shader_write_frag(kong, "output[1] = float4(0.5, 0.5, 1.0, 0.0);");
  393. node_shader_write_frag(kong, "output[2] = float4(1.0, 0.0, 0.0, 0.0);");
  394. }
  395. else {
  396. node_shader_add_texture(kong, "texpaint_nor_undo", "_texpaint_nor_undo");
  397. node_shader_add_texture(kong, "texpaint_pack_undo", "_texpaint_pack_undo");
  398. node_shader_write_frag(kong, "var sample_nor_undo: float4 = sample_lod(texpaint_nor_undo, sampler_linear, sample_tc, 0.0);");
  399. node_shader_write_frag(kong, "var sample_pack_undo: float4 = sample_lod(texpaint_pack_undo, sampler_linear, sample_tc, 0.0);");
  400. if (context_raw.tool == tool_type_t.GIZMO) {
  401. node_shader_write_frag(kong, "output[0] = float4(" + make_material_blend_mode(kong, context_raw.brush_blending, "sample_undo.rgb", "basecol", "str") + ", mat_opacity);");
  402. }
  403. else {
  404. node_shader_write_frag(kong, "output[0] = float4(" + make_material_blend_mode(kong, context_raw.brush_blending, "sample_undo.rgb", "basecol", "str") + ", max(str, sample_undo.a));");
  405. }
  406. node_shader_write_frag(kong, "output[1] = float4(lerp3(sample_nor_undo.rgb, nortan, str), matid);");
  407. if (context_raw.material.paint_height && make_material_height_used) {
  408. node_shader_write_frag(kong, "output[2] = lerp4(sample_pack_undo, float4(occlusion, roughness, metallic, height), str);");
  409. }
  410. else {
  411. node_shader_write_frag(kong, "output[2] = float4(lerp3(sample_pack_undo.rgb, float3(occlusion, roughness, metallic), str), 0.0);");
  412. }
  413. }
  414. }
  415. node_shader_write_frag(kong, "output[3] = float4(str, 0.0, 0.0, 1.0);");
  416. if (!context_raw.material.paint_base) {
  417. con_paint.data.color_writes_red[0] = false;
  418. con_paint.data.color_writes_green[0] = false;
  419. con_paint.data.color_writes_blue[0] = false;
  420. }
  421. if (!context_raw.material.paint_opac) {
  422. con_paint.data.color_writes_alpha[0] = false;
  423. }
  424. if (!context_raw.material.paint_nor) {
  425. con_paint.data.color_writes_red[1] = false;
  426. con_paint.data.color_writes_green[1] = false;
  427. con_paint.data.color_writes_blue[1] = false;
  428. }
  429. if (!context_raw.material.paint_occ) {
  430. con_paint.data.color_writes_red[2] = false;
  431. }
  432. if (!context_raw.material.paint_rough) {
  433. con_paint.data.color_writes_green[2] = false;
  434. }
  435. if (!context_raw.material.paint_met) {
  436. con_paint.data.color_writes_blue[2] = false;
  437. }
  438. if (!context_raw.material.paint_height) {
  439. con_paint.data.color_writes_alpha[2] = false;
  440. }
  441. // Base color only as mask
  442. if (is_mask) {
  443. // TODO: Apply opacity into base
  444. // write(frag, "frag_color[0].rgb *= frag_color[0].a;");
  445. con_paint.data.color_writes_green[0] = false;
  446. con_paint.data.color_writes_blue[0] = false;
  447. con_paint.data.color_writes_alpha[0] = false;
  448. con_paint.data.color_writes_red[1] = false;
  449. con_paint.data.color_writes_green[1] = false;
  450. con_paint.data.color_writes_blue[1] = false;
  451. con_paint.data.color_writes_alpha[1] = false;
  452. con_paint.data.color_writes_red[2] = false;
  453. con_paint.data.color_writes_green[2] = false;
  454. con_paint.data.color_writes_blue[2] = false;
  455. con_paint.data.color_writes_alpha[2] = false;
  456. }
  457. if (context_raw.tool == tool_type_t.BAKE) {
  458. make_bake_run(con_paint, kong);
  459. }
  460. parser_material_finalize(con_paint);
  461. parser_material_triplanar = false;
  462. parser_material_sample_keep_aspect = false;
  463. con_paint.data.shader_from_source = true;
  464. gpu_create_shaders_from_kong(node_shader_get(kong), ADDRESS(con_paint.data.vertex_shader), ADDRESS(con_paint.data.fragment_shader), ADDRESS(con_paint.data._.vertex_shader_size), ADDRESS(con_paint.data._.fragment_shader_size));
  465. return con_paint;
  466. }
  467. ///end