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));
// Create a sprite for the background
sf::Image backgroundImage;
if (!backgroundImage.LoadFromFile("resources/background.jpg"))
sf::Texture backgroundTexture;
if (!backgroundTexture.LoadFromFile("resources/background.jpg"))
return EXIT_FAILURE;
sf::Sprite background(backgroundImage);
sf::Sprite background(backgroundTexture);
// Load an OpenGL texture.
// We could directly use a sf::Image 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
// 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 an image
GLuint texture = 0;
{
sf::Image image;

View File

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

View File

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

View File

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

View File

@ -52,16 +52,12 @@ public :
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 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
/// \param buffer Sound buffer containing the audio data to play with the sound
///
////////////////////////////////////////////////////////////
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

View File

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

View File

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

View File

@ -63,17 +63,6 @@ class SFML_API Drawable
{
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
///
@ -452,6 +441,12 @@ public :
protected :
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
Drawable();
////////////////////////////////////////////////////////////
/// \brief Get the transform matrix of the object
///
@ -532,7 +527,7 @@ private :
/// \li transformations (position, rotation, scale, local origin)
/// \li global overlay color
/// \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,
/// therefore they are extremely cheap to use (unlike older
@ -591,7 +586,7 @@ private :
/// target.Draw(mySubSprite);
/// }
///
/// sf::Image myTexture;
/// sf::Texture myTexture;
/// sf::Sprite mySubSprite;
/// };
/// \endcode

View File

@ -32,7 +32,7 @@
#include <SFML/System/Vector2.hpp>
#include <SFML/System/String.hpp>
#include <SFML/Graphics/Glyph.hpp>
#include <SFML/Graphics/Image.hpp>
#include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/Rect.hpp>
#include <map>
#include <string>
@ -174,18 +174,18 @@ public :
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
/// used internally by sf::Text.
///
/// \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
@ -240,8 +240,8 @@ private :
Page();
GlyphTable Glyphs; ///< Table mapping code points to their corresponding glyph
Image Texture; ///< Image containing the pixels of the glyphs
unsigned int NextRow; ///< Y position of the next new row in the image
Texture Texture; ///< Texture containing the pixels of the glyphs
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
};
@ -288,7 +288,7 @@ private :
////////////////////////////////////////////////////////////
// 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

View File

@ -53,7 +53,7 @@ public :
////////////////////////////////////////////////////////////
int Advance; ///< Offset to move horizontically to the next character
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
@ -70,7 +70,7 @@ public :
///
/// The sf::Glyph structure provides the information needed
/// 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 the offset to apply to get the starting position of the next glyph
///

View File

@ -29,7 +29,6 @@
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/Resource.hpp>
#include <SFML/Window/GlResource.hpp>
#include <SFML/Graphics/Color.hpp>
#include <SFML/Graphics/Rect.hpp>
#include <string>
@ -38,16 +37,13 @@
namespace sf
{
class Renderer;
class RenderImage;
class RenderWindow;
class InputStream;
////////////////////////////////////////////////////////////
/// \brief Class for loading, manipulating and saving images
///
////////////////////////////////////////////////////////////
class SFML_API Image : public Resource<Image>, GlResource
class SFML_API Image
{
public :
@ -60,18 +56,29 @@ public :
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
@ -79,15 +86,13 @@ public :
/// The supported image formats are bmp, png, tga, jpg, gif,
/// psd, hdr and pic. Some format options are not supported,
/// 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.
///
/// \param filename Path of the image file to load
///
/// \return True if loading was successful
///
/// \see LoadFromMemory, LoadFromStream, LoadFromPixels, SaveToFile
/// \see LoadFromMemory, LoadFromStream, SaveToFile
///
////////////////////////////////////////////////////////////
bool LoadFromFile(const std::string& filename);
@ -98,8 +103,6 @@ public :
/// The supported image formats are bmp, png, tga, jpg, gif,
/// psd, hdr and pic. Some format options are not supported,
/// 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.
///
/// \param data Pointer to the file data in memory
@ -107,7 +110,7 @@ public :
///
/// \return True if loading was successful
///
/// \see LoadFromFile, LoadFromStream, LoadFromPixels
/// \see LoadFromFile, LoadFromStream
///
////////////////////////////////////////////////////////////
bool LoadFromMemory(const void* data, std::size_t size);
@ -126,30 +129,11 @@ public :
///
/// \return True if loading was successful
///
/// \see LoadFromFile, LoadFromMemory, LoadFromPixels
/// \see LoadFromFile, LoadFromMemory
///
////////////////////////////////////////////////////////////
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
///
@ -162,27 +146,33 @@ public :
///
/// \return True if saving was successful
///
/// \see LoadFromFile, LoadFromMemory, LoadFromPixels
/// \see Create, LoadFromFile, LoadFromMemory
///
////////////////////////////////////////////////////////////
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
/// \param height Height of the image
/// \param color Fill color
///
/// \return True if creation was successful
/// \see GetHeight
///
////////////////////////////////////////////////////////////
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
/// 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
///
/// This function does a slow pixel copy and should only
/// be used at initialization time. It can be used to prepare
/// a complex static image from several others, but if you
/// need this kind of feature in real-time you'd better use
/// sf::RenderImage.
/// This function does a slow pixel copy and should not be
/// used intensively. It can be used to prepare a complex
/// static image from several others, but if you need this
/// kind of feature in real-time you'd better use sf::RenderTexture.
///
/// If \a sourceRect is empty, the whole image is copied.
/// If \a applyAlpha is set to true, the transparency of
/// 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);
////////////////////////////////////////////////////////////
/// \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
///
@ -239,9 +213,9 @@ public :
/// coordinates, using out-of-range values will result in
/// an undefined behaviour.
///
/// \param x X coordinate of pixel to change
/// \param y Y coordinate of pixel to change
/// \param color New color of the pixel
/// \param x X coordinate of pixel to change
/// \param y Y coordinate of pixel to change
/// \param color New color of the pixel
///
/// \see GetPixel
///
@ -273,207 +247,19 @@ public :
/// modify the image, so you should never store it for too long.
/// 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;
////////////////////////////////////////////////////////////
/// \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 :
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
////////////////////////////////////////////////////////////
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 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
unsigned int myWidth; ///< Image width
unsigned int myHeight; ///< Image Height
std::vector<Uint8> myPixels; ///< Pixels of the image
};
} // namespace sf
@ -489,7 +275,7 @@ private :
/// sf::Image is an abstraction to manipulate images
/// as bidimensional arrays of pixels. The class provides
/// 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
/// pixels, which is RGBA 32 bits. This means that a pixel
@ -497,8 +283,8 @@ private :
/// channels -- just like a sf::Color.
/// All the functions that return an array of pixels follow
/// this rule, and all parameters that you pass to sf::Image
/// functions (such as LoadFromPixels or UpdatePixels) must
/// use this representation as well.
/// functions (such as LoadFromPixels) must use this
/// representation as well.
///
/// A sf::Image can be copied, but it is a heavy resource and
/// if possible you should always use [const] references to
@ -506,7 +292,7 @@ private :
///
/// Usage example:
/// \code
/// // Load an image file
/// // Load an image file from a file
/// sf::Image background;
/// if (!background.LoadFromFile("background.jpg"))
/// return -1;
@ -529,6 +315,6 @@ private :
/// return -1;
/// \endcode
///
/// \see sf::Sprite
/// \see sf::Texture
///
////////////////////////////////////////////////////////////

View File

@ -41,7 +41,7 @@ class Drawable;
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
@ -331,6 +331,6 @@ private :
/// OpenGL states are not messed up by calling the SaveGLStates /
/// 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
#define SFML_RENDERIMAGE_HPP
#ifndef SFML_RENDERTEXTURE_HPP
#define SFML_RENDERTEXTURE_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Image.hpp>
#include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/RenderTarget.hpp>
@ -36,48 +36,48 @@ namespace sf
{
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 :
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// Constructs an empty, invalid render-image. You must
/// call Create to have a valid render-image.
/// Constructs an empty, invalid render-texture. You must
/// call Create to have a valid render-texture.
///
/// \see Create
///
////////////////////////////////////////////////////////////
RenderImage();
RenderTexture();
////////////////////////////////////////////////////////////
/// \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
/// doing anything with the render-image.
/// doing anything with the render-texture.
/// 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
/// leave this parameter to false (which is its default value).
///
/// \param width Width of the render-image
/// \param height Height of the render-image
/// \param depthBuffer Do you want this render-image to have a depth buffer?
/// \param width Width of the render-texture
/// \param height Height of the render-texture
/// \param depthBuffer Do you want this render-texture to have a depth buffer?
///
/// \return True if creation has been successful
///
@ -85,9 +85,9 @@ public :
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.
///
/// \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
///
/// \return True if image smoothing is enabled
/// \return True if texture smoothing is enabled
///
/// \see SetSmooth
///
@ -108,12 +108,12 @@ public :
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
/// 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
/// (like a RenderWindow) don't forget to activate it again.
///
@ -125,18 +125,18 @@ public :
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
/// 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();
////////////////////////////////////////////////////////////
/// \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 Create function.
@ -149,7 +149,7 @@ public :
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 Create function.
@ -162,25 +162,25 @@ public :
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,
/// you can retrieve the updated image using this function,
/// After drawing to the render-texture and calling Display,
/// you can retrieve the updated texture using this function,
/// 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
/// 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.
///
/// \return Const reference to the image
/// \return Const reference to the texture
///
////////////////////////////////////////////////////////////
const Image& GetImage() const;
const Texture& GetTexture() const;
private :
////////////////////////////////////////////////////////////
/// \brief Activate the targt efor rendering
/// \brief Activate the target for rendering
///
/// This function is called by the base class
/// everytime it's going to use OpenGL calls.
@ -195,28 +195,28 @@ private :
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
Image myImage; ///< Target image to draw on
priv::RenderImageImpl* myRenderImage; ///< Platform / hardware specific implementation
Texture myTexture; ///< Target texture to draw on
priv::RenderTextureImpl* myRenderTexture; ///< Platform/hardware specific implementation
};
} // namespace sf
#endif // SFML_RENDERIMAGE_HPP
#endif // SFML_RENDERTEXTURE_HPP
////////////////////////////////////////////////////////////
/// \class sf::RenderImage
/// \class sf::RenderTexture
/// \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
/// (see their base class sf::RenderTarget for more details),
/// 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:
/// \li precomputing a complex static image (like a level's background from multiple tiles)
/// Rendering to a texture can be useful in a variety of situations:
/// \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 creating a sprite from a 3D object rendered with OpenGL
/// \li etc.
@ -224,16 +224,12 @@ private :
/// Usage example:
///
/// \code
/// // First of all: make sure that rendering to image is supported
/// if (!sf::RenderImage::IsAvailable())
/// return -1;
///
/// // Create a new render-window
/// sf::RenderWindow window(sf::VideoMode(800, 600), "SFML window");
///
/// // Create a new render-image
/// sf::RenderImage image;
/// if (!image.Create(500, 500))
/// // Create a new render-texture
/// sf::RenderTexture texture;
/// if (!texture.Create(500, 500))
/// return -1
///
/// // The main loop
@ -242,22 +238,22 @@ private :
/// // Event processing
/// // ...
///
/// // Clear the whole image with red color
/// image.Clear(sf::Color::Red);
/// // Clear the whole texture with red color
/// texture.Clear(sf::Color::Red);
///
/// // Draw stuff to the image
/// image.Draw(sprite); // sprite is a sf::Sprite
/// image.Draw(shape); // shape is a sf::Shape
/// image.Draw(text); // text is a sf::Text
/// // Draw stuff to the texture
/// texture.Draw(sprite); // sprite is a sf::Sprite
/// texture.Draw(shape); // shape is a sf::Shape
/// texture.Draw(text); // text is a sf::Text
///
/// // We're done drawing to the image
/// image.Display();
/// // We're done drawing to the texture
/// texture.Display();
///
/// // Now we start rendering to the window, clear it first
/// window.Clear();
///
/// // Draw the image
/// sf::Sprite sprite(image.GetImage());
/// // Draw the texture
/// sf::Sprite sprite(texture.GetTexture());
/// window.Draw(sprite);
///
/// // End the current frame and display its contents on screen
@ -265,11 +261,11 @@ private :
/// }
/// \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
/// 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
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Image.hpp>
#include <SFML/Graphics/RenderTarget.hpp>
#include <SFML/Graphics/Image.hpp>
#include <SFML/Window/Window.hpp>
#include <string>
@ -125,6 +125,22 @@ public :
////////////////////////////////////////////////////////////
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 :
////////////////////////////////////////////////////////////
@ -260,6 +276,6 @@ private :
/// }
/// \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
{
class Image;
class Shader;
class Texture;
////////////////////////////////////////////////////////////
/// \brief Handles the low-level rendering (states and geometry)
@ -120,9 +120,6 @@ public :
////////////////////////////////////////////////////////////
/// \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
///
/// \see ApplyModelView
@ -133,9 +130,6 @@ public :
////////////////////////////////////////////////////////////
/// \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
///
/// \see SetModelView
@ -146,9 +140,6 @@ public :
////////////////////////////////////////////////////////////
/// \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
///
/// \see ApplyProjection
@ -160,8 +151,6 @@ public :
/// \brief Set the current global 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
///
@ -174,8 +163,6 @@ public :
/// \brief Modulate the current global color with a new one
///
/// 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
///
@ -187,9 +174,6 @@ public :
////////////////////////////////////////////////////////////
/// \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
///
////////////////////////////////////////////////////////////
@ -198,9 +182,6 @@ public :
////////////////////////////////////////////////////////////
/// \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
///
////////////////////////////////////////////////////////////
@ -209,20 +190,14 @@ public :
////////////////////////////////////////////////////////////
/// \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
///
////////////////////////////////////////////////////////////
void SetTexture(const Image* texture);
void SetTexture(const Texture* texture);
////////////////////////////////////////////////////////////
/// \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
///
////////////////////////////////////////////////////////////
@ -346,18 +321,18 @@ private :
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
RenderTarget& myTarget; ///< Reference to the render target owning this renderer
States myStatesStack[64]; ///< Stack of render states
States* myStates; ///< Current set of render states
const Image* myTexture; ///< Current texture
unsigned int myTextureId; ///< Current texture identifier (the sf::Image instance may be the same, but not the internal OpenGL texture)
const Shader* myShader; ///< Current pixel shader
Blend::Mode myBlendMode; ///< Current blending mode
IntRect myViewport; ///< Current target viewport
bool myTextureIsValid; ///< Is the cached texture valid? (if not, the cached value is ignored)
bool myShaderIsValid; ///< Is the cached shader valid? (if not, the cached value is ignored)
bool myBlendModeIsValid; ///< Is the cached blend mode valid? (if not, the cached value is ignored)
bool myViewportIsValid; ///< Is the cached viewport valid? (if not, the cached value is ignored)
RenderTarget& myTarget; ///< Reference to the render target owning this renderer
States myStatesStack[64]; ///< Stack of render states
States* myStates; ///< Current set of render states
const Texture* myTexture; ///< Current 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
Blend::Mode myBlendMode; ///< Current blending mode
IntRect myViewport; ///< Current target viewport
bool myTextureIsValid; ///< Is the cached texture valid? (if not, the cached value is ignored)
bool myShaderIsValid; ///< Is the cached shader valid? (if not, the cached value is ignored)
bool myBlendModeIsValid; ///< Is the cached blend mode valid? (if not, the cached value is ignored)
bool myViewportIsValid; ///< Is the cached viewport valid? (if not, the cached value is ignored)
};
} // namespace sf

View File

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

View File

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

View File

@ -35,10 +35,10 @@
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.
///
////////////////////////////////////////////////////////////
@ -49,56 +49,50 @@ public :
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// Creates an empty sprite with no source image.
/// Creates an empty sprite with no source texture.
///
////////////////////////////////////////////////////////////
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
/// \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
/// \see SetTexture
///
////////////////////////////////////////////////////////////
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
/// 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.
/// 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.
/// 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.
///
/// \param image New image
/// \param adjustToNewSize Should the sub-rect be adjusted to the size of the new image?
/// \param texture New texture
/// \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 whole image, but rather a part of it.
/// By default, the sub-rectangle covers the entire image.
/// the whole texture, but rather a part of it.
/// 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);
@ -157,24 +151,24 @@ public :
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.
/// 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
///
@ -194,25 +188,6 @@ public :
////////////////////////////////////////////////////////////
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 :
////////////////////////////////////////////////////////////
@ -229,10 +204,10 @@ private :
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
ResourcePtr<Image> myImage; ///< Image used to draw the sprite
IntRect mySubRect; ///< Sub-rectangle of source image to assign to the sprite
bool myIsFlippedX; ///< Is the sprite flipped on the X axis ?
bool myIsFlippedY; ///< Is the sprite flipped on the Y axis ?
ResourcePtr<Texture> myTexture; ///< Texture used to draw 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 myIsFlippedY; ///< Is the sprite flipped on the Y axis ?
};
} // namespace sf
@ -246,39 +221,39 @@ private :
/// \ingroup graphics
///
/// 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:
/// position, rotation, scale, origin, global color and blend
/// 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.
///
/// sf::Sprite works in combination with the sf::Image class, which
/// loads and provides the pixel data of a given image.
/// sf::Sprite works in combination with the sf::Texture class, which
/// loads and provides the pixel data of a given texture.
///
/// The separation of sf::Sprite and sf::Image allows more flexibility
/// and better performances: indeed a sf::Image is a heavy resource,
/// The separation of sf::Sprite and sf::Texture allows more flexibility
/// and better performances: indeed a sf::Texture is a heavy resource,
/// and any operation on it is slow (often too slow for real-time
/// 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 is important to note that the sf::Sprite instance doesn't
/// copy the image that it uses, it only keeps a reference to it.
/// Thus, a sf::Image must not be destructed while it is
/// copy the texture that it uses, it only keeps a reference to it.
/// Thus, a sf::Texture must not be destructed while it is
/// 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:
/// \code
/// // Declare and load an image
/// sf::Image image;
/// image.LoadFromFile("image.png");
/// // Declare and load a texture
/// sf::Texture texture;
/// texture.LoadFromFile("texture.png");
///
/// // Create a sprite
/// sf::Sprite sprite;
/// sprite.SetImage(image);
/// sprite.SetTexture(texture);
/// sprite.SetSubRect(sf::IntRect(10, 10, 50, 30));
/// sprite.Resize(100, 60);
///
@ -286,6 +261,6 @@ private :
/// window.Draw(sprite); // window is a sf::RenderWindow
/// \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
/// what part of the 2D scene is shown, and a target viewport,
/// 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
/// of the render target, and can be used for split-screen
@ -336,6 +336,6 @@ private :
/// window.Draw(someText);
/// \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
/// 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,
/// which read data from conventional sources. However, if you
/// have data coming from a different source (over a network,
@ -130,11 +130,11 @@ public :
/// ...
/// };
///
/// // now you can load images...
/// sf::Image image;
/// // now you can load textures...
/// sf::Texture texture;
/// ZipStream stream("resources.zip");
/// stream.Open("images/img.png");
/// image.LoadFromStream(stream);
/// texture.LoadFromStream(stream);
///
/// // musics...
/// sf::Music music;

View File

@ -275,8 +275,8 @@ private :
///
/// These two classes are heavily used internally in SFML
/// to safely handle resources and the classes that use them:
/// \li sf::Image / sf::Sprite
/// \li sf::Font / sf::String
/// \li sf::Texture / sf::Sprite
/// \li sf::Font / sf::Text
/// \li sf::SoundBuffer / sf::Sound
///
/// 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)
{
SetBuffer(buffer);
SetLoop(loop);
SetPitch(pitch);
SetVolume(volume);
SetPosition(position);
}

View File

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

View File

@ -33,20 +33,6 @@
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()
{
@ -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
{

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;
}
@ -493,12 +493,11 @@ Glyph Font::LoadGlyph(Uint32 codePoint, unsigned int characterSize, bool bold) c
}
// Write the pixels to the texture
IntRect subrect = glyph.SubRect;
subrect.Left += padding;
subrect.Top += padding;
subrect.Width -= 2 * padding;
subrect.Height -= 2 * padding;
page.Texture.UpdatePixels(&myPixelBuffer[0], subrect);
unsigned int x = glyph.SubRect.Left + padding;
unsigned int y = glyph.SubRect.Top + padding;
unsigned int width = glyph.SubRect.Width - 2 * padding;
unsigned int height = glyph.SubRect.Height - 2 * padding;
page.Texture.Update(&myPixelBuffer[0], width, height, x, y);
}
// 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
unsigned int textureWidth = page.Texture.GetWidth();
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
std::size_t size = textureWidth * textureHeight * 4;
std::vector<Uint8> pixels(size);
memcpy(&pixels[0], page.Texture.GetPixelsPtr(), size);
page.Texture.Create(textureWidth * 2, textureHeight * 2, Color(255, 255, 255, 0));
page.Texture.UpdatePixels(&pixels[0], IntRect(0, 0, textureWidth, textureHeight));
sf::Image pixels = page.Texture.CopyToImage();
page.Texture.Create(textureWidth * 2, textureHeight * 2);
page.Texture.Update(pixels);
}
else
{
// 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);
}
}
@ -603,13 +600,17 @@ Font::Page::Page() :
NextRow(2)
{
// Make sure that the texture is initialized by default
Texture.Create(128, 128, Color(255, 255, 255, 0));
Texture.SetSmooth(true);
sf::Image image;
image.Create(128, 128, Color(255, 255, 255, 0));
// Reserve a 2x2 white square for texturing underlines
for (int x = 0; x < 2; ++x)
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

View File

@ -27,12 +27,8 @@
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Image.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 <algorithm>
#include <vector>
#include <cstring>
@ -40,54 +36,56 @@ namespace sf
{
////////////////////////////////////////////////////////////
Image::Image() :
myWidth (0),
myHeight (0),
myTextureWidth (0),
myTextureHeight (0),
myTexture (0),
myIsSmooth (false),
myTextureUpdated(true),
myArrayUpdated (true),
myPixelsFlipped (false)
myWidth (0),
myHeight(0)
{
}
////////////////////////////////////////////////////////////
Image::Image(const Image& copy) :
Resource<Image>()
void Image::Create(unsigned int width, unsigned int height, const Color& color)
{
// First make sure that the source image is up-to-date
copy.EnsureArrayUpdate();
// Assign the new size
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()
// Resize the pixel buffer
myPixels.resize(width * height * 4);
// Create the texture
CreateTexture(myWidth, myHeight);
}
////////////////////////////////////////////////////////////
Image::~Image()
{
// Destroy the OpenGL texture
if (myTexture)
// Fill it with the specified color
Uint8* ptr = &myPixels[0];
Uint8* end = ptr + myPixels.size();
while (ptr < end)
{
EnsureGlContext();
*ptr++ = color.r;
*ptr++ = color.g;
*ptr++ = color.b;
*ptr++ = color.a;
}
}
GLuint Texture = static_cast<GLuint>(myTexture);
GLCheck(glDeleteTextures(1, &Texture));
////////////////////////////////////////////////////////////
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
{
// Create an empty image
myWidth = 0;
myHeight = 0;
myPixels.clear();
}
}
@ -95,142 +93,48 @@ Image::~Image()
////////////////////////////////////////////////////////////
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;
return priv::ImageLoader::GetInstance().LoadImageFromFile(filename, myPixels, myWidth, myHeight);
}
////////////////////////////////////////////////////////////
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;
return priv::ImageLoader::GetInstance().LoadImageFromMemory(data, size, myPixels, myWidth, myHeight);
}
////////////////////////////////////////////////////////////
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));
}
return priv::ImageLoader::GetInstance().LoadImageFromStream(stream, myPixels, myWidth, myHeight);
}
////////////////////////////////////////////////////////////
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)
unsigned int Image::GetWidth() const
{
// First create the texture
if (CreateTexture(width, height))
{
// Resize the pixel buffer
myPixels.resize(width * height * 4);
return myWidth;
}
// Fill it with the specified color
Uint8* ptr = &myPixels[0];
Uint8* end = ptr + myPixels.size();
while (ptr < end)
{
*ptr++ = color.r;
*ptr++ = color.g;
*ptr++ = color.b;
*ptr++ = color.a;
}
return true;
}
else
{
return false;
}
////////////////////////////////////////////////////////////
unsigned int Image::GetHeight() const
{
return myHeight;
}
////////////////////////////////////////////////////////////
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
if (!myPixels.empty())
{
@ -243,9 +147,6 @@ void Image::CreateMaskFromColor(const Color& color, Uint8 alpha)
ptr[3] = alpha;
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))
return;
// Make sure both images have up-to-date arrays
EnsureArrayUpdate();
source.EnsureArrayUpdate();
// Adjust the source rectangle
IntRect srcRect = sourceRect;
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;
}
}
// 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)
{
// First check if the array of pixels needs to be updated
EnsureArrayUpdate();
// Copy the color components
Uint8* pixel = &myPixels[(x + y * myWidth) * 4];
*pixel++ = color.r;
*pixel++ = color.g;
*pixel++ = color.b;
*pixel++ = color.a;
// The texture will need to be updated
myTextureUpdated = false;
}
////////////////////////////////////////////////////////////
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];
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
{
// First check if the array of pixels needs to be updated
EnsureArrayUpdate();
if (!myPixels.empty())
{
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

View File

@ -25,57 +25,57 @@
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/RenderImage.hpp>
#include <SFML/Graphics/RenderImageImplFBO.hpp>
#include <SFML/Graphics/RenderImageImplDefault.hpp>
#include <SFML/Graphics/RenderTexture.hpp>
#include <SFML/Graphics/RenderTextureImplFBO.hpp>
#include <SFML/Graphics/RenderTextureImplDefault.hpp>
#include <SFML/System/Err.hpp>
namespace sf
{
////////////////////////////////////////////////////////////
RenderImage::RenderImage() :
myRenderImage(NULL)
RenderTexture::RenderTexture() :
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
if (!myImage.Create(width, height))
// Create the texture
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;
}
// We disable smoothing by default for render images
// We disable smoothing by default for render textures
SetSmooth(false);
// Create the implementation
delete myRenderImage;
if (priv::RenderImageImplFBO::IsAvailable())
delete myRenderTexture;
if (priv::RenderTextureImplFBO::IsAvailable())
{
// Use frame-buffer object (FBO)
myRenderImage = new priv::RenderImageImplFBO;
myRenderTexture = new priv::RenderTextureImplFBO;
}
else
{
// Use default implementation
myRenderImage = new priv::RenderImageImplDefault;
myRenderTexture = new priv::RenderTextureImplDefault;
}
// Initialize the render image
if (!myRenderImage->Create(width, height, myImage.myTexture, depthBuffer))
// Initialize the render texture
if (!myRenderTexture->Create(width, height, myTexture.myTexture, depthBuffer))
return false;
// 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))
{
myRenderImage->UpdateTexture(myImage.myTexture);
myImage.myPixelsFlipped = true;
myImage.myArrayUpdated = false;
myImage.myTextureUpdated = true;
myRenderTexture->UpdateTexture(myTexture.myTexture);
myTexture.myPixelsFlipped = 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);
}

View File

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

View File

@ -22,8 +22,8 @@
//
////////////////////////////////////////////////////////////
#ifndef SFML_RENDERIMAGEIMPL_HPP
#define SFML_RENDERIMAGEIMPL_HPP
#ifndef SFML_RENDERTEXTUREIMPL_HPP
#define SFML_RENDERTEXTUREIMPL_HPP
////////////////////////////////////////////////////////////
// Headers
@ -36,10 +36,10 @@ namespace sf
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 :
@ -47,14 +47,14 @@ public :
/// \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 height Height of the image to render to
/// \param textureId OpenGL texture identifier of the target image
/// \param width Width of the texture to render to
/// \param height Height of the texture to render to
/// \param textureId OpenGL identifier of the target texture
/// \param depthBuffer Is a depth buffer requested?
///
/// \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;
////////////////////////////////////////////////////////////
/// \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
///
@ -86,4 +86,4 @@ public :
} // namespace sf
#endif // SFML_RENDERIMAGEIMPL_HPP
#endif // SFML_RENDERTEXTUREIMPL_HPP

View File

@ -25,7 +25,7 @@
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/RenderImageImplDefault.hpp>
#include <SFML/Graphics/RenderTextureImplDefault.hpp>
#include <SFML/Graphics/GLCheck.hpp>
#include <SFML/Window/Context.hpp>
#include <SFML/System/Err.hpp>
@ -36,7 +36,7 @@ namespace sf
namespace priv
{
////////////////////////////////////////////////////////////
RenderImageImplDefault::RenderImageImplDefault() :
RenderTextureImplDefault::RenderTextureImplDefault() :
myContext(0),
myWidth (0),
myHeight (0)
@ -46,7 +46,7 @@ myHeight (0)
////////////////////////////////////////////////////////////
RenderImageImplDefault::~RenderImageImplDefault()
RenderTextureImplDefault::~RenderTextureImplDefault()
{
// Destroy the context
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
myWidth = width;
myHeight = height;
// 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;
}
////////////////////////////////////////////////////////////
bool RenderImageImplDefault::Activate(bool active)
bool RenderTextureImplDefault::Activate(bool active)
{
return myContext->SetActive(active);
}
////////////////////////////////////////////////////////////
void RenderImageImplDefault::UpdateTexture(unsigned int textureId)
void RenderTextureImplDefault::UpdateTexture(unsigned int textureId)
{
GLint 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(glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, myWidth, myHeight));

View File

@ -22,13 +22,13 @@
//
////////////////////////////////////////////////////////////
#ifndef SFML_RENDERIMAGEIMPLDEFAULT_HPP
#define SFML_RENDERIMAGEIMPLDEFAULT_HPP
#ifndef SFML_RENDERTEXTUREIMPLDEFAULT_HPP
#define SFML_RENDERTEXTUREIMPLDEFAULT_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/RenderImageImpl.hpp>
#include <SFML/Graphics/RenderTextureImpl.hpp>
#include <SFML/Window/GlResource.hpp>
#include <SFML/Window/Context.hpp>
@ -38,11 +38,11 @@ namespace sf
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Default specialization of RenderImageImpl,
/// \brief Default specialization of RenderTextureImpl,
/// using a in-memory context
///
////////////////////////////////////////////////////////////
class RenderImageImplDefault : public RenderImageImpl, GlResource
class RenderTextureImplDefault : public RenderTextureImpl, GlResource
{
public :
@ -50,22 +50,22 @@ public :
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
RenderImageImplDefault();
RenderTextureImplDefault();
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
~RenderImageImplDefault();
~RenderTextureImplDefault();
private :
////////////////////////////////////////////////////////////
/// \brief Create the render image implementation
/// \brief Create the render texture implementation
///
/// \param width Width of the image to render to
/// \param height Height of the image to render to
/// \param textureId OpenGL texture identifier of the target image
/// \param width Width of the texture to render to
/// \param height Height of the texture to render to
/// \param textureId OpenGL identifier of the target texture
/// \param depthBuffer Is a depth buffer requested?
///
/// \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);
////////////////////////////////////////////////////////////
/// \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
///
@ -104,4 +104,4 @@ private :
} // namespace sf
#endif // SFML_RENDERIMAGEIMPLDEFAULT_HPP
#endif // SFML_RENDERTEXTUREIMPLDEFAULT_HPP

View File

@ -25,8 +25,8 @@
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/RenderImageImplFBO.hpp>
#include <SFML/Graphics/Image.hpp>
#include <SFML/Graphics/RenderTextureImplFBO.hpp>
#include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/GLCheck.hpp>
#include <SFML/System/Err.hpp>
@ -36,7 +36,7 @@ namespace sf
namespace priv
{
////////////////////////////////////////////////////////////
RenderImageImplFBO::RenderImageImplFBO() :
RenderTextureImplFBO::RenderTextureImplFBO() :
myFrameBuffer(0),
myDepthBuffer(0)
{
@ -45,7 +45,7 @@ myDepthBuffer(0)
////////////////////////////////////////////////////////////
RenderImageImplFBO::~RenderImageImplFBO()
RenderTextureImplFBO::~RenderTextureImplFBO()
{
EnsureGlContext();
@ -69,7 +69,7 @@ RenderImageImplFBO::~RenderImageImplFBO()
////////////////////////////////////////////////////////////
bool RenderImageImplFBO::IsAvailable()
bool RenderTextureImplFBO::IsAvailable()
{
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
myContext = new Context;
@ -92,7 +92,7 @@ bool RenderImageImplFBO::Create(unsigned int width, unsigned int height, unsigne
myFrameBuffer = static_cast<unsigned int>(frameBuffer);
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;
}
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);
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;
}
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));
}
// 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));
// A final check, just to be sure...
if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT)
{
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;
}
@ -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);
}
////////////////////////////////////////////////////////////
void RenderImageImplFBO::UpdateTexture(unsigned int)
void RenderTextureImplFBO::UpdateTexture(unsigned int)
{
glFlush();
}

View File

@ -22,13 +22,13 @@
//
////////////////////////////////////////////////////////////
#ifndef SFML_RENDERIMAGEIMPLFBO_HPP
#define SFML_RENDERIMAGEIMPLFBO_HPP
#ifndef SFML_RENDERTEXTUREIMPLFBO_HPP
#define SFML_RENDERTEXTUREIMPLFBO_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/RenderImageImpl.hpp>
#include <SFML/Graphics/RenderTextureImpl.hpp>
#include <SFML/Window/Context.hpp>
#include <SFML/Window/GlResource.hpp>
@ -38,11 +38,11 @@ namespace sf
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Specialization of RenderImageImpl using the
/// Frame Buffer Object OpenGL extension
/// \brief Specialization of RenderTextureImpl using the
/// FrameBuffer Object OpenGL extension
///
////////////////////////////////////////////////////////////
class RenderImageImplFBO : public RenderImageImpl, GlResource
class RenderTextureImplFBO : public RenderTextureImpl, GlResource
{
public :
@ -50,18 +50,18 @@ public :
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
RenderImageImplFBO();
RenderTextureImplFBO();
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
~RenderImageImplFBO();
~RenderTextureImplFBO();
////////////////////////////////////////////////////////////
/// \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();
@ -69,11 +69,11 @@ public :
private :
////////////////////////////////////////////////////////////
/// \brief Create the render image implementation
/// \brief Create the render texture implementation
///
/// \param width Width of the image to render to
/// \param height Height of the image to render to
/// \param textureId OpenGL texture identifier of the target image
/// \param width Width of the texture to render to
/// \param height Height of the texture to render to
/// \param textureId OpenGL identifier of the target texture
/// \param depthBuffer Is a depth buffer requested?
///
/// \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);
////////////////////////////////////////////////////////////
/// \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
///
@ -112,4 +112,4 @@ private :
} // namespace sf
#endif // SFML_RENDERIMAGEIMPLFBO_HPP
#endif // SFML_RENDERTEXTUREIMPLFBO_HPP

View File

@ -26,6 +26,7 @@
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/RenderWindow.hpp>
#include <SFML/Graphics/GLCheck.hpp>
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()
{

View File

@ -27,7 +27,7 @@
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Renderer.hpp>
#include <SFML/Graphics/RenderTarget.hpp>
#include <SFML/Graphics/Image.hpp>
#include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/Shader.hpp>
#include <SFML/Graphics/GLCheck.hpp>
@ -202,7 +202,7 @@ void Renderer::SetBlendMode(Blend::Mode mode)
{
// Alpha blending
// 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 :
case Blend::Alpha :
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)
{
@ -246,12 +246,6 @@ void Renderer::SetTexture(const Image* texture)
myTextureId = texture ? texture->myTexture : 0;
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)
{

View File

@ -26,7 +26,7 @@
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Sprite.hpp>
#include <SFML/Graphics/Image.hpp>
#include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/Renderer.hpp>
#include <utility>
@ -35,6 +35,7 @@ namespace sf
{
////////////////////////////////////////////////////////////
Sprite::Sprite() :
Drawable (),
mySubRect (0, 0, 1, 1),
myIsFlippedX(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) :
Drawable (position, scale, rotation, color),
Sprite::Sprite(const Texture& texture) :
Drawable (),
mySubRect (0, 0, 1, 1),
myIsFlippedX(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 (!myImage)
// If there was no valid texture before, force adjusting to the new texture size
if (!myTexture)
adjustToNewSize = true;
// If we want to adjust the size and the new image is valid, we adjust the source rectangle
if (adjustToNewSize && (image.GetWidth() > 0) && (image.GetHeight() > 0))
// If we want to adjust the size and the new texture is valid, we adjust the source rectangle
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
myImage = &image;
// Assign the new texture
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
{
@ -156,10 +137,10 @@ void Sprite::Render(RenderTarget&, Renderer& renderer) const
float width = static_cast<float>(mySubRect.Width);
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;
if (myImage)
coords = myImage->GetTexCoords(mySubRect);
if (myTexture)
coords = myTexture->GetTexCoords(mySubRect);
// Compute the texture coordinates
float left = coords.Left;
@ -170,7 +151,7 @@ void Sprite::Render(RenderTarget&, Renderer& renderer) const
if (myIsFlippedY) std::swap(top, bottom);
// Bind the texture
renderer.SetTexture(myImage);
renderer.SetTexture(myTexture);
// Draw the sprite's geometry
renderer.Begin(Renderer::TriangleStrip);

View File

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