MakeMeshPreview.hx 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. package arm.node;
  2. import iron.object.MeshObject;
  3. import iron.data.SceneFormat;
  4. import arm.ui.UITrait;
  5. import arm.ui.UINodes;
  6. import arm.node.MaterialShader;
  7. import arm.Tool;
  8. class MakeMeshPreview {
  9. public static var opacityDiscardDecal = 0.05;
  10. public static var opacityDiscardScene = 0.5;
  11. public static function run(data: MaterialShaderData, matcon: TMaterialContext): MaterialShaderContext {
  12. var isScene = UITrait.inst.worktab.position == SpaceScene;
  13. var context_id = "mesh";
  14. var con_mesh: MaterialShaderContext = data.add_context({
  15. name: context_id,
  16. depth_write: true,
  17. compare_mode: "less",
  18. cull_mode: (UITrait.inst.cullBackfaces || !isScene) ? "clockwise" : "none",
  19. vertex_elements: [{name: "pos", data: "short4norm"}, {name: "nor", data: "short2norm"}, {name: "tex", data: "short2norm"}] });
  20. var vert = con_mesh.make_vert();
  21. var frag = con_mesh.make_frag();
  22. frag.ins = vert.outs;
  23. var pos = "pos";
  24. #if arm_skin
  25. var isMesh = Std.is(Context.object, MeshObject);
  26. var skin = isMesh && cast(Context.object, MeshObject).data.geom.bones != null;
  27. if (skin) {
  28. pos = "spos";
  29. con_mesh.add_elem("bone", 'short4norm');
  30. con_mesh.add_elem("weight", 'short4norm');
  31. vert.add_function(MaterialFunctions.str_getSkinningDualQuat);
  32. vert.add_uniform('vec4 skinBones[128 * 2]', '_skinBones');
  33. vert.add_uniform('float posUnpack', '_posUnpack');
  34. vert.write_attrib('vec4 skinA;');
  35. vert.write_attrib('vec4 skinB;');
  36. vert.write_attrib('getSkinningDualQuat(ivec4(bone * 32767), weight, skinA, skinB);');
  37. vert.write_attrib('vec3 spos = pos.xyz;');
  38. vert.write_attrib('spos.xyz *= posUnpack;');
  39. vert.write_attrib('spos.xyz += 2.0 * cross(skinA.xyz, cross(skinA.xyz, spos.xyz) + skinA.w * spos.xyz);');
  40. vert.write_attrib('spos.xyz += 2.0 * (skinA.w * skinB.xyz - skinB.w * skinA.xyz + cross(skinA.xyz, skinB.xyz));');
  41. vert.write_attrib('spos.xyz /= posUnpack;');
  42. }
  43. #end
  44. vert.add_uniform('mat4 WVP', '_worldViewProjectionMatrix');
  45. vert.write_attrib('gl_Position = mul(vec4($pos.xyz, 1.0), WVP);');
  46. vert.add_out('vec2 texCoord');
  47. vert.write_attrib('texCoord = tex;');
  48. if (MaterialBuilder.heightUsed) {
  49. frag.bposition = true;
  50. }
  51. Material.parse_height = MaterialBuilder.heightUsed;
  52. var sout = Material.parse(UINodes.inst.getCanvasMaterial(), con_mesh, vert, frag, null, null, null, matcon);
  53. Material.parse_height = false;
  54. var base = sout.out_basecol;
  55. var rough = sout.out_roughness;
  56. var met = sout.out_metallic;
  57. var occ = sout.out_occlusion;
  58. var opac = sout.out_opacity;
  59. var nortan = Material.out_normaltan;
  60. frag.write('vec3 basecol = pow($base, vec3(2.2, 2.2, 2.2));');
  61. frag.write('float roughness = $rough;');
  62. frag.write('float metallic = $met;');
  63. frag.write('float occlusion = $occ;');
  64. frag.write('float opacity = $opac;');
  65. frag.write('vec3 nortan = $nortan;');
  66. var decal = UITrait.inst.decalPreview;
  67. if (decal) {
  68. if (Context.tool == ToolDecal) {
  69. frag.add_uniform('sampler2D texdecalmask', '_texdecalmask');
  70. frag.write('opacity *= textureLod(texdecalmask, texCoord, 0.0).r;');
  71. }
  72. else if (Context.tool == ToolText) {
  73. frag.add_uniform('sampler2D textexttool', '_textexttool');
  74. frag.write('opacity *= textureLod(textexttool, texCoord, 0.0).r;');
  75. }
  76. }
  77. if (decal || isScene) {
  78. var opac = isScene ? opacityDiscardScene : opacityDiscardDecal;
  79. frag.write('if (opacity < $opac) discard;');
  80. }
  81. frag.add_out('vec4 fragColor[3]');
  82. frag.n = true;
  83. frag.add_function(MaterialFunctions.str_packFloatInt16);
  84. frag.add_function(MaterialFunctions.str_packFloat2);
  85. frag.add_function(MaterialFunctions.str_cotangentFrame);
  86. frag.add_function(MaterialFunctions.str_octahedronWrap);
  87. // Apply normal channel
  88. if (decal) {
  89. // TODO
  90. }
  91. else {
  92. frag.vVec = true;
  93. #if (kha_direct3d11 || kha_direct3d12)
  94. frag.write('mat3 TBN = cotangentFrame(n, vVec, texCoord);');
  95. #else
  96. frag.write('mat3 TBN = cotangentFrame(n, -vVec, texCoord);');
  97. #end
  98. frag.write('n = nortan * 2.0 - 1.0;');
  99. frag.write('n.y = -n.y;');
  100. frag.write('n = normalize(mul(n, TBN));');
  101. }
  102. frag.write('n /= (abs(n.x) + abs(n.y) + abs(n.z));');
  103. frag.write('n.xy = n.z >= 0.0 ? n.xy : octahedronWrap(n.xy);');
  104. // uint matid = 0;
  105. frag.write('fragColor[0] = vec4(n.x, n.y, roughness, packFloatInt16(metallic, uint(0)));'); // metallic/matid
  106. frag.write('fragColor[1] = vec4(basecol.r, basecol.g, basecol.b, packFloat2(occlusion, 1.0));'); // occ/spec
  107. frag.write('fragColor[2] = vec4(0.0, 0.0, 0.0, 0.0);'); // veloc
  108. Material.finalize(con_mesh);
  109. #if arm_skin
  110. if (skin) {
  111. vert.write('wnormal = normalize(mul(vec3(nor.xy, pos.w) + 2.0 * cross(skinA.xyz, cross(skinA.xyz, vec3(nor.xy, pos.w)) + skinA.w * vec3(nor.xy, pos.w)), N));');
  112. }
  113. #end
  114. con_mesh.data.shader_from_source = true;
  115. con_mesh.data.vertex_shader = vert.get();
  116. con_mesh.data.fragment_shader = frag.get();
  117. return con_mesh;
  118. }
  119. }