Using OpenGL 4.1, I am trying to figure out if it is possible to bind a set of vertices as a vertex array and then use that same vertex data as a uniform buffer object for a shader program (or visa versa) without sending the data to the GPU again.
EDIT: I need to add that I'm on macOS 10.15 which means I have access to openGL 4.1 core only.
My plan is that I'd like to update some point vertex data with one shader program (using GL_POINTS vertex type and no frag shader output), and then draw on a quad "canvas" using the updated vertex data as uniform data, as the quad's fragment colour calculations will rely on distances from every point that exists. I don't want to have to pull the data back and forth between the GPU and CPU, and this is one of the nicest solutions I could think of so far (if it is indeed possible and not inherently against the openGL way).
So I've bound the vertex data to a vertex array like so:
auto vertexArray = std::make_unique<VertexArray>();
vertexArray->vertexType = VertexType::Points;
std::vector<float> positions = {
-0.5f, -0.5f,
0.0f, 0.5f,
0.5f, -0.5f
};
std::vector<uint32_t> indices = {
0, 1, 2
};
vertexArray->numVertices = positions.size() / 2;
vertexArray->numIndices = indices.size();
glGenVertexArrays(1, &vertexArray->vertexArrayId);
glBindVertexArray(vertexArray->vertexArrayId);
glGenBuffers(1, &vertexArray->vertexBufferId);
glBindBuffer(GL_ARRAY_BUFFER, vertexArray->vertexBufferId);
glBufferData(GL_ARRAY_BUFFER, positions.size() * sizeof(float), positions.data(), GL_STATIC_DRAW);
glGenBuffers(1, &vertexArray->indexBufferId);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vertexArray->indexBufferId);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(uint32_t), indices.data(), GL_STATIC_DRAW);
// Call per vertex attribute (vec2 position is 1 attribute)
glVertexAttribPointer(/*index*/ 0,
/*numValues*/ 2,
/*type*/ GL_FLOAT,
/*normalised*/ GL_FALSE,
/*bytesToNextInstanceOfAttribute*/ sizeof(float) * 2,
/*offsetToNextAttribute*/ (const void*) 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
I would like then to be able to use this data that's already been sent to the GPU as a uniform buffer object in a shader program (though not the one that is being used to "render" this vertex array). Maybe something a bit like the following pseudo code that in an ideal world would give me access to the previously bound vertex buffer data in the canvas frag shader using a uniform buffer object called "u_pointVertexList":
glBindBuffer(GL_UNIFORM_BUFFER, vertexArray->vertexBufferId);
int location = glGetUniformLocation(canvasShaderProgramID, "u_pointVertexList");
debug::assertTrue(location != -1, "");
glProgramUniformFooBah(canvasShaderProgramID, location, vertexArray->vertexBufferId);
For some background, my first attempted solution was to just render the points to the window with a large point size each and a frag shader written per point object... But as far as I can tell, you can't render points with anything other than a single block colour. If that's incorrect, please let me know as that would be by far the easiest solution. Any other ideas on how to achieve this would also be appreciated if this is not a viable solution.