Advertisement
Guest User

Untitled

a guest
Oct 30th, 2014
63
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.81 KB | None | 0 0
  1. #version 400
  2.  
  3. // Only one vertex per patch (lower-left corner)
  4. layout(vertices = 1) out;
  5.  
  6. // xz position from vertex shader
  7. in terrainVertex
  8. {
  9.     vec2 position;
  10. } In[];
  11.  
  12. // xz position to tessellation evaluation shader
  13. out terrainVertex
  14. {
  15.     vec2 position;
  16. } Out[];
  17.  
  18. uniform sampler2D heightMap;
  19.  
  20. // Fully tessellated!
  21. const float tessellationLevel = 64.0;
  22.  
  23. // The number of triangles created per height-map texel
  24. uniform int maxTrianglesPerTexel = 10;
  25.  
  26. // Distance between each tessellation point at max tess level
  27. uniform float horizontalScale = 533.33333;
  28.  
  29. // Transformation matrix
  30. uniform mat4 mvp;
  31.  
  32. uniform float pixelsPerTriangleEdge = 12.0;
  33.  
  34. uniform vec2 viewportSize;
  35.  
  36. const float maxTessLevel = 64.0;
  37.  
  38. uniform float baseX = 0.0f;
  39. uniform float baseY = 0.0f;
  40.  
  41. // Determine if patch is potentially visible or not based upon the
  42. // extent of it's 4 edges. Ignores vertical extent of internal points!
  43. // A better way would be to pass in the maximum vertical extent of
  44. // all points in this patch as an additional per-vertex attribute.
  45. // We can then construct a axis-aligned bounding box for this patch
  46. // and test that against the view frustrum
  47. bool isEdgeInViewFrustum(const in vec4 p1, const in vec4 p2)
  48. {
  49.     return !( (p1.x < -p1.w && p2.x < -p2.w)
  50.            || (p1.x >  p1.w && p2.x >  p2.w)
  51.            || (p1.y < -p1.w && p2.y < -p2.w)
  52.            || (p1.y >  p1.w && p2.y >  p2.w)
  53.            || (p1.z < -p1.w && p2.z < -p2.w)
  54.            || (p1.z >  p1.w && p2.z >  p2.w));
  55. }
  56.  
  57. // Calculate a fractional tessellation level from the clip-space positions
  58. // of 2 vertices making up one edge of the patch, v1 and v2. The function
  59. // works by constructing a sphere that encapsulates the edge and projecting
  60. // this into screen space. We then use a target number of pixels per
  61. // triangle edge to calculate the required tessellation level.
  62. float calcTessellationLevel(const in vec4 v1, const in vec4 v2)
  63. {
  64.     vec4 p1 = 0.5 * (v1 + v2);
  65.     vec4 p2 = p1;
  66.  
  67.     p2.y += distance(v1, v2);
  68.  
  69.     p1 = p1 / p1.w;
  70.     p2 = p2 / p2.w;
  71.  
  72.     float l = length(0.5 * viewportSize * (p1.xy - p2.xy));
  73.  
  74.     return clamp(l / pixelsPerTriangleEdge, 1.0, 64.0);
  75. }
  76.  
  77. void main()
  78. {
  79.     // Pass along the vertex position unmodified
  80.     Out[gl_InvocationID].position = In[gl_InvocationID].position;
  81.  
  82.     // Calculate extent of this patch in texture coords [0,1]
  83.     vec2 patchExtent = maxTessLevel / (textureSize(heightMap, 0) * maxTrianglesPerTexel);
  84.  
  85.     vec2 patchCornersXZ[4];
  86.     patchCornersXZ[0] = Out[gl_InvocationID].position;                             // min x, min z
  87.     patchCornersXZ[1] = Out[gl_InvocationID].position + vec2(0.0f, patchExtent.y); // min x, max z
  88.     patchCornersXZ[2] = Out[gl_InvocationID].position + vec2(patchExtent.x, 0.0f); // max x, min z
  89.     patchCornersXZ[3] = Out[gl_InvocationID].position + patchExtent;               // max x, max z
  90.  
  91.     vec4 clipSpacePatchCorners[4];
  92.  
  93.     for(int i = 0; i < 4; i++)
  94.     {
  95.         vec4 position;
  96.         position.xz = patchCornersXZ[i] * horizontalScale;
  97.         position.y  = texture(heightMap, patchCornersXZ[i]).r;
  98.         position.w  = 1.0;
  99.  
  100.         position.x += baseX;
  101.         position.z += baseY;
  102.  
  103.         // Transform to clip-space
  104.         clipSpacePatchCorners[i] = mvp * position;
  105.     }
  106.  
  107.     // Determine if we can cull this patch
  108.     if(isEdgeInViewFrustum(clipSpacePatchCorners[0], clipSpacePatchCorners[2])
  109.     || isEdgeInViewFrustum(clipSpacePatchCorners[0], clipSpacePatchCorners[1])
  110.     || isEdgeInViewFrustum(clipSpacePatchCorners[1], clipSpacePatchCorners[3])
  111.     || isEdgeInViewFrustum(clipSpacePatchCorners[2], clipSpacePatchCorners[3]))
  112.     {
  113.         gl_TessLevelOuter[0] = calcTessellationLevel(clipSpacePatchCorners[0], clipSpacePatchCorners[1]); // x = min,   z = const
  114.         gl_TessLevelOuter[1] = calcTessellationLevel(clipSpacePatchCorners[0], clipSpacePatchCorners[2]); // x = const, z = min
  115.         gl_TessLevelOuter[2] = calcTessellationLevel(clipSpacePatchCorners[2], clipSpacePatchCorners[3]); // x = max,   z = const
  116.         gl_TessLevelOuter[3] = calcTessellationLevel(clipSpacePatchCorners[1], clipSpacePatchCorners[3]); // x = const, z = max
  117.  
  118.         gl_TessLevelInner[0] = max(gl_TessLevelOuter[1], gl_TessLevelOuter[3]); // z = const
  119.         gl_TessLevelInner[1] = max(gl_TessLevelOuter[0], gl_TessLevelOuter[2]); // x = const
  120.     }
  121.     else
  122.     {
  123.         // Set the tessellation levels to 0 to cull the patch
  124.         gl_TessLevelOuter[0] = 0.0;
  125.         gl_TessLevelOuter[1] = 0.0;
  126.         gl_TessLevelOuter[2] = 0.0;
  127.         gl_TessLevelOuter[3] = 0.0;
  128.  
  129.         gl_TessLevelInner[0] = 0.0;
  130.         gl_TessLevelInner[1] = 0.0;
  131.     }
  132.  
  133.     // test gaps
  134.     gl_TessLevelOuter[0] = 7.0;
  135.     gl_TessLevelOuter[1] = 7.0;
  136.     gl_TessLevelOuter[2] = 7.0;
  137.     gl_TessLevelOuter[3] = 7.0;
  138. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement