MsCommonTessc.glsl 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. // Copyright (C) 2009-2017, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include "shaders/MsBsCommon.glsl"
  6. layout(vertices = 3) out;
  7. // Defines
  8. #define IID gl_InvocationID
  9. #define IN_POS4(i_) gl_in[i_].gl_Position
  10. #define IN_POS3(i_) gl_in[i_].gl_Position.xyz
  11. #define OUT_POS4(i_) gl_out[i_].gl_Position
  12. //
  13. // In
  14. //
  15. in gl_PerVertex
  16. {
  17. vec4 gl_Position;
  18. }
  19. gl_in[];
  20. layout(location = 0) in vec2 inTexCoords[];
  21. layout(location = 1) in mediump vec3 inNormal[];
  22. #if PASS == COLOR
  23. layout(location = 2) in mediump vec4 inTangent[];
  24. #endif
  25. #if INSTANCE_ID_FRAGMENT_SHADER
  26. layout(location = 3) flat in uint inInstanceId[];
  27. #endif
  28. //
  29. // Out
  30. //
  31. out gl_PerVertex
  32. {
  33. vec4 gl_Position;
  34. }
  35. gl_out[];
  36. layout(location = 0) out vec2 outTexCoord[];
  37. layout(location = 1) out vec3 outNormal[];
  38. #if PASS == COLOR
  39. layout(location = 2) out vec4 outTangent[];
  40. #endif
  41. #if INSTANCE_ID_FRAGMENT_SHADER
  42. struct CommonPatch
  43. {
  44. uint instanceId;
  45. };
  46. #endif
  47. struct PNPatch
  48. {
  49. vec3 pos021;
  50. vec3 pos012;
  51. vec3 pos102;
  52. vec3 pos201;
  53. vec3 pos210;
  54. vec3 pos120;
  55. vec3 pos111;
  56. };
  57. struct PhongPatch
  58. {
  59. vec3 terms[3];
  60. };
  61. out patch PNPatch pnPatch;
  62. out patch PhongPatch phongPatch;
  63. #if INSTANCE_ID_FRAGMENT_SHADER
  64. out patch CommonPatch commonPatch;
  65. #endif
  66. // Project point to plane
  67. vec3 projectToPlane(vec3 point, vec3 planePoint, vec3 planeNormal)
  68. {
  69. vec3 v = point - planePoint;
  70. float pen = dot(v, planeNormal);
  71. vec3 d = pen * planeNormal;
  72. return (point - d);
  73. }
  74. // Calculate control points
  75. void calcPositions()
  76. {
  77. // The original vertices stay the same
  78. vec3 pos030 = IN_POS3(0);
  79. vec3 pos003 = IN_POS3(1);
  80. vec3 pos300 = IN_POS3(2);
  81. OUT_POS4(0) = IN_POS4(0);
  82. OUT_POS4(1) = IN_POS4(1);
  83. OUT_POS4(2) = IN_POS4(2);
  84. // edges are names according to the opposing vertex
  85. vec3 edgeB300 = pos003 - pos030;
  86. vec3 edgeB030 = pos300 - pos003;
  87. vec3 edgeB003 = pos030 - pos300;
  88. // Generate two midpoints on each edge
  89. pnPatch.pos021 = pos030 + edgeB300 / 3.0;
  90. pnPatch.pos012 = pos030 + edgeB300 * 2.0 / 3.0;
  91. pnPatch.pos102 = pos003 + edgeB030 / 3.0;
  92. pnPatch.pos201 = pos003 + edgeB030 * 2.0 / 3.0;
  93. pnPatch.pos210 = pos300 + edgeB003 / 3.0;
  94. pnPatch.pos120 = pos300 + edgeB003 * 2.0 / 3.0;
  95. pnPatch.pos021 = projectToPlane(pnPatch.pos021, pos030, outNormal[0]);
  96. pnPatch.pos012 = projectToPlane(pnPatch.pos012, pos003, outNormal[1]);
  97. pnPatch.pos102 = projectToPlane(pnPatch.pos102, pos003, outNormal[1]);
  98. pnPatch.pos201 = projectToPlane(pnPatch.pos201, pos300, outNormal[2]);
  99. pnPatch.pos210 = projectToPlane(pnPatch.pos210, pos300, outNormal[2]);
  100. pnPatch.pos120 = projectToPlane(pnPatch.pos120, pos030, outNormal[0]);
  101. // Handle the center
  102. vec3 center = (pos003 + pos030 + pos300) / 3.0;
  103. pnPatch.pos111 =
  104. (pnPatch.pos021 + pnPatch.pos012 + pnPatch.pos102 + pnPatch.pos201 + pnPatch.pos210 + pnPatch.pos120) / 6.0;
  105. pnPatch.pos111 += (pnPatch.pos111 - center) / 2.0;
  106. }
  107. vec3 calcFaceNormal(in vec3 v0, in vec3 v1, in vec3 v2)
  108. {
  109. return normalize(cross(v1 - v0, v2 - v0));
  110. }
  111. float calcEdgeTessLevel(in vec3 n0, in vec3 n1, in float maxTessLevel)
  112. {
  113. vec3 norm = normalize(n0 + n1);
  114. float tess = (1.0 - norm.z) * (maxTessLevel - 1.0) + 1.0;
  115. return tess;
  116. }
  117. /*float calcEdgeTessLevel(in vec2 p0, in vec2 p1, in float maxTessLevel)
  118. {
  119. float dist = distance(p0, p1) * 10.0;
  120. return dist * (maxTessLevel - 1.0) + 1.0;
  121. }*/
  122. // Given the face positions in NDC caclulate if the face is front facing or not
  123. bool isFaceFrontFacing(in vec2 posNdc[3])
  124. {
  125. vec2 a = posNdc[1] - posNdc[0];
  126. vec2 b = posNdc[2] - posNdc[1];
  127. vec2 c = a.xy * b.yx;
  128. return (c.x - c.y) > 0.0;
  129. }
  130. // Check if a single NDC position is outside the clip space
  131. bool posOutsideClipSpace(in vec2 posNdc)
  132. {
  133. bvec2 compa = lessThan(posNdc, vec2(-1.0));
  134. bvec2 compb = greaterThan(posNdc, vec2(1.0));
  135. return all(bvec4(compa, compb));
  136. }
  137. // Check if a face in NDC is outside the clip space
  138. bool isFaceOutsideClipSpace(in vec2 posNdc[3])
  139. {
  140. return any(bvec3(posOutsideClipSpace(posNdc[0]), posOutsideClipSpace(posNdc[1]), posOutsideClipSpace(posNdc[2])));
  141. }
  142. // Check if a face is visible
  143. bool isFaceVisible(in mat4 mvp)
  144. {
  145. // Calculate clip positions
  146. vec2 clip[3];
  147. for(int i = 0; i < 3; i++)
  148. {
  149. vec4 v = mvp * IN_POS4(i);
  150. clip[i] = v.xy / (v.w * 0.5 + 0.5);
  151. }
  152. // Check the face orientation and clipping
  153. return isFaceFrontFacing(clip) && !isFaceOutsideClipSpace(clip);
  154. }
  155. void setSilhouetteTessLevels(in mat3 normalMat, in float maxTessLevel)
  156. {
  157. // Calculate the normals in view space
  158. vec3 nv[3];
  159. for(int i = 0; i < 3; i++)
  160. {
  161. nv[i] = normalMat * inNormal[i];
  162. }
  163. gl_TessLevelOuter[0] = calcEdgeTessLevel(nv[1], nv[2], maxTessLevel);
  164. gl_TessLevelOuter[1] = calcEdgeTessLevel(nv[2], nv[0], maxTessLevel);
  165. gl_TessLevelOuter[2] = calcEdgeTessLevel(nv[0], nv[1], maxTessLevel);
  166. gl_TessLevelInner[0] = (gl_TessLevelOuter[0] + gl_TessLevelOuter[1] + gl_TessLevelOuter[2]) / 3.0;
  167. }
  168. void setConstantTessLevels(in float maxTessLevel)
  169. {
  170. gl_TessLevelOuter[0] = maxTessLevel;
  171. gl_TessLevelOuter[1] = maxTessLevel;
  172. gl_TessLevelOuter[2] = maxTessLevel;
  173. gl_TessLevelInner[0] = maxTessLevel;
  174. }
  175. void discardPatch()
  176. {
  177. gl_TessLevelOuter[0] = 0.0;
  178. gl_TessLevelOuter[1] = 0.0;
  179. gl_TessLevelOuter[2] = 0.0;
  180. gl_TessLevelInner[0] = 0.0;
  181. }
  182. // Used in phong method
  183. float calcPhongTerm(int ivId, int i, vec3 q)
  184. {
  185. vec3 qMinusP = q - IN_POS3(i);
  186. return q[ivId] - dot(qMinusP, inNormal[i]) * inNormal[i][ivId];
  187. }
  188. // This function is part of the point-normal tessellation method
  189. #define tessellatePNPositionNormalTangentTexCoord_DEFINED
  190. void tessellatePNPositionNormalTangentTexCoord(in float maxTessLevel, in mat4 mvp, in mat3 normalMat)
  191. {
  192. float tessLevel = 0.0;
  193. // Calculate the face normal in view space
  194. vec3 faceNorm = calcFaceNormal(IN_POS3(0), IN_POS3(1), IN_POS3(2));
  195. faceNorm = (normalMat * faceNorm);
  196. if(faceNorm.z >= 0.0)
  197. {
  198. // The face is front facing
  199. for(int i = 0; i < 3; i++)
  200. {
  201. outTexCoord[i] = inTexCoords[i];
  202. outNormal[i] = inNormal[i];
  203. #if PASS == COLOR
  204. outTangent[i] = inTangent[i];
  205. #endif
  206. }
  207. calcPositions();
  208. // Calculate the tessLevel. It's 1.0 when the normal is facing the cam
  209. // and maxTessLevel when it's facing away. This gives high tessellation
  210. // on silhouettes
  211. tessLevel = (1.0 - faceNorm.z) * (maxTessLevel - 1.0) + 1.0;
  212. }
  213. gl_TessLevelOuter[0] = tessLevel;
  214. gl_TessLevelOuter[1] = tessLevel;
  215. gl_TessLevelOuter[2] = tessLevel;
  216. gl_TessLevelInner[0] = tessLevel;
  217. }
  218. #define tessellatePhongPositionNormalTangentTexCoord_DEFINED
  219. void tessellatePhongPositionNormalTangentTexCoord(in float maxTessLevel, in mat4 mvp, in mat3 normalMat)
  220. {
  221. if(IID == 0)
  222. {
  223. if(isFaceVisible(mvp))
  224. {
  225. setSilhouetteTessLevels(normalMat, maxTessLevel);
  226. }
  227. else
  228. {
  229. discardPatch();
  230. }
  231. }
  232. OUT_POS4(IID) = IN_POS4(IID); // Do that here to trick the barrier
  233. barrier();
  234. if(gl_TessLevelOuter[0] > 0.0)
  235. {
  236. outTexCoord[IID] = inTexCoords[IID];
  237. outNormal[IID] = inNormal[IID];
  238. #if PASS == COLOR
  239. outTangent[IID] = inTangent[IID];
  240. #endif
  241. phongPatch.terms[IID][0] = calcPhongTerm(IID, 0, IN_POS3(1)) + calcPhongTerm(IID, 1, IN_POS3(0));
  242. phongPatch.terms[IID][1] = calcPhongTerm(IID, 1, IN_POS3(2)) + calcPhongTerm(IID, 2, IN_POS3(1));
  243. phongPatch.terms[IID][2] = calcPhongTerm(IID, 2, IN_POS3(0)) + calcPhongTerm(IID, 0, IN_POS3(2));
  244. }
  245. }
  246. #define tessellateDispMapPositionNormalTangentTexCoord_DEFINED
  247. void tessellateDispMapPositionNormalTangentTexCoord(in float maxTessLevel, in mat4 mvp, in mat3 normalMat)
  248. {
  249. if(IID == 0)
  250. {
  251. if(isFaceVisible(mvp))
  252. {
  253. setConstantTessLevels(maxTessLevel);
  254. #if INSTANCE_ID_FRAGMENT_SHADER
  255. commonPatch.instanceId = inInstanceId[0];
  256. #endif
  257. }
  258. else
  259. {
  260. discardPatch();
  261. }
  262. }
  263. // Passthrough
  264. OUT_POS4(IID) = IN_POS4(IID);
  265. outTexCoord[IID] = inTexCoords[IID];
  266. outNormal[IID] = inNormal[IID];
  267. #if PASS == COLOR
  268. outTangent[IID] = inTangent[IID];
  269. #endif
  270. }