1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#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);
}