#version 450 layout (points) in; layout (triangle_strip, max_vertices = 4) out; layout(location = 0) in highp uvec3 Geometry[]; layout(location = 0) out FragmentObj { vec3 GeoPos; // Реальная позиция в мире flat uint VoxMTL; // Материал вокселя vec2 LUV; flat uint Place; } Fragment; layout(push_constant) uniform UniformBufferObject { mat4 projview; mat4 model; } ubo; // struct VoxelVertexPoint { // uint32_t // FX : 9, FY : 9, FZ : 9, // Позиция // Place : 3, // Положение распространения xz, xy, zy, и обратные // N1 : 1, // Не занято // LS : 1, // Масштаб карты освещения (1м/16 или 1м) // TX : 8, TY : 8, // Размер+1 // VoxMtl : 16, // Материал вокселя DefVoxelId_t // LU : 14, LV : 14, // Позиция на карте освещения // N2 : 2; // Не занято // }; void main() { vec4 baseVec = vec4( float(Geometry[0].x & 0x1ff) / 16.f, float((Geometry[0].x >> 9) & 0x1ff) / 16.f, float((Geometry[0].x >> 18) & 0x1ff) / 16.f, 1 ); vec2 size = vec2( float(Geometry[0].y & 0xff)+1, float((Geometry[0].y >> 8) & 0xff)+1 ); uint voxMTL = ((Geometry[0].y >> 16) & 0xffff); vec2 luv = vec2(float(Geometry[0].z & 0x3fff)+0.5f, float((Geometry[0].z >> 14) & 0x3fff)+0.5f); int place = int(Geometry[0].x >> 27) & 0x7; // Стартовая вершина vec4 tempVec = baseVec; tempVec = ubo.model*tempVec; Fragment.GeoPos = vec3(tempVec); Fragment.VoxMTL = voxMTL; Fragment.LUV = luv; Fragment.Place = place; gl_Position = ubo.projview*tempVec; EmitVertex(); switch(place) { case 0: // xz tempVec = baseVec; tempVec.z += size.y / 16.f; tempVec = ubo.model*tempVec; Fragment.GeoPos = tempVec.xyz; Fragment.VoxMTL = voxMTL; Fragment.LUV = luv+vec2(0, size.y); Fragment.Place = place; gl_Position = ubo.projview*tempVec; EmitVertex(); tempVec = baseVec; tempVec.x += size.x / 16.f; tempVec = ubo.model*tempVec; Fragment.GeoPos = tempVec.xyz; Fragment.VoxMTL = voxMTL; Fragment.LUV = luv+vec2(size.x, 0); Fragment.Place = place; gl_Position = ubo.projview*tempVec; EmitVertex(); tempVec = baseVec; tempVec.x += size.x / 16.f; tempVec.z += size.y / 16.f; tempVec = ubo.model*tempVec; Fragment.GeoPos = tempVec.xyz; Fragment.VoxMTL = voxMTL; Fragment.LUV = luv+vec2(size.x, size.y); Fragment.Place = place; gl_Position = ubo.projview*tempVec; EmitVertex(); break; case 1: // xy tempVec = baseVec; tempVec.x += size.x / 16.f; tempVec = ubo.model*tempVec; Fragment.GeoPos = tempVec.xyz; Fragment.VoxMTL = voxMTL; Fragment.LUV = luv+vec2(size.x, 0); Fragment.Place = place; gl_Position = ubo.projview*tempVec; EmitVertex(); tempVec = baseVec; tempVec.y += size.y / 16.f; tempVec = ubo.model*tempVec; Fragment.GeoPos = tempVec.xyz; Fragment.VoxMTL = voxMTL; Fragment.LUV = luv+vec2(0, size.y); Fragment.Place = place; gl_Position = ubo.projview*tempVec; EmitVertex(); tempVec = baseVec; tempVec.x += size.x / 16.f; tempVec.y += size.y / 16.f; tempVec = ubo.model*tempVec; Fragment.GeoPos = tempVec.xyz; Fragment.VoxMTL = voxMTL; Fragment.LUV = luv+vec2(size.x, size.y); Fragment.Place = place; gl_Position = ubo.projview*tempVec; EmitVertex(); break; case 2: // zy tempVec = baseVec; tempVec.y += size.y / 16.f; tempVec = ubo.model*tempVec; Fragment.GeoPos = tempVec.xyz; Fragment.VoxMTL = voxMTL; Fragment.LUV = luv+vec2(0, size.y); Fragment.Place = place; gl_Position = ubo.projview*tempVec; EmitVertex(); tempVec = baseVec; tempVec.z += size.x / 16.f; tempVec = ubo.model*tempVec; Fragment.GeoPos = tempVec.xyz; Fragment.VoxMTL = voxMTL; Fragment.LUV = luv+vec2(size.x, 0); Fragment.Place = place; gl_Position = ubo.projview*tempVec; EmitVertex(); tempVec = baseVec; tempVec.z += size.x / 16.f; tempVec.y += size.y / 16.f; tempVec = ubo.model*tempVec; Fragment.GeoPos = tempVec.xyz; Fragment.VoxMTL = voxMTL; Fragment.LUV = luv+vec2(size.x, size.y); Fragment.Place = place; gl_Position = ubo.projview*tempVec; EmitVertex(); break; case 3: // xz inv tempVec = baseVec; tempVec.x += size.x / 16.f; tempVec = ubo.model*tempVec; Fragment.GeoPos = tempVec.xyz; Fragment.VoxMTL = voxMTL; Fragment.LUV = luv+vec2(size.x, 0); Fragment.Place = place; gl_Position = ubo.projview*tempVec; EmitVertex(); tempVec = baseVec; tempVec.z += size.y / 16.f; tempVec = ubo.model*tempVec; Fragment.GeoPos = tempVec.xyz; Fragment.VoxMTL = voxMTL; Fragment.LUV = luv+vec2(0, size.y); Fragment.Place = place; gl_Position = ubo.projview*tempVec; EmitVertex(); tempVec = baseVec; tempVec.x += size.x / 16.f; tempVec.z += size.y / 16.f; tempVec = ubo.model*tempVec; Fragment.GeoPos = tempVec.xyz; Fragment.VoxMTL = voxMTL; Fragment.LUV = luv+vec2(size.x, size.y); Fragment.Place = place; gl_Position = ubo.projview*tempVec; EmitVertex(); break; case 4: // xy inv tempVec = baseVec; tempVec.y += size.y / 16.f; tempVec = ubo.model*tempVec; Fragment.GeoPos = tempVec.xyz; Fragment.VoxMTL = voxMTL; Fragment.LUV = luv+vec2(0, size.y); Fragment.Place = place; gl_Position = ubo.projview*tempVec; EmitVertex(); tempVec = baseVec; tempVec.x += size.x / 16.f; tempVec = ubo.model*tempVec; Fragment.GeoPos = tempVec.xyz; Fragment.VoxMTL = voxMTL; Fragment.LUV = luv+vec2(size.x, 0); Fragment.Place = place; gl_Position = ubo.projview*tempVec; EmitVertex(); tempVec = baseVec; tempVec.x += size.x / 16.f; tempVec.y += size.y / 16.f; tempVec = ubo.model*tempVec; Fragment.GeoPos = tempVec.xyz; Fragment.VoxMTL = voxMTL; Fragment.LUV = luv+vec2(size.x, size.y); Fragment.Place = place; gl_Position = ubo.projview*tempVec; EmitVertex(); break; case 5: // zy inv tempVec = baseVec; tempVec.z += size.x / 16.f; tempVec = ubo.model*tempVec; Fragment.GeoPos = tempVec.xyz; Fragment.VoxMTL = voxMTL; Fragment.LUV = luv+vec2(size.x, 0); Fragment.Place = place; gl_Position = ubo.projview*tempVec; EmitVertex(); tempVec = baseVec; tempVec.y += size.y / 16.f; tempVec = ubo.model*tempVec; Fragment.GeoPos = tempVec.xyz; Fragment.VoxMTL = voxMTL; Fragment.LUV = luv+vec2(0, size.y); Fragment.Place = place; gl_Position = ubo.projview*tempVec; EmitVertex(); tempVec = baseVec; tempVec.z += size.x / 16.f; tempVec.y += size.y / 16.f; tempVec = ubo.model*tempVec; Fragment.GeoPos = tempVec.xyz; Fragment.VoxMTL = voxMTL; Fragment.LUV = luv+vec2(size.x, size.y); Fragment.Place = place; gl_Position = ubo.projview*tempVec; EmitVertex(); break; default: break; } EndPrimitive(); }