#version 450 core layout(vertices = 4) out; layout(binding = 0) uniform sampler2D heightTexture; uniform float tessellationFactor; layout(std140, binding = 4) uniform GeoUniforms { mat4 PV; mat4 M; float minTessellation; float maxTessellation; float displacementScale; int gridDensity; }; in VS_OUT { vec3 position; vec2 texCoord; } tc_in[]; out TC_OUT { vec3 position; vec2 texCoord; float tessLevel; } tc_out[]; float getHeight(vec2 uv) { return texture(heightTexture, uv).r * displacementScale; } float calculateSlope() { float step = 1.0f / (float(gridDensity) * maxTessellation + 1.0f); // Find surrounding heights float hLeft = getHeight(tc_in[gl_InvocationID].texCoord + vec2(-step, 0.0f)); float hRight = getHeight(tc_in[gl_InvocationID].texCoord + vec2(step, 0.0f)); float hUp = getHeight(tc_in[gl_InvocationID].texCoord + vec2(0.0f, step)); float hDown = getHeight(tc_in[gl_InvocationID].texCoord + vec2(0.0f, -step)); float slopeX = abs(hLeft - hRight) * displacementScale; float slopeY = abs(hUp - hDown) * displacementScale; float maxSlope = max(slopeX, slopeY); return maxSlope; } void main() { // Pass through position and texture coordinates to the tessellation evaluation shader tc_out[gl_InvocationID].position = tc_in[gl_InvocationID].position; tc_out[gl_InvocationID].texCoord = tc_in[gl_InvocationID].texCoord; float slope = calculateSlope(); float tessLevel = tessellationFactor * (1.0f + slope * 10.0f); tessLevel = max(tessLevel, maxTessellation); tc_out[gl_InvocationID].tessLevel = tessLevel; // Set tessellation levels if (gl_InvocationID == 0) { gl_TessLevelOuter[0] = tessLevel; gl_TessLevelOuter[1] = tessLevel; gl_TessLevelOuter[2] = tessLevel; gl_TessLevelOuter[3] = tessLevel; gl_TessLevelInner[0] = tessLevel; gl_TessLevelInner[1] = tessLevel; } }