Efficiently transferring only needed parts of the vertex data to the GPU (C++/OpenGL)
This more or less a long comment than an answer.
Some other options that come to mind are the following:

A little old school, but you can create an interface with one of the texture objects. You can query different mipmap levels for your needs inside the shader. Textures are one of the better cached objects in OpenGL.

You can defer the lightening process by sending everything to a framebuffer with multiple rendering targets. The first pass would filter out the relevant parts of your data and create a geometry buffer. You can use the g-buffer for lightening pass afterwards.

You can create a flat array where your relevant and non relevant data are divided in equal strides, then use the indices of the relevant parts stored in your Element Array Buffer object in glDrawElements call. Basically you can use something like the following:


struct MyRealData {
vec3 myRelevantData
float myNotSoRelevantData
};
void to_drawable(MyRealData[20] ds, vec3[40] flat_drawable_array){
  for (int i = 0; i &lt; 40; i+=2){
    flat_drawable_array[i] = ds[i].myRelevantData;
    flat_drawable_array[i+1] = vec3(ds[i].myNotSoRelevantData, 0, 0);
  }
}
std::vector&lt;unsigned int&gt; indices[] = { 
  0, 2, 4, // first triangle
  2, 6, 4, // second triangle
  4, 6, 8, // third triangle
// ... etc
}; 
.
. // later in the code
.
glDrawElements(GL_TRIANGLES, indices.size() , GL_UNSIGNED_INT, (GLvoid *)indices​.data());

```