make_paint.ts 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. function make_paint_color_attachments(): string[] {
  2. if (context_raw.tool == workspace_tool_t.PICKER) {
  3. return ["RGBA32", "RGBA32", "RGBA32", "RGBA32"];
  4. }
  5. return ["RGBA32", "RGBA32", "RGBA32", "R8"];
  6. }
  7. function make_paint_run(data: material_t, matcon: material_context_t): node_shader_context_t {
  8. let props: shader_context_t = {
  9. name: "paint",
  10. depth_write: false,
  11. compare_mode: "always", // TODO: align texcoords winding order
  12. // cull_mode: "counter_clockwise",
  13. cull_mode: "none",
  14. vertex_elements: [
  15. {
  16. name: "pos",
  17. data: "short4norm"
  18. },
  19. {
  20. name: "nor",
  21. data: "short2norm"
  22. },
  23. {
  24. name: "tex",
  25. data: "short2norm"
  26. }
  27. ],
  28. color_attachments: make_paint_color_attachments();
  29. };
  30. let con_paint = node_shader_context_create(data, props);
  31. con_paint.data.color_writes_red = [true, true, true, true];
  32. con_paint.data.color_writes_green = [true, true, true, true];
  33. con_paint.data.color_writes_blue = [true, true, true, true];
  34. con_paint.data.color_writes_alpha = [true, true, true, true];
  35. con_paint.allow_vcols = mesh_data_get_vertex_array(context_raw.paint_object.data, "col") != null;
  36. let vert = node_shader_context_make_vert(con_paint);
  37. let frag = node_shader_context_make_frag(con_paint);
  38. frag.ins = vert.outs;
  39. if (context_raw.tool == workspace_tool_t.PICKER) {
  40. // Mangle vertices to form full screen triangle
  41. node_shader_write(vert, "gl_Position = vec4(-1.0 + float((gl_VertexID & 1) << 2), -1.0 + float((gl_VertexID & 2) << 1), 0.0, 1.0);");
  42. node_shader_add_uniform(frag, "sampler2D gbuffer2");
  43. node_shader_add_uniform(frag, "vec2 gbufferSize", "_gbufferSize");
  44. node_shader_add_uniform(frag, "vec4 inp", "_inputBrush");
  45. ///if (krom_direct3d11 || krom_direct3d12 || krom_metal || krom_vulkan)
  46. node_shader_write(frag, "vec2 texCoordInp = texelFetch(gbuffer2, ivec2(inp.x * gbufferSize.x, inp.y * gbufferSize.y), 0).ba;");
  47. ///else
  48. node_shader_write(frag, "vec2 texCoordInp = texelFetch(gbuffer2, ivec2(inp.x * gbufferSize.x, (1.0 - inp.y) * gbufferSize.y), 0).ba;");
  49. ///end
  50. node_shader_add_out(frag, "vec4 fragColor[4]");
  51. node_shader_add_uniform(frag, "sampler2D texpaint");
  52. node_shader_add_uniform(frag, "sampler2D texpaint_nor");
  53. node_shader_add_uniform(frag, "sampler2D texpaint_pack");
  54. node_shader_write(frag, "fragColor[0] = textureLod(texpaint, texCoordInp, 0.0);");
  55. node_shader_write(frag, "fragColor[1] = textureLod(texpaint_nor, texCoordInp, 0.0);");
  56. node_shader_write(frag, "fragColor[2] = textureLod(texpaint_pack, texCoordInp, 0.0);");
  57. node_shader_write(frag, "fragColor[3].rg = texCoordInp.xy;");
  58. con_paint.data.shader_from_source = true;
  59. con_paint.data.vertex_shader = node_shader_get(vert);
  60. con_paint.data.fragment_shader = node_shader_get(frag);
  61. return con_paint;
  62. }
  63. ///if (krom_direct3d11 || krom_direct3d12 || krom_metal || krom_vulkan)
  64. node_shader_write(vert, "vec2 tpos = vec2(tex.x * 2.0 - 1.0, (1.0 - tex.y) * 2.0 - 1.0);");
  65. // node_shader_write(vert, "vec2 tpos = vec2(frac(tex.x * texScale) * 2.0 - 1.0, (1.0 - frac(tex.y * texScale)) * 2.0 - 1.0);"); // 3D View
  66. ///else
  67. node_shader_write(vert, "vec2 tpos = vec2(tex.xy * 2.0 - 1.0);");
  68. ///end
  69. node_shader_write(vert, "gl_Position = vec4(tpos, 0.0, 1.0);");
  70. node_shader_add_uniform(vert, "mat4 WVP", "_world_view_proj_matrix");
  71. node_shader_add_out(vert, "vec4 ndc");
  72. node_shader_write_attrib(vert, "ndc = mul(vec4(pos.xyz, 1.0), WVP);");
  73. node_shader_write_attrib(frag, "vec3 sp = vec3((ndc.xyz / ndc.w) * 0.5 + 0.5);");
  74. node_shader_write_attrib(frag, "sp.y = 1.0 - sp.y;");
  75. node_shader_write_attrib(frag, "sp.z -= 0.0001;"); // small bias
  76. node_shader_add_uniform(frag, "vec4 inp", "_inputBrush");
  77. node_shader_add_uniform(frag, "vec4 inplast", "_inputBrushLast");
  78. node_shader_add_uniform(frag, "float aspectRatio", "_aspect_ratio_window");
  79. node_shader_write(frag, "vec2 bsp = sp.xy * 2.0 - 1.0;");
  80. node_shader_write(frag, "bsp.x *= aspectRatio;");
  81. node_shader_write(frag, "bsp = bsp * 0.5 + 0.5;");
  82. node_shader_add_uniform(frag, "sampler2D gbufferD");
  83. node_shader_add_out(frag, "vec4 fragColor[4]");
  84. node_shader_add_uniform(frag, "float brushRadius", "_brushRadius");
  85. node_shader_add_uniform(frag, "float brushOpacity", "_brushOpacity");
  86. node_shader_add_uniform(frag, "float brushHardness", "_brushHardness");
  87. if (context_raw.tool == workspace_tool_t.ERASER ||
  88. context_raw.tool == workspace_tool_t.CLONE ||
  89. context_raw.tool == workspace_tool_t.BLUR ||
  90. context_raw.tool == workspace_tool_t.SMUDGE) {
  91. node_shader_write(frag, "float dist = 0.0;");
  92. ///if (krom_direct3d11 || krom_direct3d12 || krom_metal || krom_vulkan)
  93. node_shader_write(frag, "float depth = textureLod(gbufferD, inp.xy, 0.0).r;");
  94. ///else
  95. node_shader_write(frag, "float depth = textureLod(gbufferD, vec2(inp.x, 1.0 - inp.y), 0.0).r;");
  96. ///end
  97. node_shader_add_uniform(frag, "mat4 invVP", "_inv_view_proj_matrix");
  98. node_shader_write(frag, "vec4 winp = vec4(vec2(inp.x, 1.0 - inp.y) * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0);");
  99. node_shader_write(frag, "winp = mul(winp, invVP);");
  100. node_shader_write(frag, "winp.xyz /= winp.w;");
  101. frag.wposition = true;
  102. ///if (krom_direct3d11 || krom_direct3d12 || krom_metal || krom_vulkan)
  103. node_shader_write(frag, "float depthlast = textureLod(gbufferD, inplast.xy, 0.0).r;");
  104. ///else
  105. node_shader_write(frag, "float depthlast = textureLod(gbufferD, vec2(inplast.x, 1.0 - inplast.y), 0.0).r;");
  106. ///end
  107. node_shader_write(frag, "vec4 winplast = vec4(vec2(inplast.x, 1.0 - inplast.y) * 2.0 - 1.0, depthlast * 2.0 - 1.0, 1.0);");
  108. node_shader_write(frag, "winplast = mul(winplast, invVP);");
  109. node_shader_write(frag, "winplast.xyz /= winplast.w;");
  110. node_shader_write(frag, "vec3 pa = wposition - winp.xyz;");
  111. node_shader_write(frag, "vec3 ba = winplast.xyz - winp.xyz;");
  112. // Capsule
  113. node_shader_write(frag, "float h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0);");
  114. node_shader_write(frag, "dist = length(pa - ba * h);");
  115. node_shader_write(frag, "if (dist > brushRadius) discard;");
  116. }
  117. // node_shader_add_uniform(vert, "float brushScale", "_brushScale");
  118. // node_shader_add_uniform(vert, "float texScale", "_tex_unpack");
  119. // node_shader_add_out(vert, "vec2 texCoord");
  120. // node_shader_write(vert, "texCoord = tex * brushScale * texScale;");
  121. if (context_raw.tool == workspace_tool_t.CLONE || context_raw.tool == workspace_tool_t.BLUR || context_raw.tool == workspace_tool_t.SMUDGE) {
  122. node_shader_add_uniform(frag, "sampler2D BLUR");
  123. node_shader_add_uniform(frag, "vec2 SMUDGE", "_gbufferSize");
  124. node_shader_add_uniform(frag, "sampler2D texpaint_undo", "_texpaint_undo");
  125. node_shader_add_uniform(frag, "sampler2D texpaint_nor_undo", "_texpaint_nor_undo");
  126. node_shader_add_uniform(frag, "sampler2D texpaint_pack_undo", "_texpaint_pack_undo");
  127. if (context_raw.tool == workspace_tool_t.CLONE) {
  128. // node_shader_add_uniform(frag, "vec2 BLUR", "_cloneDelta");
  129. // ///if (krom_direct3d11 || SMUDGE || krom_metal || krom_vulkan)
  130. // node_shader_write(frag, "vec2 texCoordInp = texelFetch(gbuffer2, ivec2((sp.xy + cloneDelta) * gbufferSize), 0).ba;");
  131. // ///else
  132. // node_shader_write(frag, "vec2 texCoordInp = texelFetch(gbuffer2, ivec2((sp.x + cloneDelta.x) * gbufferSize.x, (1.0 - (sp.y + cloneDelta.y)) * gbufferSize.y), 0).ba;");
  133. // ///end
  134. // node_shader_write(frag, "vec3 texpaint_pack_sample = textureLod(texpaint_pack_undo, texCoordInp, 0.0).rgb;");
  135. // let base = "textureLod(texpaint_undo, texCoordInp, 0.0).rgb";
  136. // let rough = "texpaint_pack_sample.g";
  137. // let met = "texpaint_pack_sample.b";
  138. // let occ = "texpaint_pack_sample.r";
  139. // let nortan = "textureLod(texpaint_nor_undo, texCoordInp, 0.0).rgb";
  140. // let height = "0.0";
  141. // let opac = "1.0";
  142. // node_shader_write(frag, "vec3 basecol = " + base + ";");
  143. // node_shader_write(frag, "float roughness = " + rough + ";");
  144. // node_shader_write(frag, "float metallic = " + met + ";");
  145. // node_shader_write(frag, "float occlusion = " + occ + ";");
  146. // node_shader_write(frag, "vec3 nortan = " + nortan + ";");
  147. // node_shader_write(frag, "float height = " + height + ";");
  148. // node_shader_write(frag, "float mat_opacity = " + opac + ";");
  149. // node_shader_write(frag, "float opacity = mat_opacity * brushOpacity;");
  150. }
  151. else { // Blur
  152. // ///if (krom_direct3d11 || krom_direct3d12 || krom_metal || krom_vulkan)
  153. // node_shader_write(frag, "vec2 texCoordInp = texelFetch(gbuffer2, ivec2(sp.x * gbufferSize.x, sp.y * gbufferSize.y), 0).ba;");
  154. // ///else
  155. // node_shader_write(frag, "vec2 texCoordInp = texelFetch(gbuffer2, ivec2(sp.x * gbufferSize.x, (1.0 - sp.y) * gbufferSize.y), 0).ba;");
  156. // ///end
  157. // node_shader_write(frag, "vec3 basecol = vec3(0.0, 0.0, 0.0);");
  158. // node_shader_write(frag, "float roughness = 0.0;");
  159. // node_shader_write(frag, "float metallic = 0.0;");
  160. // node_shader_write(frag, "float occlusion = 0.0;");
  161. // node_shader_write(frag, "vec3 nortan = vec3(0.0, 0.0, 0.0);");
  162. // node_shader_write(frag, "float height = 0.0;");
  163. // node_shader_write(frag, "float mat_opacity = 1.0;");
  164. // node_shader_write(frag, "float opacity = 0.0;");
  165. // node_shader_add_uniform(frag, "vec2 texpaintSize", "_texpaintSize");
  166. // node_shader_write(frag, "float blur_step = 1.0 / texpaintSize.x;");
  167. // if (context_raw.blurDirectional) {
  168. // ///if (krom_direct3d11 || krom_direct3d12 || krom_metal)
  169. // node_shader_write(frag, "const float blur_weight[7] = {1.0 / 28.0, 2.0 / 28.0, 3.0 / 28.0, 4.0 / 28.0, 5.0 / 28.0, 6.0 / 28.0, 7.0 / 28.0};");
  170. // ///else
  171. // node_shader_write(frag, "const float blur_weight[7] = float[](1.0 / 28.0, 2.0 / 28.0, 3.0 / 28.0, 4.0 / 28.0, 5.0 / 28.0, 6.0 / 28.0, 7.0 / 28.0);");
  172. // ///end
  173. // node_shader_add_uniform(frag, "vec3 brushDirection", "_brushDirection");
  174. // node_shader_write(frag, "vec2 blur_direction = brushDirection.yx;");
  175. // node_shader_write(frag, "for (int i = 0; i < 7; ++i) {");
  176. // ///if (krom_direct3d11 || krom_direct3d12 || krom_metal || krom_vulkan)
  177. // node_shader_write(frag, "vec2 texCoordInp2 = texelFetch(gbuffer2, ivec2((sp.x + blur_direction.x * blur_step * float(i)) * gbufferSize.x, (sp.y + blur_direction.y * blur_step * float(i)) * gbufferSize.y), 0).ba;");
  178. // ///else
  179. // node_shader_write(frag, "vec2 texCoordInp2 = texelFetch(gbuffer2, ivec2((sp.x + blur_direction.x * blur_step * float(i)) * gbufferSize.x, (1.0 - (sp.y + blur_direction.y * blur_step * float(i))) * gbufferSize.y), 0).ba;");
  180. // ///end
  181. // node_shader_write(frag, "vec4 texpaint_sample = texture(texpaint_undo, texCoordInp2);");
  182. // node_shader_write(frag, "opacity += texpaint_sample.a * blur_weight[i];");
  183. // node_shader_write(frag, "basecol += texpaint_sample.rgb * blur_weight[i];");
  184. // node_shader_write(frag, "vec4 texpaint_pack_sample = texture(texpaint_pack_undo, texCoordInp2) * blur_weight[i];");
  185. // node_shader_write(frag, "roughness += texpaint_pack_sample.g;");
  186. // node_shader_write(frag, "metallic += texpaint_pack_sample.b;");
  187. // node_shader_write(frag, "occlusion += texpaint_pack_sample.r;");
  188. // node_shader_write(frag, "height += texpaint_pack_sample.a;");
  189. // node_shader_write(frag, "nortan += texture(texpaint_nor_undo, texCoordInp2).rgb * blur_weight[i];");
  190. // node_shader_write(frag, "}");
  191. // }
  192. // else {
  193. // ///if (krom_direct3d11 || krom_direct3d12 || krom_metal)
  194. // node_shader_write(frag, "const float blur_weight[15] = {0.034619 / 2.0, 0.044859 / 2.0, 0.055857 / 2.0, 0.066833 / 2.0, 0.076841 / 2.0, 0.084894 / 2.0, 0.090126 / 2.0, 0.09194 / 2.0, 0.090126 / 2.0, 0.084894 / 2.0, 0.076841 / 2.0, 0.066833 / 2.0, 0.055857 / 2.0, 0.044859 / 2.0, 0.034619 / 2.0};");
  195. // ///else
  196. // node_shader_write(frag, "const float blur_weight[15] = float[](0.034619 / 2.0, 0.044859 / 2.0, 0.055857 / 2.0, 0.066833 / 2.0, 0.076841 / 2.0, 0.084894 / 2.0, 0.090126 / 2.0, 0.09194 / 2.0, 0.090126 / 2.0, 0.084894 / 2.0, 0.076841 / 2.0, 0.066833 / 2.0, 0.055857 / 2.0, 0.044859 / 2.0, 0.034619 / 2.0);");
  197. // ///end
  198. // // X
  199. // node_shader_write(frag, "for (int i = -7; i <= 7; ++i) {");
  200. // node_shader_write(frag, "vec4 texpaint_sample = texture(texpaint_undo, texCoordInp + vec2(blur_step * float(i), 0.0));");
  201. // node_shader_write(frag, "opacity += texpaint_sample.a * blur_weight[i + 7];");
  202. // node_shader_write(frag, "basecol += texpaint_sample.rgb * blur_weight[i + 7];");
  203. // node_shader_write(frag, "vec4 texpaint_pack_sample = texture(texpaint_pack_undo, texCoordInp + vec2(blur_step * float(i), 0.0)) * blur_weight[i + 7];");
  204. // node_shader_write(frag, "roughness += texpaint_pack_sample.g;");
  205. // node_shader_write(frag, "metallic += texpaint_pack_sample.b;");
  206. // node_shader_write(frag, "occlusion += texpaint_pack_sample.r;");
  207. // node_shader_write(frag, "height += texpaint_pack_sample.a;");
  208. // node_shader_write(frag, "nortan += texture(texpaint_nor_undo, texCoordInp + vec2(blur_step * float(i), 0.0)).rgb * blur_weight[i + 7];");
  209. // node_shader_write(frag, "}");
  210. // // Y
  211. // node_shader_write(frag, "for (int j = -7; j <= 7; ++j) {");
  212. // node_shader_write(frag, "vec4 texpaint_sample = texture(texpaint_undo, texCoordInp + vec2(0.0, blur_step * float(j)));");
  213. // node_shader_write(frag, "opacity += texpaint_sample.a * blur_weight[j + 7];");
  214. // node_shader_write(frag, "basecol += texpaint_sample.rgb * blur_weight[j + 7];");
  215. // node_shader_write(frag, "vec4 texpaint_pack_sample = texture(texpaint_pack_undo, texCoordInp + vec2(0.0, blur_step * float(j))) * blur_weight[j + 7];");
  216. // node_shader_write(frag, "roughness += texpaint_pack_sample.g;");
  217. // node_shader_write(frag, "metallic += texpaint_pack_sample.b;");
  218. // node_shader_write(frag, "occlusion += texpaint_pack_sample.r;");
  219. // node_shader_write(frag, "height += texpaint_pack_sample.a;");
  220. // node_shader_write(frag, "nortan += texture(texpaint_nor_undo, texCoordInp + vec2(0.0, blur_step * float(j))).rgb * blur_weight[j + 7];");
  221. // node_shader_write(frag, "}");
  222. // }
  223. // node_shader_write(frag, "opacity *= brushOpacity;");
  224. }
  225. }
  226. node_shader_write(frag, "float opacity = 1.0;");
  227. node_shader_write(frag, "if (opacity == 0.0) discard;");
  228. node_shader_write(frag, "float str = clamp((brushRadius - dist) * brushHardness * 400.0, 0.0, 1.0) * opacity;");
  229. // Manual blending to preserve memory
  230. frag.wvpposition = true;
  231. node_shader_write(frag, "vec2 sample_tc = vec2(wvpposition.xy / wvpposition.w) * 0.5 + 0.5;");
  232. ///if (krom_direct3d11 || krom_direct3d12 || krom_metal || krom_vulkan)
  233. node_shader_write(frag, "sample_tc.y = 1.0 - sample_tc.y;");
  234. ///end
  235. node_shader_add_uniform(frag, "sampler2D paintmask");
  236. node_shader_write(frag, "float sample_mask = textureLod(paintmask, sample_tc, 0.0).r;");
  237. node_shader_write(frag, "str = max(str, sample_mask);");
  238. node_shader_add_uniform(frag, "sampler2D texpaint_undo", "_texpaint_undo");
  239. node_shader_write(frag, "vec4 sample_undo = textureLod(texpaint_undo, sample_tc, 0.0);");
  240. if (context_raw.tool == workspace_tool_t.ERASER) {
  241. // node_shader_write(frag, "fragColor[0] = vec4(mix(sample_undo.rgb, vec3(0.0, 0.0, 0.0), str), sample_undo.a - str);");
  242. node_shader_write(frag, "fragColor[0] = vec4(0.0, 0.0, 0.0, 0.0);");
  243. node_shader_write(frag, "fragColor[1] = vec4(0.5, 0.5, 1.0, 0.0);");
  244. node_shader_write(frag, "fragColor[2] = vec4(1.0, 0.0, 0.0, 0.0);");
  245. }
  246. node_shader_write(frag, "fragColor[3] = vec4(str, 0.0, 0.0, 1.0);");
  247. parser_material_finalize(con_paint);
  248. parser_material_sample_keep_aspect = false;
  249. con_paint.data.shader_from_source = true;
  250. con_paint.data.vertex_shader = node_shader_get(vert);
  251. con_paint.data.fragment_shader = node_shader_get(frag);
  252. return con_paint;
  253. }