Hi all,
I've recently decided to start giving back to this project, something that always bothered me was the lack of support of vertex attributes within ones shaders. With raw opengl, it is an ugly interface to deal with.
I decided my way of contributing would be to come up with an implementation of vertex attributes. However, I do not know everything there is when it comes to this, so I'm asking for some help with design considerations (the hardest part, I know).
Essentially, I must start out by stating I believe a clean separation of Vertex and Fragment shaders into separate files would be beneficial, but ignoring that I would add the following method with several overrides to the shader class:
void Shader::SetVertexAttribute(const std::string& name, const std::vector<float>& v);
bool Shader::SetVertexAttribute(const std::string& name, const std::vector<int>& v);
bool Shader::SetVertexAttribute(const std::string& name, const std::vector<Vector2f>& v);
bool Shader::SetVertexAttribute(const std::string& name, const std::vector<Vector3f>& v);
etc...
Rationale, it should be up to the user to get their data into a coherent format, as supporting something such as
bool Shader::SetVertexAttribute(const std::string& name, void *data);
would be asking for bugs.
I spent awhile going through a couple different implementation strategies, and what I came up with to be the cleanest/most straight-forward implementation would be to give sf::Shader a private collection of VertexAttribute objects.
When the "user" calls SetVertexAttribute(...) on a "vertex shader" internally the shader would look in a lookup table (ie: map/unordered_map<string, VertexAttribute>) if it already has an object with that name.
If the shader did not have a vertex attribute associated with the provided name, it would construct a new VertexAttribute with the data provided by the user.
The first question I have, with the above (very possibly naive) implementation would be, what does the shader do if it already contains an entry with the "name" provided by the user in the SetVertexAttribute() method call? The best solution I came up with was to have the SetVertexAttribute() method return false, printing to standard error. That seems to be the only solution...
Second consideration, the user passes their data by reference. Does this mean that the VertexAttribute object does not need to keep a copy of the users data? The reason I ask is, suppose for whatever reason, internally, we want to offloadthe user's data (vertex attribute data) back to the CPU, temporarily, it would be easy to do if our VertexAttribute class kept a copy of the user's data.
Third consideration, we assume the user wants the attribute activated immediately, however is it the best course of action to immediatly call glBufferData(...) // copying their data to the GPU
or to perhaps queue allocation the memory until another time?
I really hope to go somewhere with this, what do you guys think? Am I totally off-base with this? Does it seem doable? Do you think having a method "SetVertexAttribute()" on a non-specific shader-type is ridiculous?? (does shader need to be split into vertex and fragment seperately) ??. I would love any feedback I can get, I would really like to be able to give back to this project, I use sfml sometimes just to get an opengl window and do the rest of the code with raw opengl (3d stuff). However I really like the abstraction sf::Shader promises, it would be really useful someday to get it up the point of being able to use on any type of shader, but for now I'd love to at least begin working towards getting vertex attributes accessible through sf::Shader.
Laurent thank you for working on this project, please let me know if this is a terrible idea.