make_mesh.ts 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737
  1. let make_mesh_layer_pass_count: i32 = 1;
  2. function make_mesh_run(data: material_t, layer_pass: i32 = 0): node_shader_context_t {
  3. let context_id: string = layer_pass == 0 ? "mesh" : "mesh" + layer_pass;
  4. let props: shader_context_t = {
  5. name : context_id,
  6. depth_write : layer_pass == 0 ? true : false,
  7. compare_mode : layer_pass == 0 ? "less" : "equal",
  8. cull_mode : (context_raw.cull_backfaces || layer_pass > 0) ? "clockwise" : "none",
  9. vertex_elements : [ {name : "pos", data : "short4norm"}, {name : "nor", data : "short2norm"}, {name : "tex", data : "short2norm"} ],
  10. color_attachments : [ "RGBA64", "RGBA64", "RGBA64" ],
  11. depth_attachment : "D32"
  12. };
  13. let con_mesh: node_shader_context_t = node_shader_context_create(data, props);
  14. if (mesh_data_get_vertex_array(context_raw.paint_object.data, "col") != null) {
  15. node_shader_context_add_elem(con_mesh, "col", "short4norm");
  16. }
  17. if (mesh_data_get_vertex_array(context_raw.paint_object.data, "tex1") != null) {
  18. node_shader_context_add_elem(con_mesh, "tex1", "short2norm");
  19. }
  20. let kong: node_shader_t = node_shader_context_make_kong(con_mesh);
  21. node_shader_add_out(kong, "tex_coord: float2");
  22. kong.frag_wvpposition = true;
  23. node_shader_add_constant(kong, "VP: float4x4", "_view_proj_matrix");
  24. kong.frag_wposition = true;
  25. let texture_count: i32 = 0;
  26. let displace_strength: f32 = make_material_get_displace_strength();
  27. if (make_material_height_used && displace_strength > 0.0) {
  28. kong.vert_n = true;
  29. node_shader_write_vert(kong, "var height: float = 0.0;");
  30. let num_layers: i32 = 0;
  31. for (let i: i32 = 0; i < project_layers.length; ++i) {
  32. let l: slot_layer_t = project_layers[i];
  33. if (!slot_layer_is_visible(l) || !l.paint_height || !slot_layer_is_layer(l)) {
  34. continue;
  35. }
  36. if (num_layers > 16) {
  37. break;
  38. }
  39. num_layers++;
  40. texture_count++;
  41. node_shader_add_texture(kong, "texpaint_pack_vert" + l.id, "_texpaint_pack_vert" + l.id);
  42. node_shader_write_vert(kong, "height += sample_lod(texpaint_pack_vert" + l.id + ", sampler_linear, input.tex, 0.0).a;");
  43. let masks: slot_layer_t[] = slot_layer_get_masks(l);
  44. if (masks != null) {
  45. for (let i: i32 = 0; i < masks.length; ++i) {
  46. let m: slot_layer_t = masks[i];
  47. if (!slot_layer_is_visible(m)) {
  48. continue;
  49. }
  50. texture_count++;
  51. node_shader_add_texture(kong, "texpaint_vert" + m.id, "_texpaint_vert" + m.id);
  52. node_shader_write_vert(kong, "height *= sample_lod(texpaint_vert" + m.id + ", sampler_linear, input.tex, 0.0).r;");
  53. }
  54. }
  55. }
  56. node_shader_write_vert(kong, "output.wposition += wnormal * float3(height, height, height) * float3(" + displace_strength + ", " + displace_strength +
  57. ", " + displace_strength + ");");
  58. }
  59. node_shader_write_vert(kong, "output.pos = constants.VP * float4(output.wposition.xyz, 1.0);");
  60. node_shader_write_vert(kong, "output.tex_coord = input.tex;");
  61. node_shader_write_attrib_frag(kong, "var tex_coord: float2 = input.tex_coord;");
  62. if (mesh_data_get_vertex_array(context_raw.paint_object.data, "tex1") != null) {
  63. node_shader_add_out(kong, "tex_coord1: float2");
  64. node_shader_write_vert(kong, "output.tex_coord1 = input.tex1;");
  65. node_shader_write_attrib_frag(kong, "var tex_coord1: float2 = input.tex_coord1;");
  66. }
  67. kong.frag_out = "float4[3]";
  68. kong.frag_n = true;
  69. node_shader_add_function(kong, str_pack_float_int16);
  70. for (let i: i32 = 0; i < project_layers.length; ++i) {
  71. let l: slot_layer_t = project_layers[i];
  72. if (l.texpaint_sculpt != null) {
  73. sculpt_make_mesh_run(kong, l);
  74. }
  75. }
  76. if (context_raw.tool == tool_type_t.COLORID) {
  77. texture_count++;
  78. node_shader_add_texture(kong, "texcolorid", "_texcolorid");
  79. node_shader_write_frag(kong, "output[0] = float4(n.xy, 1.0, pack_f32_i16(0.0, uint(0)));");
  80. node_shader_write_frag(kong, "var idcol: float3 = pow3(sample_lod(texcolorid, sampler_linear, tex_coord, 0.0).rgb, float3(2.2, 2.2, 2.2));");
  81. node_shader_write_frag(kong, "output[1] = float4(idcol.rgb, 1.0);"); // occ
  82. }
  83. else {
  84. node_shader_add_function(kong, str_octahedron_wrap);
  85. node_shader_add_function(kong, str_cotangent_frame);
  86. if (layer_pass > 0) {
  87. node_shader_add_texture(kong, "gbuffer0");
  88. node_shader_add_texture(kong, "gbuffer1");
  89. node_shader_add_texture(kong, "gbuffer2");
  90. node_shader_write_frag(
  91. kong, "var fragcoord: float2 = float2(input.wvpposition.x / input.wvpposition.w, input.wvpposition.y / input.wvpposition.w) * 0.5 + 0.5;");
  92. node_shader_write_frag(kong, "fragcoord.y = 1.0 - fragcoord.y;");
  93. node_shader_write_frag(kong, "var gbuffer0_sample: float4 = sample_lod(gbuffer0, sampler_linear, fragcoord, 0.0);");
  94. node_shader_write_frag(kong, "var gbuffer1_sample: float4 = sample_lod(gbuffer1, sampler_linear, fragcoord, 0.0);");
  95. node_shader_write_frag(kong, "var gbuffer2_sample: float4 = sample_lod(gbuffer2, sampler_linear, fragcoord, 0.0);");
  96. node_shader_write_frag(kong, "var basecol: float3 = gbuffer0_sample.rgb;");
  97. node_shader_write_frag(kong, "var roughness: float = gbuffer2_sample.g;");
  98. node_shader_write_frag(kong, "var metallic: float = gbuffer2_sample.b;");
  99. node_shader_write_frag(kong, "var occlusion: float = gbuffer2_sample.r;");
  100. node_shader_write_frag(kong, "var opacity: float = 1.0;//gbuffer0_sample.a;");
  101. node_shader_write_frag(kong, "var matid: float = gbuffer1_sample.a;");
  102. node_shader_write_frag(kong, "var ntex: float3 = gbuffer1_sample.rgb;");
  103. node_shader_write_frag(kong, "var height: float = gbuffer2_sample.a;");
  104. }
  105. else {
  106. node_shader_write_frag(kong, "var basecol: float3 = float3(0.0, 0.0, 0.0);");
  107. node_shader_write_frag(kong, "var roughness: float = 0.0;");
  108. node_shader_write_frag(kong, "var metallic: float = 0.0;");
  109. node_shader_write_frag(kong, "var occlusion: float = 1.0;");
  110. node_shader_write_frag(kong, "var opacity: float = 1.0;");
  111. node_shader_write_frag(kong, "var matid: float = 0.0;");
  112. node_shader_write_frag(kong, "var ntex: float3 = float3(0.5, 0.5, 1.0);");
  113. node_shader_write_frag(kong, "var height: float = 0.0;");
  114. }
  115. node_shader_write_frag(kong, "var texpaint_sample: float4 = float4(0.0, 0.0, 0.0, 1.0);");
  116. node_shader_write_frag(kong, "var texpaint_nor_sample: float4;");
  117. node_shader_write_frag(kong, "var texpaint_pack_sample: float4;");
  118. node_shader_write_frag(kong, "var texpaint_opac: float;");
  119. if (make_material_height_used) {
  120. node_shader_write_frag(kong, "var height0: float = 0.0;");
  121. node_shader_write_frag(kong, "var height1: float = 0.0;");
  122. node_shader_write_frag(kong, "var height2: float = 0.0;");
  123. node_shader_write_frag(kong, "var height3: float = 0.0;");
  124. }
  125. if (context_raw.draw_wireframe) {
  126. texture_count++;
  127. node_shader_add_texture(kong, "texuvmap", "_texuvmap");
  128. }
  129. if (context_raw.viewport_mode == viewport_mode_t.MASK && slot_layer_get_masks(context_raw.layer) != null) {
  130. for (let i: i32 = 0; i < slot_layer_get_masks(context_raw.layer).length; ++i) {
  131. let m: slot_layer_t = slot_layer_get_masks(context_raw.layer)[i];
  132. if (!slot_layer_is_visible(m)) {
  133. continue;
  134. }
  135. texture_count++;
  136. let index: i32 = array_index_of(project_layers, m);
  137. node_shader_add_texture(kong, "texpaint_view_mask" + m.id, "_texpaint" + index);
  138. }
  139. }
  140. if (context_raw.viewport_mode == viewport_mode_t.LIT && context_raw.render_mode == render_mode_t.FORWARD) {
  141. texture_count += 6;
  142. node_shader_add_texture(kong, "senvmap_radiance", "_envmap_radiance");
  143. node_shader_add_texture(kong, "senvmap_radiance0", "_envmap_radiance0");
  144. node_shader_add_texture(kong, "senvmap_radiance1", "_envmap_radiance1");
  145. node_shader_add_texture(kong, "senvmap_radiance2", "_envmap_radiance2");
  146. node_shader_add_texture(kong, "senvmap_radiance3", "_envmap_radiance3");
  147. node_shader_add_texture(kong, "senvmap_radiance4", "_envmap_radiance4");
  148. }
  149. // Get layers for this pass
  150. make_mesh_layer_pass_count = 1;
  151. let layers: slot_layer_t[] = [];
  152. let start_count: i32 = texture_count;
  153. let is_material_tool: bool = context_raw.tool == tool_type_t.MATERIAL;
  154. for (let i: i32 = 0; i < project_layers.length; ++i) {
  155. let l: slot_layer_t = project_layers[i];
  156. if (is_material_tool && l != context_raw.layer) {
  157. continue;
  158. }
  159. if (!slot_layer_is_layer(l) || !slot_layer_is_visible(l)) {
  160. continue;
  161. }
  162. let count: i32 = 3;
  163. let masks: slot_layer_t[] = slot_layer_get_masks(l);
  164. if (masks != null) {
  165. count += masks.length;
  166. }
  167. texture_count += count;
  168. if (texture_count >= GPU_MAX_TEXTURES - 3) {
  169. texture_count = start_count + count + 3; // gbuffer0_copy, gbuffer1_copy, gbuffer2_copy
  170. make_mesh_layer_pass_count++;
  171. }
  172. if (layer_pass == make_mesh_layer_pass_count - 1) {
  173. array_push(layers, l);
  174. }
  175. }
  176. let last_pass: bool = layer_pass == make_mesh_layer_pass_count - 1;
  177. for (let i: i32 = 0; i < layers.length; ++i) {
  178. let l: slot_layer_t = layers[i];
  179. if (slot_layer_get_object_mask(l) > 0) {
  180. node_shader_add_constant(kong, "uid: int", "_uid");
  181. if (slot_layer_get_object_mask(l) > project_paint_objects.length) { // Atlas
  182. let visibles: mesh_object_t[] = project_get_atlas_objects(slot_layer_get_object_mask(l));
  183. node_shader_write_frag(kong, "if (");
  184. for (let i: i32 = 0; i < visibles.length; ++i) {
  185. if (i > 0) {
  186. node_shader_write_frag(kong, " || ");
  187. }
  188. let uid: i32 = visibles[i].base.uid;
  189. node_shader_write_frag(kong, uid + " == constants.uid");
  190. }
  191. node_shader_write_frag(kong, ") {");
  192. }
  193. else { // Object mask
  194. let uid: i32 = project_paint_objects[slot_layer_get_object_mask(l) - 1].base.uid;
  195. node_shader_write_frag(kong, "if (" + uid + " == constants.uid) {");
  196. }
  197. }
  198. let tex_coord: string = l.uv_map == 1 ? "tex_coord1" : "tex_coord";
  199. node_shader_add_texture(kong, "texpaint" + l.id);
  200. node_shader_write_frag(kong, "texpaint_sample = sample_lod(texpaint" + l.id + ", sampler_linear, " + tex_coord + ", 0.0);");
  201. node_shader_write_frag(kong, "texpaint_opac = texpaint_sample.a;");
  202. // if (context_raw.viewport_mode == viewport_mode_t.LIT && make_material_opac_used) {
  203. // kong.frag_wvpposition = true;
  204. // node_shader_add_function(kong, str_dither_bayer);
  205. // node_shader_add_constant(kong, "gbuffer_size: float2", "_gbuffer_size");
  206. // node_shader_write_frag(kong, "var fragcoord1: float2 = float2(input.wvpposition.x / input.wvpposition.w, input.wvpposition.y / input.wvpposition.w) * 0.5 + 0.5;");
  207. // node_shader_write_frag(kong, "var dither: float = dither_bayer(fragcoord1 * constants.gbuffer_size);");
  208. // node_shader_write_frag(kong, "if (texpaint_opac < dither) { discard; }");
  209. // }
  210. let masks: slot_layer_t[] = slot_layer_get_masks(l);
  211. if (masks != null) {
  212. let has_visible: bool = false;
  213. for (let i: i32 = 0; i < masks.length; ++i) {
  214. let m: slot_layer_t = masks[i];
  215. if (slot_layer_is_visible(m)) {
  216. has_visible = true;
  217. break;
  218. }
  219. }
  220. if (has_visible) {
  221. let texpaint_mask: string = "texpaint_mask" + l.id;
  222. node_shader_write_frag(kong, "var " + texpaint_mask + ": float = 0.0;");
  223. for (let i: i32 = 0; i < masks.length; ++i) {
  224. let m: slot_layer_t = masks[i];
  225. if (!slot_layer_is_visible(m)) {
  226. continue;
  227. }
  228. node_shader_add_texture(kong, "texpaint" + m.id);
  229. node_shader_write_frag(kong, "{"); // Group mask is sampled across multiple layers
  230. node_shader_write_frag(kong, "var texpaint_mask_sample" + m.id + ": float = sample_lod(texpaint" + m.id + ", sampler_linear, " +
  231. tex_coord + ", 0.0).r;");
  232. let opac: f32 = slot_layer_get_opacity(m);
  233. let mask: string = make_material_blend_mode_mask(kong, m.blending, texpaint_mask, "texpaint_mask_sample" + m.id, "float(" + opac + ")");
  234. node_shader_write_frag(kong, texpaint_mask + " = " + mask + ";");
  235. node_shader_write_frag(kong, "}");
  236. }
  237. node_shader_write_frag(kong, "texpaint_opac *= clamp(" + texpaint_mask + ", 0.0, 1.0);");
  238. }
  239. }
  240. if (slot_layer_get_opacity(l) < 1) {
  241. let opac: f32 = slot_layer_get_opacity(l);
  242. node_shader_write_frag(kong, "texpaint_opac *= " + opac + ";");
  243. }
  244. if (l.paint_base) {
  245. if (l == project_layers[0]) {
  246. node_shader_write_frag(kong, "basecol = texpaint_sample.rgb * texpaint_opac;");
  247. }
  248. else {
  249. node_shader_write_frag(kong,
  250. "basecol = " + make_material_blend_mode(kong, l.blending, "basecol", "texpaint_sample.rgb", "texpaint_opac") + ";");
  251. }
  252. }
  253. if (l.paint_nor || make_material_emis_used) {
  254. node_shader_add_texture(kong, "texpaint_nor" + l.id);
  255. node_shader_write_frag(kong, "texpaint_nor_sample = sample_lod(texpaint_nor" + l.id + ", sampler_linear, " + tex_coord + ", 0.0);");
  256. if (make_material_emis_used) {
  257. node_shader_write_frag(kong, "if (texpaint_opac > 0.0) {");
  258. node_shader_add_constant(kong, "texpaint_size: float2", "_texpaint_size");
  259. node_shader_write_frag(kong, " var texpaint_nor_raw: float4 = texpaint_nor" + l.id + "[uint2(uint(" + tex_coord +
  260. ".x * constants.texpaint_size.x), uint(" + tex_coord + ".y * constants.texpaint_size.y))];");
  261. node_shader_write_frag(kong, " matid = texpaint_nor_raw.a;");
  262. node_shader_write_frag(kong, "}");
  263. }
  264. if (l.paint_nor) {
  265. if (l.paint_nor_blend) {
  266. // Whiteout blend
  267. node_shader_write_frag(kong, "{");
  268. node_shader_write_frag(kong, "var n1: float3 = ntex * float3(2.0, 2.0, 2.0) - float3(1.0, 1.0, 1.0);");
  269. node_shader_write_frag(
  270. kong,
  271. "var n2: float3 = lerp3(float3(0.5, 0.5, 1.0), texpaint_nor_sample.rgb, texpaint_opac) * float3(2.0, 2.0, 2.0) - float3(1.0, 1.0, 1.0);");
  272. node_shader_write_frag(kong, "ntex = normalize(float3(n1.xy + n2.xy, n1.z * n2.z)) * float3(0.5, 0.5, 0.5) + float3(0.5, 0.5, 0.5);");
  273. node_shader_write_frag(kong, "}");
  274. }
  275. else {
  276. node_shader_write_frag(kong, "ntex = lerp3(ntex, texpaint_nor_sample.rgb, texpaint_opac);");
  277. }
  278. }
  279. }
  280. if (l.paint_occ || l.paint_rough || l.paint_met || (l.paint_height && make_material_height_used)) {
  281. node_shader_add_texture(kong, "texpaint_pack" + l.id);
  282. node_shader_write_frag(kong, "texpaint_pack_sample = sample_lod(texpaint_pack" + l.id + ", sampler_linear, " + tex_coord + ", 0.0);");
  283. if (l.paint_occ) {
  284. node_shader_write_frag(kong, "occlusion = lerp(occlusion, texpaint_pack_sample.r, texpaint_opac);");
  285. }
  286. if (l.paint_rough) {
  287. node_shader_write_frag(kong, "roughness = lerp(roughness, texpaint_pack_sample.g, texpaint_opac);");
  288. }
  289. if (l.paint_met) {
  290. node_shader_write_frag(kong, "metallic = lerp(metallic, texpaint_pack_sample.b, texpaint_opac);");
  291. }
  292. if (l.paint_height && make_material_height_used) {
  293. let assign: string = l.paint_height_blend ? "+=" : "=";
  294. node_shader_write_frag(kong, "height " + assign + " texpaint_pack_sample.a * texpaint_opac;");
  295. node_shader_write_frag(kong, "{");
  296. node_shader_add_constant(kong, "texpaint_size: float2", "_texpaint_size");
  297. node_shader_write_frag(kong, "var tex_step: float = 1.0 / constants.texpaint_size.x;");
  298. node_shader_write_frag(kong, "height0 " + assign + " sample_lod(texpaint_pack" + l.id + ", sampler_linear, float2(" + tex_coord +
  299. ".x - tex_step, " + tex_coord + ".y), 0.0).a * texpaint_opac;");
  300. node_shader_write_frag(kong, "height1 " + assign + " sample_lod(texpaint_pack" + l.id + ", sampler_linear, float2(" + tex_coord +
  301. ".x + tex_step, " + tex_coord + ".y), 0.0).a * texpaint_opac;");
  302. node_shader_write_frag(kong, "height2 " + assign + " sample_lod(texpaint_pack" + l.id + ", sampler_linear, float2(" + tex_coord + ".x, " +
  303. tex_coord + ".y - tex_step), 0.0).a * texpaint_opac;");
  304. node_shader_write_frag(kong, "height3 " + assign + " sample_lod(texpaint_pack" + l.id + ", sampler_linear, float2(" + tex_coord + ".x, " +
  305. tex_coord + ".y + tex_step), 0.0).a * texpaint_opac;");
  306. node_shader_write_frag(kong, "}");
  307. }
  308. }
  309. if (slot_layer_get_object_mask(l) > 0) {
  310. node_shader_write_frag(kong, "}");
  311. }
  312. }
  313. if (last_pass && context_raw.draw_texels) {
  314. node_shader_add_constant(kong, "texpaint_size: float2", "_texpaint_size");
  315. node_shader_write_frag(kong, "var texel0: float2 = tex_coord * constants.texpaint_size * 0.01;");
  316. node_shader_write_frag(kong, "var texel1: float2 = tex_coord * constants.texpaint_size * 0.1;");
  317. node_shader_write_frag(kong, "var texel2: float2 = tex_coord * constants.texpaint_size;");
  318. // node_shader_write_frag(kong, "basecol = basecol * max(float((int(texel0.x) % 2.0) == (int(texel0.y) % 2.0)), 0.9);");
  319. // node_shader_write_frag(kong, "basecol = basecol * max(float((int(texel1.x) % 2.0) == (int(texel1.y) % 2.0)), 0.9);");
  320. // node_shader_write_frag(kong, "basecol = basecol * max(float((int(texel2.x) % 2.0) == (int(texel2.y) % 2.0)), 0.9);");
  321. node_shader_write_frag(kong, "var texel0xmod: float = float(int(texel0.x)) % 2.0;");
  322. node_shader_write_frag(kong, "var texel0ymod: float = float(int(texel0.y)) % 2.0;");
  323. node_shader_write_frag(kong, "var texel1xmod: float = float(int(texel1.x)) % 2.0;");
  324. node_shader_write_frag(kong, "var texel1ymod: float = float(int(texel1.y)) % 2.0;");
  325. node_shader_write_frag(kong, "var texel2xmod: float = float(int(texel2.x)) % 2.0;");
  326. node_shader_write_frag(kong, "var texel2ymod: float = float(int(texel2.y)) % 2.0;");
  327. node_shader_write_frag(kong, "if (texel0xmod == texel0ymod) { basecol = basecol * 0.9; }");
  328. node_shader_write_frag(kong, "if (texel1xmod == texel1ymod) { basecol = basecol * 0.9; }");
  329. node_shader_write_frag(kong, "if (texel2xmod == texel2ymod) { basecol = basecol * 0.9; }");
  330. }
  331. if (last_pass && context_raw.draw_wireframe) {
  332. node_shader_write_frag(kong, "var wireframe: float = sample_lod(texuvmap, sampler_linear, tex_coord, 0.0).a;");
  333. node_shader_write_frag(kong, "basecol = basecol * (1.0 - wireframe * 0.25);");
  334. node_shader_write_frag(kong, "roughness = max(roughness, wireframe);");
  335. }
  336. if (make_material_height_used) {
  337. node_shader_write_frag(kong, "if (height > 0.0) {");
  338. node_shader_write_frag(kong, "var height_dx: float = height0 - height1;");
  339. node_shader_write_frag(kong, "var height_dy: float = height2 - height3;");
  340. // Whiteout blend
  341. node_shader_write_frag(kong, "var n1: float3 = ntex * float3(2.0, 2.0, 2.0) - float3(1.0, 1.0, 1.0);");
  342. node_shader_write_frag(kong, "var n2: float3 = normalize(float3(height_dx * 16.0, height_dy * 16.0, 1.0));");
  343. node_shader_write_frag(kong, "ntex = normalize(float3(n1.xy + n2.xy, n1.z * n2.z)) * float3(0.5, 0.5, 0.5) + float3(0.5, 0.5, 0.5);");
  344. node_shader_write_frag(kong, "}");
  345. }
  346. if (!last_pass) {
  347. node_shader_write_frag(kong, "output[0] = float4(basecol, opacity);");
  348. node_shader_write_frag(kong, "output[1] = float4(ntex, matid);");
  349. node_shader_write_frag(kong, "output[2] = float4(occlusion, roughness, metallic, height);");
  350. parser_material_finalize(con_mesh);
  351. con_mesh.data.shader_from_source = true;
  352. gpu_create_shaders_from_kong(node_shader_get(kong), ADDRESS(con_mesh.data.vertex_shader), ADDRESS(con_mesh.data.fragment_shader),
  353. ADDRESS(con_mesh.data._.vertex_shader_size), ADDRESS(con_mesh.data._.fragment_shader_size));
  354. return con_mesh;
  355. }
  356. kong.frag_vvec = true;
  357. node_shader_write_frag(kong, "var TBN: float3x3 = cotangent_frame(n, vvec, tex_coord);");
  358. node_shader_write_frag(kong, "n = ntex * float3(2.0, 2.0, 2.0) - float3(1.0, 1.0, 1.0);");
  359. node_shader_write_frag(kong, "n.y = -n.y;");
  360. node_shader_write_frag(kong, "n = normalize(TBN * n);");
  361. if (context_raw.viewport_mode == viewport_mode_t.LIT || context_raw.viewport_mode == viewport_mode_t.PATH_TRACE) {
  362. node_shader_write_frag(kong, "basecol = pow3(basecol, float3(2.2, 2.2, 2.2));");
  363. node_shader_write_frag(kong, "basecol = max3(basecol, float3(0.0, 0.0, 0.0));");
  364. if (context_raw.viewport_shader != null) {
  365. node_shader_write_frag(kong, "var output_color: float3;");
  366. js_call_ptr(context_raw.viewport_shader, kong);
  367. node_shader_write_frag(kong, "output[1] = float4(output_color, 1.0);");
  368. }
  369. else if (context_raw.render_mode == render_mode_t.FORWARD && context_raw.viewport_mode != viewport_mode_t.PATH_TRACE) {
  370. node_shader_write_frag(kong, "var albedo: float3 = lerp3(basecol, float3(0.0, 0.0, 0.0), metallic);");
  371. node_shader_write_frag(kong, "var f0: float3 = lerp3(float3(0.04, 0.04, 0.04), basecol, metallic);");
  372. kong.frag_vvec = true;
  373. node_shader_write_frag(kong, "var dotnv: float = max(0.0, dot(n, vvec));");
  374. // node_shader_add_constant(kong, "envmap_num_mipmaps: int", "_envmap_num_mipmaps");
  375. node_shader_add_constant(kong, "envmap_data: float4", "_envmap_data"); // angle, sin(angle), cos(angle), strength
  376. node_shader_write_frag(kong, "var wreflect: float3 = reflect(-vvec, n);");
  377. node_shader_add_function(kong, str_envmap_equirect);
  378. // node_shader_write_frag(kong, "var envlod: float = roughness * float(constants.envmap_num_mipmaps);");
  379. // node_shader_write_frag(kong, "var prefiltered_color: float3 = sample_lod(senvmap_radiance, sampler_linear, envmap_equirect(wreflect,
  380. // constants.envmap_data.x), envlod).rgb;");
  381. node_shader_add_function(kong, str_envmap_sample);
  382. node_shader_write_frag(kong, "var envlod: float = roughness * 5.0;");
  383. node_shader_write_frag(kong, "var lod0: float = floor(envlod);");
  384. node_shader_write_frag(kong, "var lod1: float = ceil(envlod);");
  385. node_shader_write_frag(kong, "var lodf: float = envlod - lod0;");
  386. node_shader_write_frag(kong, "var envmap_coord: float2 = envmap_equirect(wreflect, constants.envmap_data.x);");
  387. node_shader_write_frag(kong, "var lodc0: float3 = envmap_sample(lod0, envmap_coord);");
  388. node_shader_write_frag(kong, "var lodc1: float3 = envmap_sample(lod1, envmap_coord);");
  389. node_shader_write_frag(kong, "var prefiltered_color: float3 = lerp3(lodc0, lodc1, lodf);");
  390. // node_shader_add_constant(kong, "shirr: float4[7]", "_envmap_irradiance");
  391. node_shader_add_constant(kong, "shirr0: float4", "_envmap_irradiance0");
  392. node_shader_add_constant(kong, "shirr1: float4", "_envmap_irradiance1");
  393. node_shader_add_constant(kong, "shirr2: float4", "_envmap_irradiance2");
  394. node_shader_add_constant(kong, "shirr3: float4", "_envmap_irradiance3");
  395. node_shader_add_constant(kong, "shirr4: float4", "_envmap_irradiance4");
  396. node_shader_add_constant(kong, "shirr5: float4", "_envmap_irradiance5");
  397. node_shader_add_constant(kong, "shirr6: float4", "_envmap_irradiance6");
  398. node_shader_add_function(kong, str_sh_irradiance);
  399. node_shader_write_frag(
  400. kong,
  401. "var indirect: float3 = albedo * (sh_irradiance(float3(n.x * constants.envmap_data.z - n.y * constants.envmap_data.y, n.x * constants.envmap_data.y + n.y * constants.envmap_data.z, n.z)) / 3.14159265);");
  402. node_shader_add_function(kong, str_env_brdf_approx);
  403. node_shader_write_frag(kong, "indirect = indirect + prefiltered_color * env_brdf_approx(f0, roughness, dotnv) * 0.5;");
  404. node_shader_write_frag(kong, "indirect = indirect * constants.envmap_data.w * occlusion;");
  405. node_shader_write_frag(kong, "output[1] = float4(indirect, 1.0);");
  406. }
  407. else { // Deferred, Pathtraced
  408. if (make_material_emis_used) {
  409. node_shader_write_frag(kong, "if (float(int(matid * 255.0)) % float(3) == 1.0) { basecol = basecol * 10.0; }"); // Boost for bloom
  410. }
  411. node_shader_write_frag(kong, "output[1] = float4(basecol, occlusion);");
  412. }
  413. }
  414. else if (context_raw.viewport_mode == viewport_mode_t.BASE_COLOR && context_raw.layer.paint_base) {
  415. node_shader_write_frag(kong, "output[1] = float4(basecol, 1.0);");
  416. }
  417. else if (context_raw.viewport_mode == viewport_mode_t.NORMAL_MAP && context_raw.layer.paint_nor) {
  418. node_shader_write_frag(kong, "output[1] = float4(ntex.rgb, 1.0);");
  419. }
  420. else if (context_raw.viewport_mode == viewport_mode_t.OCCLUSION && context_raw.layer.paint_occ) {
  421. node_shader_write_frag(kong, "output[1] = float4(float3(occlusion, occlusion, occlusion), 1.0);");
  422. }
  423. else if (context_raw.viewport_mode == viewport_mode_t.ROUGHNESS && context_raw.layer.paint_rough) {
  424. node_shader_write_frag(kong, "output[1] = float4(float3(roughness, roughness, roughness), 1.0);");
  425. }
  426. else if (context_raw.viewport_mode == viewport_mode_t.METALLIC && context_raw.layer.paint_met) {
  427. node_shader_write_frag(kong, "output[1] = float4(float3(metallic, metallic, metallic), 1.0);");
  428. }
  429. else if (context_raw.viewport_mode == viewport_mode_t.OPACITY && context_raw.layer.paint_opac) {
  430. node_shader_write_frag(kong, "output[1] = float4(float3(texpaint_sample.a, texpaint_sample.a, texpaint_sample.a), 1.0);");
  431. }
  432. else if (context_raw.viewport_mode == viewport_mode_t.HEIGHT && context_raw.layer.paint_height) {
  433. node_shader_write_frag(kong, "output[1] = float4(float3(height, height, height), 1.0);");
  434. }
  435. else if (context_raw.viewport_mode == viewport_mode_t.EMISSION) {
  436. node_shader_write_frag(kong, "var matid_mod: float = float(int(matid * 255.0)) % float(3);");
  437. node_shader_write_frag(kong, "var emis: float = 0.0; if (matid_mod == 1.0) { emis = 1.0; }");
  438. node_shader_write_frag(kong, "output[1] = float4(float3(emis, emis, emis), 1.0);");
  439. }
  440. else if (context_raw.viewport_mode == viewport_mode_t.SUBSURFACE) {
  441. node_shader_write_frag(kong, "var matid_mod: float = float(int(matid * 255.0)) % float(3);");
  442. node_shader_write_frag(kong, "var subs: float = 0.0; if (matid_mod == 2.0) { subs = 1.0; }");
  443. node_shader_write_frag(kong, "output[1] = float4(float3(subs, subs, subs), 1.0);");
  444. }
  445. else if (context_raw.viewport_mode == viewport_mode_t.TEXCOORD) {
  446. node_shader_write_frag(kong, "output[1] = float4(tex_coord, 0.0, 1.0);");
  447. }
  448. else if (context_raw.viewport_mode == viewport_mode_t.OBJECT_NORMAL) {
  449. kong.frag_nattr = true;
  450. node_shader_write_frag(kong, "output[1] = float4(input.nattr, 1.0);");
  451. }
  452. else if (context_raw.viewport_mode == viewport_mode_t.MATERIAL_ID) {
  453. let id: i32 = context_raw.layer.id;
  454. node_shader_add_texture(kong, "texpaint_nor" + id);
  455. node_shader_add_constant(kong, "texpaint_size: float2", "_texpaint_size");
  456. // node_shader_write_frag(kong, "var sample_matid: float = texpaint_nor" + id + "[uint2(tex_coord * constants.texpaint_size)].a + 1.0 / 255.0;");
  457. node_shader_write_frag(kong, "var sample_matid_coord: float2 = tex_coord * constants.texpaint_size;");
  458. node_shader_write_frag(kong, "var sample_matid4: float4 = texpaint_nor" + id + "[uint2(uint(sample_matid_coord.x), uint(sample_matid_coord.y))];");
  459. node_shader_write_frag(kong, "var sample_matid: float = sample_matid4.a + 1.0 / 255.0;");
  460. node_shader_write_frag(kong,
  461. "var matid_r: float = frac(sin(dot(float2(sample_matid, sample_matid * 20.0), float2(12.9898, 78.233))) * 43758.5453);");
  462. node_shader_write_frag(kong,
  463. "var matid_g: float = frac(sin(dot(float2(sample_matid * 20.0, sample_matid), float2(12.9898, 78.233))) * 43758.5453);");
  464. node_shader_write_frag(kong,
  465. "var matid_b: float = frac(sin(dot(float2(sample_matid, sample_matid * 40.0), float2(12.9898, 78.233))) * 43758.5453);");
  466. node_shader_write_frag(kong, "output[1] = float4(matid_r, matid_g, matid_b, 1.0);");
  467. }
  468. else if (context_raw.viewport_mode == viewport_mode_t.OBJECT_ID) {
  469. node_shader_add_constant(kong, "object_id: float", "_object_id");
  470. node_shader_write_frag(kong, "var obid: float = constants.object_id + 1.0 / 255.0;");
  471. node_shader_write_frag(kong, "var id_r: float = frac(sin(dot(float2(obid, obid * 20.0), float2(12.9898, 78.233))) * 43758.5453);");
  472. node_shader_write_frag(kong, "var id_g: float = frac(sin(dot(float2(obid * 20.0, obid), float2(12.9898, 78.233))) * 43758.5453);");
  473. node_shader_write_frag(kong, "var id_b: float = frac(sin(dot(float2(obid, obid * 40.0), float2(12.9898, 78.233))) * 43758.5453);");
  474. node_shader_write_frag(kong, "output[1] = float4(id_r, id_g, id_b, 1.0);");
  475. }
  476. else if (context_raw.viewport_mode == viewport_mode_t.MASK &&
  477. (slot_layer_get_masks(context_raw.layer) != null || slot_layer_is_mask(context_raw.layer))) {
  478. if (slot_layer_is_mask(context_raw.layer)) {
  479. let id: i32 = context_raw.layer.id;
  480. node_shader_write_frag(kong, "var mask_view: float = sample_lod(texpaint" + id + ", sampler_linear, tex_coord, 0.0).r;");
  481. }
  482. else {
  483. node_shader_write_frag(kong, "var mask_view: float = 0.0;");
  484. for (let i: i32 = 0; i < slot_layer_get_masks(context_raw.layer).length; ++i) {
  485. let m: slot_layer_t = slot_layer_get_masks(context_raw.layer)[i];
  486. if (!slot_layer_is_visible(m)) {
  487. continue;
  488. }
  489. node_shader_write_frag(kong, "var mask_sample" + m.id + ": float = sample_lod(texpaint_view_mask" + m.id +
  490. ", sampler_linear, tex_coord, 0.0).r;");
  491. let opac: f32 = slot_layer_get_opacity(m);
  492. let mask: string = make_material_blend_mode_mask(kong, m.blending, "mask_view", "mask_sample" + m.id, "float(" + opac + ")");
  493. node_shader_write_frag(kong, "mask_view = " + mask + ";");
  494. }
  495. }
  496. node_shader_write_frag(kong, "output[1] = float4(mask_view, mask_view, mask_view, 1.0);");
  497. }
  498. else {
  499. node_shader_write_frag(kong, "output[1] = float4(1.0, 0.0, 1.0, 1.0);"); // Pink
  500. }
  501. node_shader_write_frag(kong, "n = n / (abs(n.x) + abs(n.y) + abs(n.z));");
  502. // node_shader_write_frag(kong, "n.xy = n.z >= 0.0 ? n.xy : octahedron_wrap(n.xy);");
  503. node_shader_write_frag(kong, "if (n.z < 0.0) { n.xy = octahedron_wrap(n.xy); }");
  504. node_shader_write_frag(kong, "output[0] = float4(n.xy, roughness, pack_f32_i16(metallic, uint(float(int(matid * 255.0)) % float(3))));");
  505. }
  506. node_shader_write_frag(kong, "output[2] = float4(0.0, 0.0, tex_coord.xy);");
  507. parser_material_finalize(con_mesh);
  508. con_mesh.data.shader_from_source = true;
  509. gpu_create_shaders_from_kong(node_shader_get(kong), ADDRESS(con_mesh.data.vertex_shader), ADDRESS(con_mesh.data.fragment_shader),
  510. ADDRESS(con_mesh.data._.vertex_shader_size), ADDRESS(con_mesh.data._.fragment_shader_size));
  511. return con_mesh;
  512. }
  513. let str_cotangent_frame: string = "\
  514. fun cotangent_frame(n: float3, p: float3, tex_coord: float2): float3x3 { \
  515. var duv1: float2 = ddx2(tex_coord); \
  516. var duv2: float2 = ddy2(tex_coord); \
  517. var dp1: float3 = ddx3(p); \
  518. var dp2: float3 = ddy3(p); \
  519. var dp2perp: float3 = cross(dp2, n); \
  520. var dp1perp: float3 = cross(n, dp1); \
  521. var t: float3 = dp2perp * duv1.x + dp1perp * duv2.x; \
  522. var b: float3 = dp2perp * duv1.y + dp1perp * duv2.y; \
  523. var invmax: float = rsqrt(max(dot(t, t), dot(b, b))); \
  524. return float3x3(t * invmax, b * invmax, n); \
  525. } \
  526. ";
  527. let str_octahedron_wrap: string = "\
  528. fun octahedron_wrap(v: float2): float2 { \
  529. var a: float2; \
  530. if (v.x >= 0.0) { a.x = 1.0; } else { a.x = -1.0; } \
  531. if (v.y >= 0.0) { a.y = 1.0; } else { a.y = -1.0; } \
  532. var r: float2; \
  533. r.x = abs(v.y); \
  534. r.y = abs(v.x); \
  535. r.x = 1.0 - r.x; \
  536. r.y = 1.0 - r.y; \
  537. return r * a; \
  538. } \
  539. ";
  540. // let str_octahedron_wrap: string = "\
  541. // fun octahedron_wrap(v: float2): float2 { \
  542. // return (1.0 - abs(v.yx)) * (float2(v.x >= 0.0 ? 1.0 : -1.0, v.y >= 0.0 ? 1.0 : -1.0)); \
  543. // } \
  544. // ";
  545. let str_pack_float_int16: string = "\
  546. fun pack_f32_i16(f: float, i: uint): float { \
  547. return 0.062504762 * min(f, 0.9999) + 0.062519999 * float(i); \
  548. } \
  549. ";
  550. // let str_pack_float_int16: string = "\
  551. // fun pack_f32_i16(f: float, i: uint): float { \
  552. // var prec: float = float(1 << 16); \
  553. // var maxi: float = float(1 << 4); \
  554. // var prec_minus_one: float = prec - 1.0; \
  555. // var t1: float = ((prec / maxi) - 1.0) / prec_minus_one; \
  556. // var t2: float = (prec / maxi) / prec_minus_one; \
  557. // return t1 * f + t2 * float(i); \
  558. // } \
  559. // ";
  560. let str_sh_irradiance: string = "\
  561. fun sh_irradiance(nor: float3): float3 { \
  562. var c1: float = 0.429043; \
  563. var c2: float = 0.511664; \
  564. var c3: float = 0.743125; \
  565. var c4: float = 0.886227; \
  566. var c5: float = 0.247708; \
  567. var cl00: float3 = float3(constants.shirr0.x, constants.shirr0.y, constants.shirr0.z); \
  568. var cl1m1: float3 = float3(constants.shirr0.w, constants.shirr1.x, constants.shirr1.y); \
  569. var cl10: float3 = float3(constants.shirr1.z, constants.shirr1.w, constants.shirr2.x); \
  570. var cl11: float3 = float3(constants.shirr2.y, constants.shirr2.z, constants.shirr2.w); \
  571. var cl2m2: float3 = float3(constants.shirr3.x, constants.shirr3.y, constants.shirr3.z); \
  572. var cl2m1: float3 = float3(constants.shirr3.w, constants.shirr4.x, constants.shirr4.y); \
  573. var cl20: float3 = float3(constants.shirr4.z, constants.shirr4.w, constants.shirr5.x); \
  574. var cl21: float3 = float3(constants.shirr5.y, constants.shirr5.z, constants.shirr5.w); \
  575. var cl22: float3 = float3(constants.shirr6.x, constants.shirr6.y, constants.shirr6.z); \
  576. return ( \
  577. cl22 * c1 * (nor.y * nor.y - (-nor.z) * (-nor.z)) + \
  578. cl20 * c3 * nor.x * nor.x + \
  579. cl00 * c4 - \
  580. cl20 * c5 + \
  581. cl2m2 * 2.0 * c1 * nor.y * (-nor.z) + \
  582. cl21 * 2.0 * c1 * nor.y * nor.x + \
  583. cl2m1 * 2.0 * c1 * (-nor.z) * nor.x + \
  584. cl11 * 2.0 * c2 * nor.y + \
  585. cl1m1 * 2.0 * c2 * (-nor.z) + \
  586. cl10 * 2.0 * c2 * nor.x \
  587. ); \
  588. } \
  589. ";
  590. let str_envmap_equirect: string = "\
  591. fun envmap_equirect(normal: float3, angle: float): float2 { \
  592. var PI: float = 3.1415926535; \
  593. var PI2: float = PI * 2.0; \
  594. var phi: float = acos(normal.z); \
  595. var theta: float = atan2(-normal.y, normal.x) + PI + angle; \
  596. return float2(theta / PI2, phi / PI); \
  597. } \
  598. ";
  599. let str_envmap_sample: string = "\
  600. fun envmap_sample(lod: float, coord: float2): float3 { \
  601. if (lod == 0.0) { \
  602. return sample_lod(senvmap_radiance, sampler_linear, coord, 0.0).rgb; \
  603. } \
  604. if (lod == 1.0) { \
  605. return sample_lod(senvmap_radiance0, sampler_linear, coord, 0.0).rgb; \
  606. } \
  607. if (lod == 2.0) { \
  608. return sample_lod(senvmap_radiance1, sampler_linear, coord, 0.0).rgb; \
  609. } \
  610. if (lod == 3.0) { \
  611. return sample_lod(senvmap_radiance2, sampler_linear, coord, 0.0).rgb; \
  612. } \
  613. if (lod == 4.0) { \
  614. return sample_lod(senvmap_radiance3, sampler_linear, coord, 0.0).rgb; \
  615. } \
  616. return sample_lod(senvmap_radiance4, sampler_linear, coord, 0.0).rgb; \
  617. } \
  618. ";
  619. // https://www.unrealengine.com/en-US/blog/physically-based-shading-on-mobile
  620. let str_env_brdf_approx: string = "\
  621. fun env_brdf_approx(specular: float3, roughness: float, dotnv: float): float3 { \
  622. var c0: float4 = float4(-1.0, -0.0275, -0.572, 0.022); \
  623. var c1: float4 = float4(1.0, 0.0425, 1.04, -0.04); \
  624. var r: float4 = c0 * roughness + c1; \
  625. var a004: float = min(r.x * r.x, exp((-9.28 * dotnv) * log(2.0))) * r.x + r.y; \
  626. var ab: float2 = float2(-1.04, 1.04) * a004 + r.zw; \
  627. return specular * ab.x + ab.y; \
  628. } \
  629. ";
  630. let str_dither_bayer: string = "\
  631. fun dither_bayer(uv: float2): float { \
  632. var x: int = int(uv.x % 4.0); \
  633. var y: int = int(uv.y % 4.0); \
  634. if (y == 0) { \
  635. if (x == 0) { \
  636. return 0.0 / 16.0; \
  637. } \
  638. if (x == 1) { \
  639. return 8.0 / 16.0; \
  640. } \
  641. if (x == 2) { \
  642. return 2.0 / 16.0; \
  643. } \
  644. return 10.0 / 16.0; \
  645. } \
  646. if (y == 1) { \
  647. if (x == 0) { \
  648. return 12.0 / 16.0; \
  649. } \
  650. if (x == 1) { \
  651. return 4.0 / 16.0; \
  652. } \
  653. if (x == 2) { \
  654. return 14.0 / 16.0; \
  655. } \
  656. return 6.0 / 16.0; \
  657. } \
  658. if (y == 2) { \
  659. if (x == 0) { \
  660. return 3.0 / 16.0; \
  661. } \
  662. if (x == 1) { \
  663. return 11.0 / 16.0; \
  664. } \
  665. if (x == 2) { \
  666. return 1.0 / 16.0; \
  667. } \
  668. return 9.0 / 16.0; \
  669. } \
  670. if (x == 0) { \
  671. return 15.0 / 16.0; \
  672. } \
  673. if (x == 1) { \
  674. return 7.0 / 16.0; \
  675. } \
  676. if (x == 2) { \
  677. return 13.0 / 16.0; \
  678. } \
  679. return 5.0 / 16.0; \
  680. } \
  681. ";