New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
New API to set shader uniforms #983
Conversation
👍 for finalizing this task. I have two comments so far:
|
Like this? 😃 |
Of course, the moment I wrote that, I realized that I could as well have outsourced the entire class definitions, since a declaration is enough for So it should be even cleaner now. |
I haven't got time to check everything in details but I would have included the (*) if I remember correctly it's file to define a typedef to an incomplete type if it's full definition is available when using it so in this case it should work I believe. |
I would have done it like this too (see Thor), but I looked at Rect.inl and adhered to that style... Laurent? ;)
Yes, where "using" depends on how you're accessing the type -- it's a matter of whether the type is complete at that time or not. For example, you can declare pointers and references to incomplete types. |
Good point. Also note that in But I'd say we should avoid this style, at least from now on. What @SFML/sfml think? |
In Thread.inl, the namespace
Do you really need to ask if you should do like in all other files? ;) Regarding the modifications: looks perfect now 👍 |
No, I already did it like in all other files ;) the question is rather:
But it's a different question, so let's discuss it elsewhere and not pollute this pull request any further....
Okay, cool :) By the way, for those who haven't seen it yet, I attached a small self-contained example to my initial post, so everybody can test it. |
/// <algorithm> and MSVC's annoying 4996 warning in header | ||
/// | ||
//////////////////////////////////////////////////////////// | ||
void copyMatrix(const float* source, std::size_t elements, float* dest); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason for this parameter ordering? I find following the same ordering as std::memcpy
to be more "intuitive" and probably easier for people to remember.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function is identical to C++11 std::copy_n<float*>()
. But maybe you're right, it's also more consistent with initializeMatrix()
above...
df1c2f0
to
4025ac6
Compare
I applied the suggestions and some other changes.
|
It still needs to be called (it was there before your modifications, it was for a good reason ;)), in case
Although it reduces the number of lines to type for you, it clutters the public header. I prefer hiding such details, even if it involves typing more useless code for us. It's not as if it was going to change often. |
Okay, I misunderstood you. Thanks for the explanation! 😀
It makes me sad how we have all kinds of powerful abstractions in C++, but resort to silly boilerplate code 😟 are those 15 lines in the header a real problem? I'm not worried about typing (my IDE is powerful enough), but about code readability. Having a .cpp file of which the half are just empty dummy implementations is awful... But I can change it of course, if keeping things out of the header is the priority. |
Don't forget that it is not true code, just a quick and dirty placeholder until we switch to OpenGL ES 2 and have a proper implementation of shaders for all platforms.
I like keeping public headers clean.
Nobody's supposed to "read" this code, it's empty.
Would you feel better if we created a separate cpp file for the empty implementation, and leave the original Shader.cpp clean? |
I don't see headers so much as the public interface, because they're in fact not. The documentation should be the primary source to learn about the API, headers are more tailored to developers/"power users" than average users. And as a developer, it may be more intuitive to see the same thing handled with less code, but it depends of course on the person. Still, I totally understand your point, and generally I agree that it's a good idea to let .hpp files give a clean and concise overview of the class.
I thought about that too, but I don't think it's worth the special case for the configuration script. Handling it in code would require headers, and that's probably only more confusing. I'll just add the empty functions to the bottom of Shader.cpp 😉 |
Sooner or later, the backend implementations using the underlying GL objects will probably have to be split anyway since supporting multiple specifications (GL vs GLES) and multiple versions of the same specification (2.1 vs e.g. 4.5 which supports DSA) within a single file will become a complete mess. This is also one of the reasons why I favoured keeping |
4025ac6
to
6e21ef6
Compare
@binary1248 Okay, good to know. I think we should keep such things in a separate future PR though, there's also some optimization potential. I applied the changes as discussed above: reintroduced Something to keep in mind: the API currently provides an implicit conversion from It would be possible to add explicit conversions from sf::Glsl::Ivec4 colors[3] =
{
sf::Color::Yellow,
sf::Color::Cyan,
sf::Color::Red,
}; So the question really boils down to whether the syntax shader.setUniform("color", sf::Glsl::Vec4(color)); is such a big issue, that we desperately need shader.setUniform("color", color); at the cost of future limitations as outlined above. To demonstrate the difference, I added another commit that implements implicit conversions from sf::Color color;
shader.setUniform("color", sf::Glsl::Vec4(color));
shader.setUniform("color", sf::Glsl::Ivec4(color));
sf::Transform transform;
shader.setUniform("transform", sf::Glsl::Mat3(transform));
shader.setUniform("transform", sf::Glsl::Mat4(transform)); What do you think? Or is it unrealistic that people use other GLSL types than |
In an sfml-graphics only context (not If we are to stay somewhat future-proof, we should probably allow for other types as well. Already now, shaders can be used in a limited way as GL wrappers although I don't know whether people would actually bother using |
Okay. So should I merge the two commits? |
Sure. I guess this looks fine now. Like I said, there is optimization potential, but I'll leave that for another time in the (hopefully not to distant) future. 😉 👍 |
af68756
to
98faba0
Compare
Now that the corresponding PR has been merged, I introduced the I also improved the documentation in several parts, and provided a usage example. |
void Shader::setUniform(const std::string& name, const Glsl::Vec2& v) | ||
{ | ||
UniformBinder binder(*this, name); | ||
if (binder.location != -1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tab spotted ;)
Same in all other overloads.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed. I wonder why EditorConfig didn't prevent them... Maybe the VS plugin isn't perfect.
Implements a new design for the shader uniform API. * Added Shader::setUniform() and Shader::setUniformArray() overloads for the following types: -> scalars: float, int, bool -> vectors: 2D, 3D, 4D -> matrices: 3x3, 4x4 -> arrays of basic types -> samplers (sf::Texture) -> conversions for SFML types (sf::Transform, sf::Color) * Added sf::Glsl namespace with GLSL-equivalent types * Deprecated Shader::setParameter() overloads Other related changes: * Refactored sf::Shader internals to avoid code duplication * Improved documentation * Added SFML_DEPRECATED macro to Doxyfile * Defined _SCL_SECURE_NO_WARNINGS to disable std::copy() warnings on MSVC
98faba0
to
9c5c750
Compare
Anything left? Final reviews? |
Looks good to me. I can't spot anything that I would want to comment on right now, but from what I can tell, this should serve as a good starting point for future work anyway. 👍 |
This PR has been added to my merge list, meaning it will be merged soon, unless someone raises any concerns. |
Link to forum thread.
This pull request implements #538 and introduces a new API to set uniform variables in
sf::Shader
. The oldsetParameter()
overloads are deprecated in favor of newsetUniform()
ones.The
sf::Glsl
namespace is added to SFML. It contains type definitions for types that can be passed toShader::setUniform()
. Most types aretypedef
s to existing SFML types (such assf::Vector2<T>
), there are however a couple of new ones:I provided implicit conversions from
sf::Transform
andsf::Color
to these types where appropriate. Where necessary for ambiguity reasons, an explicit conversion must be used:In addition to basic GLSL types, arrays are now supported as well. They can be specified with
Shader::setUniformArray()
that takes a pointer to the first element and the length:Design rationale
After extensive thinking about the design (see 2 forum threads), I came to the conclusion that
setUniform()
overloads are more appropriate than named functionssetUniformFloat()
, for the following reasons:setUniformMat3()
forsf::Glsl::Mat3
,float*
andsf::Transform
separately, one method takingsf::Glsl::Mat3
is enough.Try it out
A self-contained archive containing a C++ file, two GLSL shader files and an image can be downloaded temporarily from my homepage: www.bromeon.ch/sfml/feature-shader-uniforms.zip