#version 430 layout(triangles, equal_spacing) in; in TCS_OUT { vec2 pos; } vIn[]; patch in uint triId; out vec4 vertexColor; uniform int R; struct TriData { vec2 cornerTexCoords[3]; vec2 edgeTexCoords[3]; uint cPtr; }; layout(std430, binding = 0) buffer triData { TriData tris[]; }; layout(std430, binding = 1) buffer colorData { vec4 c[]; }; vec4 colorDisplacement(uvec3 rev, vec3 bary) { vec4 ret; //face uint index = 3 * rev.x * (R + 1 - rev.x) //all texels from larger rings + rev.y * (R - 2 * rev.x) //all texels from previous edges of the same ring + rev.z; ret = c[tris[triId].cPtr + index]; return ret; } uvec3 barycentricToRingEdgeVertex(vec3 barycentric) { uvec3 rev; //ring, edge, vector float minBary; if(barycentric.x < barycentric.y && barycentric.x < barycentric.z) { minBary = barycentric.x; rev.y = 1; } else if(barycentric.y < barycentric.z) { minBary = barycentric.y; rev.y = 2; } else { minBary = barycentric.z; rev.y = 0; } rev.x = uint(round(3.0 / 2.0 * R * minBary)); uint verticesOnRingEdge = R - 2 * rev.x; float denom = 3 * minBary - 1; rev.z = (denom == 0 ? 0 : uint(round((barycentric[rev.y] + 2 * minBary - 1) * (R - 2 * rev.x) / denom)) ); if(rev.z >= verticesOnRingEdge) { rev.z = 0; rev.y = (rev.y + 1) % 3; } return rev; } void main(void) { vec3 barycentric = gl_TessCoord.xyz; uvec3 rev = barycentricToRingEdgeVertex(barycentric); //uvec2 i = uvec2(round(R * uv)); vec4 cd = colorDisplacement(rev, barycentric); vertexColor = vec4(cd.rgb, 1); const float gamma = 2.2 * 1.2; vertexColor.rgb = pow(vertexColor.rgb, vec3(1.0 / gamma)); vec2 p = barycentric.x * vIn[0].pos + barycentric.y * vIn[1].pos + barycentric.z * vIn[2].pos; gl_Position = vec4(2 * p - vec2(1, 1), 0, 1); }