#version 330 core layout (location = 0) in vec3 in_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; out float pass_ao; const mat3 ROT90 = mat3( 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, -1.0, 0.0, 0.0 ); 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); } bool get_ao_rotate(uint data) { vec4 ao; ao.x = (data >> 0) & 3u; ao.y = (data >> 2) & 3u; ao.z = (data >> 4) & 3u; ao.w = (data >> 6) & 3u; float a = abs(ao.x - ao.w); float b = abs(ao.y - ao.z); return a > b; } float get_ao(uint data, uint face) { vec4 ao; ao.x = (data >> 0) & 3u; ao.y = (data >> 2) & 3u; ao.z = (data >> 4) & 3u; ao.w = (data >> 6) & 3u; switch (face) { case 0u: // PX case 2u: // PY case 4u: // PZ ao = ao.xywz; if (get_ao_rotate(data)) ao = ao.wxyz; break; case 1u: // NX case 3u: // NY case 5u: // NZ if (get_ao_rotate(data)) ao = ao.ywxz; ao = ao.wzxy; break; } return ao[gl_VertexID]; } vec3 rotate(vec3 v, uint face) { switch(face) { case 0u: // PX case 1u: // NX v = vec3(v.x, v.z, -v.y + 1); break; case 2u: // PY case 3u: // NY v = vec3(-v.z + 1, v.y, v.x); break; case 4u: // PZ case 5u: // NZ v = vec3(v.y, -v.x + 1, v.z); break; } return v; } vec3 get_quad(uint face, uint width, uint height) { vec3 quad = in_quad; quad.x *= width; quad.y *= height; switch(face) { case 0u: // PX quad = quad.yzx + vec3(1, 0, 0); break; case 1u: // NX quad = quad.yxz; break; case 2u: // PY quad = quad.xyz + vec3(0, 1, 0); break; case 3u: // NY quad = quad.zyx; break; case 4u: // PZ quad = quad.zxy + vec3(0, 0, 1); break; case 5u: // NZ quad = quad.xzy; break; } return quad; } 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); if (get_ao_rotate(data.y)) quad = rotate(quad, face); // get position vec3 position = vec3(x, y, z); position += chunk_position * CHUNK_SIZE; position += quad; // draw gl_Position = proj * view * vec4(position, 1.0); // fragment input pass_data = data; pass_ao = get_ao(data.y, face); }