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
|
#version 330 core
layout (location = 0) in vec3 quad;
layout (std140) uniform Matrices {
mat4 proj;
mat4 view;
};
// world chunk position
const int CHUNK_SIZE = 16;
uniform ivec3 chunk_position;
const int MAX_FACES = CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE;
layout (std140) uniform Face {
// normaly a uint but std140 layout
// requires 16-byte alignment
uvec4 face_data[MAX_FACES / 4];
};
flat out uvec2 pass_data;
uint get_half(int index)
{
int arr_index = index / 4;
int vec_index = index % 4;
return face_data[arr_index][vec_index];
}
uvec2 get_data(int index)
{
uint lower = get_half(index * 2);
uint upper = get_half(index * 2 + 1);
return uvec2(lower, upper);
}
vec3 get_quad(uint face, uint width, uint height)
{
vec3 squad = quad;
squad.x *= width;
squad.y *= height;
switch(face) {
case 0u: // PX
return squad.yzx + vec3(1, 0, 0);
case 1u: // NX
return squad.yxz;
case 2u: // PY
return squad.xyz + vec3(0, 1, 0);
case 3u: // NY
return squad.zyx;
case 4u: // PZ
return squad.zxy + vec3(0, 0, 1);
case 5u: // NZ
return squad.xzy;
}
// should not happen
return vec3(0);
}
void main(void)
{
// get face data
uvec2 data = get_data(gl_InstanceID);
uint x = (data.x >> 0) & 31u;
uint y = (data.x >> 5) & 31u;
uint z = (data.x >> 10) & 31u;
uint width = (data.x >> 15) & 31u;
uint height = (data.x >> 20) & 31u;
uint face = (data.x >> 25) & 7u;
// get quad verts
vec3 quad = get_quad(face, width, height);
// get position
vec3 position = vec3(x, y, z);
position += chunk_position * CHUNK_SIZE;
position += quad;
// draw
gl_Position = proj * view * vec4(position, 1.0);
pass_data = data;
}
|