diff --git a/dotnet/samples/shader/Shader.cs b/dotnet/samples/shader/Shader.cs index 3c1e5470..74205bf3 100644 --- a/dotnet/samples/shader/Shader.cs +++ b/dotnet/samples/shader/Shader.cs @@ -149,6 +149,7 @@ namespace sample_shader // Process events window.DispatchEvents(); + // TOFIX -- using window.Input together with image.Draw apparently causes a memory corruption // Get the mouse position in the range [0, 1] //float x = window.Input.GetMouseX() / (float)window.Width; //float y = window.Input.GetMouseY() / (float)window.Height; diff --git a/include/SFML/Graphics/Shader.hpp b/include/SFML/Graphics/Shader.hpp index 584718f4..a70b8ce4 100644 --- a/include/SFML/Graphics/Shader.hpp +++ b/include/SFML/Graphics/Shader.hpp @@ -39,129 +39,257 @@ namespace sf { //////////////////////////////////////////////////////////// -/// Wrapper for pixel shaders +/// \brief Pixel/fragment shader class +/// //////////////////////////////////////////////////////////// class SFML_API Shader { public : //////////////////////////////////////////////////////////// - /// Default constructor + /// \brief Default constructor + /// + /// This constructor creates an invalid shader /// //////////////////////////////////////////////////////////// Shader(); //////////////////////////////////////////////////////////// - /// Copy constructor + /// \brief Copy constructor /// - /// \param copy : Instance to copy + /// \param copy Instance to copy /// //////////////////////////////////////////////////////////// Shader(const Shader& copy); //////////////////////////////////////////////////////////// - /// Destructor + /// \brief Destructor /// //////////////////////////////////////////////////////////// ~Shader(); //////////////////////////////////////////////////////////// - /// Load the shader from a file + /// \brief Load the shader from a file /// - /// \param filename : Path of the shader file to load + /// The source must be a text file containing a valid + /// fragment shader in GLSL language. GLSL is a C-like + /// language dedicated to OpenGL shaders; you'll probably + /// need to read a good documentation for it before writing + /// your own shaders. /// - /// \return True on success + /// \param filename Path of the shader file to load + /// + /// \return True if loading succeeded, false if it failed + /// + /// \see LoadFromMemory /// //////////////////////////////////////////////////////////// bool LoadFromFile(const std::string& filename); //////////////////////////////////////////////////////////// - /// Load the shader from a text in memory + /// \brief Load the shader from a source code in memory /// - /// \param effect : String containing the code of the shader + /// The source code must be a valid fragment shader in + /// GLSL language. GLSL is a C-like language dedicated + /// to OpenGL shaders; you'll probably need to read a + /// good documentation for it before writing your own shaders. /// - /// \return True on success + /// \param shader String containing the source code of the shader + /// + /// \return True if loading succeeded, false if it failed + /// + /// \see LoadFromFile /// //////////////////////////////////////////////////////////// bool LoadFromMemory(const std::string& shader); //////////////////////////////////////////////////////////// - /// Change a parameter of the shader (1 float) + /// \brief Change a float parameter of the shader /// - /// \param name : Name of the parameter in the shader - /// \param x : Value to assign + /// \a name is the name of the variable to change in the shader. + /// For example: + /// \code + /// uniform float myparam; // this is the variable in the pixel shader + /// \endcode + /// \code + /// shader.SetParameter("myparam", 5.2f); + /// \endcode + /// + /// \param name Name of the parameter in the shader + /// \param x Value to assign + /// + /// \see SetTexture /// //////////////////////////////////////////////////////////// void SetParameter(const std::string& name, float x); //////////////////////////////////////////////////////////// - /// Change a parameter of the shader (2 floats) + /// \brief Change a 2-components vector parameter of the shader /// - /// \param name : Name of the parameter in the shader - /// \param x, y : Values to assign + /// \a name is the name of the variable to change in the shader. + /// For example: + /// \code + /// uniform vec2 myparam; // this is the variable in the pixel shader + /// \endcode + /// \code + /// shader.SetParameter("myparam", 5.2f, 6.0f); + /// \endcode + /// + /// \param name Name of the parameter in the shader + /// \param x First component of the value to assign + /// \param y Second component of the value to assign + /// + /// \see SetTexture /// //////////////////////////////////////////////////////////// void SetParameter(const std::string& Name, float x, float y); //////////////////////////////////////////////////////////// - /// Change a parameter of the shader (3 floats) + /// \brief Change a 3-components vector parameter of the shader /// - /// \param name : Name of the parameter in the shader - /// \param x, y, z : Values to assign + /// \a name is the name of the variable to change in the shader. + /// For example: + /// \code + /// uniform vec3 myparam; // this is the variable in the pixel shader + /// \endcode + /// \code + /// shader.SetParameter("myparam", 5.2f, 6.0f, -8.1f); + /// \endcode + /// + /// \param name Name of the parameter in the shader + /// \param x First component of the value to assign + /// \param y Second component of the value to assign + /// \param z Third component of the value to assign + /// + /// \see SetTexture /// //////////////////////////////////////////////////////////// void SetParameter(const std::string& Name, float x, float y, float z); //////////////////////////////////////////////////////////// - /// Change a parameter of the shader (4 floats) + /// \brief Change a 4-components vector parameter of the shader /// - /// \param name : Name of the parameter in the shader - /// \param x, y, z, w : Values to assign + /// \a name is the name of the variable to change in the shader. + /// For example: + /// \code + /// uniform vec4 myparam; // this is the variable in the pixel shader + /// \endcode + /// \code + /// shader.SetParameter("myparam", 5.2f, 6.0f, -8.1f, 0.4f); + /// \endcode + /// + /// \param name Name of the parameter in the shader + /// \param x First component of the value to assign + /// \param y Second component of the value to assign + /// \param z Third component of the value to assign + /// \param w Fourth component of the value to assign + /// + /// \see SetTexture /// //////////////////////////////////////////////////////////// void SetParameter(const std::string& Name, float x, float y, float z, float w); //////////////////////////////////////////////////////////// - /// Change a parameter of the shader (1 vector2) + /// \brief Change a 2-components vector parameter of the shader /// - /// \param name : Name of the parameter in the shader - /// \param v : Value to assign + /// \a name is the name of the variable to change in the shader. + /// For example: + /// \code + /// uniform vec2 myparam; // this is the variable in the pixel shader + /// \endcode + /// \code + /// shader.SetParameter("myparam", sf::Vector2f(5.2f, 6.0f)); + /// \endcode + /// + /// \param name Name of the parameter in the shader + /// \param vector Vector to assign + /// + /// \see SetTexture /// //////////////////////////////////////////////////////////// - void SetParameter(const std::string& name, const Vector2f& v); + void SetParameter(const std::string& name, const Vector2f& vector); //////////////////////////////////////////////////////////// - /// Change a parameter of the shader (1 vector3) + /// \brief Change a 2-components vector parameter of the shader /// - /// \param name : Name of the parameter in the shader - /// \param v : Value to assign + /// \a name is the name of the variable to change in the shader. + /// For example: + /// \code + /// uniform vec3 myparam; // this is the variable in the pixel shader + /// \endcode + /// \code + /// shader.SetParameter("myparam", sf::Vector3f(5.2f, 6.0f, -8.1f)); + /// \endcode + /// + /// \param name Name of the parameter in the shader + /// \param vector Vector to assign + /// + /// \see SetTexture /// //////////////////////////////////////////////////////////// - void SetParameter(const std::string& name, const Vector3f& v); + void SetParameter(const std::string& name, const Vector3f& vector); //////////////////////////////////////////////////////////// - /// Set a texture parameter + /// \brief Change a texture parameter of the shader /// - /// \param name : Name of the texture in the shader - /// \param texture : Image to set (pass Shader::CurrentTexture to use the current texture) + /// \a name is the name of the texture to change in the shader. + /// To tell the shader to use the current texture of the object being + /// drawn, pass Shader::CurrentTexture. + /// Example: + /// \code + /// // These are the variables in the pixel shader + /// uniform sampler2D current; + /// uniform sampler2D other; + /// \endcode + /// \code + /// sf::Image image; + /// ... + /// shader.SetParameter("current", sf::Shader::CurrentTexture); + /// shader.SetParameter("other", image); + /// \endcode + /// It is important to note that \a texture must remain alive as long + /// as the shader uses it, no copy is made internally. + /// + /// \param name Name of the texture in the shader + /// \param texture Image to assign + /// + /// \see SetParameter /// //////////////////////////////////////////////////////////// void SetTexture(const std::string& name, const Image& texture); //////////////////////////////////////////////////////////// - /// Bind the shader for rendering + /// \brief Bind the shader for rendering (activate it) + /// + /// This function is normally for internal use only, unless + /// you want to use the shader with a custom OpenGL rendering + /// instead of a SFML drawable. + /// \code + /// window.SetActive(); + /// shader.Bind(); + /// ... render OpenGL geometry ... + /// shader.Unbind(); + /// \endcode + /// + /// \see Unbind /// //////////////////////////////////////////////////////////// void Bind() const; //////////////////////////////////////////////////////////// - /// Unbind the shader + /// \brief Bind the shader (deactivate it) + /// + /// This function is normally for internal use only, unless + /// you want to use the shader with a custom OpenGL rendering + /// instead of a SFML drawable. + /// + /// \see Bind /// //////////////////////////////////////////////////////////// void Unbind() const; //////////////////////////////////////////////////////////// - /// Assignment operator + /// \brief Overload of assignment operator /// /// \param right Instance to assign /// @@ -171,9 +299,13 @@ public : Shader& operator =(const Shader& right); //////////////////////////////////////////////////////////// - /// Tell whether or not the system supports shaders + /// \brief Tell whether or not the system supports shaders /// - /// \return True if the system can use shaders + /// This function should always be called before using + /// the shader features. If it returns false, then + /// any attempt to use sf::Shader will fail. + /// + /// \return True if shaders are supported, false otherwise /// //////////////////////////////////////////////////////////// static bool IsAvailable(); @@ -186,7 +318,7 @@ public : private : //////////////////////////////////////////////////////////// - /// Create the program and attach the shaders + /// \brief Create the program and attach the shaders /// /// \return True on success, false if any error happened /// @@ -211,3 +343,64 @@ private : #endif // SFML_SHADER_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Shader +/// +/// Pixel shaders (or fragment shaders) are programs written +/// using a specific language, executed directly by the +/// graphics card and allowing to apply per-pixel real-time +/// operations to the rendered entities. +/// +/// Pixel shaders are written in GLSL, which is a C-like +/// language dedicated to OpenGL shaders. You'll probably +/// need to learn its basics before writing your own shaders +/// for SFML. +/// +/// Like any C/C++ program, a shader has its own variables +/// that you can set from your C++ application. sf::Shader +/// handles 3 different types of variables: +/// \li floats +/// \li vectors (2, 3 or 4 components) +/// \li textures +/// +/// The value of the variables can be changed at any time +/// with either Shader::SetParameter or Shader::SetTexture: +/// \code +/// shader.SetParameter("offset", 2.f); +/// shader.SetParameter("color", 0.5f, 0.8f, 0.3f); +/// shader.SetTexture("image", image); // image is a sf::Image +/// shader.SetTexture("current", sf::Shader::CurrentTexture); +/// \endcode +/// +/// Shader::CurrentTexture is a special value that represents +/// the texture that the object being drawn is using. +/// +/// To apply a shader to a drawable, you must pass it as an +/// additional parameter to the Draw function: +/// \code +/// window.Draw(sprite, shader); +/// \endcode +/// +/// Shaders can be used on any drawable, but they are mainly +/// made for sf::Sprite. Using a shader on a sf::String is more +/// limited, because the texture of the string is not the +/// actual text that you see on screen, it is a big image +/// containing all the characters of the font in an arbitrary +/// order. Thus, texture lookups on pixels other than the current +/// one may not give you the expected result. Using a shader +/// with sf::Shape is even more limited, as shapes don't use +/// any texture. +/// +/// Like sf::Image that can be used as a raw OpenGL texture, +/// sf::Shader can also be used directly as a raw fragment +/// shader for custom OpenGL geometry. +/// \code +/// window.SetActive(); +/// shader.Bind(); +/// ... render OpenGL geometry ... +/// shader.Unbind(); +/// \endcode +/// +//////////////////////////////////////////////////////////// diff --git a/src/SFML/Graphics/Shader.cpp b/src/SFML/Graphics/Shader.cpp index b1ddc732..799620b6 100644 --- a/src/SFML/Graphics/Shader.cpp +++ b/src/SFML/Graphics/Shader.cpp @@ -319,10 +319,11 @@ bool Shader::IsAvailable() //////////////////////////////////////////////////////////// bool Shader::CompileProgram() { - // First make sure that we can use shaders! + // First make sure that we can use shaders if (!IsAvailable()) { - std::cerr << "Failed to create a shader: your system doesn't support shaders" << std::endl; + std::cerr << "Failed to create a shader: your system doesn't support shaders " + << "(you should test Shader::IsAvailable() before trying to use the Shader class)" << std::endl; return false; } @@ -331,7 +332,7 @@ bool Shader::CompileProgram() GLCheck(glDeleteObjectARB(myShaderProgram)); // Define the vertex shader source (we provide it directly as it doesn't have to change) - static const std::string vertexShaderSrc = + static const char* vertexSrc = "void main()" "{" " gl_TexCoord[0] = gl_MultiTexCoord0;" @@ -347,7 +348,6 @@ bool Shader::CompileProgram() GLhandleARB fragmentShader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); // Compile them - const char* vertexSrc = vertexShaderSrc.c_str(); const char* fragmentSrc = myFragmentShader.c_str(); GLCheck(glShaderSourceARB(vertexShader, 1, &vertexSrc, NULL)); GLCheck(glShaderSourceARB(fragmentShader, 1, &fragmentSrc, NULL));