MakeMesh.hx 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. package arm.node;
  2. import arm.ui.UISidebar;
  3. import arm.shader.MaterialParser;
  4. import arm.shader.NodeShader;
  5. import arm.shader.NodeShaderContext;
  6. import arm.shader.NodeShaderData;
  7. import arm.shader.ShaderFunctions;
  8. import arm.data.LayerSlot;
  9. import arm.Enums;
  10. class MakeMesh {
  11. public static var layerPassCount = 1;
  12. public static function run(data: NodeShaderData, layerPass = 0): NodeShaderContext {
  13. var context_id = layerPass == 0 ? "mesh" : "mesh" + layerPass;
  14. var con_mesh: NodeShaderContext = data.add_context({
  15. name: context_id,
  16. depth_write: layerPass == 0 ? true : false,
  17. compare_mode: layerPass == 0 ? "less" : "equal",
  18. cull_mode: (Context.cullBackfaces || layerPass > 0) ? "clockwise" : "none",
  19. vertex_elements: [{name: "pos", data: "short4norm"}, {name: "nor", data: "short2norm"}, {name: "tex", data: "short2norm"}],
  20. color_attachments: ["RGBA64", "RGBA64", "RGBA64"],
  21. depth_attachment: "DEPTH32"
  22. });
  23. var vert = con_mesh.make_vert();
  24. var frag = con_mesh.make_frag();
  25. frag.ins = vert.outs;
  26. vert.add_out('vec2 texCoord');
  27. frag.wvpposition = true;
  28. vert.add_out('vec4 prevwvpposition');
  29. vert.add_uniform('mat4 VP', '_viewProjectionMatrix');
  30. vert.add_uniform('mat4 prevWVP', '_prevWorldViewProjectionMatrix');
  31. vert.wposition = true;
  32. var textureCount = 0;
  33. var displaceStrength = MakeMaterial.getDisplaceStrength();
  34. if (MakeMaterial.heightUsed && displaceStrength > 0.0) {
  35. vert.n = true;
  36. vert.write('float height = 0.0;');
  37. var numLayers = 0;
  38. for (l in Project.layers) {
  39. if (!l.isVisible() || !l.paintHeight || !l.isLayer()) continue;
  40. if (numLayers > 16) break;
  41. numLayers++;
  42. textureCount++;
  43. vert.add_uniform('sampler2D texpaint_pack_vert' + l.id, '_texpaint_pack_vert' + l.id);
  44. vert.write('height += textureLod(texpaint_pack_vert' + l.id + ', tex, 0.0).a;');
  45. var masks = l.getMasks();
  46. if (masks != null) {
  47. for (m in masks) {
  48. if (!m.isVisible()) continue;
  49. textureCount++;
  50. vert.add_uniform('sampler2D texpaint_vert' + m.id, '_texpaint_vert' + m.id);
  51. vert.write('height *= textureLod(texpaint_vert' + m.id + ', tex, 0.0).r;');
  52. }
  53. }
  54. }
  55. vert.write('wposition += wnormal * vec3(height, height, height) * vec3($displaceStrength, $displaceStrength, $displaceStrength);');
  56. }
  57. vert.write('gl_Position = mul(vec4(wposition.xyz, 1.0), VP);');
  58. vert.write('texCoord = tex;');
  59. if (MakeMaterial.heightUsed && displaceStrength > 0) {
  60. vert.add_uniform('mat4 invW', '_inverseWorldMatrix');
  61. vert.write('prevwvpposition = mul(mul(vec4(wposition, 1.0), invW), prevWVP);');
  62. }
  63. else {
  64. vert.write('prevwvpposition = mul(vec4(pos.xyz, 1.0), prevWVP);');
  65. }
  66. frag.add_out('vec4 fragColor[3]');
  67. frag.n = true;
  68. frag.add_function(ShaderFunctions.str_packFloatInt16);
  69. if (Context.tool == ToolColorId) {
  70. textureCount++;
  71. frag.add_uniform('sampler2D texcolorid', '_texcolorid');
  72. frag.write('fragColor[0] = vec4(n.xy, 1.0, packFloatInt16(0.0, uint(0)));'); // met/rough
  73. frag.write('vec3 idcol = pow(textureLod(texcolorid, texCoord, 0.0).rgb, vec3(2.2, 2.2, 2.2));');
  74. frag.write('fragColor[1] = vec4(idcol.rgb, 1.0);'); // occ
  75. }
  76. else {
  77. frag.add_function(ShaderFunctions.str_octahedronWrap);
  78. frag.add_function(ShaderFunctions.str_cotangentFrame);
  79. if (layerPass > 0) {
  80. frag.add_uniform('sampler2D gbuffer0');
  81. frag.add_uniform('sampler2D gbuffer1');
  82. frag.add_uniform('sampler2D gbuffer2');
  83. frag.write('vec2 fragcoord = (wvpposition.xy / wvpposition.w) * 0.5 + 0.5;');
  84. #if (kha_direct3d11 || kha_direct3d12 || kha_metal || kha_vulkan)
  85. frag.write('fragcoord.y = 1.0 - fragcoord.y;');
  86. #end
  87. frag.write('vec4 gbuffer0_sample = textureLod(gbuffer0, fragcoord, 0.0);');
  88. frag.write('vec4 gbuffer1_sample = textureLod(gbuffer1, fragcoord, 0.0);');
  89. frag.write('vec4 gbuffer2_sample = textureLod(gbuffer2, fragcoord, 0.0);');
  90. frag.write('vec3 basecol = gbuffer0_sample.rgb;');
  91. frag.write('float roughness = gbuffer2_sample.g;');
  92. frag.write('float metallic = gbuffer2_sample.b;');
  93. frag.write('float occlusion = gbuffer2_sample.r;');
  94. frag.write('float opacity = 1.0;//gbuffer0_sample.a;');
  95. frag.write('float matid = gbuffer1_sample.a;');
  96. frag.write('vec3 ntex = gbuffer1_sample.rgb;');
  97. frag.write('float height = gbuffer2_sample.a;');
  98. }
  99. else {
  100. frag.write('vec3 basecol = vec3(0.0, 0.0, 0.0);');
  101. frag.write('float roughness = 0.0;');
  102. frag.write('float metallic = 0.0;');
  103. frag.write('float occlusion = 1.0;');
  104. frag.write('float opacity = 1.0;');
  105. frag.write('float matid = 0.0;');
  106. frag.write('vec3 ntex = vec3(0.5, 0.5, 1.0);');
  107. frag.write('float height = 0.0;');
  108. }
  109. frag.write('vec4 texpaint_sample = vec4(0.0, 0.0, 0.0, 1.0);');
  110. frag.write('vec4 texpaint_nor_sample;');
  111. frag.write('vec4 texpaint_pack_sample;');
  112. frag.write('float texpaint_opac;');
  113. if (MakeMaterial.heightUsed) {
  114. frag.write('float height0 = 0.0;');
  115. frag.write('float height1 = 0.0;');
  116. frag.write('float height2 = 0.0;');
  117. frag.write('float height3 = 0.0;');
  118. }
  119. if (Context.drawWireframe) {
  120. textureCount++;
  121. frag.add_uniform('sampler2D texuvmap', '_texuvmap');
  122. }
  123. if (Context.viewportMode == ViewMask && Context.layer.getMasks() != null) {
  124. for (m in Context.layer.getMasks()) {
  125. if (!m.isVisible()) continue;
  126. textureCount++;
  127. frag.add_uniform('sampler2D texpaint_view_mask' + m.id, '_texpaint' + Project.layers.indexOf(m));
  128. }
  129. }
  130. if (Context.viewportMode == ViewLit && Context.renderMode == RenderForward) {
  131. textureCount += 4;
  132. frag.add_uniform('sampler2D senvmapBrdf', "$brdf.k");
  133. frag.add_uniform('sampler2D senvmapRadiance', '_envmapRadiance');
  134. frag.add_uniform('sampler2D sltcMat', '_ltcMat');
  135. frag.add_uniform('sampler2D sltcMag', '_ltcMag');
  136. }
  137. // Get layers for this pass
  138. layerPassCount = 1;
  139. var layers: Array<LayerSlot> = [];
  140. var startCount = textureCount;
  141. var isMaterialSpace = arm.ui.UIHeader.inst.worktab.position == SpaceMaterial;
  142. for (l in Project.layers) {
  143. if (isMaterialSpace && l != Context.layer) continue;
  144. if (!l.isLayer() || !l.isVisible()) continue;
  145. var count = 3;
  146. var masks = l.getMasks();
  147. if (masks != null) count += masks.length;
  148. textureCount += count;
  149. if (textureCount >= getMaxTextures()) {
  150. textureCount = startCount + count + 3; // gbuffer0_copy, gbuffer1_copy, gbuffer2_copy
  151. layerPassCount++;
  152. }
  153. if (layerPass == layerPassCount - 1) {
  154. layers.push(l);
  155. }
  156. }
  157. var lastPass = layerPass == layerPassCount - 1;
  158. for (l in layers) {
  159. if (l.getObjectMask() > 0) {
  160. frag.add_uniform('int uid', '_uid');
  161. if (l.getObjectMask() > Project.paintObjects.length) { // Atlas
  162. var visibles = Project.getAtlasObjects(l.getObjectMask());
  163. frag.write('if (');
  164. for (i in 0...visibles.length) {
  165. if (i > 0) frag.write(' || ');
  166. frag.write('${visibles[i].uid} == uid');
  167. }
  168. frag.write(') {');
  169. }
  170. else { // Object mask
  171. var uid = Project.paintObjects[l.getObjectMask() - 1].uid;
  172. frag.write('if ($uid == uid) {');
  173. }
  174. }
  175. frag.add_shared_sampler('sampler2D texpaint' + l.id);
  176. frag.write('texpaint_sample = textureLodShared(texpaint' + l.id + ', texCoord, 0.0);');
  177. frag.write('texpaint_opac = texpaint_sample.a;');
  178. // #if (kha_direct3d12 || kha_vulkan)
  179. // if (Context.viewportMode == ViewLit) {
  180. // frag.write('if (texpaint_opac < 0.1) discard;');
  181. // }
  182. // #end
  183. var masks = l.getMasks();
  184. if (masks != null) {
  185. var hasVisible = false;
  186. for (m in masks) {
  187. if (m.isVisible()) {
  188. hasVisible = true;
  189. break;
  190. }
  191. }
  192. if (hasVisible) {
  193. var texpaint_mask = 'texpaint_mask' + l.id;
  194. frag.write('float $texpaint_mask = 0.0;');
  195. for (m in masks) {
  196. if (!m.isVisible()) continue;
  197. frag.add_shared_sampler('sampler2D texpaint' + m.id);
  198. frag.write('float texpaint_mask_sample' + m.id + ' = textureLodShared(texpaint' + m.id + ', texCoord, 0.0).r;');
  199. frag.write('$texpaint_mask = ' + MakeMaterial.blendModeMask(frag, m.blending, '$texpaint_mask', 'texpaint_mask_sample' + m.id, 'float(' + m.getOpacity() + ')') + ';');
  200. }
  201. frag.write('texpaint_opac *= clamp($texpaint_mask, 0.0, 1.0);');
  202. }
  203. }
  204. if (l.getOpacity() < 1) {
  205. frag.write('texpaint_opac *= ${l.getOpacity()};');
  206. }
  207. if (l.paintBase) {
  208. if (l == Project.layers[0]) {
  209. frag.write('basecol = texpaint_sample.rgb * texpaint_opac;');
  210. }
  211. else {
  212. frag.write('basecol = ' + MakeMaterial.blendMode(frag, l.blending, 'basecol', 'texpaint_sample.rgb', 'texpaint_opac') + ';');
  213. }
  214. }
  215. if (l.paintNor || MakeMaterial.emisUsed) {
  216. frag.add_shared_sampler('sampler2D texpaint_nor' + l.id);
  217. frag.write('texpaint_nor_sample = textureLodShared(texpaint_nor' + l.id + ', texCoord, 0.0);');
  218. if (MakeMaterial.emisUsed) {
  219. frag.write('matid = texpaint_nor_sample.a;');
  220. }
  221. if (l.paintNor) {
  222. if (l.paintNorBlend) {
  223. // Whiteout blend
  224. frag.write('{');
  225. frag.write('vec3 n1 = ntex * vec3(2.0, 2.0, 2.0) - vec3(1.0, 1.0, 1.0);');
  226. frag.write('vec3 n2 = mix(vec3(0.5, 0.5, 1.0), texpaint_nor_sample.rgb, texpaint_opac) * vec3(2.0, 2.0, 2.0) - vec3(1.0, 1.0, 1.0);');
  227. frag.write('ntex = normalize(vec3(n1.xy + n2.xy, n1.z * n2.z)) * vec3(0.5, 0.5, 0.5) + vec3(0.5, 0.5, 0.5);');
  228. frag.write('}');
  229. }
  230. else {
  231. frag.write('ntex = mix(ntex, texpaint_nor_sample.rgb, texpaint_opac);');
  232. }
  233. }
  234. }
  235. if (l.paintOcc || l.paintRough || l.paintMet || (l.paintHeight && MakeMaterial.heightUsed)) {
  236. frag.add_shared_sampler('sampler2D texpaint_pack' + l.id);
  237. frag.write('texpaint_pack_sample = textureLodShared(texpaint_pack' + l.id + ', texCoord, 0.0);');
  238. if (l.paintOcc) {
  239. frag.write('occlusion = mix(occlusion, texpaint_pack_sample.r, texpaint_opac);');
  240. }
  241. if (l.paintRough) {
  242. frag.write('roughness = mix(roughness, texpaint_pack_sample.g, texpaint_opac);');
  243. }
  244. if (l.paintMet) {
  245. frag.write('metallic = mix(metallic, texpaint_pack_sample.b, texpaint_opac);');
  246. }
  247. if (l.paintHeight && MakeMaterial.heightUsed) {
  248. var assign = l.paintHeightBlend ? "+=" : "=";
  249. frag.write('height $assign texpaint_pack_sample.a * texpaint_opac;');
  250. frag.write('{');
  251. frag.add_uniform('vec2 texpaintSize', '_texpaintSize');
  252. frag.write('float tex_step = 1.0 / texpaintSize.x;');
  253. frag.write('height0 $assign textureLodShared(texpaint_pack' + l.id + ', vec2(texCoord.x - tex_step, texCoord.y), 0.0).a * texpaint_opac;');
  254. frag.write('height1 $assign textureLodShared(texpaint_pack' + l.id + ', vec2(texCoord.x + tex_step, texCoord.y), 0.0).a * texpaint_opac;');
  255. frag.write('height2 $assign textureLodShared(texpaint_pack' + l.id + ', vec2(texCoord.x, texCoord.y - tex_step), 0.0).a * texpaint_opac;');
  256. frag.write('height3 $assign textureLodShared(texpaint_pack' + l.id + ', vec2(texCoord.x, texCoord.y + tex_step), 0.0).a * texpaint_opac;');
  257. frag.write('}');
  258. }
  259. }
  260. if (l.getObjectMask() > 0) {
  261. frag.write('}');
  262. }
  263. }
  264. if (lastPass && Context.drawTexels) {
  265. frag.add_uniform('vec2 texpaintSize', '_texpaintSize');
  266. frag.write('vec2 texel = texCoord * texpaintSize;');
  267. frag.write('basecol *= max(float(mod(int(texel.x), 2.0) == mod(int(texel.y), 2.0)), 0.9);');
  268. }
  269. if (lastPass && Context.drawWireframe) {
  270. frag.write('basecol *= 1.0 - textureLod(texuvmap, texCoord, 0.0).r;');
  271. }
  272. if (MakeMaterial.heightUsed) {
  273. frag.write('if (height > 0.0) {');
  274. // frag.write('float height_dx = dFdx(height * 16.0);');
  275. // frag.write('float height_dy = dFdy(height * 16.0);');
  276. frag.write('float height_dx = height0 - height1;');
  277. frag.write('float height_dy = height2 - height3;');
  278. // Whiteout blend
  279. frag.write('vec3 n1 = ntex * vec3(2.0, 2.0, 2.0) - vec3(1.0, 1.0, 1.0);');
  280. frag.write('vec3 n2 = normalize(vec3(height_dx * 16.0, height_dy * 16.0, 1.0));');
  281. frag.write('ntex = normalize(vec3(n1.xy + n2.xy, n1.z * n2.z)) * vec3(0.5, 0.5, 0.5) + vec3(0.5, 0.5, 0.5);');
  282. frag.write('}');
  283. }
  284. if (!lastPass) {
  285. frag.write('fragColor[0] = vec4(basecol, opacity);');
  286. frag.write('fragColor[1] = vec4(ntex, matid);');
  287. frag.write('fragColor[2] = vec4(occlusion, roughness, metallic, height);');
  288. MaterialParser.finalize(con_mesh);
  289. con_mesh.data.shader_from_source = true;
  290. con_mesh.data.vertex_shader = vert.get();
  291. con_mesh.data.fragment_shader = frag.get();
  292. return con_mesh;
  293. }
  294. frag.vVec = true;
  295. #if (kha_direct3d11 || kha_direct3d12 || kha_metal || kha_vulkan)
  296. frag.write('mat3 TBN = cotangentFrame(n, vVec, texCoord);');
  297. #else
  298. frag.write('mat3 TBN = cotangentFrame(n, -vVec, texCoord);');
  299. #end
  300. frag.write('n = ntex * 2.0 - 1.0;');
  301. frag.write('n.y = -n.y;');
  302. frag.write('n = normalize(mul(n, TBN));');
  303. if (Context.viewportMode == ViewLit || Context.viewportMode == ViewPathTrace) {
  304. frag.write('basecol = pow(basecol, vec3(2.2, 2.2, 2.2));');
  305. if (Context.viewportShader != null) {
  306. var color = Context.viewportShader(frag);
  307. frag.write('fragColor[1] = vec4($color, 1.0);');
  308. }
  309. else if (Context.renderMode == RenderForward) {
  310. frag.wposition = true;
  311. frag.write('vec3 albedo = mix(basecol, vec3(0.0, 0.0, 0.0), metallic);');
  312. frag.write('vec3 f0 = mix(vec3(0.04, 0.04, 0.04), basecol, metallic);');
  313. frag.vVec = true;
  314. frag.write('float dotNV = max(dot(n, vVec), 0.0);');
  315. frag.write('vec2 envBRDF = texture(senvmapBrdf, vec2(roughness, 1.0 - dotNV)).xy;');
  316. frag.add_uniform('int envmapNumMipmaps', '_envmapNumMipmaps');
  317. frag.add_uniform('vec4 envmapData', '_envmapData'); // angle, sin(angle), cos(angle), strength
  318. frag.write('vec3 wreflect = reflect(-vVec, n);');
  319. frag.write('float envlod = roughness * float(envmapNumMipmaps);');
  320. frag.add_function(ShaderFunctions.str_envMapEquirect);
  321. frag.write('vec4 envmapDataLocal = envmapData;'); // TODO: spirv workaround
  322. frag.write('vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(wreflect, envmapDataLocal.x), envlod).rgb;');
  323. frag.add_uniform('vec3 lightArea0', '_lightArea0');
  324. frag.add_uniform('vec3 lightArea1', '_lightArea1');
  325. frag.add_uniform('vec3 lightArea2', '_lightArea2');
  326. frag.add_uniform('vec3 lightArea3', '_lightArea3');
  327. frag.add_function(ShaderFunctions.str_ltcEvaluate);
  328. frag.add_uniform('vec3 lightPos', '_pointPosition');
  329. frag.add_uniform('vec3 lightColor', '_pointColor');
  330. // frag.write('float dotNL = max(dot(n, normalize(lightPos - wposition)), 0.0);');
  331. // frag.write('vec3 direct = albedo * dotNL;');
  332. frag.write('float ldist = distance(wposition, lightPos);');
  333. frag.write('const float LUT_SIZE = 64.0;');
  334. frag.write('const float LUT_SCALE = (LUT_SIZE - 1.0) / LUT_SIZE;');
  335. frag.write('const float LUT_BIAS = 0.5 / LUT_SIZE;');
  336. frag.write('float theta = acos(dotNV);');
  337. frag.write('vec2 tuv = vec2(roughness, theta / (0.5 * 3.14159265));');
  338. frag.write('tuv = tuv * LUT_SCALE + LUT_BIAS;');
  339. frag.write('vec4 t = textureLod(sltcMat, tuv, 0.0);');
  340. frag.write('mat3 minv = mat3(vec3(1.0, 0.0, t.y), vec3(0.0, t.z, 0.0), vec3(t.w, 0.0, t.x));');
  341. frag.write('float ltcspec = ltcEvaluate(n, vVec, dotNV, wposition, minv, lightArea0, lightArea1, lightArea2, lightArea3);');
  342. frag.write('ltcspec *= textureLod(sltcMag, tuv, 0.0).a;');
  343. frag.write('mat3 mident = mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0);');
  344. frag.write('float ltcdiff = ltcEvaluate(n, vVec, dotNV, wposition, mident, lightArea0, lightArea1, lightArea2, lightArea3);');
  345. frag.write('vec3 direct = albedo * ltcdiff + ltcspec * 0.05;');
  346. frag.write('direct *= lightColor * (1.0 / (ldist * ldist));');
  347. frag.add_uniform('vec4 shirr[7]', '_envmapIrradiance');
  348. frag.add_function(ShaderFunctions.str_shIrradiance);
  349. frag.write('vec3 indirect = albedo * (shIrradiance(vec3(n.x * envmapDataLocal.z - n.y * envmapDataLocal.y, n.x * envmapDataLocal.y + n.y * envmapDataLocal.z, n.z), shirr) / 3.14159265);');
  350. frag.write('indirect += prefilteredColor * (f0 * envBRDF.x + envBRDF.y) * 1.5;');
  351. frag.write('indirect *= envmapDataLocal.w * occlusion;');
  352. frag.write('fragColor[1] = vec4(direct + indirect, 1.0);');
  353. }
  354. else { // Deferred, Pathtraced
  355. if (MakeMaterial.emisUsed) frag.write('if (int(matid * 255.0) % 3 == 1) basecol *= 10.0;'); // Boost for bloom
  356. frag.write('fragColor[1] = vec4(basecol, occlusion);');
  357. }
  358. }
  359. else if (Context.viewportMode == ViewBaseColor && Context.layer.paintBase) {
  360. frag.write('fragColor[1] = vec4(basecol, 1.0);');
  361. }
  362. else if (Context.viewportMode == ViewNormalMap && Context.layer.paintNor) {
  363. frag.write('fragColor[1] = vec4(ntex.rgb, 1.0);');
  364. }
  365. else if (Context.viewportMode == ViewOcclusion && Context.layer.paintOcc) {
  366. frag.write('fragColor[1] = vec4(vec3(occlusion, occlusion, occlusion), 1.0);');
  367. }
  368. else if (Context.viewportMode == ViewRoughness && Context.layer.paintRough) {
  369. frag.write('fragColor[1] = vec4(vec3(roughness, roughness, roughness), 1.0);');
  370. }
  371. else if (Context.viewportMode == ViewMetallic && Context.layer.paintMet) {
  372. frag.write('fragColor[1] = vec4(vec3(metallic, metallic, metallic), 1.0);');
  373. }
  374. else if (Context.viewportMode == ViewOpacity && Context.layer.paintOpac) {
  375. frag.write('fragColor[1] = vec4(vec3(texpaint_sample.a, texpaint_sample.a, texpaint_sample.a), 1.0);');
  376. }
  377. else if (Context.viewportMode == ViewHeight && Context.layer.paintHeight) {
  378. frag.write('fragColor[1] = vec4(vec3(height, height, height), 1.0);');
  379. }
  380. else if (Context.viewportMode == ViewTexCoord) {
  381. frag.write('fragColor[1] = vec4(texCoord, 0.0, 1.0);');
  382. }
  383. else if (Context.viewportMode == ViewObjectNormal) {
  384. frag.nAttr = true;
  385. frag.write('fragColor[1] = vec4(nAttr, 1.0);');
  386. }
  387. else if (Context.viewportMode == ViewMaterialID) {
  388. frag.add_shared_sampler('sampler2D texpaint_nor' + Context.layer.id);
  389. frag.add_uniform('vec2 texpaintSize', '_texpaintSize');
  390. frag.write('float sample_matid = texelFetch(texpaint_nor' + Context.layer.id + ', ivec2(texCoord * texpaintSize), 0).a + 1.0 / 255.0;');
  391. frag.write('float matid_r = fract(sin(dot(vec2(sample_matid, sample_matid * 20.0), vec2(12.9898, 78.233))) * 43758.5453);');
  392. frag.write('float matid_g = fract(sin(dot(vec2(sample_matid * 20.0, sample_matid), vec2(12.9898, 78.233))) * 43758.5453);');
  393. frag.write('float matid_b = fract(sin(dot(vec2(sample_matid, sample_matid * 40.0), vec2(12.9898, 78.233))) * 43758.5453);');
  394. frag.write('fragColor[1] = vec4(matid_r, matid_g, matid_b, 1.0);');
  395. }
  396. else if (Context.viewportMode == ViewObjectID) {
  397. frag.add_uniform('float objectId', '_objectId');
  398. frag.write('float obid = objectId + 1.0 / 255.0;');
  399. frag.write('float id_r = fract(sin(dot(vec2(obid, obid * 20.0), vec2(12.9898, 78.233))) * 43758.5453);');
  400. frag.write('float id_g = fract(sin(dot(vec2(obid * 20.0, obid), vec2(12.9898, 78.233))) * 43758.5453);');
  401. frag.write('float id_b = fract(sin(dot(vec2(obid, obid * 40.0), vec2(12.9898, 78.233))) * 43758.5453);');
  402. frag.write('fragColor[1] = vec4(id_r, id_g, id_b, 1.0);');
  403. }
  404. else if (Context.viewportMode == ViewMask && (Context.layer.getMasks() != null || Context.layer.isMask())) {
  405. if (Context.layer.isMask()) {
  406. frag.write('float mask_view = textureLodShared(texpaint' + Context.layer.id + ', texCoord, 0.0).r;');
  407. }
  408. else {
  409. frag.write('float mask_view = 0.0;');
  410. for (m in Context.layer.getMasks()) {
  411. if (!m.isVisible()) continue;
  412. frag.write('float mask_sample' + m.id + ' = textureLodShared(texpaint_view_mask' + m.id + ', texCoord, 0.0).r;');
  413. frag.write('mask_view = ' + MakeMaterial.blendModeMask(frag, m.blending, 'mask_view', 'mask_sample' + m.id, 'float(' + m.getOpacity() + ')') + ';');
  414. }
  415. }
  416. frag.write('fragColor[1] = vec4(mask_view, mask_view, mask_view, 1.0);');
  417. }
  418. else {
  419. frag.write('fragColor[1] = vec4(1.0, 0.0, 1.0, 1.0);'); // Pink
  420. }
  421. frag.write('n /= (abs(n.x) + abs(n.y) + abs(n.z));');
  422. frag.write('n.xy = n.z >= 0.0 ? n.xy : octahedronWrap(n.xy);');
  423. frag.write('fragColor[0] = vec4(n.xy, roughness, packFloatInt16(metallic, uint(int(matid * 255.0) % 3)));');
  424. }
  425. frag.write('vec2 posa = (wvpposition.xy / wvpposition.w) * 0.5 + 0.5;');
  426. frag.write('vec2 posb = (prevwvpposition.xy / prevwvpposition.w) * 0.5 + 0.5;');
  427. frag.write('fragColor[2] = vec4(posa - posb, texCoord.xy);');
  428. MaterialParser.finalize(con_mesh);
  429. con_mesh.data.shader_from_source = true;
  430. con_mesh.data.vertex_shader = vert.get();
  431. con_mesh.data.fragment_shader = frag.get();
  432. return con_mesh;
  433. }
  434. static inline function getMaxTextures(): Int {
  435. #if (kha_direct3d11 || kha_metal)
  436. return 128 - 66;
  437. #elseif (kha_direct3d12 || kha_vulkan)
  438. // CommandList5Impl->textureCount = 16;
  439. return 16 - 3;
  440. #else
  441. return 16 - 3;
  442. #end
  443. }
  444. }