1#version 310 es 2#extension GL_EXT_tessellation_shader : require 3 4layout(vertices = 1) out; 5layout(location = 0) in vec2 vPatchPosBase[]; 6 7layout(std140) uniform UBO 8{ 9 vec4 uScale; 10 highp vec3 uCamPos; 11 vec2 uPatchSize; 12 vec2 uMaxTessLevel; 13 float uDistanceMod; 14 vec4 uFrustum[6]; 15}; 16 17layout(location = 1) patch out vec2 vOutPatchPosBase; 18layout(location = 2) patch out vec4 vPatchLods; 19 20float lod_factor(vec2 pos_) 21{ 22 vec2 pos = pos_ * uScale.xy; 23 vec3 dist_to_cam = uCamPos - vec3(pos.x, 0.0, pos.y); 24 float level = log2((length(dist_to_cam) + 0.0001) * uDistanceMod); 25 return clamp(level, 0.0, uMaxTessLevel.x); 26} 27 28float tess_level(float lod) 29{ 30 return uMaxTessLevel.y * exp2(-lod); 31} 32 33vec4 tess_level(vec4 lod) 34{ 35 return uMaxTessLevel.y * exp2(-lod); 36} 37 38// Guard band for vertex displacement. 39#define GUARD_BAND 10.0 40bool frustum_cull(vec2 p0) 41{ 42 vec2 min_xz = (p0 - GUARD_BAND) * uScale.xy; 43 vec2 max_xz = (p0 + uPatchSize + GUARD_BAND) * uScale.xy; 44 45 vec3 bb_min = vec3(min_xz.x, -GUARD_BAND, min_xz.y); 46 vec3 bb_max = vec3(max_xz.x, +GUARD_BAND, max_xz.y); 47 vec3 center = 0.5 * (bb_min + bb_max); 48 float radius = 0.5 * length(bb_max - bb_min); 49 50 vec3 f0 = vec3( 51 dot(uFrustum[0], vec4(center, 1.0)), 52 dot(uFrustum[1], vec4(center, 1.0)), 53 dot(uFrustum[2], vec4(center, 1.0))); 54 55 vec3 f1 = vec3( 56 dot(uFrustum[3], vec4(center, 1.0)), 57 dot(uFrustum[4], vec4(center, 1.0)), 58 dot(uFrustum[5], vec4(center, 1.0))); 59 60 return !(any(lessThanEqual(f0, vec3(-radius))) || any(lessThanEqual(f1, vec3(-radius)))); 61} 62 63void compute_tess_levels(vec2 p0) 64{ 65 vOutPatchPosBase = p0; 66 67 float l00 = lod_factor(p0 + vec2(-0.5, -0.5) * uPatchSize); 68 float l10 = lod_factor(p0 + vec2(+0.5, -0.5) * uPatchSize); 69 float l20 = lod_factor(p0 + vec2(+1.5, -0.5) * uPatchSize); 70 float l01 = lod_factor(p0 + vec2(-0.5, +0.5) * uPatchSize); 71 float l11 = lod_factor(p0 + vec2(+0.5, +0.5) * uPatchSize); 72 float l21 = lod_factor(p0 + vec2(+1.5, +0.5) * uPatchSize); 73 float l02 = lod_factor(p0 + vec2(-0.5, +1.5) * uPatchSize); 74 float l12 = lod_factor(p0 + vec2(+0.5, +1.5) * uPatchSize); 75 float l22 = lod_factor(p0 + vec2(+1.5, +1.5) * uPatchSize); 76 77 vec4 lods = vec4( 78 dot(vec4(l01, l11, l02, l12), vec4(0.25)), 79 dot(vec4(l00, l10, l01, l11), vec4(0.25)), 80 dot(vec4(l10, l20, l11, l21), vec4(0.25)), 81 dot(vec4(l11, l21, l12, l22), vec4(0.25))); 82 83 vPatchLods = lods; 84 85 vec4 outer_lods = min(lods.xyzw, lods.yzwx); 86 vec4 levels = tess_level(outer_lods); 87 gl_TessLevelOuter[0] = levels.x; 88 gl_TessLevelOuter[1] = levels.y; 89 gl_TessLevelOuter[2] = levels.z; 90 gl_TessLevelOuter[3] = levels.w; 91 92 float min_lod = min(min(lods.x, lods.y), min(lods.z, lods.w)); 93 float inner = tess_level(min(min_lod, l11)); 94 gl_TessLevelInner[0] = inner; 95 gl_TessLevelInner[1] = inner; 96} 97 98void main() 99{ 100 vec2 p0 = vPatchPosBase[0]; 101 if (!frustum_cull(p0)) 102 { 103 gl_TessLevelOuter[0] = -1.0; 104 gl_TessLevelOuter[1] = -1.0; 105 gl_TessLevelOuter[2] = -1.0; 106 gl_TessLevelOuter[3] = -1.0; 107 gl_TessLevelInner[0] = -1.0; 108 gl_TessLevelInner[1] = -1.0; 109 } 110 else 111 { 112 compute_tess_levels(p0); 113 } 114} 115 116