Split sf::Image into sf::Image and sf::Texture (implements issue #18)

This commit is contained in:
Laurent Gomila 2011-07-22 22:31:27 +02:00
parent d337a98321
commit e509f01180
40 changed files with 1585 additions and 1294 deletions

View File

@ -18,14 +18,14 @@ int main()
sf::RenderWindow window(sf::VideoMode(800, 600), "SFML OpenGL", sf::Style::Default, sf::ContextSettings(32)); sf::RenderWindow window(sf::VideoMode(800, 600), "SFML OpenGL", sf::Style::Default, sf::ContextSettings(32));
// Create a sprite for the background // Create a sprite for the background
sf::Image backgroundImage; sf::Texture backgroundTexture;
if (!backgroundImage.LoadFromFile("resources/background.jpg")) if (!backgroundTexture.LoadFromFile("resources/background.jpg"))
return EXIT_FAILURE; return EXIT_FAILURE;
sf::Sprite background(backgroundImage); sf::Sprite background(backgroundTexture);
// Load an OpenGL texture. // Load an OpenGL texture.
// We could directly use a sf::Image as an OpenGL texture (with its Bind() member function), // We could directly use a sf::Texture as an OpenGL texture (with its Bind() member function),
// but here we want more control on it (generate mipmaps, ...) so we create a new one from the image pixels // but here we want more control on it (generate mipmaps, ...) so we create a new one from an image
GLuint texture = 0; GLuint texture = 0;
{ {
sf::Image image; sf::Image image;

View File

@ -33,12 +33,12 @@ int main()
} }
sf::Sound ballSound(ballSoundBuffer); sf::Sound ballSound(ballSoundBuffer);
// Load the images used in the game // Load the textures used in the game
sf::Image backgroundImage, leftPaddleImage, rightPaddleImage, ballImage; sf::Texture backgroundTexture, leftPaddleTexture, rightPaddleTexture, ballTexture;
if (!backgroundImage.LoadFromFile("resources/background.jpg") || if (!backgroundTexture.LoadFromFile("resources/background.jpg") ||
!leftPaddleImage.LoadFromFile("resources/paddle_left.png") || !leftPaddleTexture.LoadFromFile("resources/paddle_left.png") ||
!rightPaddleImage.LoadFromFile("resources/paddle_right.png") || !rightPaddleTexture.LoadFromFile("resources/paddle_right.png") ||
!ballImage.LoadFromFile("resources/ball.png")) !ballTexture.LoadFromFile("resources/ball.png"))
{ {
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -56,10 +56,10 @@ int main()
end.SetColor(sf::Color(50, 50, 250)); end.SetColor(sf::Color(50, 50, 250));
// Create the sprites of the background, the paddles and the ball // Create the sprites of the background, the paddles and the ball
sf::Sprite background(backgroundImage); sf::Sprite background(backgroundTexture);
sf::Sprite leftPaddle(leftPaddleImage); sf::Sprite leftPaddle(leftPaddleTexture);
sf::Sprite rightPaddle(rightPaddleImage); sf::Sprite rightPaddle(rightPaddleTexture);
sf::Sprite ball(ballImage); sf::Sprite ball(ballTexture);
leftPaddle.Move(10, (window.GetView().GetSize().y - leftPaddle.GetSize().y) / 2); leftPaddle.Move(10, (window.GetView().GetSize().y - leftPaddle.GetSize().y) / 2);
rightPaddle.Move(window.GetView().GetSize().x - rightPaddle.GetSize().x - 10, (window.GetView().GetSize().y - rightPaddle.GetSize().y) / 2); rightPaddle.Move(window.GetView().GetSize().x - rightPaddle.GetSize().x - 10, (window.GetView().GetSize().y - rightPaddle.GetSize().y) / 2);

View File

@ -4,7 +4,7 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Graphics.hpp> #include <SFML/Graphics.hpp>
#include <map> #include <map>
#include <math.h> #include <cmath>
void DisplayError(); void DisplayError();
@ -88,32 +88,31 @@ int main()
// Create the main window // Create the main window
sf::RenderWindow window(sf::VideoMode(800, 600), "SFML Shader"); sf::RenderWindow window(sf::VideoMode(800, 600), "SFML Shader");
// Create the render image // Create the render texture
sf::RenderImage image; sf::RenderTexture texture;
if (!image.Create(window.GetWidth(), window.GetHeight())) if (!texture.Create(window.GetWidth(), window.GetHeight()))
return EXIT_FAILURE; return EXIT_FAILURE;
// Load a background image to display // Load a background texture to display
sf::Image backgroundImage; sf::Texture backgroundTexture;
if (!backgroundImage.LoadFromFile("resources/background.jpg")) if (!backgroundTexture.LoadFromFile("resources/background.jpg"))
return EXIT_FAILURE; return EXIT_FAILURE;
sf::Sprite background(backgroundImage); sf::Sprite background(backgroundTexture);
backgroundImage.SetSmooth(false);
// Load a sprite which we'll move into the scene // Load a sprite which we'll move into the scene
sf::Image entityImage; sf::Texture entityTexture;
if (!entityImage.LoadFromFile("resources/sprite.png")) if (!entityTexture.LoadFromFile("resources/sprite.png"))
return EXIT_FAILURE; return EXIT_FAILURE;
sf::Sprite entity(entityImage); sf::Sprite entity(entityTexture);
// Load the text font // Load the text font
sf::Font font; sf::Font font;
if (!font.LoadFromFile("resources/sansation.ttf")) if (!font.LoadFromFile("resources/sansation.ttf"))
return EXIT_FAILURE; return EXIT_FAILURE;
// Load the image needed for the wave shader // Load the texture needed for the wave shader
sf::Image waveImage; sf::Texture waveTexture;
if (!waveImage.LoadFromFile("resources/wave.jpg")) if (!waveTexture.LoadFromFile("resources/wave.jpg"))
return EXIT_FAILURE; return EXIT_FAILURE;
// Load all shaders // Load all shaders
@ -138,7 +137,7 @@ int main()
shaders["edge"].SetCurrentTexture("texture"); shaders["edge"].SetCurrentTexture("texture");
shaders["fisheye"].SetCurrentTexture("texture"); shaders["fisheye"].SetCurrentTexture("texture");
shaders["wave"].SetCurrentTexture("texture"); shaders["wave"].SetCurrentTexture("texture");
shaders["wave"].SetTexture("wave", waveImage); shaders["wave"].SetTexture("wave", waveTexture);
shaders["pixelate"].SetCurrentTexture("texture"); shaders["pixelate"].SetCurrentTexture("texture");
// Define a string for displaying the description of the current shader // Define a string for displaying the description of the current shader
@ -211,19 +210,19 @@ int main()
globalShader.Update(mouseX, mouseY); globalShader.Update(mouseX, mouseY);
// Animate the entity // Animate the entity
float entityX = (cos(clock.GetElapsedTime() * 0.0013f) + 1.2f) * 300; float entityX = (std::cos(clock.GetElapsedTime() * 0.0013f) + 1.2f) * 300;
float entityY = (cos(clock.GetElapsedTime() * 0.0008f) + 1.2f) * 200; float entityY = (std::cos(clock.GetElapsedTime() * 0.0008f) + 1.2f) * 200;
entity.SetPosition(entityX, entityY); entity.SetPosition(entityX, entityY);
entity.Rotate(window.GetFrameTime() * 0.1f); entity.Rotate(window.GetFrameTime() * 0.1f);
// Draw the background and the moving entity to the render image // Draw the background and the moving entity to the render texture
image.Clear(); texture.Clear();
image.Draw(background, backgroundShader.GetShader()); texture.Draw(background, backgroundShader.GetShader());
image.Draw(entity, entityShader.GetShader()); texture.Draw(entity, entityShader.GetShader());
image.Display(); texture.Display();
// Draw the contents of the render image to the window // Draw the contents of the render texture to the window
sf::Sprite screen(image.GetImage()); sf::Sprite screen(texture.GetTexture());
window.Draw(screen, globalShader.GetShader()); window.Draw(screen, globalShader.GetShader());
// Draw the interface texts // Draw the interface texts

View File

@ -75,12 +75,12 @@ INT WINAPI WinMain(HINSTANCE instance, HINSTANCE, LPSTR, INT)
sf::RenderWindow SFMLView1(view1); sf::RenderWindow SFMLView1(view1);
sf::RenderWindow SFMLView2(view2); sf::RenderWindow SFMLView2(view2);
// Load some images to display // Load some textures to display
sf::Image image1, image2; sf::Texture texture1, texture2;
if (!image1.LoadFromFile("resources/image1.jpg") || !image2.LoadFromFile("resources/image2.jpg")) if (!texture1.LoadFromFile("resources/image1.jpg") || !texture2.LoadFromFile("resources/image2.jpg"))
return EXIT_FAILURE; return EXIT_FAILURE;
sf::Sprite sprite1(image1); sf::Sprite sprite1(texture1);
sf::Sprite sprite2(image2); sf::Sprite sprite2(texture2);
sprite1.SetOrigin(sprite1.GetSize() / 2.f); sprite1.SetOrigin(sprite1.GetSize() / 2.f);
sprite1.SetPosition(sprite1.GetSize() / 2.f); sprite1.SetPosition(sprite1.GetSize() / 2.f);

View File

@ -52,16 +52,12 @@ public :
Sound(); Sound();
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Construct the sound with parameters /// \brief Construct the sound with a buffer
/// ///
/// \param buffer Sound buffer containing the audio data to play with the sound /// \param buffer Sound buffer containing the audio data to play with the sound
/// \param loop Should the sound loop?
/// \param pitch Pitch of the sound
/// \param volume Volume of the sound, in the range [0, 100]
/// \param position 3D position of the sound source in the audio scene
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Sound(const SoundBuffer& buffer, bool loop = false, float pitch = 1.f, float volume = 100.f, const Vector3f& position = Vector3f(0, 0, 0)); Sound(const SoundBuffer& buffer);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Copy constructor /// \brief Copy constructor

View File

@ -301,8 +301,8 @@ private :
/// The sound is then restituted by playing these samples at /// The sound is then restituted by playing these samples at
/// a high rate (for example, 44100 samples per second is the /// a high rate (for example, 44100 samples per second is the
/// standard rate used for playing CDs). In short, audio samples /// standard rate used for playing CDs). In short, audio samples
/// are like image pixels, and a sf::SoundBuffer is similar to /// are like texture pixels, and a sf::SoundBuffer is similar to
/// a sf::Image. /// a sf::Texture.
/// ///
/// A sound buffer can be loaded from a file (see LoadFromFile() /// A sound buffer can be loaded from a file (see LoadFromFile()
/// for the complete list of supported formats), from memory, from /// for the complete list of supported formats), from memory, from

View File

@ -35,12 +35,13 @@
#include <SFML/Graphics/Glyph.hpp> #include <SFML/Graphics/Glyph.hpp>
#include <SFML/Graphics/Image.hpp> #include <SFML/Graphics/Image.hpp>
#include <SFML/Graphics/Renderer.hpp> #include <SFML/Graphics/Renderer.hpp>
#include <SFML/Graphics/RenderImage.hpp> #include <SFML/Graphics/RenderTexture.hpp>
#include <SFML/Graphics/RenderWindow.hpp> #include <SFML/Graphics/RenderWindow.hpp>
#include <SFML/Graphics/Shader.hpp> #include <SFML/Graphics/Shader.hpp>
#include <SFML/Graphics/Shape.hpp> #include <SFML/Graphics/Shape.hpp>
#include <SFML/Graphics/Sprite.hpp> #include <SFML/Graphics/Sprite.hpp>
#include <SFML/Graphics/Text.hpp> #include <SFML/Graphics/Text.hpp>
#include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/View.hpp> #include <SFML/Graphics/View.hpp>

View File

@ -63,17 +63,6 @@ class SFML_API Drawable
{ {
public : public :
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// \param position Position of the object
/// \param scale Scale factor
/// \param rotation Orientation, in degrees
/// \param color Global color of the object
///
////////////////////////////////////////////////////////////
Drawable(const Vector2f& position = Vector2f(0, 0), const Vector2f& scale = Vector2f(1, 1), float rotation = 0.f, const Color& color = Color(255, 255, 255));
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Virtual destructor /// \brief Virtual destructor
/// ///
@ -452,6 +441,12 @@ public :
protected : protected :
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
Drawable();
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Get the transform matrix of the object /// \brief Get the transform matrix of the object
/// ///
@ -532,7 +527,7 @@ private :
/// \li transformations (position, rotation, scale, local origin) /// \li transformations (position, rotation, scale, local origin)
/// \li global overlay color /// \li global overlay color
/// \li blending mode with background pixels /// \li blending mode with background pixels
/// \li the ability to be drawn on a sf::RenderTarget (either RenderWindow or RenderImage) /// \li the ability to be drawn on a sf::RenderTarget (either RenderWindow or RenderTexture)
/// ///
/// Please note that all these attributes are hardware accelerated, /// Please note that all these attributes are hardware accelerated,
/// therefore they are extremely cheap to use (unlike older /// therefore they are extremely cheap to use (unlike older
@ -591,7 +586,7 @@ private :
/// target.Draw(mySubSprite); /// target.Draw(mySubSprite);
/// } /// }
/// ///
/// sf::Image myTexture; /// sf::Texture myTexture;
/// sf::Sprite mySubSprite; /// sf::Sprite mySubSprite;
/// }; /// };
/// \endcode /// \endcode

View File

@ -32,7 +32,7 @@
#include <SFML/System/Vector2.hpp> #include <SFML/System/Vector2.hpp>
#include <SFML/System/String.hpp> #include <SFML/System/String.hpp>
#include <SFML/Graphics/Glyph.hpp> #include <SFML/Graphics/Glyph.hpp>
#include <SFML/Graphics/Image.hpp> #include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/Rect.hpp> #include <SFML/Graphics/Rect.hpp>
#include <map> #include <map>
#include <string> #include <string>
@ -174,18 +174,18 @@ public :
int GetLineSpacing(unsigned int characterSize) const; int GetLineSpacing(unsigned int characterSize) const;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Retrieve the image containing the loaded glyphs of a certain size /// \brief Retrieve the texture containing the loaded glyphs of a certain size
/// ///
/// The contents of the returned image changes as more glyphs /// The contents of the returned texture changes as more glyphs
/// are requested, thus it is not very relevant. It is mainly /// are requested, thus it is not very relevant. It is mainly
/// used internally by sf::Text. /// used internally by sf::Text.
/// ///
/// \param characterSize Reference character size /// \param characterSize Reference character size
/// ///
/// \return Image containing the glyphs of the requested size /// \return Texture containing the glyphs of the requested size
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
const Image& GetImage(unsigned int characterSize) const; const Texture& GetTexture(unsigned int characterSize) const;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Overload of assignment operator /// \brief Overload of assignment operator
@ -240,8 +240,8 @@ private :
Page(); Page();
GlyphTable Glyphs; ///< Table mapping code points to their corresponding glyph GlyphTable Glyphs; ///< Table mapping code points to their corresponding glyph
Image Texture; ///< Image containing the pixels of the glyphs Texture Texture; ///< Texture containing the pixels of the glyphs
unsigned int NextRow; ///< Y position of the next new row in the image unsigned int NextRow; ///< Y position of the next new row in the texture
std::vector<Row> Rows; ///< List containing the position of all the existing rows std::vector<Row> Rows; ///< List containing the position of all the existing rows
}; };
@ -288,7 +288,7 @@ private :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Types // Types
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
typedef std::map<unsigned int, Page> PageTable; ///< Table mapping a character size to its page (image) typedef std::map<unsigned int, Page> PageTable; ///< Table mapping a character size to its page (texture)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Member data // Member data

View File

@ -53,7 +53,7 @@ public :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
int Advance; ///< Offset to move horizontically to the next character int Advance; ///< Offset to move horizontically to the next character
IntRect Bounds; ///< Bounding rectangle of the glyph, in coordinates relative to the baseline IntRect Bounds; ///< Bounding rectangle of the glyph, in coordinates relative to the baseline
IntRect SubRect; ///< Texture coordinates of the glyph inside the font's image IntRect SubRect; ///< Texture coordinates of the glyph inside the font's texture
}; };
} // namespace sf } // namespace sf
@ -70,7 +70,7 @@ public :
/// ///
/// The sf::Glyph structure provides the information needed /// The sf::Glyph structure provides the information needed
/// to handle the glyph: /// to handle the glyph:
/// \li its coordinates in the font's image /// \li its coordinates in the font's texture
/// \li its bounding rect /// \li its bounding rect
/// \li the offset to apply to get the starting position of the next glyph /// \li the offset to apply to get the starting position of the next glyph
/// ///

View File

@ -29,7 +29,6 @@
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/System/Resource.hpp> #include <SFML/System/Resource.hpp>
#include <SFML/Window/GlResource.hpp>
#include <SFML/Graphics/Color.hpp> #include <SFML/Graphics/Color.hpp>
#include <SFML/Graphics/Rect.hpp> #include <SFML/Graphics/Rect.hpp>
#include <string> #include <string>
@ -38,16 +37,13 @@
namespace sf namespace sf
{ {
class Renderer;
class RenderImage;
class RenderWindow;
class InputStream; class InputStream;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Class for loading, manipulating and saving images /// \brief Class for loading, manipulating and saving images
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
class SFML_API Image : public Resource<Image>, GlResource class SFML_API Image
{ {
public : public :
@ -60,18 +56,29 @@ public :
Image(); Image();
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Copy constructor /// \brief Create the image and fill it with a unique color
/// ///
/// \param copy instance to copy /// \param width Width of the image
/// \param height Height of the image
/// \param color Fill color
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Image(const Image& copy); void Create(unsigned int width, unsigned int height, const Color& color = Color(0, 0, 0));
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Destructor /// \brief Create the image from an arry of pixels
///
/// The \a pixels array is assumed to contain 32-bits RGBA pixels,
/// and have the given \a width and \a height. If not, this is
/// an undefined behaviour.
/// If \a pixels is null, an empty image is created.
///
/// \param width Width of the image
/// \param height Height of the image
/// \param pixels Array of pixels to copy to the image
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
~Image(); void Create(unsigned int width, unsigned int height, const Uint8* pixels);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Load the image from a file on disk /// \brief Load the image from a file on disk
@ -79,15 +86,13 @@ public :
/// The supported image formats are bmp, png, tga, jpg, gif, /// The supported image formats are bmp, png, tga, jpg, gif,
/// psd, hdr and pic. Some format options are not supported, /// psd, hdr and pic. Some format options are not supported,
/// like progressive jpeg. /// like progressive jpeg.
/// The maximum size for an image depends on the graphics
/// driver and can be retrieve with the GetMaximumSize function.
/// If this function fails, the image is left unchanged. /// If this function fails, the image is left unchanged.
/// ///
/// \param filename Path of the image file to load /// \param filename Path of the image file to load
/// ///
/// \return True if loading was successful /// \return True if loading was successful
/// ///
/// \see LoadFromMemory, LoadFromStream, LoadFromPixels, SaveToFile /// \see LoadFromMemory, LoadFromStream, SaveToFile
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool LoadFromFile(const std::string& filename); bool LoadFromFile(const std::string& filename);
@ -98,8 +103,6 @@ public :
/// The supported image formats are bmp, png, tga, jpg, gif, /// The supported image formats are bmp, png, tga, jpg, gif,
/// psd, hdr and pic. Some format options are not supported, /// psd, hdr and pic. Some format options are not supported,
/// like progressive jpeg. /// like progressive jpeg.
/// The maximum size for an image depends on the graphics
/// driver and can be retrieve with the GetMaximumSize function.
/// If this function fails, the image is left unchanged. /// If this function fails, the image is left unchanged.
/// ///
/// \param data Pointer to the file data in memory /// \param data Pointer to the file data in memory
@ -107,7 +110,7 @@ public :
/// ///
/// \return True if loading was successful /// \return True if loading was successful
/// ///
/// \see LoadFromFile, LoadFromStream, LoadFromPixels /// \see LoadFromFile, LoadFromStream
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool LoadFromMemory(const void* data, std::size_t size); bool LoadFromMemory(const void* data, std::size_t size);
@ -126,30 +129,11 @@ public :
/// ///
/// \return True if loading was successful /// \return True if loading was successful
/// ///
/// \see LoadFromFile, LoadFromMemory, LoadFromPixels /// \see LoadFromFile, LoadFromMemory
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool LoadFromStream(InputStream& stream); bool LoadFromStream(InputStream& stream);
////////////////////////////////////////////////////////////
/// \brief Load the image from an array of pixels
///
/// The \a pixels argument must point to an array of 32 bits
/// RGBA pixels. In other words, the pixel array must have
/// this memory layout: [r0 g0 b0 a0 r1 g1 b1 a1 r2...]
/// If this function fails, the image is left unchanged.
///
/// \param width Width of the image
/// \param height Height of the image
/// \param pixels Pointer to the pixels in memory
///
/// \return True if loading was successful
///
/// \see LoadFromFile, LoadFromMemory, SaveToFile
///
////////////////////////////////////////////////////////////
bool LoadFromPixels(unsigned int width, unsigned int height, const Uint8* pixels);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Save the image to a file on disk /// \brief Save the image to a file on disk
/// ///
@ -162,27 +146,33 @@ public :
/// ///
/// \return True if saving was successful /// \return True if saving was successful
/// ///
/// \see LoadFromFile, LoadFromMemory, LoadFromPixels /// \see Create, LoadFromFile, LoadFromMemory
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool SaveToFile(const std::string& filename) const; bool SaveToFile(const std::string& filename) const;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Create the image and fill it with a unique color /// \brief Return the width of the image
/// ///
/// If this function fails, the image is left unchanged. /// \return Width in pixels
/// ///
/// \param width Width of the image /// \see GetHeight
/// \param height Height of the image
/// \param color Fill color
///
/// \return True if creation was successful
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool Create(unsigned int width, unsigned int height, const Color& color = Color(0, 0, 0)); unsigned int GetWidth() const;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Create a transparency mask from a specified colorkey /// \brief Return the height of the image
///
/// \return Height in pixels
///
/// \see GetWidth
///
////////////////////////////////////////////////////////////
unsigned int GetHeight() const;
////////////////////////////////////////////////////////////
/// \brief Create a transparency mask from a specified color-key
/// ///
/// This function sets the alpha value of every pixel matching /// This function sets the alpha value of every pixel matching
/// the given color to \a alpha (0 by default), so that they /// the given color to \a alpha (0 by default), so that they
@ -197,11 +187,11 @@ public :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Copy pixels from another image onto this one /// \brief Copy pixels from another image onto this one
/// ///
/// This function does a slow pixel copy and should only /// This function does a slow pixel copy and should not be
/// be used at initialization time. It can be used to prepare /// used intensively. It can be used to prepare a complex
/// a complex static image from several others, but if you /// static image from several others, but if you need this
/// need this kind of feature in real-time you'd better use /// kind of feature in real-time you'd better use sf::RenderTexture.
/// sf::RenderImage. ///
/// If \a sourceRect is empty, the whole image is copied. /// If \a sourceRect is empty, the whole image is copied.
/// If \a applyAlpha is set to true, the transparency of /// If \a applyAlpha is set to true, the transparency of
/// source pixels is applied. If it is false, the pixels are /// source pixels is applied. If it is false, the pixels are
@ -216,22 +206,6 @@ public :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void Copy(const Image& source, unsigned int destX, unsigned int destY, const IntRect& sourceRect = IntRect(0, 0, 0, 0), bool applyAlpha = false); void Copy(const Image& source, unsigned int destX, unsigned int destY, const IntRect& sourceRect = IntRect(0, 0, 0, 0), bool applyAlpha = false);
////////////////////////////////////////////////////////////
/// \brief Copy the contents of a window to the image
///
/// If \a sourceRect is empty, the whole window is copied.
/// Warning: this is a slow operation, if you need to draw
/// dynamic contents to an image then use sf::RenderImage.
/// If this function fails, the image is left unchanged.
///
/// \param window Window to capture
/// \param sourceRect Sub-rectangle of the screen to copy
///
/// \return True if copy was successful
///
////////////////////////////////////////////////////////////
bool CopyScreen(RenderWindow& window, const IntRect& sourceRect = IntRect(0, 0, 0, 0));
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Change the color of a pixel /// \brief Change the color of a pixel
/// ///
@ -273,207 +247,19 @@ public :
/// modify the image, so you should never store it for too long. /// modify the image, so you should never store it for too long.
/// If the image is empty, a null pointer is returned. /// If the image is empty, a null pointer is returned.
/// ///
/// \return Const pointer to the array of pixels /// \return Read-only pointer to the array of pixels
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
const Uint8* GetPixelsPtr() const; const Uint8* GetPixelsPtr() const;
////////////////////////////////////////////////////////////
/// \brief Update the whole image from an array of pixels
///
/// The \a pixels array is assumed to have the same size as
/// the image, and to store RGBA 32 bits pixels.
/// See the other overload of this function to update only
/// a sub-rectangle of the image.
/// This function does nothing if \a pixels is null.
///
/// \param pixels Array of pixels to write to the image
///
////////////////////////////////////////////////////////////
void UpdatePixels(const Uint8* pixels);
////////////////////////////////////////////////////////////
/// \brief Update a sub-rectangle of the image from an array of pixels
///
/// The \a pixels array is assumed to store RGBA 32 bits pixels.
/// Warning: for performances reasons, this function doesn't
/// perform any check; thus you're responsible of ensuring that
/// \a rectangle does not exceed the image size, and that
/// \a pixels contains enough elements.
/// This function does nothing if \a pixels is null.
/// See the other overload of this function to update the
/// whole image.
///
/// \param rectangle Sub-rectangle of the image to update
/// \param pixels Array of pixels to write to the image
///
////////////////////////////////////////////////////////////
void UpdatePixels(const Uint8* pixels, const IntRect& rectangle);
////////////////////////////////////////////////////////////
/// \brief Activate the image for rendering
///
/// This function is mainly used internally by the SFML
/// render system. However it can be useful when
/// using sf::Image together with OpenGL code (it calls
/// glBindTexture).
///
////////////////////////////////////////////////////////////
void Bind() const;
////////////////////////////////////////////////////////////
/// \brief Enable or disable the smooth filter
///
/// When the filter is activated, the image appears smoother
/// so that pixels are less noticeable. However if you want
/// the image to look exactly the same as its source file, you
/// should disable it.
/// The smooth filter is disabled by default.
///
/// \param smooth True to enable smoothing, false to disable it
///
/// \see IsSmooth
///
////////////////////////////////////////////////////////////
void SetSmooth(bool smooth);
////////////////////////////////////////////////////////////
/// \brief Tell whether the smooth filter is enabled or not
///
/// \return True if smoothing is enabled, false if it is disabled
///
/// \see SetSmooth
///
////////////////////////////////////////////////////////////
bool IsSmooth() const;
////////////////////////////////////////////////////////////
/// \brief Return the width of the image
///
/// \return Width in pixels
///
/// \see GetHeight
///
////////////////////////////////////////////////////////////
unsigned int GetWidth() const;
////////////////////////////////////////////////////////////
/// \brief Return the height of the image
///
/// \return Height in pixels
///
/// \see GetWidth
///
////////////////////////////////////////////////////////////
unsigned int GetHeight() const;
////////////////////////////////////////////////////////////
/// \brief Convert a rectangle of pixels into texture coordinates
///
/// This function is used by code that needs to map the image
/// to some OpenGL geometry. It converts the source rectangle,
/// expressed in pixels, to float coordinates in the range [0, 1].
///
/// \param rectangle Rectangle to convert
///
/// \return Texture coordinates corresponding to \a rectangle
///
////////////////////////////////////////////////////////////
FloatRect GetTexCoords(const IntRect& rectangle) const;
////////////////////////////////////////////////////////////
/// \brief Get the maximum image size allowed
///
/// This maximum size is defined by the graphics driver.
/// You can expect a value of 512 pixels for low-end graphics
/// card, and up to 8192 pixels for newer hardware.
///
/// \return Maximum size allowed for images, in pixels
///
////////////////////////////////////////////////////////////
static unsigned int GetMaximumSize();
////////////////////////////////////////////////////////////
/// \brief Overload of assignment operator
///
/// \param right Instance to assign
///
/// \return Reference to self
///
////////////////////////////////////////////////////////////
Image& operator =(const Image& right);
private : private :
friend class Renderer;
friend class RenderImage;
////////////////////////////////////////////////////////////
/// \brief Get a valid image size according to hardware support
///
/// This function checks whether the graphics driver supports
/// non power of two sizes or not, and adjusts the size
/// accordingly.
/// The returned size is greater than or equal to the original size.
///
/// \param Size size to convert
///
/// \return Valid nearest size (greater than or equal to specified size)
///
////////////////////////////////////////////////////////////
static unsigned int GetValidSize(unsigned int size);
////////////////////////////////////////////////////////////
/// \brief Create the OpenGL texture
///
/// If this function fails, the image's members are left unchanged.
///
/// \param width Texture width
/// \param height Texture height
///
/// \return True if texture was successfully created, false if it failed
///
////////////////////////////////////////////////////////////
bool CreateTexture(unsigned int width, unsigned int height);
////////////////////////////////////////////////////////////
/// \brief Make sure that the texture in video memory is
/// synchronized with the pixels cache
///
////////////////////////////////////////////////////////////
void EnsureTextureUpdate() const;
////////////////////////////////////////////////////////////
/// \brief Make sure the pixels cache is synchronized with
/// the texture in video memory
///
////////////////////////////////////////////////////////////
void EnsureArrayUpdate() const;
////////////////////////////////////////////////////////////
/// \brief Make sure that the image is ready to be used
///
////////////////////////////////////////////////////////////
void Use() const;
////////////////////////////////////////////////////////////
// Types
////////////////////////////////////////////////////////////
typedef std::vector<Uint8> ColorArray; ///< Array of colors
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Member data // Member data
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
unsigned int myWidth; ///< Image width unsigned int myWidth; ///< Image width
unsigned int myHeight; ///< Image Height unsigned int myHeight; ///< Image Height
unsigned int myTextureWidth; ///< Actual texture width (can be greater than image width because of padding) std::vector<Uint8> myPixels; ///< Pixels of the image
unsigned int myTextureHeight; ///< Actual texture height (can be greater than image height because of padding)
unsigned int myTexture; ///< Internal texture identifier
bool myIsSmooth; ///< Status of the smooth filter
mutable ColorArray myPixels; ///< Pixels of the image
mutable bool myTextureUpdated; ///< Status of synchronization between pixels in central memory and the internal texture un video memory
mutable bool myArrayUpdated; ///< Status of synchronization between pixels in central memory and the internal texture un video memory
mutable bool myPixelsFlipped; ///< To work around the inconsistency in Y orientation
}; };
} // namespace sf } // namespace sf
@ -489,7 +275,7 @@ private :
/// sf::Image is an abstraction to manipulate images /// sf::Image is an abstraction to manipulate images
/// as bidimensional arrays of pixels. The class provides /// as bidimensional arrays of pixels. The class provides
/// functions to load, read, write and save pixels, as well /// functions to load, read, write and save pixels, as well
/// as many other useful functions to... /// as many other useful functions.
/// ///
/// sf::Image can handle a unique internal representation of /// sf::Image can handle a unique internal representation of
/// pixels, which is RGBA 32 bits. This means that a pixel /// pixels, which is RGBA 32 bits. This means that a pixel
@ -497,8 +283,8 @@ private :
/// channels -- just like a sf::Color. /// channels -- just like a sf::Color.
/// All the functions that return an array of pixels follow /// All the functions that return an array of pixels follow
/// this rule, and all parameters that you pass to sf::Image /// this rule, and all parameters that you pass to sf::Image
/// functions (such as LoadFromPixels or UpdatePixels) must /// functions (such as LoadFromPixels) must use this
/// use this representation as well. /// representation as well.
/// ///
/// A sf::Image can be copied, but it is a heavy resource and /// A sf::Image can be copied, but it is a heavy resource and
/// if possible you should always use [const] references to /// if possible you should always use [const] references to
@ -506,7 +292,7 @@ private :
/// ///
/// Usage example: /// Usage example:
/// \code /// \code
/// // Load an image file /// // Load an image file from a file
/// sf::Image background; /// sf::Image background;
/// if (!background.LoadFromFile("background.jpg")) /// if (!background.LoadFromFile("background.jpg"))
/// return -1; /// return -1;
@ -529,6 +315,6 @@ private :
/// return -1; /// return -1;
/// \endcode /// \endcode
/// ///
/// \see sf::Sprite /// \see sf::Texture
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

View File

@ -41,7 +41,7 @@ class Drawable;
class Shader; class Shader;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Base class for all render targets (window, image, ...) /// \brief Base class for all render targets (window, texture, ...)
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
class SFML_API RenderTarget : NonCopyable class SFML_API RenderTarget : NonCopyable
@ -331,6 +331,6 @@ private :
/// OpenGL states are not messed up by calling the SaveGLStates / /// OpenGL states are not messed up by calling the SaveGLStates /
/// RestoreGLStates functions. /// RestoreGLStates functions.
/// ///
/// \see sf::RenderWindow, sf::RenderImage, sf::View /// \see sf::RenderWindow, sf::RenderTexture, sf::View
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

View File

@ -22,13 +22,13 @@
// //
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#ifndef SFML_RENDERIMAGE_HPP #ifndef SFML_RENDERTEXTURE_HPP
#define SFML_RENDERIMAGE_HPP #define SFML_RENDERTEXTURE_HPP
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Graphics/Image.hpp> #include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/RenderTarget.hpp> #include <SFML/Graphics/RenderTarget.hpp>
@ -36,48 +36,48 @@ namespace sf
{ {
namespace priv namespace priv
{ {
class RenderImageImpl; class RenderTextureImpl;
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Target for off-screen 2D rendering into an image /// \brief Target for off-screen 2D rendering into an texture
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
class SFML_API RenderImage : public RenderTarget class SFML_API RenderTexture : public RenderTarget
{ {
public : public :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Default constructor /// \brief Default constructor
/// ///
/// Constructs an empty, invalid render-image. You must /// Constructs an empty, invalid render-texture. You must
/// call Create to have a valid render-image. /// call Create to have a valid render-texture.
/// ///
/// \see Create /// \see Create
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
RenderImage(); RenderTexture();
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Destructor /// \brief Destructor
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
virtual ~RenderImage(); virtual ~RenderTexture();
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Create the render-image /// \brief Create the render-texture
/// ///
/// Before calling this function, the render-image is in /// Before calling this function, the render-texture is in
/// an invalid state, thus it is mandatory to call it before /// an invalid state, thus it is mandatory to call it before
/// doing anything with the render-image. /// doing anything with the render-texture.
/// The last parameter, \a depthBuffer, is useful if you want /// The last parameter, \a depthBuffer, is useful if you want
/// to use the render-image for 3D OpenGL rendering that requires /// to use the render-texture for 3D OpenGL rendering that requires
/// a depth-buffer. Otherwise it is unnecessary, and you should /// a depth-buffer. Otherwise it is unnecessary, and you should
/// leave this parameter to false (which is its default value). /// leave this parameter to false (which is its default value).
/// ///
/// \param width Width of the render-image /// \param width Width of the render-texture
/// \param height Height of the render-image /// \param height Height of the render-texture
/// \param depthBuffer Do you want this render-image to have a depth buffer? /// \param depthBuffer Do you want this render-texture to have a depth buffer?
/// ///
/// \return True if creation has been successful /// \return True if creation has been successful
/// ///
@ -85,9 +85,9 @@ public :
bool Create(unsigned int width, unsigned int height, bool depthBuffer = false); bool Create(unsigned int width, unsigned int height, bool depthBuffer = false);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Enable or disable image smoothing /// \brief Enable or disable texture smoothing
/// ///
/// This function is similar to Image::SetSmooth. /// This function is similar to Texture::SetSmooth.
/// This parameter is enabled by default. /// This parameter is enabled by default.
/// ///
/// \param smooth True to enable smoothing, false to disable it /// \param smooth True to enable smoothing, false to disable it
@ -100,7 +100,7 @@ public :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Tell whether the smooth filtering is enabled or not /// \brief Tell whether the smooth filtering is enabled or not
/// ///
/// \return True if image smoothing is enabled /// \return True if texture smoothing is enabled
/// ///
/// \see SetSmooth /// \see SetSmooth
/// ///
@ -108,12 +108,12 @@ public :
bool IsSmooth() const; bool IsSmooth() const;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Activate of deactivate the render-image for rendering /// \brief Activate of deactivate the render-texture for rendering
/// ///
/// This function makes the render-image's context current for /// This function makes the render-texture's context current for
/// future OpenGL rendering operations (so you shouldn't care /// future OpenGL rendering operations (so you shouldn't care
/// about it if you're not doing direct OpenGL stuff). /// about it if you're not doing direct OpenGL stuff).
/// Only one context can be current on a thread, so if you /// Only one context can be current in a thread, so if you
/// want to draw OpenGL geometry to another render target /// want to draw OpenGL geometry to another render target
/// (like a RenderWindow) don't forget to activate it again. /// (like a RenderWindow) don't forget to activate it again.
/// ///
@ -125,18 +125,18 @@ public :
bool SetActive(bool active = true); bool SetActive(bool active = true);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Update the contents of the target image /// \brief Update the contents of the target texture
/// ///
/// This function updates the target image with what /// This function updates the target texture with what
/// has been drawn so far. Like for windows, calling this /// has been drawn so far. Like for windows, calling this
/// function is mandatory at the end of rendering. Not calling /// function is mandatory at the end of rendering. Not calling
/// it may leave the image in an undefined state. /// it may leave the texture in an undefined state.
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void Display(); void Display();
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Return the width of the rendering region of the image /// \brief Return the width of the rendering region of the texture
/// ///
/// The returned value is the size that you passed to /// The returned value is the size that you passed to
/// the Create function. /// the Create function.
@ -149,7 +149,7 @@ public :
virtual unsigned int GetWidth() const; virtual unsigned int GetWidth() const;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Return the height of the rendering region of the image /// \brief Return the height of the rendering region of the texture
/// ///
/// The returned value is the size that you passed to /// The returned value is the size that you passed to
/// the Create function. /// the Create function.
@ -162,25 +162,25 @@ public :
virtual unsigned int GetHeight() const; virtual unsigned int GetHeight() const;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Get a read-only reference to the target image /// \brief Get a read-only reference to the target texture
/// ///
/// After drawing to the render-image and calling Display, /// After drawing to the render-texture and calling Display,
/// you can retrieve the updated image using this function, /// you can retrieve the updated texture using this function,
/// and draw it using a sprite (for example). /// and draw it using a sprite (for example).
/// The internal sf::Image of a render-image is always the /// The internal sf::Texture of a render-texture is always the
/// same instance, so that it is possible to call this function /// same instance, so that it is possible to call this function
/// once and keep a reference to the image even after is it /// once and keep a reference to the texture even after it is
/// modified. /// modified.
/// ///
/// \return Const reference to the image /// \return Const reference to the texture
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
const Image& GetImage() const; const Texture& GetTexture() const;
private : private :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Activate the targt efor rendering /// \brief Activate the target for rendering
/// ///
/// This function is called by the base class /// This function is called by the base class
/// everytime it's going to use OpenGL calls. /// everytime it's going to use OpenGL calls.
@ -195,28 +195,28 @@ private :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Member data // Member data
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Image myImage; ///< Target image to draw on Texture myTexture; ///< Target texture to draw on
priv::RenderImageImpl* myRenderImage; ///< Platform / hardware specific implementation priv::RenderTextureImpl* myRenderTexture; ///< Platform/hardware specific implementation
}; };
} // namespace sf } // namespace sf
#endif // SFML_RENDERIMAGE_HPP #endif // SFML_RENDERTEXTURE_HPP
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \class sf::RenderImage /// \class sf::RenderTexture
/// \ingroup graphics /// \ingroup graphics
/// ///
/// sf::RenderImage is the little brother of sf::RenderWindow. /// sf::RenderTexture is the little brother of sf::RenderWindow.
/// It implements the same 2D drawing and OpenGL-related functions /// It implements the same 2D drawing and OpenGL-related functions
/// (see their base class sf::RenderTarget for more details), /// (see their base class sf::RenderTarget for more details),
/// the difference is that the result is stored in an off-screen /// the difference is that the result is stored in an off-screen
/// image rather than being show in a window. /// texture rather than being show in a window.
/// ///
/// Rendering to an image can be useful in a variety of situations: /// Rendering to a texture can be useful in a variety of situations:
/// \li precomputing a complex static image (like a level's background from multiple tiles) /// \li precomputing a complex static texture (like a level's background from multiple tiles)
/// \li applying post-effects to the whole scene with shaders /// \li applying post-effects to the whole scene with shaders
/// \li creating a sprite from a 3D object rendered with OpenGL /// \li creating a sprite from a 3D object rendered with OpenGL
/// \li etc. /// \li etc.
@ -224,16 +224,12 @@ private :
/// Usage example: /// Usage example:
/// ///
/// \code /// \code
/// // First of all: make sure that rendering to image is supported
/// if (!sf::RenderImage::IsAvailable())
/// return -1;
///
/// // Create a new render-window /// // Create a new render-window
/// sf::RenderWindow window(sf::VideoMode(800, 600), "SFML window"); /// sf::RenderWindow window(sf::VideoMode(800, 600), "SFML window");
/// ///
/// // Create a new render-image /// // Create a new render-texture
/// sf::RenderImage image; /// sf::RenderTexture texture;
/// if (!image.Create(500, 500)) /// if (!texture.Create(500, 500))
/// return -1 /// return -1
/// ///
/// // The main loop /// // The main loop
@ -242,22 +238,22 @@ private :
/// // Event processing /// // Event processing
/// // ... /// // ...
/// ///
/// // Clear the whole image with red color /// // Clear the whole texture with red color
/// image.Clear(sf::Color::Red); /// texture.Clear(sf::Color::Red);
/// ///
/// // Draw stuff to the image /// // Draw stuff to the texture
/// image.Draw(sprite); // sprite is a sf::Sprite /// texture.Draw(sprite); // sprite is a sf::Sprite
/// image.Draw(shape); // shape is a sf::Shape /// texture.Draw(shape); // shape is a sf::Shape
/// image.Draw(text); // text is a sf::Text /// texture.Draw(text); // text is a sf::Text
/// ///
/// // We're done drawing to the image /// // We're done drawing to the texture
/// image.Display(); /// texture.Display();
/// ///
/// // Now we start rendering to the window, clear it first /// // Now we start rendering to the window, clear it first
/// window.Clear(); /// window.Clear();
/// ///
/// // Draw the image /// // Draw the texture
/// sf::Sprite sprite(image.GetImage()); /// sf::Sprite sprite(texture.GetTexture());
/// window.Draw(sprite); /// window.Draw(sprite);
/// ///
/// // End the current frame and display its contents on screen /// // End the current frame and display its contents on screen
@ -265,11 +261,11 @@ private :
/// } /// }
/// \endcode /// \endcode
/// ///
/// Like sf::RenderWindow, sf::RenderImage is still able to render direct /// Like sf::RenderWindow, sf::RenderTexture is still able to render direct
/// OpenGL stuff. It is even possible to mix together OpenGL calls /// OpenGL stuff. It is even possible to mix together OpenGL calls
/// and regular SFML drawing commands. If you need a depth buffer for /// and regular SFML drawing commands. If you need a depth buffer for
/// 3D rendering, don't forget to request it when calling RenderImage::Create. /// 3D rendering, don't forget to request it when calling RenderTexture::Create.
/// ///
/// \see sf::RenderTarget, sf::RenderWindow, sf::View /// \see sf::RenderTarget, sf::RenderWindow, sf::View, sf::Texture
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

View File

@ -28,8 +28,8 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Graphics/Image.hpp>
#include <SFML/Graphics/RenderTarget.hpp> #include <SFML/Graphics/RenderTarget.hpp>
#include <SFML/Graphics/Image.hpp>
#include <SFML/Window/Window.hpp> #include <SFML/Window/Window.hpp>
#include <string> #include <string>
@ -125,6 +125,22 @@ public :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
virtual unsigned int GetHeight() const; virtual unsigned int GetHeight() const;
////////////////////////////////////////////////////////////
/// \brief Copy the current contents of the window to an image
///
/// This is a slow operation, whose main purpose is to make
/// screenshots of the application. If you want to update an
/// image with the contents of the window and then use it for
/// drawing, you should rather use a sf::Texture and its
/// Update(Window&) function.
/// You can also draw things directly to a texture with the
/// sf::RenderTexture class.
///
/// \return Image containing the captured contents
///
////////////////////////////////////////////////////////////
Image Capture() const;
private : private :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -260,6 +276,6 @@ private :
/// } /// }
/// \endcode /// \endcode
/// ///
/// \see sf::Window, sf::RenderTarget, sf::RenderImage, sf::View /// \see sf::Window, sf::RenderTarget, sf::RenderTexture, sf::View
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

View File

@ -38,8 +38,8 @@
namespace sf namespace sf
{ {
class Image;
class Shader; class Shader;
class Texture;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Handles the low-level rendering (states and geometry) /// \brief Handles the low-level rendering (states and geometry)
@ -120,9 +120,6 @@ public :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Set a new model-view matrix /// \brief Set a new model-view matrix
/// ///
/// Note: any call to this function after a call to BeginBatch
/// will be ignored, and delayed until BeginBatch is called again.
///
/// \param matrix New model-view matrix /// \param matrix New model-view matrix
/// ///
/// \see ApplyModelView /// \see ApplyModelView
@ -133,9 +130,6 @@ public :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Combine a new model-view matrix with the current one /// \brief Combine a new model-view matrix with the current one
/// ///
/// Note: any call to this function after a call to BeginBatch
/// will be ignored, and delayed until BeginBatch is called again.
///
/// \param matrix Model-view matrix to combine /// \param matrix Model-view matrix to combine
/// ///
/// \see SetModelView /// \see SetModelView
@ -146,9 +140,6 @@ public :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Set a new projection matrix /// \brief Set a new projection matrix
/// ///
/// Note: any call to this function after a call to BeginBatch
/// will be ignored, and delayed until BeginBatch is called again.
///
/// \param matrix New projection matrix /// \param matrix New projection matrix
/// ///
/// \see ApplyProjection /// \see ApplyProjection
@ -160,8 +151,6 @@ public :
/// \brief Set the current global color /// \brief Set the current global color
/// ///
/// This color will be modulated with each vertex's color. /// This color will be modulated with each vertex's color.
/// Note: any call to this function after a call to BeginBatch
/// will be ignored, and delayed until BeginBatch is called again.
/// ///
/// \param color New global color /// \param color New global color
/// ///
@ -174,8 +163,6 @@ public :
/// \brief Modulate the current global color with a new one /// \brief Modulate the current global color with a new one
/// ///
/// This color will be modulated with each vertex's color. /// This color will be modulated with each vertex's color.
/// Note: any call to this function after a call to BeginBatch
/// will be ignored, and delayed until BeginBatch is called again.
/// ///
/// \param color Color to modulate /// \param color Color to modulate
/// ///
@ -187,9 +174,6 @@ public :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Set the current viewport /// \brief Set the current viewport
/// ///
/// Note: any call to this function after a call to BeginBatch
/// will be ignored, and delayed until BeginBatch is called again.
///
/// \param viewport New viewport to apply /// \param viewport New viewport to apply
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -198,9 +182,6 @@ public :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Set the current alpha-blending mode /// \brief Set the current alpha-blending mode
/// ///
/// Note: any call to this function after a call to BeginBatch
/// will be ignored, and delayed until BeginBatch is called again.
///
/// \param mode New blending mode /// \param mode New blending mode
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -209,20 +190,14 @@ public :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Set the current texture /// \brief Set the current texture
/// ///
/// Note: any call to this function after a call to BeginBatch
/// will be ignored, and delayed until BeginBatch is called again.
///
/// \param texture New texture /// \param texture New texture
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void SetTexture(const Image* texture); void SetTexture(const Texture* texture);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Set the current shader /// \brief Set the current shader
/// ///
/// Note: any call to this function after a call to BeginBatch
/// will be ignored, and delayed until BeginBatch is called again.
///
/// \param shader New Shader /// \param shader New Shader
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -349,8 +324,8 @@ private :
RenderTarget& myTarget; ///< Reference to the render target owning this renderer RenderTarget& myTarget; ///< Reference to the render target owning this renderer
States myStatesStack[64]; ///< Stack of render states States myStatesStack[64]; ///< Stack of render states
States* myStates; ///< Current set of render states States* myStates; ///< Current set of render states
const Image* myTexture; ///< Current texture const Texture* myTexture; ///< Current texture
unsigned int myTextureId; ///< Current texture identifier (the sf::Image instance may be the same, but not the internal OpenGL texture) unsigned int myTextureId; ///< Current texture identifier (the sf::Texture instance may be the same, but not the internal OpenGL texture)
const Shader* myShader; ///< Current pixel shader const Shader* myShader; ///< Current pixel shader
Blend::Mode myBlendMode; ///< Current blending mode Blend::Mode myBlendMode; ///< Current blending mode
IntRect myViewport; ///< Current target viewport IntRect myViewport; ///< Current target viewport

View File

@ -29,7 +29,7 @@
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Config.hpp> #include <SFML/Config.hpp>
#include <SFML/Graphics/Image.hpp> #include <SFML/Graphics/Texture.hpp>
#include <SFML/Window/GlResource.hpp> #include <SFML/Window/GlResource.hpp>
#include <SFML/System/Vector2.hpp> #include <SFML/System/Vector2.hpp>
#include <SFML/System/Vector3.hpp> #include <SFML/System/Vector3.hpp>
@ -253,35 +253,35 @@ public :
/// \brief Change a texture parameter of the shader /// \brief Change a texture parameter of the shader
/// ///
/// \a name is the name of the texture to change in the shader. /// \a name is the name of the texture to change in the shader.
/// This function maps an external image to the texture variable; /// This function maps an external texture to the given shader
/// to use the current texture of the object being drawn, use /// variable; to use the current texture of the object being drawn,
/// SetCurrentTexture instead. /// use SetCurrentTexture instead.
/// Example: /// Example:
/// \code /// \code
/// // These are the variables in the pixel shader /// // These are the variables in the pixel shader
/// uniform sampler2D texture; /// uniform sampler2D the_texture;
/// \endcode /// \endcode
/// \code /// \code
/// sf::Image image; /// sf::Texture texture;
/// ... /// ...
/// shader.SetTexture("texture", image); /// shader.SetTexture("the_texture", texture);
/// \endcode /// \endcode
/// It is important to note that \a texture must remain alive as long /// It is important to note that \a texture must remain alive as long
/// as the shader uses it, no copy is made internally. /// as the shader uses it, no copy is made internally.
/// ///
/// \param name Name of the texture in the shader /// \param name Name of the texture in the shader
/// \param texture Image to assign /// \param texture Texture to assign
/// ///
/// \see SetParameter, SetCurrentTexture /// \see SetParameter, SetCurrentTexture
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void SetTexture(const std::string& name, const Image& texture); void SetTexture(const std::string& name, const Texture& texture);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Set the current object texture in the shader /// \brief Set the current object texture in the shader
/// ///
/// This function maps a shader texture variable to the /// This function maps a shader texture variable to the
/// image of the object being drawn. /// texture of the object being drawn.
/// Example: /// Example:
/// \code /// \code
/// // This is the variable in the pixel shader /// // This is the variable in the pixel shader
@ -384,7 +384,7 @@ private :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Types // Types
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
typedef std::map<int, const Image*> TextureTable; typedef std::map<int, const Texture*> TextureTable;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Member data // Member data
@ -427,7 +427,7 @@ private :
/// \code /// \code
/// shader.SetParameter("offset", 2.f); /// shader.SetParameter("offset", 2.f);
/// shader.SetParameter("color", 0.5f, 0.8f, 0.3f); /// shader.SetParameter("color", 0.5f, 0.8f, 0.3f);
/// shader.SetTexture("overlay", image); // image is a sf::Image /// shader.SetTexture("overlay", texture); // texture is a sf::Texture
/// shader.SetCurrentTexture("texture"); /// shader.SetCurrentTexture("texture");
/// \endcode /// \endcode
/// ///
@ -442,8 +442,8 @@ private :
/// ///
/// Shaders can be used on any drawable, but they are mainly /// Shaders can be used on any drawable, but they are mainly
/// made for sf::Sprite. Using a shader on a sf::String is more /// made for sf::Sprite. Using a shader on a sf::String is more
/// limited, because the texture of the string is not the /// limited, because the texture of the text is not the
/// actual text that you see on screen, it is a big image /// actual text that you see on screen, it is a big texture
/// containing all the characters of the font in an arbitrary /// containing all the characters of the font in an arbitrary
/// order. Thus, texture lookups on pixels other than the current /// order. Thus, texture lookups on pixels other than the current
/// one may not give you the expected result. Using a shader /// one may not give you the expected result. Using a shader
@ -453,18 +453,18 @@ private :
/// Shaders can also be used to apply global post-effects to the /// Shaders can also be used to apply global post-effects to the
/// current contents of the target (like the old sf::PostFx class /// current contents of the target (like the old sf::PostFx class
/// in SFML 1). This can be done in two different ways: /// in SFML 1). This can be done in two different ways:
/// \li draw everything to a sf::RenderImage, then draw it to /// \li draw everything to a sf::RenderTexture, then draw it to
/// the main target using the shader /// the main target using the shader
/// \li draw everything directly to the main target, then use /// \li draw everything directly to the main target, then use
/// sf::Image::CopyScreen to copy its contents to an image and /// sf::Texture::Update(Window&) to copy its contents to a texture
/// draw it to the main target using the shader /// and draw it to the main target using the shader
/// ///
/// The first technique is more optimized because it doesn't involve /// The first technique is more optimized because it doesn't involve
/// retrieving the target's pixels to system memory, but the /// retrieving the target's pixels to system memory, but the
/// second one doesn't impact the rendering process and can be /// second one doesn't impact the rendering process and can be
/// easily inserted anywhere. /// easily inserted anywhere.
/// ///
/// Like sf::Image that can be used as a raw OpenGL texture, /// Like sf::Texture that can be used as a raw OpenGL texture,
/// sf::Shader can also be used directly as a raw fragment /// sf::Shader can also be used directly as a raw fragment
/// shader for custom OpenGL geometry. /// shader for custom OpenGL geometry.
/// \code /// \code

View File

@ -534,6 +534,6 @@ private :
/// window.Draw(sf::Shape::Circle(500, 500, 20, sf::Color::Blue, 5, sf::Color::Black)); /// window.Draw(sf::Shape::Circle(500, 500, 20, sf::Color::Blue, 5, sf::Color::Black));
/// \endcode /// \endcode
/// ///
/// \see sf::Image /// \see sf::Sprite
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

View File

@ -35,10 +35,10 @@
namespace sf namespace sf
{ {
class Image; class Texture;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Drawable representation of an image, with its /// \brief Drawable representation of a texture, with its
/// own transformations, color, blend mode, etc. /// own transformations, color, blend mode, etc.
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -49,56 +49,50 @@ public :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Default constructor /// \brief Default constructor
/// ///
/// Creates an empty sprite with no source image. /// Creates an empty sprite with no source texture.
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Sprite(); Sprite();
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Construct the sprite from a source image /// \brief Construct the sprite from a source texture
/// ///
/// \param image Source image, that the sprite will display /// \see SetTexture
/// \param position Position of the sprite in the scene
/// \param scale Scale factor of the sprite
/// \param rotation Rotation angle, in degrees
/// \param color Global color of the sprite
///
/// \see SetImage
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
explicit Sprite(const Image& image, const Vector2f& position = Vector2f(0, 0), const Vector2f& scale = Vector2f(1, 1), float rotation = 0.f, const Color& color = Color(255, 255, 255, 255)); explicit Sprite(const Texture& texture);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Change the source image of the sprite /// \brief Change the source texture of the sprite
/// ///
/// The \a image argument refers to an image that must /// The \a texture argument refers to a texture that must
/// exist as long as the sprite uses it. Indeed, the sprite /// exist as long as the sprite uses it. Indeed, the sprite
/// doesn't store its own copy of the image, but rather keeps /// doesn't store its own copy of the texture, but rather keeps
/// a pointer to the one that you passed to this function. /// a pointer to the one that you passed to this function.
/// If the source image is destroyed and the sprite tries to /// If the source texture is destroyed and the sprite tries to
/// use it, it may appear as a white rectangle. /// use it, it may appear as a white rectangle.
/// If \a adjustToNewSize is true, the SubRect property of /// If \a adjustToNewSize is true, the SubRect property of
/// the sprite is adjusted to the size of the new image. If /// the sprite is adjusted to the size of the new texture. If
/// it is false, the SubRect is unchanged. /// it is false, the SubRect is unchanged.
/// ///
/// \param image New image /// \param texture New texture
/// \param adjustToNewSize Should the sub-rect be adjusted to the size of the new image? /// \param adjustToNewSize Should the sub-rect be adjusted to the size of the new texture?
/// ///
/// \see GetImage, SetSubRect /// \see GetTexture, SetSubRect
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void SetImage(const Image& image, bool adjustToNewSize = false); void SetTexture(const Texture& texture, bool adjustToNewSize = false);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Set the part of the image that the sprite will display /// \brief Set the part of the texture that the sprite will display
/// ///
/// The sub-rectangle is useful when you don't want to display /// The sub-rectangle is useful when you don't want to display
/// the whole image, but rather a part of it. /// the whole texture, but rather a part of it.
/// By default, the sub-rectangle covers the entire image. /// By default, the sub-rectangle covers the entire texture.
/// ///
/// \param rectangle Rectangle defining the region of the image to display /// \param rectangle Rectangle defining the region of the texture to display
/// ///
/// \see GetSubRect, SetImage /// \see GetSubRect, SetTexture
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void SetSubRect(const IntRect& rectangle); void SetSubRect(const IntRect& rectangle);
@ -157,24 +151,24 @@ public :
void FlipY(bool flipped); void FlipY(bool flipped);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Get the source image of the sprite /// \brief Get the source texture of the sprite
/// ///
/// If the sprite has no source image, or if the image /// If the sprite has no source texture, or if the texture
/// doesn't exist anymore, a NULL pointer is returned. /// doesn't exist anymore, a NULL pointer is returned.
/// The returned pointer is const, which means that you can't /// The returned pointer is const, which means that you can't
/// modify the image when you retrieve it with this function. /// modify the texture when you retrieve it with this function.
/// ///
/// \return Pointer to the sprite's image /// \return Pointer to the sprite's texture
/// ///
/// \see SetImage /// \see SetTexture
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
const Image* GetImage() const; const Texture* GetTexture() const;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Get the region of the image displayed by the sprite /// \brief Get the region of the texture displayed by the sprite
/// ///
/// \return Rectangle defining the region of the image /// \return Rectangle defining the region of the texture
/// ///
/// \see SetSubRect /// \see SetSubRect
/// ///
@ -194,25 +188,6 @@ public :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Vector2f GetSize() const; Vector2f GetSize() const;
////////////////////////////////////////////////////////////
/// \brief Get the color of a given pixel in the sprite
///
/// This function returns the source image pixel, multiplied
/// by the global color of the sprite.
/// The input point must be in local coordinates. If you have
/// a global point, you can use the TransformToLocal function
/// to make it local.
/// This function doesn't perform any check, you must ensure that
/// the \a x and \a y coordinates are not out of bounds.
///
/// \param x X coordinate of the pixel to get
/// \param y Y coordinate of the pixel to get
///
/// \return Color of the pixel
///
////////////////////////////////////////////////////////////
Color GetPixel(unsigned int x, unsigned int y) const;
protected : protected :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -229,8 +204,8 @@ private :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Member data // Member data
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
ResourcePtr<Image> myImage; ///< Image used to draw the sprite ResourcePtr<Texture> myTexture; ///< Texture used to draw the sprite
IntRect mySubRect; ///< Sub-rectangle of source image to assign to the sprite IntRect mySubRect; ///< Sub-rectangle of source texture to assign to the sprite
bool myIsFlippedX; ///< Is the sprite flipped on the X axis ? bool myIsFlippedX; ///< Is the sprite flipped on the X axis ?
bool myIsFlippedY; ///< Is the sprite flipped on the Y axis ? bool myIsFlippedY; ///< Is the sprite flipped on the Y axis ?
}; };
@ -246,39 +221,39 @@ private :
/// \ingroup graphics /// \ingroup graphics
/// ///
/// sf::Sprite is a drawable class that allows to easily display /// sf::Sprite is a drawable class that allows to easily display
/// an image (or a part of it) on a render target. /// a texture (or a part of it) on a render target.
/// ///
/// It inherits all the functions from sf::Drawable: /// It inherits all the functions from sf::Drawable:
/// position, rotation, scale, origin, global color and blend /// position, rotation, scale, origin, global color and blend
/// mode. It also adds sprite-specific properties such as the /// mode. It also adds sprite-specific properties such as the
/// image to use, the part of it to display, and some convenience /// texture to use, the part of it to display, and some convenience
/// functions to flip or resize the sprite. /// functions to flip or resize the sprite.
/// ///
/// sf::Sprite works in combination with the sf::Image class, which /// sf::Sprite works in combination with the sf::Texture class, which
/// loads and provides the pixel data of a given image. /// loads and provides the pixel data of a given texture.
/// ///
/// The separation of sf::Sprite and sf::Image allows more flexibility /// The separation of sf::Sprite and sf::Texture allows more flexibility
/// and better performances: indeed a sf::Image is a heavy resource, /// and better performances: indeed a sf::Texture is a heavy resource,
/// and any operation on it is slow (often too slow for real-time /// and any operation on it is slow (often too slow for real-time
/// applications). On the other side, a sf::Sprite is a lightweight /// applications). On the other side, a sf::Sprite is a lightweight
/// object which can use the pixel data of a sf::Image and draw /// object which can use the pixel data of a sf::Texture and draw
/// it with its own transformation / color / blending attributes. /// it with its own transformation / color / blending attributes.
/// ///
/// It is important to note that the sf::Sprite instance doesn't /// It is important to note that the sf::Sprite instance doesn't
/// copy the image that it uses, it only keeps a reference to it. /// copy the texture that it uses, it only keeps a reference to it.
/// Thus, a sf::Image must not be destructed while it is /// Thus, a sf::Texture must not be destructed while it is
/// used by a sf::Sprite (i.e. never write a function that /// used by a sf::Sprite (i.e. never write a function that
/// uses a local sf::Image instance for creating a sprite). /// uses a local sf::Texture instance for creating a sprite).
/// ///
/// Usage example: /// Usage example:
/// \code /// \code
/// // Declare and load an image /// // Declare and load a texture
/// sf::Image image; /// sf::Texture texture;
/// image.LoadFromFile("image.png"); /// texture.LoadFromFile("texture.png");
/// ///
/// // Create a sprite /// // Create a sprite
/// sf::Sprite sprite; /// sf::Sprite sprite;
/// sprite.SetImage(image); /// sprite.SetTexture(texture);
/// sprite.SetSubRect(sf::IntRect(10, 10, 50, 30)); /// sprite.SetSubRect(sf::IntRect(10, 10, 50, 30));
/// sprite.Resize(100, 60); /// sprite.Resize(100, 60);
/// ///
@ -286,6 +261,6 @@ private :
/// window.Draw(sprite); // window is a sf::RenderWindow /// window.Draw(sprite); // window is a sf::RenderWindow
/// \endcode /// \endcode
/// ///
/// \see sf::Image /// \see sf::Texture
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

View File

@ -0,0 +1,551 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#ifndef SFML_TEXTURE_HPP
#define SFML_TEXTURE_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/Resource.hpp>
#include <SFML/Window/GlResource.hpp>
#include <SFML/Graphics/Image.hpp>
namespace sf
{
class Window;
class Renderer;
class RenderTexture;
class InputStream;
////////////////////////////////////////////////////////////
/// \brief Image living on the graphics card that can be used for drawing
///
////////////////////////////////////////////////////////////
class SFML_API Texture : public Resource<Texture>, GlResource
{
public :
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// Creates an empty texture.
///
////////////////////////////////////////////////////////////
Texture();
////////////////////////////////////////////////////////////
/// \brief Copy constructor
///
/// \param copy instance to copy
///
////////////////////////////////////////////////////////////
Texture(const Texture& copy);
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
~Texture();
////////////////////////////////////////////////////////////
/// \brief Create the texture
///
/// If this function fails, the texture is left unchanged.
///
/// \param width Width of the texture
/// \param height Height of the texture
///
/// \return True if creation was successful
///
////////////////////////////////////////////////////////////
bool Create(unsigned int width, unsigned int height);
////////////////////////////////////////////////////////////
/// \brief Load the texture from a file on disk
///
/// This function is a shortcut for the following code:
/// \code
/// sf::Image image;
/// image.LoadFromFile(filename);
/// texture.LoadFromImage(image, area);
/// \endcode
///
/// The \a area argument can be used to load only a sub-rectangle
/// of the whole image. If you want the entire image then leave
/// the default value (which is an empty IntRect).
/// If the \a area rectangle crosses the bounds of the image, it
/// is adjusted to fit the image size.
///
/// The maximum size for a texture depends on the graphics
/// driver and can be retrieved with the GetMaximumSize function.
///
/// If this function fails, the texture is left unchanged.
///
/// \param filename Path of the image file to load
/// \param area Area of the image to load
///
/// \return True if loading was successful
///
/// \see LoadFromMemory, LoadFromStream, LoadFromImage
///
////////////////////////////////////////////////////////////
bool LoadFromFile(const std::string& filename, const IntRect& area = IntRect());
////////////////////////////////////////////////////////////
/// \brief Load the texture from a file in memory
///
/// This function is a shortcut for the following code:
/// \code
/// sf::Image image;
/// image.LoadFromMemory(data, size);
/// texture.LoadFromImage(image, area);
/// \endcode
///
/// The \a area argument can be used to load only a sub-rectangle
/// of the whole image. If you want the entire image then leave
/// the default value (which is an empty IntRect).
/// If the \a area rectangle crosses the bounds of the image, it
/// is adjusted to fit the image size.
///
/// The maximum size for a texture depends on the graphics
/// driver and can be retrieved with the GetMaximumSize function.
///
/// If this function fails, the texture is left unchanged.
///
/// \param data Pointer to the file data in memory
/// \param size Size of the data to load, in bytes
/// \param area Area of the image to load
///
/// \return True if loading was successful
///
/// \see LoadFromFile, LoadFromStream, LoadFromImage
///
////////////////////////////////////////////////////////////
bool LoadFromMemory(const void* data, std::size_t size, const IntRect& area = IntRect());
////////////////////////////////////////////////////////////
/// \brief Load the texture from a file in memory
///
/// This function is a shortcut for the following code:
/// \code
/// sf::Image image;
/// image.LoadFromStream(stream);
/// texture.LoadFromImage(image, area);
/// \endcode
///
/// The \a area argument can be used to load only a sub-rectangle
/// of the whole image. If you want the entire image then leave
/// the default value (which is an empty IntRect).
/// If the \a area rectangle crosses the bounds of the image, it
/// is adjusted to fit the image size.
///
/// The maximum size for a texture depends on the graphics
/// driver and can be retrieved with the GetMaximumSize function.
///
/// If this function fails, the texture is left unchanged.
///
/// \param stream Source stream to read from
/// \param area Area of the image to load
///
/// \return True if loading was successful
///
/// \see LoadFromFile, LoadFromMemory, LoadFromImage
///
////////////////////////////////////////////////////////////
bool LoadFromStream(sf::InputStream& stream, const IntRect& area = IntRect());
////////////////////////////////////////////////////////////
/// \brief Load the texture from an image
///
/// The \a area argument can be used to load only a sub-rectangle
/// of the whole image. If you want the entire image then leave
/// the default value (which is an empty IntRect).
/// If the \a area rectangle crosses the bounds of the image, it
/// is adjusted to fit the image size.
///
/// The maximum size for a texture depends on the graphics
/// driver and can be retrieved with the GetMaximumSize function.
///
/// If this function fails, the texture is left unchanged.
///
/// \param image Image to load into the texture
/// \param area Area of the image to load
///
/// \return True if loading was successful
///
/// \see LoadFromFile, LoadFromMemory
///
////////////////////////////////////////////////////////////
bool LoadFromImage(const Image& image, const IntRect& area = IntRect());
////////////////////////////////////////////////////////////
/// \brief Return the width of the texture
///
/// \return Width in pixels
///
/// \see GetHeight
///
////////////////////////////////////////////////////////////
unsigned int GetWidth() const;
////////////////////////////////////////////////////////////
/// \brief Return the height of the texture
///
/// \return Height in pixels
///
/// \see GetWidth
///
////////////////////////////////////////////////////////////
unsigned int GetHeight() const;
////////////////////////////////////////////////////////////
/// \brief Copy the texture pixels to an image
///
/// This function performs a slow operation that downloads
/// the texture's pixels from the graphics card and copies
/// them to a new image, potentially applying transformations
/// to pixels if necessary (texture may be padded or flipped).
///
/// \return Image containing the texture's pixels
///
/// \see LoadFromImage
///
////////////////////////////////////////////////////////////
Image CopyToImage() const;
////////////////////////////////////////////////////////////
/// \brief Update the whole texture from an array of pixels
///
/// The \a pixels array is assumed to have the same size as
/// the \a area rectangle, and to contain 32-bits RGBA pixels.
///
/// No additional check is performed on the size of the pixel
/// array, passing invalid arguments will lead to an undefined
/// behaviour.
///
/// This function does nothing if \a pixels is null or if the
/// texture was not previously created.
///
/// \param pixels Array of pixels to copy to the texture
///
////////////////////////////////////////////////////////////
void Update(const Uint8* pixels);
////////////////////////////////////////////////////////////
/// \brief Update a part of the texture from an array of pixels
///
/// The size of the \a pixels array must match the \a width and
/// \a height arguments, and it must contain 32-bits RGBA pixels.
///
/// No additional check is performed on the size of the pixel
/// array or the bounds of the area to update, passing invalid
/// arguments will lead to an undefined behaviour.
///
/// This function does nothing if \a pixels is null or if the
/// texture was not previously created.
///
/// \param pixels Array of pixels to copy to the texture
/// \param width Width of the pixel region contained in \a pixels
/// \param height Height of the pixel region contained in \a pixels
/// \param x X offset in the texture where to copy the source pixels
/// \param y Y offset in the texture where to copy the source pixels
///
////////////////////////////////////////////////////////////
void Update(const Uint8* pixels, unsigned int width, unsigned int height, unsigned int x, unsigned int y);
////////////////////////////////////////////////////////////
/// \brief Update the texture from an image
///
/// Although the source image can be smaller than the texture,
/// this function is usually used for updating the whole texture.
/// The other overload, which has (x, y) additional arguments,
/// is more convenient for updating a sub-area of the texture.
///
/// No additional check is performed on the size of the image,
/// passing an image bigger than the texture will lead to an
/// undefined behaviour.
///
/// This function does nothing if the texture was not
/// previously created.
///
/// \param image Image to copy to the texture
///
////////////////////////////////////////////////////////////
void Update(const Image& image);
////////////////////////////////////////////////////////////
/// \brief Update a part of the texture from an image
///
/// No additional check is performed on the size of the image,
/// passing an invalid combination of image size and offset
/// will lead to an undefined behaviour.
///
/// This function does nothing if the texture was not
/// previously created.
///
/// \param image Image to copy to the texture
/// \param x X offset in the texture where to copy the source image
/// \param y Y offset in the texture where to copy the source image
///
////////////////////////////////////////////////////////////
void Update(const Image& image, unsigned int x, unsigned int y);
////////////////////////////////////////////////////////////
/// \brief Update the texture from the contents of a window
///
/// Although the source window can be smaller than the texture,
/// this function is usually used for updating the whole texture.
/// The other overload, which has (x, y) additional arguments,
/// is more convenient for updating a sub-area of the texture.
///
/// No additional check is performed on the size of the window,
/// passing a window bigger than the texture will lead to an
/// undefined behaviour.
///
/// This function does nothing if either the texture or the window
/// was not previously created.
///
/// \param window Window to copy to the texture
///
////////////////////////////////////////////////////////////
void Update(const Window& window);
////////////////////////////////////////////////////////////
/// \brief Update a part of the texture from the contents of a window
///
/// No additional check is performed on the size of the window,
/// passing an invalid combination of window size and offset
/// will lead to an undefined behaviour.
///
/// This function does nothing if either the texture or the window
/// was not previously created.
///
/// \param window Window to copy to the texture
/// \param x X offset in the texture where to copy the source window
/// \param y Y offset in the texture where to copy the source window
///
////////////////////////////////////////////////////////////
void Update(const Window& window, unsigned int x, unsigned int y);
////////////////////////////////////////////////////////////
/// \brief Activate the texture for rendering
///
/// This function is mainly used internally by the SFML
/// render system. However it can be useful when
/// using sf::Texture together with OpenGL code (this function
/// is equivalent to glBindTexture).
///
////////////////////////////////////////////////////////////
void Bind() const;
////////////////////////////////////////////////////////////
/// \brief Enable or disable the smooth filter
///
/// When the filter is activated, the texture appears smoother
/// so that pixels are less noticeable. However if you want
/// the texture to look exactly the same as its source file,
/// you should leave it disabled.
/// The smooth filter is disabled by default.
///
/// \param smooth True to enable smoothing, false to disable it
///
/// \see IsSmooth
///
////////////////////////////////////////////////////////////
void SetSmooth(bool smooth);
////////////////////////////////////////////////////////////
/// \brief Tell whether the smooth filter is enabled or not
///
/// \return True if smoothing is enabled, false if it is disabled
///
/// \see SetSmooth
///
////////////////////////////////////////////////////////////
bool IsSmooth() const;
////////////////////////////////////////////////////////////
/// \brief Convert a rectangle of pixels into texture coordinates
///
/// This function is used by code that needs to map the texture
/// to some OpenGL geometry. It converts the source rectangle,
/// expressed in pixels, to float coordinates in the range [0, 1].
///
/// \param rectangle Rectangle to convert
///
/// \return Texture coordinates corresponding to \a rectangle
///
////////////////////////////////////////////////////////////
FloatRect GetTexCoords(const IntRect& rectangle) const;
////////////////////////////////////////////////////////////
/// \brief Overload of assignment operator
///
/// \param right Instance to assign
///
/// \return Reference to self
///
////////////////////////////////////////////////////////////
Texture& operator =(const Texture& right);
////////////////////////////////////////////////////////////
/// \brief Get the maximum texture size allowed
///
/// This maximum size is defined by the graphics driver.
/// You can expect a value of 512 pixels for low-end graphics
/// card, and up to 8192 pixels or more for newer hardware.
///
/// \return Maximum size allowed for textures, in pixels
///
////////////////////////////////////////////////////////////
static unsigned int GetMaximumSize();
private :
friend class Renderer;
friend class RenderTexture;
////////////////////////////////////////////////////////////
/// \brief Get a valid image size according to hardware support
///
/// This function checks whether the graphics driver supports
/// non power of two sizes or not, and adjusts the size
/// accordingly.
/// The returned size is greater than or equal to the original size.
///
/// \param Size size to convert
///
/// \return Valid nearest size (greater than or equal to specified size)
///
////////////////////////////////////////////////////////////
static unsigned int GetValidSize(unsigned int size);
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
unsigned int myWidth; ///< Image width
unsigned int myHeight; ///< Image Height
unsigned int myTextureWidth; ///< Actual texture width (can be greater than image width because of padding)
unsigned int myTextureHeight; ///< Actual texture height (can be greater than image height because of padding)
unsigned int myTexture; ///< Internal texture identifier
bool myIsSmooth; ///< Status of the smooth filter
mutable bool myPixelsFlipped; ///< To work around the inconsistency in Y orientation
};
} // namespace sf
#endif // SFML_TEXTURE_HPP
////////////////////////////////////////////////////////////
/// \class sf::Texture
/// \ingroup graphics
///
/// sf::Texture stores pixels that can be drawn, with a sprite
/// for example. A texture lives in the graphics card memory,
/// therefore it is very fast to draw a texture to a render target,
/// or copy a render target to a texture (the graphics card can
/// access both directly).
///
/// Being stored in the graphics card memory has some drawbacks.
/// A texture cannot be manipulated as freely as a sf::Image,
/// you need to prepare the pixels first and then upload them
/// to the texture in a single operation (see Texture::Update).
///
/// sf::Texture makes it easy to convert from/to sf::Image, but
/// keep in mind that these calls require transfers between
/// the graphics card and the central memory, therefore they are
/// slow operations.
///
/// A texture can be loaded from an image, but also directly
/// from a file/memory/stream. The necessary shortcuts are defined
/// so that you don't need an image first for the most common cases.
/// However, if you want to perform some modifications on the pixels
/// before creating the final texture, you can load your file to a
/// sf::Image, do whatever you need with the pixels, and then call
/// Texture::LoadFromImage.
///
/// Since they live in the graphics card memory, the pixels of a texture
/// cannot be accessed without a slow copy first. And they cannot be
/// accessed individually. Therefore, if you need to read the texture's
/// pixels (like for pixel-perfect collisions), it is recommended to
/// store the collision information separately, for example in an array
/// of booleans.
///
/// Like sf::Image, sf::Texture can handle a unique internal
/// representation of pixels, which is RGBA 32 bits. This means
/// that a pixel must be composed of 8 bits red, green, blue and
/// alpha channels -- just like a sf::Color.
///
/// Usage example:
/// \code
/// // This example shows the most common use of sf::Texture:
/// // drawing a sprite
///
/// // Load a texture from a file
/// sf::Texture texture;
/// if (!texture.LoadFromFile("texture.png"))
/// return -1;
///
/// // Assign it to a sprite
/// sf::Sprite sprite;
/// sprite.SetTexture(texture);
///
/// // Draw the textured sprite
/// window.Draw(sprite); // window is a sf::RenderWindow
/// \endcode
///
/// \code
/// // This example shows another common use of sf::Texture:
/// // streaming real-time data, like video frames
///
/// // Create an empty texture
/// sf::Texture texture;
/// if (!texture.Create(640, 480))
/// return -1;
///
/// // Create a sprite that will display the texture
/// sf::Sprite sprite(texture);
///
/// while (...) // the main loop
/// {
/// ...
///
/// // update the texture
/// sf::Uint8* pixels = ...; // get a fresh chunk of pixels (the next frame of a movie, for example)
/// texture.Update(pixels);
///
/// // draw it
/// window.Draw(sprite);
///
/// ...
/// }
///
/// \endcode
///
/// \see sf::Sprite, sf::Image, sf::RenderTexture
///
////////////////////////////////////////////////////////////

View File

@ -297,7 +297,7 @@ private :
/// A view is composed of a source rectangle, which defines /// A view is composed of a source rectangle, which defines
/// what part of the 2D scene is shown, and a target viewport, /// what part of the 2D scene is shown, and a target viewport,
/// which defines where the contents of the source rectangle /// which defines where the contents of the source rectangle
/// will be displayed on the render target (window or render-image). /// will be displayed on the render target (window or texture).
/// ///
/// The viewport allows to map the scene to a custom part /// The viewport allows to map the scene to a custom part
/// of the render target, and can be used for split-screen /// of the render target, and can be used for split-screen
@ -336,6 +336,6 @@ private :
/// window.Draw(someText); /// window.Draw(someText);
/// \endcode /// \endcode
/// ///
/// \see RenderWindow, RenderImage /// \see sf::RenderWindow, sf::RenderTexture
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

View File

@ -98,7 +98,7 @@ public :
/// This class allows users to define their own file input sources /// This class allows users to define their own file input sources
/// from which SFML can load resources. /// from which SFML can load resources.
/// ///
/// SFML resource classes like sf::Image and /// SFML resource classes like sf::Texture and
/// sf::SoundBuffer provide LoadFromFile and LoadFromMemory functions, /// sf::SoundBuffer provide LoadFromFile and LoadFromMemory functions,
/// which read data from conventional sources. However, if you /// which read data from conventional sources. However, if you
/// have data coming from a different source (over a network, /// have data coming from a different source (over a network,
@ -130,11 +130,11 @@ public :
/// ... /// ...
/// }; /// };
/// ///
/// // now you can load images... /// // now you can load textures...
/// sf::Image image; /// sf::Texture texture;
/// ZipStream stream("resources.zip"); /// ZipStream stream("resources.zip");
/// stream.Open("images/img.png"); /// stream.Open("images/img.png");
/// image.LoadFromStream(stream); /// texture.LoadFromStream(stream);
/// ///
/// // musics... /// // musics...
/// sf::Music music; /// sf::Music music;

View File

@ -275,8 +275,8 @@ private :
/// ///
/// These two classes are heavily used internally in SFML /// These two classes are heavily used internally in SFML
/// to safely handle resources and the classes that use them: /// to safely handle resources and the classes that use them:
/// \li sf::Image / sf::Sprite /// \li sf::Texture / sf::Sprite
/// \li sf::Font / sf::String /// \li sf::Font / sf::Text
/// \li sf::SoundBuffer / sf::Sound /// \li sf::SoundBuffer / sf::Sound
/// ///
/// sf::Resource and sf::ResourcePtr are designed for internal use, /// sf::Resource and sf::ResourcePtr are designed for internal use,

View File

@ -39,14 +39,10 @@ Sound::Sound()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Sound::Sound(const SoundBuffer& buffer, bool loop, float pitch, float volume, const Vector3f& position) : Sound::Sound(const SoundBuffer& buffer) :
myBuffer(NULL) myBuffer(NULL)
{ {
SetBuffer(buffer); SetBuffer(buffer);
SetLoop(loop);
SetPitch(pitch);
SetVolume(volume);
SetPosition(position);
} }

View File

@ -25,14 +25,14 @@ set(SRC
${INCROOT}/Rect.inl ${INCROOT}/Rect.inl
${SRCROOT}/Renderer.cpp ${SRCROOT}/Renderer.cpp
${INCROOT}/Renderer.hpp ${INCROOT}/Renderer.hpp
${SRCROOT}/RenderImage.cpp ${SRCROOT}/RenderTexture.cpp
${INCROOT}/RenderImage.hpp ${INCROOT}/RenderTexture.hpp
${SRCROOT}/RenderImageImpl.cpp ${SRCROOT}/RenderTextureImpl.cpp
${SRCROOT}/RenderImageImpl.hpp ${SRCROOT}/RenderTextureImpl.hpp
${SRCROOT}/RenderImageImplFBO.cpp ${SRCROOT}/RenderTextureImplFBO.cpp
${SRCROOT}/RenderImageImplFBO.hpp ${SRCROOT}/RenderTextureImplFBO.hpp
${SRCROOT}/RenderImageImplDefault.cpp ${SRCROOT}/RenderTextureImplDefault.cpp
${SRCROOT}/RenderImageImplDefault.hpp ${SRCROOT}/RenderTextureImplDefault.hpp
${SRCROOT}/RenderTarget.cpp ${SRCROOT}/RenderTarget.cpp
${INCROOT}/RenderTarget.hpp ${INCROOT}/RenderTarget.hpp
${SRCROOT}/RenderWindow.cpp ${SRCROOT}/RenderWindow.cpp
@ -45,6 +45,8 @@ set(SRC
${INCROOT}/Sprite.hpp ${INCROOT}/Sprite.hpp
${SRCROOT}/Text.cpp ${SRCROOT}/Text.cpp
${INCROOT}/Text.hpp ${INCROOT}/Text.hpp
${SRCROOT}/Texture.cpp
${INCROOT}/Texture.hpp
${SRCROOT}/View.cpp ${SRCROOT}/View.cpp
${INCROOT}/View.hpp ${INCROOT}/View.hpp
${SRCROOT}/stb_image/stb_image.h ${SRCROOT}/stb_image/stb_image.h

View File

@ -33,20 +33,6 @@
namespace sf namespace sf
{ {
////////////////////////////////////////////////////////////
Drawable::Drawable(const Vector2f& position, const Vector2f& scale, float rotation, const Color& color) :
myPosition (position),
myScale (scale),
myOrigin (0, 0),
myRotation (rotation),
myColor (color),
myBlendMode (Blend::Alpha),
myMatrixUpdated (false),
myInvMatrixUpdated(false)
{
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Drawable::~Drawable() Drawable::~Drawable()
{ {
@ -267,6 +253,20 @@ Vector2f Drawable::TransformToGlobal(const Vector2f& point) const
} }
////////////////////////////////////////////////////////////
Drawable::Drawable() :
myPosition (0, 0),
myScale (1, 1),
myOrigin (0, 0),
myRotation (0),
myColor (255, 255, 255, 255),
myBlendMode (Blend::Alpha),
myMatrixUpdated (false),
myInvMatrixUpdated(false)
{
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
const Matrix3& Drawable::GetMatrix() const const Matrix3& Drawable::GetMatrix() const
{ {

View File

@ -309,7 +309,7 @@ int Font::GetLineSpacing(unsigned int characterSize) const
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
const Image& Font::GetImage(unsigned int characterSize) const const Texture& Font::GetTexture(unsigned int characterSize) const
{ {
return myPages[characterSize].Texture; return myPages[characterSize].Texture;
} }
@ -493,12 +493,11 @@ Glyph Font::LoadGlyph(Uint32 codePoint, unsigned int characterSize, bool bold) c
} }
// Write the pixels to the texture // Write the pixels to the texture
IntRect subrect = glyph.SubRect; unsigned int x = glyph.SubRect.Left + padding;
subrect.Left += padding; unsigned int y = glyph.SubRect.Top + padding;
subrect.Top += padding; unsigned int width = glyph.SubRect.Width - 2 * padding;
subrect.Width -= 2 * padding; unsigned int height = glyph.SubRect.Height - 2 * padding;
subrect.Height -= 2 * padding; page.Texture.Update(&myPixelBuffer[0], width, height, x, y);
page.Texture.UpdatePixels(&myPixelBuffer[0], subrect);
} }
// Delete the FT glyph // Delete the FT glyph
@ -545,19 +544,17 @@ IntRect Font::FindGlyphRect(Page& page, unsigned int width, unsigned int height)
// Not enough space: resize the texture if possible // Not enough space: resize the texture if possible
unsigned int textureWidth = page.Texture.GetWidth(); unsigned int textureWidth = page.Texture.GetWidth();
unsigned int textureHeight = page.Texture.GetHeight(); unsigned int textureHeight = page.Texture.GetHeight();
if ((textureWidth * 2 <= Image::GetMaximumSize()) && (textureHeight * 2 <= Image::GetMaximumSize())) if ((textureWidth * 2 <= Texture::GetMaximumSize()) && (textureHeight * 2 <= Texture::GetMaximumSize()))
{ {
// Make the texture 2 times bigger // Make the texture 2 times bigger
std::size_t size = textureWidth * textureHeight * 4; sf::Image pixels = page.Texture.CopyToImage();
std::vector<Uint8> pixels(size); page.Texture.Create(textureWidth * 2, textureHeight * 2);
memcpy(&pixels[0], page.Texture.GetPixelsPtr(), size); page.Texture.Update(pixels);
page.Texture.Create(textureWidth * 2, textureHeight * 2, Color(255, 255, 255, 0));
page.Texture.UpdatePixels(&pixels[0], IntRect(0, 0, textureWidth, textureHeight));
} }
else else
{ {
// Oops, we've reached the maximum texture size... // Oops, we've reached the maximum texture size...
Err() << "Failed to add a new character to the font: the maximum image size has been reached" << std::endl; Err() << "Failed to add a new character to the font: the maximum texture size has been reached" << std::endl;
return IntRect(0, 0, 2, 2); return IntRect(0, 0, 2, 2);
} }
} }
@ -603,13 +600,17 @@ Font::Page::Page() :
NextRow(2) NextRow(2)
{ {
// Make sure that the texture is initialized by default // Make sure that the texture is initialized by default
Texture.Create(128, 128, Color(255, 255, 255, 0)); sf::Image image;
Texture.SetSmooth(true); image.Create(128, 128, Color(255, 255, 255, 0));
// Reserve a 2x2 white square for texturing underlines // Reserve a 2x2 white square for texturing underlines
for (int x = 0; x < 2; ++x) for (int x = 0; x < 2; ++x)
for (int y = 0; y < 2; ++y) for (int y = 0; y < 2; ++y)
Texture.SetPixel(x, y, Color(255, 255, 255, 255)); image.SetPixel(x, y, Color(255, 255, 255, 255));
// Create the texture
Texture.LoadFromImage(image);
Texture.SetSmooth(true);
} }
} // namespace sf } // namespace sf

View File

@ -27,12 +27,8 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Graphics/Image.hpp> #include <SFML/Graphics/Image.hpp>
#include <SFML/Graphics/ImageLoader.hpp> #include <SFML/Graphics/ImageLoader.hpp>
#include <SFML/Graphics/RenderImage.hpp>
#include <SFML/Graphics/RenderWindow.hpp>
#include <SFML/Graphics/GLCheck.hpp>
#include <SFML/System/Err.hpp> #include <SFML/System/Err.hpp>
#include <algorithm> #include <algorithm>
#include <vector>
#include <cstring> #include <cstring>
@ -41,167 +37,19 @@ namespace sf
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Image::Image() : Image::Image() :
myWidth (0), myWidth (0),
myHeight (0), myHeight(0)
myTextureWidth (0),
myTextureHeight (0),
myTexture (0),
myIsSmooth (false),
myTextureUpdated(true),
myArrayUpdated (true),
myPixelsFlipped (false)
{ {
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Image::Image(const Image& copy) : void Image::Create(unsigned int width, unsigned int height, const Color& color)
Resource<Image>()
{ {
// First make sure that the source image is up-to-date // Assign the new size
copy.EnsureArrayUpdate(); myWidth = width;
myHeight = height;
// Copy all its members
myWidth = copy.myWidth;
myHeight = copy.myHeight;
myTextureWidth = copy.myTextureWidth;
myTextureHeight = copy.myTextureHeight;
myTexture = 0;
myIsSmooth = copy.myIsSmooth;
myPixels = copy.myPixels;
myTextureUpdated = true;
myArrayUpdated = true;
myPixelsFlipped = false; // pixels can't be flipped, this is handled in copy.EnsureArrayUpdate()
// Create the texture
CreateTexture(myWidth, myHeight);
}
////////////////////////////////////////////////////////////
Image::~Image()
{
// Destroy the OpenGL texture
if (myTexture)
{
EnsureGlContext();
GLuint Texture = static_cast<GLuint>(myTexture);
GLCheck(glDeleteTextures(1, &Texture));
}
}
////////////////////////////////////////////////////////////
bool Image::LoadFromFile(const std::string& filename)
{
// Forward the job to the image loader
std::vector<Uint8> pixels;
unsigned int width;
unsigned int height;
if (priv::ImageLoader::GetInstance().LoadImageFromFile(filename, pixels, width, height))
{
// Loading succeeded : we can create the texture
if (CreateTexture(width, height))
{
// Copy the pixels
myPixels.swap(pixels);
return true;
}
}
return false;
}
////////////////////////////////////////////////////////////
bool Image::LoadFromMemory(const void* data, std::size_t size)
{
// Forward the job to the image loader
std::vector<Uint8> pixels;
unsigned int width;
unsigned int height;
if (priv::ImageLoader::GetInstance().LoadImageFromMemory(data, size, pixels, width, height))
{
// Loading succeeded : we can create the texture
if (CreateTexture(width, height))
{
// Copy the pixels
myPixels.swap(pixels);
return true;
}
}
return false;
}
////////////////////////////////////////////////////////////
bool Image::LoadFromStream(InputStream& stream)
{
// Forward the job to the image loader
std::vector<Uint8> pixels;
unsigned int width;
unsigned int height;
if (priv::ImageLoader::GetInstance().LoadImageFromStream(stream, pixels, width, height))
{
// Loading succeeded : we can create the texture
if (CreateTexture(width, height))
{
// Copy the pixels
myPixels.swap(pixels);
return true;
}
}
return false;
}
////////////////////////////////////////////////////////////
bool Image::LoadFromPixels(unsigned int width, unsigned int height, const Uint8* data)
{
if (data)
{
// Create the internal texture
if (CreateTexture(width, height))
{
// Copy the pixels
std::size_t size = width * height * 4;
myPixels.resize(size);
std::memcpy(&myPixels[0], data, size); // faster than vector::assign
return true;
}
else
{
return false;
}
}
else
{
// No data provided : create a white image
return Create(width, height, Color(255, 255, 255));
}
}
////////////////////////////////////////////////////////////
bool Image::SaveToFile(const std::string& filename) const
{
// Check if the array of pixels needs to be updated
EnsureArrayUpdate();
// Let the image loader save our pixel array into the image
return priv::ImageLoader::GetInstance().SaveImageToFile(filename, myPixels, myWidth, myHeight);
}
////////////////////////////////////////////////////////////
bool Image::Create(unsigned int width, unsigned int height, const Color& color)
{
// First create the texture
if (CreateTexture(width, height))
{
// Resize the pixel buffer // Resize the pixel buffer
myPixels.resize(width * height * 4); myPixels.resize(width * height * 4);
@ -215,22 +63,78 @@ bool Image::Create(unsigned int width, unsigned int height, const Color& color)
*ptr++ = color.b; *ptr++ = color.b;
*ptr++ = color.a; *ptr++ = color.a;
} }
}
return true;
////////////////////////////////////////////////////////////
void Image::Create(unsigned int width, unsigned int height, const Uint8* pixels)
{
if (pixels)
{
// Assign the new size
myWidth = width;
myHeight = height;
// Copy the pixels
std::size_t size = width * height * 4;
myPixels.resize(size);
std::memcpy(&myPixels[0], pixels, size); // faster than vector::assign
} }
else else
{ {
return false; // Create an empty image
myWidth = 0;
myHeight = 0;
myPixels.clear();
} }
} }
////////////////////////////////////////////////////////////
bool Image::LoadFromFile(const std::string& filename)
{
return priv::ImageLoader::GetInstance().LoadImageFromFile(filename, myPixels, myWidth, myHeight);
}
////////////////////////////////////////////////////////////
bool Image::LoadFromMemory(const void* data, std::size_t size)
{
return priv::ImageLoader::GetInstance().LoadImageFromMemory(data, size, myPixels, myWidth, myHeight);
}
////////////////////////////////////////////////////////////
bool Image::LoadFromStream(InputStream& stream)
{
return priv::ImageLoader::GetInstance().LoadImageFromStream(stream, myPixels, myWidth, myHeight);
}
////////////////////////////////////////////////////////////
bool Image::SaveToFile(const std::string& filename) const
{
return priv::ImageLoader::GetInstance().SaveImageToFile(filename, myPixels, myWidth, myHeight);
}
////////////////////////////////////////////////////////////
unsigned int Image::GetWidth() const
{
return myWidth;
}
////////////////////////////////////////////////////////////
unsigned int Image::GetHeight() const
{
return myHeight;
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void Image::CreateMaskFromColor(const Color& color, Uint8 alpha) void Image::CreateMaskFromColor(const Color& color, Uint8 alpha)
{ {
// Check if the array of pixels needs to be updated
EnsureArrayUpdate();
// Make sure that the image is not empty // Make sure that the image is not empty
if (!myPixels.empty()) if (!myPixels.empty())
{ {
@ -243,9 +147,6 @@ void Image::CreateMaskFromColor(const Color& color, Uint8 alpha)
ptr[3] = alpha; ptr[3] = alpha;
ptr += 4; ptr += 4;
} }
// The texture will need to be updated
myTextureUpdated = false;
} }
} }
@ -257,10 +158,6 @@ void Image::Copy(const Image& source, unsigned int destX, unsigned int destY, co
if ((source.myWidth == 0) || (source.myHeight == 0) || (myWidth == 0) || (myHeight == 0)) if ((source.myWidth == 0) || (source.myHeight == 0) || (myWidth == 0) || (myHeight == 0))
return; return;
// Make sure both images have up-to-date arrays
EnsureArrayUpdate();
source.EnsureArrayUpdate();
// Adjust the source rectangle // Adjust the source rectangle
IntRect srcRect = sourceRect; IntRect srcRect = sourceRect;
if (srcRect.Width == 0 || (srcRect.Height == 0)) if (srcRect.Width == 0 || (srcRect.Height == 0))
@ -330,84 +227,24 @@ void Image::Copy(const Image& source, unsigned int destX, unsigned int destY, co
dstPixels += dstStride; dstPixels += dstStride;
} }
} }
// The texture will need an update
myTextureUpdated = false;
}
////////////////////////////////////////////////////////////
bool Image::CopyScreen(RenderWindow& window, const IntRect& sourceRect)
{
// Adjust the source rectangle
IntRect rect = sourceRect;
if (rect.Width == 0 || (rect.Height == 0))
{
rect.Left = 0;
rect.Top = 0;
rect.Width = window.GetWidth();
rect.Height = window.GetHeight();
}
else
{
if (rect.Left < 0) rect.Left = 0;
if (rect.Top < 0) rect.Top = 0;
if (rect.Width > static_cast<int>(window.GetWidth())) rect.Width = window.GetWidth();
if (rect.Height > static_cast<int>(window.GetHeight())) rect.Height = window.GetHeight();
}
// We can then create the texture
if (window.SetActive() && CreateTexture(rect.Width, rect.Height))
{
GLint previous;
GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous));
GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture));
int y = window.GetHeight() - (rect.Top + rect.Height); // Y axis is inverted
GLCheck(glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, rect.Left, y, myWidth, myHeight));
GLCheck(glBindTexture(GL_TEXTURE_2D, previous));
myTextureUpdated = true;
myArrayUpdated = false;
myPixelsFlipped = true;
return true;
}
else
{
return false;
}
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void Image::SetPixel(unsigned int x, unsigned int y, const Color& color) void Image::SetPixel(unsigned int x, unsigned int y, const Color& color)
{ {
// First check if the array of pixels needs to be updated
EnsureArrayUpdate();
// Copy the color components
Uint8* pixel = &myPixels[(x + y * myWidth) * 4]; Uint8* pixel = &myPixels[(x + y * myWidth) * 4];
*pixel++ = color.r; *pixel++ = color.r;
*pixel++ = color.g; *pixel++ = color.g;
*pixel++ = color.b; *pixel++ = color.b;
*pixel++ = color.a; *pixel++ = color.a;
// The texture will need to be updated
myTextureUpdated = false;
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Color Image::GetPixel(unsigned int x, unsigned int y) const Color Image::GetPixel(unsigned int x, unsigned int y) const
{ {
// First check if the array of pixels needs to be updated
EnsureArrayUpdate();
// Get the color at (x, y)
const Uint8* pixel = &myPixels[(x + y * myWidth) * 4]; const Uint8* pixel = &myPixels[(x + y * myWidth) * 4];
return Color(pixel[0], pixel[1], pixel[2], pixel[3]); return Color(pixel[0], pixel[1], pixel[2], pixel[3]);
} }
@ -415,9 +252,6 @@ Color Image::GetPixel(unsigned int x, unsigned int y) const
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
const Uint8* Image::GetPixelsPtr() const const Uint8* Image::GetPixelsPtr() const
{ {
// First check if the array of pixels needs to be updated
EnsureArrayUpdate();
if (!myPixels.empty()) if (!myPixels.empty())
{ {
return &myPixels[0]; return &myPixels[0];
@ -429,339 +263,4 @@ const Uint8* Image::GetPixelsPtr() const
} }
} }
////////////////////////////////////////////////////////////
void Image::UpdatePixels(const Uint8* pixels)
{
if (pixels && myTexture)
{
EnsureGlContext();
GLint previous;
GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous));
// Update the texture from the array of pixels
GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture));
GLCheck(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, myWidth, myHeight, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
GLCheck(glBindTexture(GL_TEXTURE_2D, previous));
myArrayUpdated = false;
myTextureUpdated = true;
}
}
////////////////////////////////////////////////////////////
void Image::UpdatePixels(const Uint8* pixels, const IntRect& rectangle)
{
// Make sure that the texture is up-to-date
EnsureTextureUpdate();
if (pixels && myTexture)
{
GLint previous;
GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous));
// Update the texture from the array of pixels
GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture));
GLCheck(glTexSubImage2D(GL_TEXTURE_2D, 0, rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
GLCheck(glBindTexture(GL_TEXTURE_2D, previous));
// The pixel cache is no longer up-to-date
myArrayUpdated = false;
}
}
////////////////////////////////////////////////////////////
void Image::Bind() const
{
// First check if the texture needs to be updated
EnsureTextureUpdate();
// Bind it
GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture));
}
////////////////////////////////////////////////////////////
void Image::SetSmooth(bool smooth)
{
if (smooth != myIsSmooth)
{
myIsSmooth = smooth;
if (myTexture)
{
EnsureGlContext();
GLint previous;
GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous));
GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture));
GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, myIsSmooth ? GL_LINEAR : GL_NEAREST));
GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, myIsSmooth ? GL_LINEAR : GL_NEAREST));
GLCheck(glBindTexture(GL_TEXTURE_2D, previous));
}
}
}
////////////////////////////////////////////////////////////
unsigned int Image::GetWidth() const
{
return myWidth;
}
////////////////////////////////////////////////////////////
unsigned int Image::GetHeight() const
{
return myHeight;
}
////////////////////////////////////////////////////////////
bool Image::IsSmooth() const
{
return myIsSmooth;
}
////////////////////////////////////////////////////////////
FloatRect Image::GetTexCoords(const IntRect& rect) const
{
if ((myTextureWidth != 0) && (myTextureHeight != 0))
{
float width = static_cast<float>(myTextureWidth);
float height = static_cast<float>(myTextureHeight);
if (myPixelsFlipped)
{
return FloatRect( rect.Left / width,
(myHeight - rect.Top) / height,
rect.Width / width,
-rect.Height / height);
}
else
{
return FloatRect(rect.Left / width,
rect.Top / height,
rect.Width / width,
rect.Height / height);
}
}
else
{
return FloatRect(0, 0, 0, 0);
}
}
////////////////////////////////////////////////////////////
unsigned int Image::GetMaximumSize()
{
EnsureGlContext();
GLint size;
GLCheck(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &size));
return static_cast<unsigned int>(size);
}
////////////////////////////////////////////////////////////
Image& Image::operator =(const Image& right)
{
Image temp(right);
std::swap(myWidth, temp.myWidth);
std::swap(myHeight, temp.myHeight);
std::swap(myTextureWidth, temp.myTextureWidth);
std::swap(myTextureHeight, temp.myTextureHeight);
std::swap(myTexture, temp.myTexture);
std::swap(myIsSmooth, temp.myIsSmooth);
std::swap(myArrayUpdated, temp.myArrayUpdated);
std::swap(myTextureUpdated, temp.myTextureUpdated);
std::swap(myPixelsFlipped, temp.myPixelsFlipped);
std::swap(myPixels, temp.myPixels);
return *this;
}
////////////////////////////////////////////////////////////
unsigned int Image::GetValidSize(unsigned int size)
{
EnsureGlContext();
// Make sure that GLEW is initialized
priv::EnsureGlewInit();
if (GLEW_ARB_texture_non_power_of_two)
{
// If hardware supports NPOT textures, then just return the unmodified size
return size;
}
else
{
// If hardware doesn't support NPOT textures, we calculate the nearest power of two
unsigned int powerOfTwo = 1;
while (powerOfTwo < size)
powerOfTwo *= 2;
return powerOfTwo;
}
}
////////////////////////////////////////////////////////////
bool Image::CreateTexture(unsigned int width, unsigned int height)
{
// Check if texture parameters are valid before creating it
if (!width || !height)
return false;
// Compute the internal texture dimensions depending on NPOT textures support
unsigned int textureWidth = GetValidSize(width);
unsigned int textureHeight = GetValidSize(height);
// Check the maximum texture size
unsigned int maxSize = GetMaximumSize();
if ((textureWidth > maxSize) || (textureHeight > maxSize))
{
Err() << "Failed to create image, its internal size is too high "
<< "(" << textureWidth << "x" << textureHeight << ", "
<< "maximum is " << maxSize << "x" << maxSize << ")"
<< std::endl;
return false;
}
// All the validity checks passed, we can store the new texture settings
myWidth = width;
myHeight = height;
myTextureWidth = textureWidth;
myTextureHeight = textureHeight;
EnsureGlContext();
// Create the OpenGL texture if it doesn't exist yet
if (!myTexture)
{
GLuint texture;
GLCheck(glGenTextures(1, &texture));
myTexture = static_cast<unsigned int>(texture);
}
// Initialize the texture
GLint previous;
GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous));
GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture));
GLCheck(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, myTextureWidth, myTextureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL));
GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, myIsSmooth ? GL_LINEAR : GL_NEAREST));
GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, myIsSmooth ? GL_LINEAR : GL_NEAREST));
GLCheck(glBindTexture(GL_TEXTURE_2D, previous));
myTextureUpdated = false;
return true;
}
////////////////////////////////////////////////////////////
void Image::EnsureTextureUpdate() const
{
if (!myTextureUpdated)
{
if (myTexture && !myPixels.empty())
{
EnsureGlContext();
GLint previous;
GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous));
// Update the texture with the pixels array in RAM
GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture));
GLCheck(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, myWidth, myHeight, GL_RGBA, GL_UNSIGNED_BYTE, &myPixels[0]));
myPixelsFlipped = false;
GLCheck(glBindTexture(GL_TEXTURE_2D, previous));
}
myTextureUpdated = true;
}
}
////////////////////////////////////////////////////////////
void Image::EnsureArrayUpdate() const
{
if (!myArrayUpdated)
{
EnsureGlContext();
// Save the previous texture
GLint previous;
GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous));
// Resize the destination array of pixels
myPixels.resize(myWidth * myHeight * 4);
if ((myWidth == myTextureWidth) && (myHeight == myTextureHeight) && !myPixelsFlipped)
{
// Texture and array have the same size, we can use a direct copy
// Copy pixels from texture to array
GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture));
GLCheck(glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &myPixels[0]));
}
else
{
// Texture and array don't have the same size, we have to use a slower algorithm
// All the pixels will first be copied to a temporary array
ColorArray allPixels(myTextureWidth * myTextureHeight * 4);
GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture));
GLCheck(glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &allPixels[0]));
// Then we copy the useful pixels from the temporary array to the final one
const Uint8* src = &allPixels[0];
Uint8* dst = &myPixels[0];
int srcPitch = myTextureWidth * 4;
int dstPitch = myWidth * 4;
// Handle the case where source pixels are flipped vertically
if (myPixelsFlipped)
{
src += srcPitch * (myHeight - 1);
srcPitch = -srcPitch;
}
for (unsigned int i = 0; i < myHeight; ++i)
{
std::memcpy(dst, src, dstPitch);
src += srcPitch;
dst += dstPitch;
}
}
// Restore the previous texture
GLCheck(glBindTexture(GL_TEXTURE_2D, previous));
myArrayUpdated = true;
}
}
////////////////////////////////////////////////////////////
void Image::Use() const
{
EnsureTextureUpdate();
}
} // namespace sf } // namespace sf

View File

@ -25,57 +25,57 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Graphics/RenderImage.hpp> #include <SFML/Graphics/RenderTexture.hpp>
#include <SFML/Graphics/RenderImageImplFBO.hpp> #include <SFML/Graphics/RenderTextureImplFBO.hpp>
#include <SFML/Graphics/RenderImageImplDefault.hpp> #include <SFML/Graphics/RenderTextureImplDefault.hpp>
#include <SFML/System/Err.hpp> #include <SFML/System/Err.hpp>
namespace sf namespace sf
{ {
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
RenderImage::RenderImage() : RenderTexture::RenderTexture() :
myRenderImage(NULL) myRenderTexture(NULL)
{ {
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
RenderImage::~RenderImage() RenderTexture::~RenderTexture()
{ {
delete myRenderImage; delete myRenderTexture;
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool RenderImage::Create(unsigned int width, unsigned int height, bool depthBuffer) bool RenderTexture::Create(unsigned int width, unsigned int height, bool depthBuffer)
{ {
// Create the image // Create the texture
if (!myImage.Create(width, height)) if (!myTexture.Create(width, height))
{ {
Err() << "Impossible to create render image (failed to create the target image)" << std::endl; Err() << "Impossible to create render texture (failed to create the target texture)" << std::endl;
return false; return false;
} }
// We disable smoothing by default for render images // We disable smoothing by default for render textures
SetSmooth(false); SetSmooth(false);
// Create the implementation // Create the implementation
delete myRenderImage; delete myRenderTexture;
if (priv::RenderImageImplFBO::IsAvailable()) if (priv::RenderTextureImplFBO::IsAvailable())
{ {
// Use frame-buffer object (FBO) // Use frame-buffer object (FBO)
myRenderImage = new priv::RenderImageImplFBO; myRenderTexture = new priv::RenderTextureImplFBO;
} }
else else
{ {
// Use default implementation // Use default implementation
myRenderImage = new priv::RenderImageImplDefault; myRenderTexture = new priv::RenderTextureImplDefault;
} }
// Initialize the render image // Initialize the render texture
if (!myRenderImage->Create(width, height, myImage.myTexture, depthBuffer)) if (!myRenderTexture->Create(width, height, myTexture.myTexture, depthBuffer))
return false; return false;
// We can now initialize the render target part // We can now initialize the render target part
@ -86,64 +86,61 @@ bool RenderImage::Create(unsigned int width, unsigned int height, bool depthBuff
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void RenderImage::SetSmooth(bool smooth) void RenderTexture::SetSmooth(bool smooth)
{ {
myImage.SetSmooth(smooth); myTexture.SetSmooth(smooth);
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool RenderImage::IsSmooth() const bool RenderTexture::IsSmooth() const
{ {
return myImage.IsSmooth(); return myTexture.IsSmooth();
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool RenderImage::SetActive(bool active) bool RenderTexture::SetActive(bool active)
{ {
return myRenderImage && myRenderImage->Activate(active); return myRenderTexture && myRenderTexture->Activate(active);
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void RenderImage::Display() void RenderTexture::Display()
{ {
// Update the target image // Update the target texture
if (SetActive(true)) if (SetActive(true))
{ {
myRenderImage->UpdateTexture(myImage.myTexture); myRenderTexture->UpdateTexture(myTexture.myTexture);
myTexture.myPixelsFlipped = true;
myImage.myPixelsFlipped = true;
myImage.myArrayUpdated = false;
myImage.myTextureUpdated = true;
} }
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
unsigned int RenderImage::GetWidth() const unsigned int RenderTexture::GetWidth() const
{ {
return myImage.GetWidth(); return myTexture.GetWidth();
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
unsigned int RenderImage::GetHeight() const unsigned int RenderTexture::GetHeight() const
{ {
return myImage.GetHeight(); return myTexture.GetHeight();
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
const Image& RenderImage::GetImage() const const Texture& RenderTexture::GetTexture() const
{ {
return myImage; return myTexture;
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool RenderImage::Activate(bool active) bool RenderTexture::Activate(bool active)
{ {
return SetActive(active); return SetActive(active);
} }

View File

@ -25,7 +25,7 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Graphics/RenderImageImpl.hpp> #include <SFML/Graphics/RenderTextureImpl.hpp>
namespace sf namespace sf
@ -33,7 +33,7 @@ namespace sf
namespace priv namespace priv
{ {
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
RenderImageImpl::~RenderImageImpl() RenderTextureImpl::~RenderTextureImpl()
{ {
// Nothing to do // Nothing to do
} }

View File

@ -22,8 +22,8 @@
// //
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#ifndef SFML_RENDERIMAGEIMPL_HPP #ifndef SFML_RENDERTEXTUREIMPL_HPP
#define SFML_RENDERIMAGEIMPL_HPP #define SFML_RENDERTEXTUREIMPL_HPP
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Headers // Headers
@ -36,10 +36,10 @@ namespace sf
namespace priv namespace priv
{ {
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Abstract base class for render-image implementations /// \brief Abstract base class for render-texture implementations
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
class RenderImageImpl : NonCopyable class RenderTextureImpl : NonCopyable
{ {
public : public :
@ -47,14 +47,14 @@ public :
/// \brief Destructor /// \brief Destructor
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
virtual ~RenderImageImpl(); virtual ~RenderTextureImpl();
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Create the render image implementation /// \brief Create the render texture implementation
/// ///
/// \param width Width of the image to render to /// \param width Width of the texture to render to
/// \param height Height of the image to render to /// \param height Height of the texture to render to
/// \param textureId OpenGL texture identifier of the target image /// \param textureId OpenGL identifier of the target texture
/// \param depthBuffer Is a depth buffer requested? /// \param depthBuffer Is a depth buffer requested?
/// ///
/// \return True if creation has been successful /// \return True if creation has been successful
@ -63,7 +63,7 @@ public :
virtual bool Create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer) = 0; virtual bool Create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer) = 0;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Activate or deactivate the render image for rendering /// \brief Activate or deactivate the render texture for rendering
/// ///
/// \param active True to activate, false to deactivate /// \param active True to activate, false to deactivate
/// ///
@ -86,4 +86,4 @@ public :
} // namespace sf } // namespace sf
#endif // SFML_RENDERIMAGEIMPL_HPP #endif // SFML_RENDERTEXTUREIMPL_HPP

View File

@ -25,7 +25,7 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Graphics/RenderImageImplDefault.hpp> #include <SFML/Graphics/RenderTextureImplDefault.hpp>
#include <SFML/Graphics/GLCheck.hpp> #include <SFML/Graphics/GLCheck.hpp>
#include <SFML/Window/Context.hpp> #include <SFML/Window/Context.hpp>
#include <SFML/System/Err.hpp> #include <SFML/System/Err.hpp>
@ -36,7 +36,7 @@ namespace sf
namespace priv namespace priv
{ {
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
RenderImageImplDefault::RenderImageImplDefault() : RenderTextureImplDefault::RenderTextureImplDefault() :
myContext(0), myContext(0),
myWidth (0), myWidth (0),
myHeight (0) myHeight (0)
@ -46,7 +46,7 @@ myHeight (0)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
RenderImageImplDefault::~RenderImageImplDefault() RenderTextureImplDefault::~RenderTextureImplDefault()
{ {
// Destroy the context // Destroy the context
delete myContext; delete myContext;
@ -54,33 +54,33 @@ RenderImageImplDefault::~RenderImageImplDefault()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool RenderImageImplDefault::Create(unsigned int width, unsigned int height, unsigned int, bool depthBuffer) bool RenderTextureImplDefault::Create(unsigned int width, unsigned int height, unsigned int, bool depthBuffer)
{ {
// Store the dimensions // Store the dimensions
myWidth = width; myWidth = width;
myHeight = height; myHeight = height;
// Create the in-memory OpenGL context // Create the in-memory OpenGL context
myContext = new Context(ContextSettings(depthBuffer ? 32 : 0, 0, 4), width, height); myContext = new Context(ContextSettings(depthBuffer ? 32 : 0), width, height);
return true; return true;
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool RenderImageImplDefault::Activate(bool active) bool RenderTextureImplDefault::Activate(bool active)
{ {
return myContext->SetActive(active); return myContext->SetActive(active);
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void RenderImageImplDefault::UpdateTexture(unsigned int textureId) void RenderTextureImplDefault::UpdateTexture(unsigned int textureId)
{ {
GLint previous; GLint previous;
GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous)); GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous));
// Copy the rendered pixels to the image // Copy the rendered pixels to the texture
GLCheck(glBindTexture(GL_TEXTURE_2D, textureId)); GLCheck(glBindTexture(GL_TEXTURE_2D, textureId));
GLCheck(glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, myWidth, myHeight)); GLCheck(glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, myWidth, myHeight));

View File

@ -22,13 +22,13 @@
// //
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#ifndef SFML_RENDERIMAGEIMPLDEFAULT_HPP #ifndef SFML_RENDERTEXTUREIMPLDEFAULT_HPP
#define SFML_RENDERIMAGEIMPLDEFAULT_HPP #define SFML_RENDERTEXTUREIMPLDEFAULT_HPP
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Graphics/RenderImageImpl.hpp> #include <SFML/Graphics/RenderTextureImpl.hpp>
#include <SFML/Window/GlResource.hpp> #include <SFML/Window/GlResource.hpp>
#include <SFML/Window/Context.hpp> #include <SFML/Window/Context.hpp>
@ -38,11 +38,11 @@ namespace sf
namespace priv namespace priv
{ {
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Default specialization of RenderImageImpl, /// \brief Default specialization of RenderTextureImpl,
/// using a in-memory context /// using a in-memory context
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
class RenderImageImplDefault : public RenderImageImpl, GlResource class RenderTextureImplDefault : public RenderTextureImpl, GlResource
{ {
public : public :
@ -50,22 +50,22 @@ public :
/// \brief Default constructor /// \brief Default constructor
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
RenderImageImplDefault(); RenderTextureImplDefault();
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Destructor /// \brief Destructor
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
~RenderImageImplDefault(); ~RenderTextureImplDefault();
private : private :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Create the render image implementation /// \brief Create the render texture implementation
/// ///
/// \param width Width of the image to render to /// \param width Width of the texture to render to
/// \param height Height of the image to render to /// \param height Height of the texture to render to
/// \param textureId OpenGL texture identifier of the target image /// \param textureId OpenGL identifier of the target texture
/// \param depthBuffer Is a depth buffer requested? /// \param depthBuffer Is a depth buffer requested?
/// ///
/// \return True if creation has been successful /// \return True if creation has been successful
@ -74,7 +74,7 @@ private :
virtual bool Create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer); virtual bool Create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Activate or deactivate the render image for rendering /// \brief Activate or deactivate the render texture for rendering
/// ///
/// \param active True to activate, false to deactivate /// \param active True to activate, false to deactivate
/// ///
@ -104,4 +104,4 @@ private :
} // namespace sf } // namespace sf
#endif // SFML_RENDERIMAGEIMPLDEFAULT_HPP #endif // SFML_RENDERTEXTUREIMPLDEFAULT_HPP

View File

@ -25,8 +25,8 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Graphics/RenderImageImplFBO.hpp> #include <SFML/Graphics/RenderTextureImplFBO.hpp>
#include <SFML/Graphics/Image.hpp> #include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/GLCheck.hpp> #include <SFML/Graphics/GLCheck.hpp>
#include <SFML/System/Err.hpp> #include <SFML/System/Err.hpp>
@ -36,7 +36,7 @@ namespace sf
namespace priv namespace priv
{ {
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
RenderImageImplFBO::RenderImageImplFBO() : RenderTextureImplFBO::RenderTextureImplFBO() :
myFrameBuffer(0), myFrameBuffer(0),
myDepthBuffer(0) myDepthBuffer(0)
{ {
@ -45,7 +45,7 @@ myDepthBuffer(0)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
RenderImageImplFBO::~RenderImageImplFBO() RenderTextureImplFBO::~RenderTextureImplFBO()
{ {
EnsureGlContext(); EnsureGlContext();
@ -69,7 +69,7 @@ RenderImageImplFBO::~RenderImageImplFBO()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool RenderImageImplFBO::IsAvailable() bool RenderTextureImplFBO::IsAvailable()
{ {
EnsureGlContext(); EnsureGlContext();
@ -81,7 +81,7 @@ bool RenderImageImplFBO::IsAvailable()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool RenderImageImplFBO::Create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer) bool RenderTextureImplFBO::Create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer)
{ {
//Create the context //Create the context
myContext = new Context; myContext = new Context;
@ -92,7 +92,7 @@ bool RenderImageImplFBO::Create(unsigned int width, unsigned int height, unsigne
myFrameBuffer = static_cast<unsigned int>(frameBuffer); myFrameBuffer = static_cast<unsigned int>(frameBuffer);
if (!myFrameBuffer) if (!myFrameBuffer)
{ {
Err() << "Impossible to create render image (failed to create the frame buffer object)" << std::endl; Err() << "Impossible to create render texture (failed to create the frame buffer object)" << std::endl;
return false; return false;
} }
GLCheck(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, myFrameBuffer)); GLCheck(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, myFrameBuffer));
@ -105,7 +105,7 @@ bool RenderImageImplFBO::Create(unsigned int width, unsigned int height, unsigne
myDepthBuffer = static_cast<unsigned int>(depth); myDepthBuffer = static_cast<unsigned int>(depth);
if (!myDepthBuffer) if (!myDepthBuffer)
{ {
Err() << "Impossible to create render image (failed to create the attached depth buffer)" << std::endl; Err() << "Impossible to create render texture (failed to create the attached depth buffer)" << std::endl;
return false; return false;
} }
GLCheck(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, myDepthBuffer)); GLCheck(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, myDepthBuffer));
@ -113,14 +113,14 @@ bool RenderImageImplFBO::Create(unsigned int width, unsigned int height, unsigne
GLCheck(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, myDepthBuffer)); GLCheck(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, myDepthBuffer));
} }
// Link the image to the frame buffer // Link the texture to the frame buffer
GLCheck(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, textureId, 0)); GLCheck(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, textureId, 0));
// A final check, just to be sure... // A final check, just to be sure...
if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT)
{ {
GLCheck(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0)); GLCheck(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
Err() << "Impossible to create render image (failed to link the target image to the frame buffer)" << std::endl; Err() << "Impossible to create render texture (failed to link the target texture to the frame buffer)" << std::endl;
return false; return false;
} }
@ -129,13 +129,13 @@ bool RenderImageImplFBO::Create(unsigned int width, unsigned int height, unsigne
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool RenderImageImplFBO::Activate(bool active) bool RenderTextureImplFBO::Activate(bool active)
{ {
return myContext->SetActive(active); return myContext->SetActive(active);
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void RenderImageImplFBO::UpdateTexture(unsigned int) void RenderTextureImplFBO::UpdateTexture(unsigned int)
{ {
glFlush(); glFlush();
} }

View File

@ -22,13 +22,13 @@
// //
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#ifndef SFML_RENDERIMAGEIMPLFBO_HPP #ifndef SFML_RENDERTEXTUREIMPLFBO_HPP
#define SFML_RENDERIMAGEIMPLFBO_HPP #define SFML_RENDERTEXTUREIMPLFBO_HPP
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Graphics/RenderImageImpl.hpp> #include <SFML/Graphics/RenderTextureImpl.hpp>
#include <SFML/Window/Context.hpp> #include <SFML/Window/Context.hpp>
#include <SFML/Window/GlResource.hpp> #include <SFML/Window/GlResource.hpp>
@ -38,11 +38,11 @@ namespace sf
namespace priv namespace priv
{ {
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Specialization of RenderImageImpl using the /// \brief Specialization of RenderTextureImpl using the
/// FrameBuffer Object OpenGL extension /// FrameBuffer Object OpenGL extension
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
class RenderImageImplFBO : public RenderImageImpl, GlResource class RenderTextureImplFBO : public RenderTextureImpl, GlResource
{ {
public : public :
@ -50,18 +50,18 @@ public :
/// \brief Default constructor /// \brief Default constructor
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
RenderImageImplFBO(); RenderTextureImplFBO();
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Destructor /// \brief Destructor
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
~RenderImageImplFBO(); ~RenderTextureImplFBO();
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Check whether the system supports FBOs or not /// \brief Check whether the system supports FBOs or not
/// ///
/// \return True if FBO render images are supported /// \return True if FBO render textures are supported
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
static bool IsAvailable(); static bool IsAvailable();
@ -69,11 +69,11 @@ public :
private : private :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Create the render image implementation /// \brief Create the render texture implementation
/// ///
/// \param width Width of the image to render to /// \param width Width of the texture to render to
/// \param height Height of the image to render to /// \param height Height of the texture to render to
/// \param textureId OpenGL texture identifier of the target image /// \param textureId OpenGL identifier of the target texture
/// \param depthBuffer Is a depth buffer requested? /// \param depthBuffer Is a depth buffer requested?
/// ///
/// \return True if creation has been successful /// \return True if creation has been successful
@ -82,7 +82,7 @@ private :
virtual bool Create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer); virtual bool Create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Activate or deactivate the render image for rendering /// \brief Activate or deactivate the render texture for rendering
/// ///
/// \param active True to activate, false to deactivate /// \param active True to activate, false to deactivate
/// ///
@ -112,4 +112,4 @@ private :
} // namespace sf } // namespace sf
#endif // SFML_RENDERIMAGEIMPLFBO_HPP #endif // SFML_RENDERTEXTUREIMPLFBO_HPP

View File

@ -26,6 +26,7 @@
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Graphics/RenderWindow.hpp> #include <SFML/Graphics/RenderWindow.hpp>
#include <SFML/Graphics/GLCheck.hpp>
namespace sf namespace sf
@ -81,6 +82,30 @@ unsigned int RenderWindow::GetHeight() const
} }
////////////////////////////////////////////////////////////
Image RenderWindow::Capture() const
{
Image image;
if (SetActive())
{
int width = static_cast<int>(GetWidth());
int height = static_cast<int>(GetHeight());
// copy rows one by one and flip them (OpenGL's origin is bottom while SFML's origin is top)
std::vector<Uint8> pixels(width * height * 4);
for (int i = 0; i < height; ++i)
{
Uint8* ptr = &pixels[i * width * 4];
GLCheck(glReadPixels(0, height - i - 1, width, 1, GL_RGBA, GL_UNSIGNED_BYTE, ptr));
}
image.Create(width, height, &pixels[0]);
}
return image;
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void RenderWindow::OnCreate() void RenderWindow::OnCreate()
{ {

View File

@ -27,7 +27,7 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Graphics/Renderer.hpp> #include <SFML/Graphics/Renderer.hpp>
#include <SFML/Graphics/RenderTarget.hpp> #include <SFML/Graphics/RenderTarget.hpp>
#include <SFML/Graphics/Image.hpp> #include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/Shader.hpp> #include <SFML/Graphics/Shader.hpp>
#include <SFML/Graphics/GLCheck.hpp> #include <SFML/Graphics/GLCheck.hpp>
@ -202,7 +202,7 @@ void Renderer::SetBlendMode(Blend::Mode mode)
{ {
// Alpha blending // Alpha blending
// glBlendFuncSeparateEXT is used when available to avoid an incorrect alpha value when the target // glBlendFuncSeparateEXT is used when available to avoid an incorrect alpha value when the target
// is a RenderImage -- in this case the alpha value must be written directly to the target buffer // is a RenderTexture -- in this case the alpha value must be written directly to the target buffer
default : default :
case Blend::Alpha : case Blend::Alpha :
if (GLEW_EXT_blend_func_separate) if (GLEW_EXT_blend_func_separate)
@ -231,7 +231,7 @@ void Renderer::SetBlendMode(Blend::Mode mode)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void Renderer::SetTexture(const Image* texture) void Renderer::SetTexture(const Texture* texture)
{ {
if ((texture != myTexture) || (texture && (texture->myTexture != myTextureId)) || !myTextureIsValid) if ((texture != myTexture) || (texture && (texture->myTexture != myTextureId)) || !myTextureIsValid)
{ {
@ -246,12 +246,6 @@ void Renderer::SetTexture(const Image* texture)
myTextureId = texture ? texture->myTexture : 0; myTextureId = texture ? texture->myTexture : 0;
myTextureIsValid = true; myTextureIsValid = true;
} }
else if (texture && myTextureIsValid)
{
// If the texture was already the current one, make sure that
// it is synchronized (in case it was modified since last use)
texture->Use();
}
} }

View File

@ -225,7 +225,7 @@ void Shader::SetParameter(const std::string& name, const Vector3f& v)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void Shader::SetTexture(const std::string& name, const Image& texture) void Shader::SetTexture(const std::string& name, const Texture& texture)
{ {
if (myShaderProgram) if (myShaderProgram)
{ {

View File

@ -26,7 +26,7 @@
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Graphics/Sprite.hpp> #include <SFML/Graphics/Sprite.hpp>
#include <SFML/Graphics/Image.hpp> #include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/Renderer.hpp> #include <SFML/Graphics/Renderer.hpp>
#include <utility> #include <utility>
@ -35,6 +35,7 @@ namespace sf
{ {
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Sprite::Sprite() : Sprite::Sprite() :
Drawable (),
mySubRect (0, 0, 1, 1), mySubRect (0, 0, 1, 1),
myIsFlippedX(false), myIsFlippedX(false),
myIsFlippedY(false) myIsFlippedY(false)
@ -44,31 +45,31 @@ myIsFlippedY(false)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Sprite::Sprite(const Image& image, const Vector2f& position, const Vector2f& scale, float rotation, const Color& color) : Sprite::Sprite(const Texture& texture) :
Drawable (position, scale, rotation, color), Drawable (),
mySubRect (0, 0, 1, 1), mySubRect (0, 0, 1, 1),
myIsFlippedX(false), myIsFlippedX(false),
myIsFlippedY(false) myIsFlippedY(false)
{ {
SetImage(image); SetTexture(texture);
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void Sprite::SetImage(const Image& image, bool adjustToNewSize) void Sprite::SetTexture(const Texture& texture, bool adjustToNewSize)
{ {
// If there was no valid image before, force adjusting to the new image size // If there was no valid texture before, force adjusting to the new texture size
if (!myImage) if (!myTexture)
adjustToNewSize = true; adjustToNewSize = true;
// If we want to adjust the size and the new image is valid, we adjust the source rectangle // If we want to adjust the size and the new texture is valid, we adjust the source rectangle
if (adjustToNewSize && (image.GetWidth() > 0) && (image.GetHeight() > 0)) if (adjustToNewSize && (texture.GetWidth() > 0) && (texture.GetHeight() > 0))
{ {
SetSubRect(IntRect(0, 0, image.GetWidth(), image.GetHeight())); SetSubRect(IntRect(0, 0, texture.GetWidth(), texture.GetHeight()));
} }
// Assign the new image // Assign the new texture
myImage = &image; myTexture = &texture;
} }
@ -109,9 +110,9 @@ void Sprite::FlipY(bool flipped)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
const Image* Sprite::GetImage() const const Texture* Sprite::GetTexture() const
{ {
return myImage; return myTexture;
} }
@ -129,26 +130,6 @@ Vector2f Sprite::GetSize() const
} }
////////////////////////////////////////////////////////////
Color Sprite::GetPixel(unsigned int x, unsigned int y) const
{
if (myImage)
{
unsigned int imageX = mySubRect.Left + x;
unsigned int imageY = mySubRect.Top + y;
if (myIsFlippedX) imageX = mySubRect.Width - imageX - 1;
if (myIsFlippedY) imageY = mySubRect.Height - imageY - 1;
return myImage->GetPixel(imageX, imageY) * GetColor();
}
else
{
return GetColor();
}
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void Sprite::Render(RenderTarget&, Renderer& renderer) const void Sprite::Render(RenderTarget&, Renderer& renderer) const
{ {
@ -156,10 +137,10 @@ void Sprite::Render(RenderTarget&, Renderer& renderer) const
float width = static_cast<float>(mySubRect.Width); float width = static_cast<float>(mySubRect.Width);
float height = static_cast<float>(mySubRect.Height); float height = static_cast<float>(mySubRect.Height);
// Check if the image is valid, and calculate the texture coordinates // Check if the texture is valid, and calculate the texture coordinates
FloatRect coords; FloatRect coords;
if (myImage) if (myTexture)
coords = myImage->GetTexCoords(mySubRect); coords = myTexture->GetTexCoords(mySubRect);
// Compute the texture coordinates // Compute the texture coordinates
float left = coords.Left; float left = coords.Left;
@ -170,7 +151,7 @@ void Sprite::Render(RenderTarget&, Renderer& renderer) const
if (myIsFlippedY) std::swap(top, bottom); if (myIsFlippedY) std::swap(top, bottom);
// Bind the texture // Bind the texture
renderer.SetTexture(myImage); renderer.SetTexture(myTexture);
// Draw the sprite's geometry // Draw the sprite's geometry
renderer.Begin(Renderer::TriangleStrip); renderer.Begin(Renderer::TriangleStrip);

View File

@ -26,7 +26,7 @@
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Graphics/Text.hpp> #include <SFML/Graphics/Text.hpp>
#include <SFML/Graphics/Image.hpp> #include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/Renderer.hpp> #include <SFML/Graphics/Renderer.hpp>
@ -190,7 +190,7 @@ void Text::Render(RenderTarget&, Renderer& renderer) const
return; return;
// Bind the font texture // Bind the font texture
const Image& texture = myFont->GetImage(myCharacterSize); const Texture& texture = myFont->GetTexture(myCharacterSize);
renderer.SetTexture(&texture); renderer.SetTexture(&texture);
// Computes values related to the text style // Computes values related to the text style

View File

@ -0,0 +1,506 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/Image.hpp>
#include <SFML/Graphics/GLCheck.hpp>
#include <SFML/Window/Window.hpp>
#include <SFML/System/Err.hpp>
#include <cassert>
#include <cstring>
namespace sf
{
////////////////////////////////////////////////////////////
Texture::Texture() :
myWidth (0),
myHeight (0),
myTextureWidth (0),
myTextureHeight(0),
myTexture (0),
myIsSmooth (false),
myPixelsFlipped(false)
{
}
////////////////////////////////////////////////////////////
Texture::Texture(const Texture& copy) :
Resource<Texture>(),
myWidth (0),
myHeight (0),
myTextureWidth (0),
myTextureHeight(0),
myTexture (0),
myIsSmooth (false),
myPixelsFlipped(false)
{
LoadFromImage(copy.CopyToImage());
}
////////////////////////////////////////////////////////////
Texture::~Texture()
{
// Destroy the OpenGL texture
if (myTexture)
{
EnsureGlContext();
GLuint Texture = static_cast<GLuint>(myTexture);
GLCheck(glDeleteTextures(1, &Texture));
}
}
////////////////////////////////////////////////////////////
bool Texture::Create(unsigned int width, unsigned int height)
{
// Check if texture parameters are valid before creating it
if (!width || !height)
{
Err() << "Failed to create texture, invalid size (" << width << "x" << height << ")" << std::endl;
return false;
}
// Compute the internal texture dimensions depending on NPOT textures support
unsigned int textureWidth = GetValidSize(width);
unsigned int textureHeight = GetValidSize(height);
// Check the maximum texture size
unsigned int maxSize = GetMaximumSize();
if ((textureWidth > maxSize) || (textureHeight > maxSize))
{
Err() << "Failed to create texture, its internal size is too high "
<< "(" << textureWidth << "x" << textureHeight << ", "
<< "maximum is " << maxSize << "x" << maxSize << ")"
<< std::endl;
return false;
}
// All the validity checks passed, we can store the new texture settings
myWidth = width;
myHeight = height;
myTextureWidth = textureWidth;
myTextureHeight = textureHeight;
myPixelsFlipped = false;
EnsureGlContext();
// Create the OpenGL texture if it doesn't exist yet
if (!myTexture)
{
GLuint texture;
GLCheck(glGenTextures(1, &texture));
myTexture = static_cast<unsigned int>(texture);
}
// Save the current texture binding
GLint previous;
GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous));
// Initialize the texture
GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture));
GLCheck(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, myTextureWidth, myTextureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL));
GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, myIsSmooth ? GL_LINEAR : GL_NEAREST));
GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, myIsSmooth ? GL_LINEAR : GL_NEAREST));
// Restore the previous texture
GLCheck(glBindTexture(GL_TEXTURE_2D, previous));
return true;
}
////////////////////////////////////////////////////////////
bool Texture::LoadFromFile(const std::string& filename, const IntRect& area)
{
Image image;
return image.LoadFromFile(filename) && LoadFromImage(image, area);
}
////////////////////////////////////////////////////////////
bool Texture::LoadFromMemory(const void* data, std::size_t size, const IntRect& area)
{
Image image;
return image.LoadFromMemory(data, size) && LoadFromImage(image, area);
}
////////////////////////////////////////////////////////////
bool Texture::LoadFromStream(InputStream& stream, const IntRect& area)
{
Image image;
return image.LoadFromStream(stream) && LoadFromImage(image, area);
}
////////////////////////////////////////////////////////////
bool Texture::LoadFromImage(const Image& image, const IntRect& area)
{
// Retrieve the image size
int width = static_cast<int>(image.GetWidth());
int height = static_cast<int>(image.GetHeight());
// Load the entire image if the source area is either empty or contains the whole image
if (area.Width == 0 || (area.Height == 0) ||
((area.Left <= 0) && (area.Top <= 0) && (area.Width >= width) && (area.Height >= height)))
{
// Load the entire image
if (Create(image.GetWidth(), image.GetHeight()))
{
Update(image);
return true;
}
else
{
return false;
}
}
else
{
// Load a sub-area of the image
// Adjust the rectangle to the size of the image
IntRect rectangle = area;
if (rectangle.Left < 0) rectangle.Left = 0;
if (rectangle.Top < 0) rectangle.Top = 0;
if (rectangle.Width > width) rectangle.Width = width;
if (rectangle.Height > height) rectangle.Height = height;
// Create the texture and upload the pixels
if (Create(rectangle.Width, rectangle.Height))
{
// Save the current texture binding
GLint previous;
GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous));
// Copy the pixels to the texture, row by row
const Uint8* pixels = image.GetPixelsPtr() + rectangle.Left + (width * rectangle.Top);
GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture));
for (int i = 0; i < rectangle.Height; ++i)
{
GLCheck(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, i, myWidth, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
pixels += width;
}
myPixelsFlipped = false;
// Restore the previous texture
GLCheck(glBindTexture(GL_TEXTURE_2D, previous));
return true;
}
else
{
return false;
}
}
}
////////////////////////////////////////////////////////////
unsigned int Texture::GetWidth() const
{
return myWidth;
}
////////////////////////////////////////////////////////////
unsigned int Texture::GetHeight() const
{
return myHeight;
}
////////////////////////////////////////////////////////////
Image Texture::CopyToImage() const
{
// Easy case: empty texture
if (!myTexture)
return Image();
EnsureGlContext();
// Save the previous texture
GLint previous;
GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous));
// Create an array of pixels
std::vector<Uint8> pixels(myWidth * myHeight * 4);
if ((myWidth == myTextureWidth) && (myHeight == myTextureHeight) && !myPixelsFlipped)
{
// Texture is not padded nor flipped, we can use a direct copy
GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture));
GLCheck(glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &pixels[0]));
}
else
{
// Texture is either padded or flipped, we have to use a slower algorithm
// All the pixels will first be copied to a temporary array
std::vector<Uint8> allPixels(myTextureWidth * myTextureHeight * 4);
GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture));
GLCheck(glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &allPixels[0]));
// Then we copy the useful pixels from the temporary array to the final one
const Uint8* src = &allPixels[0];
Uint8* dst = &pixels[0];
int srcPitch = myTextureWidth * 4;
int dstPitch = myWidth * 4;
// Handle the case where source pixels are flipped vertically
if (myPixelsFlipped)
{
src += srcPitch * (myHeight - 1);
srcPitch = -srcPitch;
}
for (unsigned int i = 0; i < myHeight; ++i)
{
std::memcpy(dst, src, dstPitch);
src += srcPitch;
dst += dstPitch;
}
}
// Restore the previous texture
GLCheck(glBindTexture(GL_TEXTURE_2D, previous));
// Create the image
Image image;
image.Create(myWidth, myHeight, &pixels[0]);
return image;
}
////////////////////////////////////////////////////////////
void Texture::Update(const Uint8* pixels)
{
// Update the whole texture
Update(pixels, myWidth, myHeight, 0, 0);
}
////////////////////////////////////////////////////////////
void Texture::Update(const Uint8* pixels, unsigned int width, unsigned int height, unsigned int x, unsigned int y)
{
assert(x + width <= myWidth);
assert(y + height <= myHeight);
if (pixels && myTexture)
{
EnsureGlContext();
// Save the current texture binding
GLint previous;
GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous));
// Copy pixels from the given array to the texture
GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture));
GLCheck(glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
myPixelsFlipped = false;
// Restore the previous texture
GLCheck(glBindTexture(GL_TEXTURE_2D, previous));
}
}
////////////////////////////////////////////////////////////
void Texture::Update(const Image& image)
{
// Update the whole texture
Update(image.GetPixelsPtr(), image.GetWidth(), image.GetHeight(), 0, 0);
}
////////////////////////////////////////////////////////////
void Texture::Update(const Image& image, unsigned int x, unsigned int y)
{
Update(image.GetPixelsPtr(), image.GetWidth(), image.GetHeight(), x, y);
}
////////////////////////////////////////////////////////////
void Texture::Update(const Window& window)
{
Update(window, 0, 0);
}
////////////////////////////////////////////////////////////
void Texture::Update(const Window& window, unsigned int x, unsigned int y)
{
assert(x + window.GetWidth() <= myWidth);
assert(y + window.GetHeight() <= myHeight);
if (myTexture && window.SetActive(true))
{
// Save the current texture binding
GLint previous;
GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous));
// Copy pixels from the back-buffer to the texture
GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture));
GLCheck(glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x, y, 0, 0, window.GetWidth(), window.GetHeight()));
myPixelsFlipped = true;
// Restore the previous texture
GLCheck(glBindTexture(GL_TEXTURE_2D, previous));
}
}
////////////////////////////////////////////////////////////
void Texture::Bind() const
{
GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture));
}
////////////////////////////////////////////////////////////
void Texture::SetSmooth(bool smooth)
{
if (smooth != myIsSmooth)
{
myIsSmooth = smooth;
if (myTexture)
{
EnsureGlContext();
GLint previous;
GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous));
GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture));
GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, myIsSmooth ? GL_LINEAR : GL_NEAREST));
GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, myIsSmooth ? GL_LINEAR : GL_NEAREST));
GLCheck(glBindTexture(GL_TEXTURE_2D, previous));
}
}
}
////////////////////////////////////////////////////////////
bool Texture::IsSmooth() const
{
return myIsSmooth;
}
////////////////////////////////////////////////////////////
FloatRect Texture::GetTexCoords(const IntRect& rect) const
{
if ((myTextureWidth != 0) && (myTextureHeight != 0))
{
float width = static_cast<float>(myTextureWidth);
float height = static_cast<float>(myTextureHeight);
if (myPixelsFlipped)
{
return FloatRect( rect.Left / width,
(myHeight - rect.Top) / height,
rect.Width / width,
-rect.Height / height);
}
else
{
return FloatRect(rect.Left / width,
rect.Top / height,
rect.Width / width,
rect.Height / height);
}
}
else
{
return FloatRect(0, 0, 0, 0);
}
}
////////////////////////////////////////////////////////////
unsigned int Texture::GetMaximumSize()
{
EnsureGlContext();
GLint size;
GLCheck(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &size));
return static_cast<unsigned int>(size);
}
////////////////////////////////////////////////////////////
Texture& Texture::operator =(const Texture& right)
{
Texture temp(right);
std::swap(myWidth, temp.myWidth);
std::swap(myHeight, temp.myHeight);
std::swap(myTextureWidth, temp.myTextureWidth);
std::swap(myTextureHeight, temp.myTextureHeight);
std::swap(myTexture, temp.myTexture);
std::swap(myIsSmooth, temp.myIsSmooth);
std::swap(myPixelsFlipped, temp.myPixelsFlipped);
return *this;
}
////////////////////////////////////////////////////////////
unsigned int Texture::GetValidSize(unsigned int size)
{
EnsureGlContext();
// Make sure that GLEW is initialized
priv::EnsureGlewInit();
if (GLEW_ARB_texture_non_power_of_two)
{
// If hardware supports NPOT textures, then just return the unmodified size
return size;
}
else
{
// If hardware doesn't support NPOT textures, we calculate the nearest power of two
unsigned int powerOfTwo = 1;
while (powerOfTwo < size)
powerOfTwo *= 2;
return powerOfTwo;
}
}
} // namespace sf