MakeMesh.hx 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. package arm.node;
  2. import arm.ui.UITrait;
  3. import arm.node.MaterialShader;
  4. import arm.Tool;
  5. class MakeMesh {
  6. public static function run(data: MaterialShaderData): MaterialShaderContext {
  7. var context_id = "mesh";
  8. var con_mesh: MaterialShaderContext = data.add_context({
  9. name: context_id,
  10. depth_write: true,
  11. compare_mode: "less",
  12. cull_mode: UITrait.inst.cullBackfaces ? "clockwise" : "none",
  13. vertex_elements: [{name: "pos", data: "short4norm"},{name: "nor", data: "short2norm"},{name: "tex", data: "short2norm"}] });
  14. var vert = con_mesh.make_vert();
  15. var frag = con_mesh.make_frag();
  16. frag.ins = vert.outs;
  17. vert.add_out('vec2 texCoord');
  18. frag.wvpposition = true;
  19. vert.add_out('vec4 prevwvpposition');
  20. vert.add_uniform('mat4 VP', '_viewProjectionMatrix');
  21. vert.add_uniform('mat4 prevWVP', '_prevWorldViewProjectionMatrix');
  22. vert.wposition = true;
  23. // Height
  24. // TODO: can cause TAA issues
  25. if (MaterialBuilder.heightUsed) {
  26. var displaceStrength = MaterialBuilder.getDisplaceStrength();
  27. vert.n = true;
  28. vert.write('float height = 0.0;');
  29. var numLayers = 0;
  30. for (l in Project.layers) {
  31. if (!l.visible) continue;
  32. if (numLayers > 16) break;
  33. numLayers++;
  34. vert.add_uniform('sampler2D texpaint_pack_vert' + l.id, '_texpaint_pack_vert' + l.id);
  35. vert.write('height += textureLod(texpaint_pack_vert' + l.id + ', tex, 0.0).a;');
  36. }
  37. vert.write('wposition += wnormal * vec3(height, height, height) * vec3($displaceStrength, $displaceStrength, $displaceStrength);');
  38. }
  39. //
  40. vert.write('gl_Position = mul(vec4(wposition.xyz, 1.0), VP);');
  41. vert.write('texCoord = tex;');
  42. if (MaterialBuilder.heightUsed) {
  43. vert.add_uniform('mat4 invW', '_inverseWorldMatrix');
  44. vert.write('prevwvpposition = mul(mul(vec4(wposition, 1.0), invW), prevWVP);');
  45. }
  46. else {
  47. vert.write('prevwvpposition = mul(vec4(pos.xyz, 1.0), prevWVP);');
  48. }
  49. frag.add_out('vec4 fragColor[3]');
  50. frag.n = true;
  51. frag.add_function(MaterialFunctions.str_packFloatInt16);
  52. frag.add_function(MaterialFunctions.str_packFloat2);
  53. if (Context.tool == ToolColorId) {
  54. frag.add_uniform('sampler2D texcolorid', '_texcolorid');
  55. frag.write('fragColor[0] = vec4(n.xy, 1.0, packFloatInt16(0.0, uint(0)));'); // met/rough
  56. frag.write('vec3 idcol = pow(textureLod(texcolorid, texCoord, 0.0).rgb, vec3(2.2, 2.2, 2.2));');
  57. frag.write('fragColor[1] = vec4(idcol.rgb, packFloat2(1.0, 1.0));'); // occ/spec
  58. }
  59. else {
  60. frag.add_function(MaterialFunctions.str_octahedronWrap);
  61. frag.write('vec3 basecol;');
  62. frag.write('float roughness;');
  63. frag.write('float metallic;');
  64. frag.write('float occlusion;');
  65. frag.write('float opacity;');
  66. frag.write('float specular;');
  67. frag.write('float matid = 0.0;');
  68. frag.vVec = true;
  69. frag.add_function(MaterialFunctions.str_cotangentFrame);
  70. #if (kha_direct3d11 || kha_direct3d12)
  71. frag.write('mat3 TBN = cotangentFrame(n, vVec, texCoord);');
  72. #else
  73. frag.write('mat3 TBN = cotangentFrame(n, -vVec, texCoord);');
  74. #end
  75. if (Project.layers[0].visible) {
  76. if (Context.layer.paintBase) {
  77. frag.add_shared_sampler('sampler2D texpaint');
  78. frag.write('basecol = textureLodShared(texpaint, texCoord, 0.0).rgb;');
  79. }
  80. else {
  81. frag.write('basecol = vec3(0.0, 0.0, 0.0);');
  82. }
  83. if (Context.layer.paintNor || MaterialBuilder.emisUsed) {
  84. frag.add_shared_sampler('sampler2D texpaint_nor');
  85. frag.write('vec4 texpaint_nor_sample = textureLodShared(texpaint_nor, texCoord, 0.0);');
  86. if (MaterialBuilder.emisUsed) {
  87. frag.write('matid = texpaint_nor_sample.a;');
  88. }
  89. if (Context.layer.paintNor) {
  90. frag.write('vec3 ntex = texpaint_nor_sample.rgb;');
  91. frag.write('n = ntex * 2.0 - 1.0;');
  92. frag.write('n.y = -n.y;');
  93. frag.write('n = normalize(mul(n, TBN));');
  94. }
  95. }
  96. if (MaterialBuilder.heightUsed ||
  97. Context.layer.paintOcc ||
  98. Context.layer.paintRough ||
  99. Context.layer.paintMet) {
  100. frag.add_shared_sampler('sampler2D texpaint_pack');
  101. frag.write('vec4 pack = textureLodShared(texpaint_pack, texCoord, 0.0);');
  102. }
  103. // Height
  104. if (MaterialBuilder.heightUsed) {
  105. var ds = MaterialBuilder.getDisplaceStrength() * 5;
  106. if (ds < 0.1) ds = 0.1;
  107. else if (ds > 2.0) ds = 2.0;
  108. frag.wposition = true;
  109. frag.write('vec3 dpdx = dFdx(wposition);');
  110. frag.write('vec3 dpdy = dFdy(wposition);');
  111. frag.write('float dhdx = dFdx(pack.a * $ds);');
  112. frag.write('float dhdy = dFdy(pack.a * $ds);');
  113. frag.write('vec3 cross_x = cross(n, dpdx);');
  114. frag.write('vec3 cross_y = cross(dpdy, n);');
  115. frag.write('vec3 ngrad = (cross_y * dhdx + cross_x * dhdy) / dot(dpdx, cross_y);');
  116. frag.write('n = normalize(n - ngrad);');
  117. // frag.add_uniform('float texpaintSize', '_texpaintSize');
  118. // frag.write('float tex_step = 1.0 / texpaintSize;');
  119. // frag.wposition = true;
  120. // frag.write('float pack_a = textureLodShared(texpaint_pack, vec2(texCoord.x + tex_step, texCoord.y), 0.0).a;');
  121. // frag.write('float pack_b = textureLodShared(texpaint_pack, vec2(texCoord.x - tex_step, texCoord.y), 0.0).a;');
  122. // frag.write('float pack_c = textureLodShared(texpaint_pack, vec2(texCoord.x, texCoord.y + tex_step), 0.0).a;');
  123. // frag.write('float pack_d = textureLodShared(texpaint_pack, vec2(texCoord.x, texCoord.y - tex_step), 0.0).a;');
  124. // frag.write('vec3 dpdx = dFdx(wposition);');
  125. // frag.write('vec3 dpdy = dFdy(wposition);');
  126. // frag.write('float dhdx = pack_a - pack_b;');
  127. // frag.write('float dhdy = pack_c - pack_d;');
  128. // frag.write('vec3 cross_x = cross(n, dpdx);');
  129. // frag.write('vec3 cross_y = cross(dpdy, n);');
  130. // frag.write('vec3 ngrad = (cross_y * dhdx + cross_x * dhdy) / dot(dpdx, cross_y);');
  131. // frag.write('n = normalize(n - ngrad);');
  132. }
  133. //
  134. if (Context.layer.paintOcc) {
  135. frag.write('occlusion = pack.r;');
  136. }
  137. else {
  138. frag.write('occlusion = 1.0;');
  139. }
  140. if (Context.layer.paintRough) {
  141. frag.write('roughness = pack.g;');
  142. }
  143. else {
  144. frag.write('roughness = 1.0;');
  145. }
  146. if (Context.layer.paintMet) {
  147. frag.write('metallic = pack.b;');
  148. }
  149. else {
  150. frag.write('metallic = 0.0;');
  151. }
  152. var l = Project.layers[0];
  153. if (l.maskOpacity < 1) {
  154. frag.write('basecol *= ${l.maskOpacity};');
  155. frag.write('occlusion *= ${l.maskOpacity};');
  156. frag.write('roughness *= ${l.maskOpacity};');
  157. frag.write('metallic *= ${l.maskOpacity};');
  158. }
  159. }
  160. else {
  161. frag.write('basecol = vec3(0.0, 0.0, 0.0);');
  162. frag.write('occlusion = 1.0;');
  163. frag.write('roughness = 1.0;');
  164. frag.write('metallic = 0.0;');
  165. frag.write('specular = 1.0;');
  166. }
  167. if (Project.layers.length > 1) {
  168. frag.write('float factor0;');
  169. frag.write('vec4 col_tex0;');
  170. frag.write('vec4 col_nor0;');
  171. frag.write('vec4 col_pack0;');
  172. frag.write('vec3 n0;');
  173. var len = Project.layers.length;
  174. var start = len - 1;
  175. var maxLayers = getMaxVisibleLayers();
  176. var count = 1;
  177. for (i in 1...len) {
  178. if (start == 1) break;
  179. start--;
  180. var l = Project.layers[len - i];
  181. if (l.visible) {
  182. count++;
  183. if (count >= maxLayers) break;
  184. }
  185. }
  186. for (i in start...len) {
  187. var l = Project.layers[i];
  188. if (!l.visible) continue;
  189. var id = l.id;
  190. if (l.objectMask > 0) {
  191. var uid = Project.paintObjects[l.objectMask - 1].uid;
  192. frag.add_uniform('int objectId', '_uid');
  193. frag.write('if ($uid == objectId) {');
  194. }
  195. frag.add_shared_sampler('sampler2D texpaint' + id);
  196. frag.write('col_tex0 = textureLodShared(texpaint' + id + ', texCoord, 0.0);');
  197. frag.write('factor0 = col_tex0.a;');
  198. if (l.texpaint_mask != null) {
  199. frag.add_shared_sampler('sampler2D texpaint_mask' + id);
  200. frag.write('factor0 *= textureLodShared(texpaint_mask' + id + ', texCoord, 0.0).r;');
  201. }
  202. if (l.maskOpacity < 1) {
  203. frag.write('factor0 *= ${l.maskOpacity};');
  204. }
  205. if (Context.layer.paintBase) {
  206. frag.write('basecol = ' + MaterialBuilder.blendMode(frag, l.blending, 'basecol', 'col_tex0.rgb', 'factor0') + ';');
  207. }
  208. if (MaterialBuilder.emisUsed || Context.layer.paintNor) {
  209. frag.add_shared_sampler('sampler2D texpaint_nor' + id);
  210. frag.write('col_nor0 = textureLodShared(texpaint_nor' + id + ', texCoord, 0.0);');
  211. if (MaterialBuilder.emisUsed) {
  212. frag.write('matid = col_nor0.a;');
  213. }
  214. if (Context.layer.paintNor) {
  215. frag.write('n0 = col_nor0.rgb * 2.0 - 1.0;');
  216. frag.write('n0.y = -n0.y;');
  217. frag.write('n0 = normalize(mul(n0, TBN));');
  218. frag.write('n = normalize(mix(n, n0, factor0));');
  219. }
  220. }
  221. if (Context.layer.paintOcc || Context.layer.paintRough || Context.layer.paintMet) {
  222. frag.add_shared_sampler('sampler2D texpaint_pack' + id);
  223. frag.write('col_pack0 = textureLodShared(texpaint_pack' + id + ', texCoord, 0.0);');
  224. if (Context.layer.paintOcc) {
  225. frag.write('occlusion = mix(occlusion, col_pack0.r, factor0);');
  226. }
  227. if (Context.layer.paintRough) {
  228. frag.write('roughness = mix(roughness, col_pack0.g, factor0);');
  229. }
  230. if (Context.layer.paintMet) {
  231. frag.write('metallic = mix(metallic, col_pack0.b, factor0);');
  232. }
  233. }
  234. if (l.objectMask > 0) {
  235. frag.write('}');
  236. }
  237. }
  238. }
  239. if (UITrait.inst.drawTexels) {
  240. frag.add_uniform('float texpaintSize', '_texpaintSize');
  241. frag.write('vec2 texel = texCoord * texpaintSize;');
  242. frag.write('basecol *= max(float(mod(int(texel.x), 2.0) == mod(int(texel.y), 2.0)), 0.9);');
  243. }
  244. if (UITrait.inst.drawWireframe) {
  245. // GL_NV_fragment_shader_barycentric
  246. // VK_AMD_shader_explicit_vertex_parameter
  247. frag.add_uniform('sampler2D texuvmap', '_texuvmap');
  248. frag.write('basecol *= 1.0 - textureLod(texuvmap, texCoord, 0.0).r;');
  249. // frag.write('if (basecol == vec3(0,0,0)) discard;');
  250. }
  251. frag.write('n /= (abs(n.x) + abs(n.y) + abs(n.z));');
  252. frag.write('n.xy = n.z >= 0.0 ? n.xy : octahedronWrap(n.xy);');
  253. frag.write('basecol = pow(basecol, vec3(2.2, 2.2, 2.2));');
  254. frag.write('fragColor[0] = vec4(n.xy, roughness, packFloatInt16(metallic, uint(matid)));');
  255. var deferred = UITrait.inst.viewportMode == ViewRender || UITrait.inst.viewportMode == ViewPathTrace;
  256. if (deferred) {
  257. if (MaterialBuilder.emisUsed) frag.write('if (matid == 1.0) basecol *= 10.0;'); // Boost for bloom
  258. frag.write('fragColor[1] = vec4(basecol, packFloat2(occlusion, 1.0));'); // occ/spec
  259. }
  260. else if (UITrait.inst.viewportMode == ViewBaseColor) {
  261. frag.write('fragColor[1] = vec4(basecol, 1.0);');
  262. }
  263. else if (UITrait.inst.viewportMode == ViewNormalMap) {
  264. frag.write('fragColor[1] = vec4(ntex.rgb, 1.0);');
  265. }
  266. else if (UITrait.inst.viewportMode == ViewOcclusion) {
  267. frag.write('fragColor[1] = vec4(vec3(occlusion, occlusion, occlusion), 1.0);');
  268. }
  269. else if (UITrait.inst.viewportMode == ViewRoughness) {
  270. frag.write('fragColor[1] = vec4(vec3(roughness, roughness, roughness), 1.0);');
  271. }
  272. else if (UITrait.inst.viewportMode == ViewMetallic) {
  273. frag.write('fragColor[1] = vec4(vec3(metallic, metallic, metallic), 1.0);');
  274. }
  275. else if (UITrait.inst.viewportMode == ViewTexCoord) {
  276. frag.write('fragColor[1] = vec4(texCoord, 0.0, 1.0);');
  277. }
  278. else if (UITrait.inst.viewportMode == ViewObjectNormal) {
  279. frag.nAttr = true;
  280. frag.write('fragColor[1] = vec4(nAttr, 1.0);');
  281. }
  282. else if (UITrait.inst.viewportMode == ViewMaterialID) {
  283. frag.write('float sample_matid = textureLodShared(texpaint_nor, texCoord, 0.0).a + 1.0 / 255.0;');
  284. frag.write('float matid_r = fract(sin(dot(vec2(sample_matid, sample_matid * 20.0), vec2(12.9898, 78.233))) * 43758.5453);');
  285. frag.write('float matid_g = fract(sin(dot(vec2(sample_matid * 20.0, sample_matid), vec2(12.9898, 78.233))) * 43758.5453);');
  286. frag.write('float matid_b = fract(sin(dot(vec2(sample_matid, sample_matid * 40.0), vec2(12.9898, 78.233))) * 43758.5453);');
  287. frag.write('fragColor[1] = vec4(matid_r, matid_g, matid_b, 1.0);');
  288. }
  289. else if (UITrait.inst.viewportMode == ViewObjectID) {
  290. frag.add_uniform('float objectId', '_objectId');
  291. frag.write('float obid = objectId + 1.0 / 255.0;');
  292. frag.write('float id_r = fract(sin(dot(vec2(obid, obid * 20.0), vec2(12.9898, 78.233))) * 43758.5453);');
  293. frag.write('float id_g = fract(sin(dot(vec2(obid * 20.0, obid), vec2(12.9898, 78.233))) * 43758.5453);');
  294. frag.write('float id_b = fract(sin(dot(vec2(obid, obid * 40.0), vec2(12.9898, 78.233))) * 43758.5453);');
  295. frag.write('fragColor[1] = vec4(id_r, id_g, id_b, 1.0);');
  296. }
  297. else if (UITrait.inst.viewportMode == ViewMask) {
  298. frag.write('float sample_mask = 1.0;');
  299. if (Context.layer.texpaint_mask != null) {
  300. frag.add_uniform('sampler2D texpaint_mask_view', '_texpaint_mask');
  301. frag.write('sample_mask = textureLod(texpaint_mask_view, texCoord, 0.0).r;');
  302. }
  303. frag.write('fragColor[1] = vec4(sample_mask, sample_mask, sample_mask, 1.0);');
  304. }
  305. }
  306. frag.write('vec2 posa = (wvpposition.xy / wvpposition.w) * 0.5 + 0.5;');
  307. frag.write('vec2 posb = (prevwvpposition.xy / prevwvpposition.w) * 0.5 + 0.5;');
  308. frag.write('fragColor[2] = vec4(posa - posb, texCoord.xy);');
  309. Material.finalize(con_mesh);
  310. con_mesh.data.shader_from_source = true;
  311. con_mesh.data.vertex_shader = vert.get();
  312. con_mesh.data.fragment_shader = frag.get();
  313. return con_mesh;
  314. }
  315. static function getMaxVisibleLayers(): Int {
  316. #if (kha_direct3d11 || kha_direct3d12)
  317. // 128 texture slots available
  318. // 4 textures per layer (3 + 1 mask)
  319. // 32 layers - base + 31 on top
  320. return 31;
  321. #else
  322. // 32 texture slots available
  323. return 4; // base + 4 on top
  324. #end
  325. }
  326. }