Added automatic batching to improve performances
Moved the ConvertCoords function from RenderWindow to RenderTarget git-svn-id: https://sfml.svn.sourceforge.net/svnroot/sfml/branches/sfml2@1221 4e206d99-4929-0410-ac5d-dfc041789085
This commit is contained in:
parent
1852614e16
commit
565172fc75
51 changed files with 2835 additions and 865 deletions
123
src/SFML/Graphics/Batch.cpp
Normal file
123
src/SFML/Graphics/Batch.cpp
Normal file
|
@ -0,0 +1,123 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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/Batch.hpp>
|
||||
#include <SFML/Graphics/Image.hpp>
|
||||
#include <SFML/Graphics/GLCheck.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
Batch::Batch(const Image* texture, Blend::Mode blendMode, const IntRect& viewport) :
|
||||
myTexture (texture),
|
||||
myBlendMode(blendMode),
|
||||
myViewport (viewport),
|
||||
myStart (0),
|
||||
myCount (0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Batch::Matches(const Image* texture, Blend::Mode blendMode, const IntRect& viewport) const
|
||||
{
|
||||
return myTexture == texture &&
|
||||
myBlendMode == blendMode &&
|
||||
myViewport.Left == viewport.Left &&
|
||||
myViewport.Top == viewport.Top &&
|
||||
myViewport.Right == viewport.Right &&
|
||||
myViewport.Bottom == viewport.Bottom;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Batch::Begin(std::size_t index)
|
||||
{
|
||||
myStart = index;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Batch::End(std::size_t index)
|
||||
{
|
||||
myCount = index - myStart;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::size_t Batch::GetStartIndex() const
|
||||
{
|
||||
return myStart;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::size_t Batch::GetIndexCount() const
|
||||
{
|
||||
return myCount;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Batch::ApplyStates() const
|
||||
{
|
||||
// Set the viewport
|
||||
GLCheck(glViewport(myViewport.Left, myViewport.Top, myViewport.GetSize().x, myViewport.GetSize().y));
|
||||
|
||||
// Set the blending mode
|
||||
if (myBlendMode == Blend::None)
|
||||
{
|
||||
GLCheck(glDisable(GL_BLEND));
|
||||
}
|
||||
else
|
||||
{
|
||||
GLCheck(glEnable(GL_BLEND));
|
||||
|
||||
// @todo the resulting alpha may not be correct, which matters when target is a RenderImage.
|
||||
// find a fix for this (glBlendFuncSeparate -- but not supported by every graphics card)
|
||||
switch (myBlendMode)
|
||||
{
|
||||
default :
|
||||
case Blend::Alpha : GLCheck(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); break;
|
||||
case Blend::Add : GLCheck(glBlendFunc(GL_SRC_ALPHA, GL_ONE)); break;
|
||||
case Blend::Multiply : GLCheck(glBlendFunc(GL_DST_COLOR, GL_ZERO)); break;
|
||||
}
|
||||
}
|
||||
|
||||
// Bind the texture
|
||||
if (myTexture)
|
||||
myTexture->Bind();
|
||||
else
|
||||
GLCheck(glDisable(GL_TEXTURE_2D));
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
125
src/SFML/Graphics/Batch.hpp
Normal file
125
src/SFML/Graphics/Batch.hpp
Normal file
|
@ -0,0 +1,125 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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_BATCH_HPP
|
||||
#define SFML_BATCH_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Graphics/Drawable.hpp>
|
||||
#include <SFML/Graphics/Rect.hpp>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
class Image;
|
||||
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Batch of geometry / render states to render
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class Batch
|
||||
{
|
||||
public :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Construct the batch with its render states
|
||||
///
|
||||
/// \param texture Texture to use
|
||||
/// \param blendMode Blending mode
|
||||
/// \param viewport Target viewport
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Batch(const Image* texture = NULL, Blend::Mode blendMode = Blend::Alpha, const IntRect& viewport = IntRect());
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Check if the batch matches a set of render states
|
||||
///
|
||||
/// \param texture Texture to use
|
||||
/// \param blendMode Blending mode
|
||||
/// \param viewport Target viewport
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Matches(const Image* texture, Blend::Mode blendMode, const IntRect& viewport) const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Setup the start index of the batch
|
||||
///
|
||||
/// \param index Start index
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void Begin(std::size_t index);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Setup the end index of the batch
|
||||
///
|
||||
/// \param index End index
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void End(std::size_t index);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Return the start index of the batch
|
||||
///
|
||||
/// \return Start index
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
std::size_t GetStartIndex() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Return the number of indices to render with this batch
|
||||
///
|
||||
/// \return Index count
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
std::size_t GetIndexCount() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Apply the render states of the batch
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void ApplyStates() const;
|
||||
|
||||
private :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
const Image* myTexture; ///< Texture used by the batch
|
||||
Blend::Mode myBlendMode; ///< Blending mode used by the batch
|
||||
IntRect myViewport; ///< Target viewport for the batch
|
||||
std::size_t myStart; ///< Index of the first index to render with this batch
|
||||
std::size_t myCount; ///< Number of indices to render with this batch
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_BATCH_HPP
|
|
@ -26,8 +26,8 @@
|
|||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Graphics/Drawable.hpp>
|
||||
#include <SFML/Graphics/GLCheck.hpp>
|
||||
#include <SFML/Window/Window.hpp>
|
||||
#include <SFML/Graphics/RenderQueue.hpp>
|
||||
#include <SFML/Graphics/RenderTarget.hpp>
|
||||
#include <math.h>
|
||||
|
||||
|
||||
|
@ -358,44 +358,21 @@ const Matrix3& Drawable::GetInverseMatrix() const
|
|||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Draw the object into the specified window
|
||||
/// Draw the object into the specified render target
|
||||
////////////////////////////////////////////////////////////
|
||||
void Drawable::Draw(RenderTarget& target) const
|
||||
void Drawable::Draw(RenderTarget& target, RenderQueue& queue) const
|
||||
{
|
||||
// Save the current modelview matrix and set the new one
|
||||
GLCheck(glMatrixMode(GL_MODELVIEW));
|
||||
GLCheck(glPushMatrix());
|
||||
GLCheck(glMultMatrixf(GetMatrix().Get4x4Elements()));
|
||||
// Set the current model-view matrix
|
||||
queue.ApplyModelView(GetMatrix());
|
||||
|
||||
// Setup alpha-blending
|
||||
if (myBlendMode == Blend::None)
|
||||
{
|
||||
GLCheck(glDisable(GL_BLEND));
|
||||
}
|
||||
else
|
||||
{
|
||||
GLCheck(glEnable(GL_BLEND));
|
||||
// Set the current global color
|
||||
queue.ApplyColor(myColor);
|
||||
|
||||
// @todo the resulting alpha may not be correct, which matters when target is a RenderImage.
|
||||
// find a fix for this (glBlendFuncSeparate -- but not supported by every graphics card)
|
||||
switch (myBlendMode)
|
||||
{
|
||||
case Blend::Alpha : GLCheck(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); break;
|
||||
case Blend::Add : GLCheck(glBlendFunc(GL_SRC_ALPHA, GL_ONE)); break;
|
||||
case Blend::Multiply : GLCheck(glBlendFunc(GL_DST_COLOR, GL_ZERO)); break;
|
||||
default : break;
|
||||
}
|
||||
}
|
||||
|
||||
// Set color
|
||||
GLCheck(glColor4ub(myColor.r, myColor.g, myColor.b, myColor.a));
|
||||
// Set the current alpha-blending mode
|
||||
queue.SetBlendMode(myBlendMode);
|
||||
|
||||
// Let the derived class render the object geometry
|
||||
Render(target);
|
||||
|
||||
// Restore the previous modelview matrix
|
||||
GLCheck(glMatrixMode(GL_MODELVIEW));
|
||||
GLCheck(glPopMatrix());
|
||||
Render(target, queue);
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -214,6 +214,11 @@ FT_Error FontLoader::CreateBitmapFont(FT_Face face, unsigned int charSize, const
|
|||
glyphs.insert(std::make_pair(bitmapGlyph, charset[i]));
|
||||
}
|
||||
|
||||
// Leave a small margin around characters, so that filtering doesn't
|
||||
// pollute them with pixels from neighbours
|
||||
unsigned int offset = 1;
|
||||
unsigned int margin = offset + 1;
|
||||
|
||||
// Copy the rendered glyphs into the texture
|
||||
unsigned int maxHeight = 0;
|
||||
std::map<Uint32, IntRect> coords;
|
||||
|
@ -225,31 +230,31 @@ FT_Error FontLoader::CreateBitmapFont(FT_Face face, unsigned int charSize, const
|
|||
FT_Bitmap& bitmap = bitmapGlyph->bitmap;
|
||||
|
||||
// Make sure we don't go over the texture width
|
||||
if (left + bitmap.width + 1 >= texWidth)
|
||||
if (left + bitmap.width + margin >= texWidth)
|
||||
left = 0;
|
||||
|
||||
// Compute the top coordinate
|
||||
top = tops[left];
|
||||
for (int x = 0; x < bitmap.width + 1; ++x)
|
||||
for (unsigned int x = 0; x < bitmap.width + margin; ++x)
|
||||
top = std::max(top, tops[left + x]);
|
||||
top++;
|
||||
top += margin;
|
||||
|
||||
// Make sure we don't go over the texture height -- resize it if we need more space
|
||||
if (top + bitmap.rows + 1 >= texHeight)
|
||||
if (top + bitmap.rows + margin >= texHeight)
|
||||
{
|
||||
texHeight *= 2;
|
||||
glyphsBuffer.resize(texWidth * texHeight * 4);
|
||||
}
|
||||
|
||||
// Store the character's position and size
|
||||
curGlyph.Rectangle.Left = bitmapGlyph->left;
|
||||
curGlyph.Rectangle.Top = -bitmapGlyph->top;
|
||||
curGlyph.Rectangle.Right = curGlyph.Rectangle.Left + bitmap.width;
|
||||
curGlyph.Rectangle.Bottom = bitmap.rows - bitmapGlyph->top;
|
||||
curGlyph.Rectangle.Left = bitmapGlyph->left - offset;
|
||||
curGlyph.Rectangle.Top = -bitmapGlyph->top - offset;
|
||||
curGlyph.Rectangle.Right = (curGlyph.Rectangle.Left + bitmap.width + offset) / 1;
|
||||
curGlyph.Rectangle.Bottom = bitmap.rows - bitmapGlyph->top + offset;
|
||||
curGlyph.Advance = bitmapGlyph->root.advance.x >> 16;
|
||||
|
||||
// Texture size may change, so let the texture coordinates be calculated later
|
||||
coords[i->second] = IntRect(left + 1, top + 1, left + bitmap.width + 1, top + bitmap.rows + 1);
|
||||
coords[i->second] = IntRect(left + offset, top + offset, left + bitmap.width + offset + margin, top + bitmap.rows + offset + margin);
|
||||
|
||||
// Draw the glyph into our bitmap font
|
||||
const Uint8* pixels = bitmap.buffer;
|
||||
|
@ -257,19 +262,19 @@ FT_Error FontLoader::CreateBitmapFont(FT_Face face, unsigned int charSize, const
|
|||
{
|
||||
for (int x = 0; x < bitmap.width; ++x)
|
||||
{
|
||||
std::size_t index = x + left + 1 + (y + top + 1) * texWidth;
|
||||
std::size_t index = x + left + margin + (y + top + margin) * texWidth;
|
||||
glyphsBuffer[index * 4 + 0] = 255;
|
||||
glyphsBuffer[index * 4 + 1] = 255;
|
||||
glyphsBuffer[index * 4 + 2] = 255;
|
||||
glyphsBuffer[index * 4 + 3] = pixels[x];
|
||||
glyphsBuffer[index * 4 + 3] = pixels[x] * pixels[x] / 255;
|
||||
}
|
||||
pixels += bitmap.pitch;
|
||||
}
|
||||
|
||||
// Update the rendering coordinates
|
||||
for (int x = 0; x < bitmap.width + 1; ++x)
|
||||
for (unsigned int x = 0; x < bitmap.width + margin; ++x)
|
||||
tops[left + x] = top + bitmap.rows;
|
||||
left += bitmap.width + 1;
|
||||
left += bitmap.width + margin;
|
||||
if (top + bitmap.rows > maxHeight)
|
||||
maxHeight = top + bitmap.rows;
|
||||
|
||||
|
@ -278,7 +283,7 @@ FT_Error FontLoader::CreateBitmapFont(FT_Face face, unsigned int charSize, const
|
|||
}
|
||||
|
||||
// Create the font's texture
|
||||
texHeight = maxHeight + 1;
|
||||
texHeight = maxHeight + margin;
|
||||
glyphsBuffer.resize(texWidth * texHeight * 4);
|
||||
font.myTexture.LoadFromPixels(texWidth, texHeight, &glyphsBuffer[0]);
|
||||
|
||||
|
|
68
src/SFML/Graphics/GeometryRenderer.cpp
Normal file
68
src/SFML/Graphics/GeometryRenderer.cpp
Normal file
|
@ -0,0 +1,68 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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/GeometryRenderer.hpp>
|
||||
#include <SFML/Graphics/GeometryRendererVBO.hpp>
|
||||
#include <SFML/Graphics/GeometryRendererVA.hpp>
|
||||
#include <SFML/Graphics/GeometryRendererIM.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
GeometryRenderer* GeometryRenderer::New()
|
||||
{
|
||||
// Choose the best implementation according to the graphics card's capabilities
|
||||
if (priv::GeometryRendererVBO::IsSupported())
|
||||
{
|
||||
// Use Vertex Buffer Objects
|
||||
return new priv::GeometryRendererVBO;
|
||||
}
|
||||
else if (priv::GeometryRendererVA::IsSupported())
|
||||
{
|
||||
// Use Vertex Arrays
|
||||
return new priv::GeometryRendererVA;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use Immediate Mode
|
||||
return new priv::GeometryRendererIM;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
GeometryRenderer::~GeometryRenderer()
|
||||
{
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
106
src/SFML/Graphics/GeometryRenderer.hpp
Normal file
106
src/SFML/Graphics/GeometryRenderer.hpp
Normal file
|
@ -0,0 +1,106 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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_GEOMETRYRENDERER_HPP
|
||||
#define SFML_GEOMETRYRENDERER_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/NonCopyable.hpp>
|
||||
#include <cstdlib>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Abstract base class for optimized geometry renderers
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class GeometryRenderer : NonCopyable
|
||||
{
|
||||
public :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Construct a new GeometryRenderer
|
||||
///
|
||||
/// This function selects the best specialization available,
|
||||
/// according to the capabilities of the system.
|
||||
///
|
||||
/// \return New instance of GeometryRenderer; cannot be NULL
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static GeometryRenderer* New();
|
||||
|
||||
public :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Virtual destructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual ~GeometryRenderer();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Prepare the geometry for rendering
|
||||
///
|
||||
/// This function is called once before all the triangles
|
||||
/// are rendered.
|
||||
///
|
||||
/// \param vertices Pointer to the vertex array
|
||||
/// \param verticesCount Number of vertices to render
|
||||
/// \param indices Pointer to the index array
|
||||
/// \param indicesCount Number of indices to render
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual void Begin(const float* vertices, std::size_t verticesCount, const unsigned int* indices, std::size_t indicesCount) = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Stop rendering geometry
|
||||
///
|
||||
/// This function is called once after all the triangles
|
||||
/// have been rendered.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual void End() = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Render a chunk of triangles
|
||||
///
|
||||
/// The primitives are rendered as a list of triangles (no strip or fan).
|
||||
///
|
||||
/// \param start Index in the indices array of the first index to be rendered
|
||||
/// \param count Number of indices to be rendered
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual void RenderTriangles(std::size_t start, std::size_t count) = 0;
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_GEOMETRYRENDERER_HPP
|
95
src/SFML/Graphics/GeometryRendererIM.cpp
Normal file
95
src/SFML/Graphics/GeometryRendererIM.cpp
Normal file
|
@ -0,0 +1,95 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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/GeometryRendererIM.hpp>
|
||||
#include <SFML/Graphics/GLCheck.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
bool GeometryRendererIM::IsSupported()
|
||||
{
|
||||
// Immediate mode is always supported
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
GeometryRendererIM::GeometryRendererIM() :
|
||||
myVertices(NULL),
|
||||
myIndices (NULL)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void GeometryRendererIM::Begin(const float* vertices, std::size_t, const unsigned int* indices, std::size_t)
|
||||
{
|
||||
// Store the geometry informations for later rendering
|
||||
myVertices = vertices;
|
||||
myIndices = indices;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void GeometryRendererIM::End()
|
||||
{
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void GeometryRendererIM::RenderTriangles(std::size_t start, std::size_t count)
|
||||
{
|
||||
// Caculate the bounds of the geometry range to render
|
||||
const unsigned int* begin = myIndices + start;
|
||||
const unsigned int* end = begin + count;
|
||||
|
||||
// Begin rendering
|
||||
glBegin(GL_TRIANGLES);
|
||||
|
||||
// Send the vertices one by one
|
||||
for (const unsigned int* index = begin; index != end; index++)
|
||||
{
|
||||
const float* vertex = myVertices + *index * 8;
|
||||
|
||||
glColor4f(vertex[2], vertex[3], vertex[4], vertex[5]);
|
||||
glTexCoord2f(vertex[6], vertex[7]);
|
||||
glVertex2f(vertex[0], vertex[1]);
|
||||
}
|
||||
|
||||
// End rendering
|
||||
glEnd();
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
108
src/SFML/Graphics/GeometryRendererIM.hpp
Normal file
108
src/SFML/Graphics/GeometryRendererIM.hpp
Normal file
|
@ -0,0 +1,108 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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_GEOMETRYRENDERERIM_HPP
|
||||
#define SFML_GEOMETRYRENDERERIM_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Graphics/GeometryRenderer.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Geometry renderer using immediate mode
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class GeometryRendererIM : public GeometryRenderer
|
||||
{
|
||||
public :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Check if this implementation is supported by the system
|
||||
///
|
||||
/// \return True if the immediate mode renderer is supported
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static bool IsSupported();
|
||||
|
||||
public :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
GeometryRendererIM();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Prepare the geometry for rendering
|
||||
///
|
||||
/// This function is called once before all the triangles
|
||||
/// are rendered.
|
||||
///
|
||||
/// \param vertices Pointer to the vertex array
|
||||
/// \param verticesCount Number of vertices to render
|
||||
/// \param indices Pointer to the index array
|
||||
/// \param indicesCount Number of indices to render
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual void Begin(const float* vertices, std::size_t verticesCount, const unsigned int* indices, std::size_t indicesCount);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Stop rendering geometry
|
||||
///
|
||||
/// This function is called once after all the triangles
|
||||
/// have been rendered.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual void End();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Render a chunk of triangles
|
||||
///
|
||||
/// The primitives are rendered as a list of triangles (no strip or fan).
|
||||
///
|
||||
/// \param start Index in the indices array of the first index to be rendered
|
||||
/// \param count Number of indices to be rendered
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual void RenderTriangles(std::size_t start, std::size_t count);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
const float* myVertices; ///< Pointer to the vertices to render
|
||||
const unsigned int* myIndices; ///< Pointer to the indices to render
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_GEOMETRYRENDERERIM_HPP
|
99
src/SFML/Graphics/GeometryRendererVA.cpp
Normal file
99
src/SFML/Graphics/GeometryRendererVA.cpp
Normal file
|
@ -0,0 +1,99 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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/GeometryRendererVA.hpp>
|
||||
#include <SFML/Graphics/GLCheck.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
bool GeometryRendererVA::IsSupported()
|
||||
{
|
||||
EnsureGlewInit();
|
||||
|
||||
return glewIsSupported("GL_EXT_vertex_array") != 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
GeometryRendererVA::GeometryRendererVA() :
|
||||
myIndices(NULL)
|
||||
{
|
||||
EnsureGlewInit();
|
||||
|
||||
myCanLock = glewIsSupported("GL_EXT_compiled_vertex_array") != 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void GeometryRendererVA::Begin(const float* vertices, std::size_t verticesCount, const unsigned int* indices, std::size_t)
|
||||
{
|
||||
static const GLsizei stride = 8 * sizeof(float);
|
||||
|
||||
// Setup positions
|
||||
GLCheck(glEnableClientState(GL_VERTEX_ARRAY));
|
||||
GLCheck(glVertexPointer(2, GL_FLOAT, stride, vertices));
|
||||
|
||||
// Setup colors
|
||||
GLCheck(glEnableClientState(GL_COLOR_ARRAY));
|
||||
GLCheck(glColorPointer(4, GL_FLOAT, stride, vertices + 2));
|
||||
|
||||
// Setup texture coordinates
|
||||
GLCheck(glClientActiveTextureARB(GL_TEXTURE0_ARB));
|
||||
GLCheck(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
|
||||
GLCheck(glTexCoordPointer(2, GL_FLOAT, stride, vertices + 6));
|
||||
|
||||
// Lock (compile) the vertex array if supported
|
||||
if (myCanLock)
|
||||
GLCheck(glLockArraysEXT(0, verticesCount / 8));
|
||||
|
||||
// Store indices for later use
|
||||
myIndices = indices;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void GeometryRendererVA::End()
|
||||
{
|
||||
// Unlock the vertex array if it was locked
|
||||
if (myCanLock)
|
||||
GLCheck(glUnlockArraysEXT());
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void GeometryRendererVA::RenderTriangles(std::size_t start, std::size_t count)
|
||||
{
|
||||
GLCheck(glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, myIndices + start));
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
108
src/SFML/Graphics/GeometryRendererVA.hpp
Normal file
108
src/SFML/Graphics/GeometryRendererVA.hpp
Normal file
|
@ -0,0 +1,108 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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_GEOMETRYRENDERERVA_HPP
|
||||
#define SFML_GEOMETRYRENDERERVA_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Graphics/GeometryRenderer.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Geometry renderer using vertex arrays
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class GeometryRendererVA : public GeometryRenderer
|
||||
{
|
||||
public :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Check if this implementation is supported by the system
|
||||
///
|
||||
/// \return True if the vertex array renderer is supported
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static bool IsSupported();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
GeometryRendererVA();
|
||||
|
||||
public :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Prepare the geometry for rendering
|
||||
///
|
||||
/// This function is called once before all the triangles
|
||||
/// are rendered.
|
||||
///
|
||||
/// \param vertices Pointer to the vertex array
|
||||
/// \param verticesCount Number of vertices to render
|
||||
/// \param indices Pointer to the index array
|
||||
/// \param indicesCount Number of indices to render
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual void Begin(const float* vertices, std::size_t verticesCount, const unsigned int* indices, std::size_t indicesCount);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Stop rendering geometry
|
||||
///
|
||||
/// This function is called once after all the triangles
|
||||
/// have been rendered.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual void End();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Render a chunk of triangles
|
||||
///
|
||||
/// The primitives are rendered as a list of triangles (no strip or fan).
|
||||
///
|
||||
/// \param start Index in the indices array of the first index to be rendered
|
||||
/// \param count Number of indices to be rendered
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual void RenderTriangles(std::size_t start, std::size_t count);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
bool myCanLock; ///< Is geometry locking supported?
|
||||
const unsigned int* myIndices; ///< Pointer to the indices to render
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_GEOMETRYRENDERERVA_HPP
|
127
src/SFML/Graphics/GeometryRendererVBO.cpp
Normal file
127
src/SFML/Graphics/GeometryRendererVBO.cpp
Normal file
|
@ -0,0 +1,127 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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/GeometryRendererVBO.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
bool GeometryRendererVBO::IsSupported()
|
||||
{
|
||||
EnsureGlewInit();
|
||||
|
||||
return glewIsSupported("GL_ARB_vertex_buffer_object") != 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
GeometryRendererVBO::GeometryRendererVBO() :
|
||||
myVertexBufferSize(0),
|
||||
myIndexBufferSize (0)
|
||||
{
|
||||
EnsureGlewInit();
|
||||
|
||||
// Create the buffers
|
||||
GLCheck(glGenBuffersARB(1, &myVertexBuffer));
|
||||
GLCheck(glGenBuffersARB(1, &myIndexBuffer));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
GeometryRendererVBO::~GeometryRendererVBO()
|
||||
{
|
||||
// Free the buffers
|
||||
GLCheck(glDeleteBuffersARB(1, &myVertexBuffer));
|
||||
GLCheck(glDeleteBuffersARB(1, &myIndexBuffer));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void GeometryRendererVBO::Begin(const float* vertices, std::size_t verticesCount, const unsigned int* indices, std::size_t indicesCount)
|
||||
{
|
||||
// Update the vertex buffer data (make it grow if it is not large enough)
|
||||
GLCheck(glBindBufferARB(GL_ARRAY_BUFFER_ARB, myVertexBuffer));
|
||||
if (verticesCount > myVertexBufferSize)
|
||||
{
|
||||
GLCheck(glBufferDataARB(GL_ARRAY_BUFFER_ARB, verticesCount * sizeof(float), vertices, GL_DYNAMIC_DRAW_ARB));
|
||||
myVertexBufferSize = verticesCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
GLCheck(glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, verticesCount * sizeof(float), vertices));
|
||||
}
|
||||
|
||||
// Update the index buffer data (make it grow if it is not large enough)
|
||||
GLCheck(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, myIndexBuffer));
|
||||
if (indicesCount > myIndexBufferSize)
|
||||
{
|
||||
GLCheck(glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, indicesCount * sizeof(unsigned int), indices, GL_DYNAMIC_DRAW_ARB));
|
||||
myIndexBufferSize = indicesCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
GLCheck(glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, indicesCount * sizeof(unsigned int), indices));
|
||||
}
|
||||
|
||||
static const GLsizei stride = 8 * sizeof(float);
|
||||
static const float* pointer = NULL;
|
||||
|
||||
// Setup positions
|
||||
GLCheck(glEnableClientState(GL_VERTEX_ARRAY));
|
||||
GLCheck(glVertexPointer(2, GL_FLOAT, stride, pointer));
|
||||
|
||||
// Setup colors
|
||||
GLCheck(glEnableClientState(GL_COLOR_ARRAY));
|
||||
GLCheck(glColorPointer(4, GL_FLOAT, stride, pointer + 2));
|
||||
|
||||
// Setup texture coordinates
|
||||
GLCheck(glClientActiveTextureARB(GL_TEXTURE0_ARB));
|
||||
GLCheck(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
|
||||
GLCheck(glTexCoordPointer(2, GL_FLOAT, stride, pointer + 6));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void GeometryRendererVBO::End()
|
||||
{
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void GeometryRendererVBO::RenderTriangles(std::size_t start, std::size_t count)
|
||||
{
|
||||
static const unsigned int* pointer = NULL;
|
||||
GLCheck(glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, pointer + start));
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
117
src/SFML/Graphics/GeometryRendererVBO.hpp
Normal file
117
src/SFML/Graphics/GeometryRendererVBO.hpp
Normal file
|
@ -0,0 +1,117 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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_GEOMETRYRENDERERVBO_HPP
|
||||
#define SFML_GEOMETRYRENDERERVBO_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Graphics/GeometryRenderer.hpp>
|
||||
#include <SFML/Graphics/GLCheck.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Geometry renderer using vertex buffer objects
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class GeometryRendererVBO : public GeometryRenderer
|
||||
{
|
||||
public :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Check if this implementation is supported by the system
|
||||
///
|
||||
/// \return True if the vertex buffer objects renderer is supported
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static bool IsSupported();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
GeometryRendererVBO();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
~GeometryRendererVBO();
|
||||
|
||||
public :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Prepare the geometry for rendering
|
||||
///
|
||||
/// This function is called once before all the triangles
|
||||
/// are rendered.
|
||||
///
|
||||
/// \param vertices Pointer to the vertex array
|
||||
/// \param verticesCount Number of vertices to render
|
||||
/// \param indices Pointer to the index array
|
||||
/// \param indicesCount Number of indices to render
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual void Begin(const float* vertices, std::size_t verticesCount, const unsigned int* indices, std::size_t indicesCount);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Stop rendering geometry
|
||||
///
|
||||
/// This function is called once after all the triangles
|
||||
/// have been rendered.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual void End();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Render a chunk of triangles
|
||||
///
|
||||
/// The primitives are rendered as a list of triangles (no strip or fan).
|
||||
///
|
||||
/// \param start Index in the indices array of the first index to be rendered
|
||||
/// \param count Number of indices to be rendered
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual void RenderTriangles(std::size_t start, std::size_t count);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
GLuint myVertexBuffer;
|
||||
GLuint myIndexBuffer;
|
||||
std::size_t myVertexBufferSize;
|
||||
std::size_t myIndexBufferSize;
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_GEOMETRYRENDERERVBO_HPP
|
|
@ -50,7 +50,6 @@ myTexture (0),
|
|||
myIsSmooth (true),
|
||||
myNeedTextureUpdate(false),
|
||||
myNeedArrayUpdate (false),
|
||||
myUpdateSource (NULL),
|
||||
myPixelsFlipped (false)
|
||||
{
|
||||
|
||||
|
@ -71,7 +70,6 @@ myIsSmooth (copy.myIsSmooth),
|
|||
myPixels (copy.myPixels),
|
||||
myNeedTextureUpdate(false),
|
||||
myNeedArrayUpdate (false),
|
||||
myUpdateSource (copy.myUpdateSource),
|
||||
myPixelsFlipped (copy.myPixelsFlipped)
|
||||
{
|
||||
CreateTexture();
|
||||
|
@ -90,7 +88,6 @@ myTexture (0),
|
|||
myIsSmooth (true),
|
||||
myNeedTextureUpdate(false),
|
||||
myNeedArrayUpdate (false),
|
||||
myUpdateSource (NULL),
|
||||
myPixelsFlipped (false)
|
||||
{
|
||||
Create(width, height, color);
|
||||
|
@ -109,7 +106,6 @@ myTexture (0),
|
|||
myIsSmooth (true),
|
||||
myNeedTextureUpdate(false),
|
||||
myNeedArrayUpdate (false),
|
||||
myUpdateSource (NULL),
|
||||
myPixelsFlipped (false)
|
||||
{
|
||||
LoadFromPixels(width, height, data);
|
||||
|
@ -387,6 +383,9 @@ bool Image::CopyScreen(RenderWindow& window, const IntRect& sourceRect)
|
|||
myWidth = srcRect.GetSize().x;
|
||||
myHeight = srcRect.GetSize().y;
|
||||
|
||||
// Make sure that pending drawables are rendered on the target window
|
||||
window.Flush();
|
||||
|
||||
// We can then create the texture
|
||||
if (window.SetActive() && CreateTexture())
|
||||
{
|
||||
|
@ -402,6 +401,8 @@ bool Image::CopyScreen(RenderWindow& window, const IntRect& sourceRect)
|
|||
myNeedArrayUpdate = true;
|
||||
myPixelsFlipped = true;
|
||||
|
||||
window.SetActive(false);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
@ -553,12 +554,13 @@ FloatRect Image::GetTexCoords(const IntRect& rect) const
|
|||
{
|
||||
float width = static_cast<float>(myTextureWidth);
|
||||
float height = static_cast<float>(myTextureHeight);
|
||||
float offset = myIsSmooth ? 0.5f : 0.0f;
|
||||
|
||||
FloatRect coords;
|
||||
coords.Left = rect.Left / width;
|
||||
coords.Top = rect.Top / height;
|
||||
coords.Right = rect.Right / width;
|
||||
coords.Bottom = rect.Bottom / height;
|
||||
coords.Left = (rect.Left + offset) / width;
|
||||
coords.Top = (rect.Top + offset) / height;
|
||||
coords.Right = (rect.Right - offset) / width;
|
||||
coords.Bottom = (rect.Bottom - offset) / height;
|
||||
|
||||
if (myPixelsFlipped)
|
||||
std::swap(coords.Top, coords.Bottom);
|
||||
|
@ -607,7 +609,6 @@ Image& Image::operator =(const Image& other)
|
|||
std::swap(myIsSmooth, temp.myIsSmooth);
|
||||
std::swap(myNeedArrayUpdate, temp.myNeedArrayUpdate);
|
||||
std::swap(myNeedTextureUpdate, temp.myNeedTextureUpdate);
|
||||
std::swap(myUpdateSource, temp.myUpdateSource);
|
||||
std::swap(myPixelsFlipped, temp.myPixelsFlipped);
|
||||
myPixels.swap(temp.myPixels);
|
||||
|
||||
|
@ -678,24 +679,15 @@ void Image::EnsureTextureUpdate()
|
|||
{
|
||||
if (myNeedTextureUpdate)
|
||||
{
|
||||
if (myTexture)
|
||||
if (myTexture && !myPixels.empty())
|
||||
{
|
||||
GLint previous;
|
||||
GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous));
|
||||
|
||||
if (myUpdateSource)
|
||||
{
|
||||
// External update
|
||||
myPixelsFlipped = myUpdateSource->UpdateImage(*this);
|
||||
myUpdateSource = NULL;
|
||||
}
|
||||
else if (!myPixels.empty())
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
// 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));
|
||||
}
|
||||
|
@ -769,19 +761,6 @@ void Image::EnsureArrayUpdate()
|
|||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Notify the image that an external source has modified
|
||||
/// its content.
|
||||
/// For internal use only (see RenderImage class).
|
||||
////////////////////////////////////////////////////////////
|
||||
void Image::ExternalUpdate(RenderImage& source)
|
||||
{
|
||||
myNeedTextureUpdate = true;
|
||||
myNeedArrayUpdate = true;
|
||||
myUpdateSource = &source;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Reset the image attributes
|
||||
////////////////////////////////////////////////////////////
|
||||
|
@ -797,7 +776,6 @@ void Image::Reset()
|
|||
myIsSmooth = true;
|
||||
myNeedTextureUpdate = false;
|
||||
myNeedArrayUpdate = false;
|
||||
myUpdateSource = NULL;
|
||||
myPixelsFlipped = false;
|
||||
myPixels.clear();
|
||||
}
|
||||
|
|
|
@ -275,7 +275,7 @@ bool PostFX::CanUsePostFX()
|
|||
////////////////////////////////////////////////////////////
|
||||
/// /see Drawable::Render
|
||||
////////////////////////////////////////////////////////////
|
||||
void PostFX::Render(RenderTarget& target) const
|
||||
void PostFX::Render(RenderTarget& target, RenderQueue&) const
|
||||
{
|
||||
// Check that we have a valid program
|
||||
if (!myShaderProgram)
|
||||
|
@ -283,7 +283,9 @@ void PostFX::Render(RenderTarget& target) const
|
|||
|
||||
// Copy the current framebuffer pixels to our frame buffer texture
|
||||
// The ugly cast is temporary until PostFx are rewritten :)
|
||||
myFrameBuffer.CopyScreen((RenderWindow&)target);
|
||||
RenderWindow& window = static_cast<RenderWindow&>(target);
|
||||
myFrameBuffer.CopyScreen(window);
|
||||
window.SetActive();
|
||||
|
||||
// Enable program
|
||||
GLCheck(glUseProgramObjectARB(myShaderProgram));
|
||||
|
|
|
@ -105,18 +105,24 @@ bool RenderImage::Create(unsigned int width, unsigned int height, bool depthBuff
|
|||
////////////////////////////////////////////////////////////
|
||||
bool RenderImage::SetActive(bool active)
|
||||
{
|
||||
if (myRenderImage && myRenderImage->Activate(active))
|
||||
{
|
||||
// After the RenderImage has been modified, we have to notify
|
||||
// the underlying image that its pixels have changed
|
||||
if (!active)
|
||||
myImage.ExternalUpdate(*this);
|
||||
return myRenderImage && myRenderImage->Activate(active);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Update the contents of the target
|
||||
////////////////////////////////////////////////////////////
|
||||
void RenderImage::Display()
|
||||
{
|
||||
// Render everything that has been drawn so far
|
||||
Flush();
|
||||
|
||||
// Update the target image
|
||||
if (myRenderImage)
|
||||
{
|
||||
return false;
|
||||
bool pixelsFlipped = myRenderImage->UpdateTexture(myImage.myTexture);
|
||||
myImage.myPixelsFlipped = pixelsFlipped;
|
||||
myImage.myNeedArrayUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -158,17 +164,6 @@ bool RenderImage::CanUseRenderImage()
|
|||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Update the pixels of the target image.
|
||||
/// This function is called automatically by the image when it
|
||||
/// needs to update its pixels, and is only meant for internal use.
|
||||
////////////////////////////////////////////////////////////
|
||||
bool RenderImage::UpdateImage(Image& target)
|
||||
{
|
||||
return myRenderImage && myRenderImage->UpdateTexture(target.myTexture);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Activate / deactivate the render image for rendering
|
||||
////////////////////////////////////////////////////////////
|
||||
|
|
328
src/SFML/Graphics/RenderQueue.cpp
Normal file
328
src/SFML/Graphics/RenderQueue.cpp
Normal file
|
@ -0,0 +1,328 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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/RenderQueue.hpp>
|
||||
#include <SFML/Graphics/Batch.hpp>
|
||||
#include <SFML/Graphics/GeometryRenderer.hpp>
|
||||
#include <SFML/Graphics/GLCheck.hpp>
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Private data
|
||||
////////////////////////////////////////////////////////////
|
||||
namespace
|
||||
{
|
||||
// Fast float to int conversion
|
||||
inline sf::Int32 Round(double value)
|
||||
{
|
||||
value += 6755399441055744.0;
|
||||
|
||||
#if defined(SFML_ENDIAN_LITTLE)
|
||||
return (reinterpret_cast<sf::Int32*>(&value))[0];
|
||||
#else
|
||||
return (reinterpret_cast<sf::Int32*>(&value))[1];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
RenderQueue::RenderQueue() :
|
||||
myCurrentTexture (NULL),
|
||||
myCurrentBlendMode (Blend::Alpha),
|
||||
myBaseIndex (0),
|
||||
myRenderer (priv::GeometryRenderer::New()),
|
||||
myCurrentBatch (NULL),
|
||||
myVertices (512),
|
||||
myIndices (512),
|
||||
myCurrentVertexCount(0),
|
||||
myCurrentIndexCount (0)
|
||||
{
|
||||
myCurrentStates = &myStatesStack[0];
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
RenderQueue::~RenderQueue()
|
||||
{
|
||||
// Destroy the geometry renderer
|
||||
delete myRenderer;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void RenderQueue::PushStates()
|
||||
{
|
||||
myCurrentStates++;
|
||||
*myCurrentStates = *(myCurrentStates - 1);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void RenderQueue::PopStates()
|
||||
{
|
||||
myCurrentStates--;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void RenderQueue::SetModelView(const Matrix3& matrix)
|
||||
{
|
||||
myCurrentStates->modelView = matrix;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void RenderQueue::ApplyModelView(const Matrix3& matrix)
|
||||
{
|
||||
myCurrentStates->modelView *= matrix;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void RenderQueue::SetProjection(const Matrix3& matrix)
|
||||
{
|
||||
myCurrentStates->projection = matrix;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void RenderQueue::ApplyProjection(const Matrix3& matrix)
|
||||
{
|
||||
myCurrentStates->projection *= matrix;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void RenderQueue::SetColor(const Color& color)
|
||||
{
|
||||
myCurrentStates->color = color;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void RenderQueue::ApplyColor(const Color& color)
|
||||
{
|
||||
myCurrentStates->color *= color;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void RenderQueue::SetViewport(const IntRect& viewport)
|
||||
{
|
||||
myCurrentViewport = viewport;
|
||||
myCurrentViewportSize.x = viewport.GetSize().x / 2.f;
|
||||
myCurrentViewportSize.y = viewport.GetSize().y / 2.f;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void RenderQueue::SetBlendMode(Blend::Mode mode)
|
||||
{
|
||||
myCurrentBlendMode = mode;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void RenderQueue::SetTexture(const Image* texture)
|
||||
{
|
||||
myCurrentTexture = texture;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void RenderQueue::BeginBatch()
|
||||
{
|
||||
// Check if the current batch differs from the new render states
|
||||
if (!myCurrentBatch || !myCurrentBatch->Matches(myCurrentTexture, myCurrentBlendMode, myCurrentViewport))
|
||||
{
|
||||
// Close the current batch
|
||||
if (myCurrentBatch)
|
||||
myCurrentBatch->End(myCurrentIndexCount);
|
||||
|
||||
// Create a new one
|
||||
priv::Batch batch(myCurrentTexture, myCurrentBlendMode, myCurrentViewport);
|
||||
myBatches.push_back(batch);
|
||||
myCurrentBatch = &myBatches.back();
|
||||
myCurrentBatch->Begin(myCurrentIndexCount);
|
||||
}
|
||||
|
||||
// Update the combined transform matrix
|
||||
myCurrentTransform = myCurrentStates->projection * myCurrentStates->modelView;
|
||||
|
||||
// Update the current base index
|
||||
myBaseIndex = myCurrentVertexCount / 8;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void RenderQueue::AddVertex(float x, float y)
|
||||
{
|
||||
AddVertex(x, y, 0.f, 0.f, Color::White);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void RenderQueue::AddVertex(float x, float y, float u, float v)
|
||||
{
|
||||
AddVertex(x, y, u, v, Color::White);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void RenderQueue::AddVertex(float x, float y, const Color& color)
|
||||
{
|
||||
AddVertex(x, y, 0.f, 0.f, color);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void RenderQueue::AddVertex(float x, float y, float u, float v, const Color& color)
|
||||
{
|
||||
// Apply the current transform matrix to the vertex position
|
||||
sf::Vector2f transformedPoint = myCurrentTransform.Transform(sf::Vector2f(x, y));
|
||||
|
||||
// Apply the current global color
|
||||
sf::Color combinedColor = myCurrentStates->color * color;
|
||||
|
||||
// Round the vertex position so that it matches the
|
||||
// viewport's pixels, and thus avoid rendering artifacts
|
||||
int i1 = Round((transformedPoint.x + 1.f) * myCurrentViewportSize.x);
|
||||
int i2 = Round((transformedPoint.y + 1.f) * myCurrentViewportSize.y);
|
||||
transformedPoint.x = i1 / myCurrentViewportSize.x - 1.f;
|
||||
transformedPoint.y = i2 / myCurrentViewportSize.y - 1.f;
|
||||
|
||||
// Here we choose not to rely on vector::clear and vector::push_back,
|
||||
// and to handle resizing and appending manually, for performances reasons
|
||||
|
||||
// Resize the vertex buffer if it is too small
|
||||
std::size_t size = myVertices.size();
|
||||
if (myCurrentVertexCount + 8 > size)
|
||||
myVertices.resize(size + size / 2);
|
||||
|
||||
// Copy the vertex data
|
||||
float* ptr = &myVertices[myCurrentVertexCount];
|
||||
*ptr++ = transformedPoint.x;
|
||||
*ptr++ = transformedPoint.y;
|
||||
*ptr++ = combinedColor.r / 255.f;
|
||||
*ptr++ = combinedColor.g / 255.f;
|
||||
*ptr++ = combinedColor.b / 255.f;
|
||||
*ptr++ = combinedColor.a / 255.f;
|
||||
*ptr++ = u;
|
||||
*ptr++ = v;
|
||||
|
||||
// Increase the vertex count
|
||||
myCurrentVertexCount += 8;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void RenderQueue::AddTriangle(unsigned int index0, unsigned int index1, unsigned int index2)
|
||||
{
|
||||
// Here we choose not to rely on vector::clear and vector::push_back,
|
||||
// and to handle resizing and appending manually, for performances reasons
|
||||
|
||||
// Resize the index buffer if it is too small
|
||||
std::size_t size = myIndices.size();
|
||||
if (myCurrentIndexCount + 3 > size)
|
||||
myIndices.resize(size + size / 2);
|
||||
|
||||
// Copy the index data
|
||||
myIndices[myCurrentIndexCount + 0] = index0 + myBaseIndex;
|
||||
myIndices[myCurrentIndexCount + 1] = index1 + myBaseIndex;
|
||||
myIndices[myCurrentIndexCount + 2] = index2 + myBaseIndex;
|
||||
|
||||
// Increase the index count
|
||||
myCurrentIndexCount += 3;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void RenderQueue::Render()
|
||||
{
|
||||
if (myCurrentVertexCount && myCurrentIndexCount)
|
||||
{
|
||||
// Save the current OpenGL states
|
||||
GLCheck(glPushAttrib(GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_VIEWPORT_BIT));
|
||||
GLCheck(glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT));
|
||||
GLCheck(glDisable(GL_LIGHTING));
|
||||
GLCheck(glDisable(GL_DEPTH_TEST));
|
||||
GLCheck(glEnable(GL_ALPHA_TEST));
|
||||
GLCheck(glAlphaFunc(GL_GREATER, 0));
|
||||
GLCheck(glMatrixMode(GL_MODELVIEW));
|
||||
GLCheck(glPushMatrix());
|
||||
GLCheck(glLoadIdentity());
|
||||
GLCheck(glMatrixMode(GL_PROJECTION));
|
||||
GLCheck(glPushMatrix());
|
||||
GLCheck(glLoadIdentity());
|
||||
|
||||
// Close the last batch
|
||||
if (myCurrentBatch)
|
||||
myCurrentBatch->End(myCurrentIndexCount);
|
||||
|
||||
// Prepare the geometry renderer
|
||||
myRenderer->Begin(&myVertices[0], myCurrentVertexCount, &myIndices[0], myCurrentIndexCount);
|
||||
|
||||
// Render the batches in order
|
||||
for (BatchArray::const_iterator it = myBatches.begin(); it != myBatches.end(); ++it)
|
||||
{
|
||||
it->ApplyStates();
|
||||
myRenderer->RenderTriangles(it->GetStartIndex(), it->GetIndexCount());
|
||||
}
|
||||
|
||||
// Stop rendering
|
||||
myRenderer->End();
|
||||
|
||||
// Restore the previous OpenGL states
|
||||
GLCheck(glMatrixMode(GL_PROJECTION));
|
||||
GLCheck(glPopMatrix());
|
||||
GLCheck(glMatrixMode(GL_MODELVIEW));
|
||||
GLCheck(glPopMatrix());
|
||||
GLCheck(glPopAttrib());
|
||||
GLCheck(glPopClientAttrib());
|
||||
}
|
||||
|
||||
// Clear everything
|
||||
Clear();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void RenderQueue::Clear()
|
||||
{
|
||||
// Reset the vertex and index counts
|
||||
myCurrentVertexCount = 0;
|
||||
myCurrentIndexCount = 0;
|
||||
|
||||
// Clear the batches
|
||||
myBatches.clear();
|
||||
myCurrentBatch = NULL;
|
||||
}
|
||||
|
||||
} // namespace sf
|
|
@ -37,9 +37,7 @@ namespace sf
|
|||
/// Default constructor
|
||||
////////////////////////////////////////////////////////////
|
||||
RenderTarget::RenderTarget() :
|
||||
myCurrentView (&myDefaultView),
|
||||
myPreserveStates(false),
|
||||
myIsDrawing (false)
|
||||
myCurrentView(&myDefaultView)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -61,10 +59,13 @@ void RenderTarget::Clear(const Color& color)
|
|||
{
|
||||
if (Activate(true))
|
||||
{
|
||||
// Clear the frame buffer
|
||||
// Clear the color buffer
|
||||
GLCheck(glClearColor(color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f));
|
||||
GLCheck(glClear(GL_COLOR_BUFFER_BIT));
|
||||
|
||||
// Clear the render queue
|
||||
myRenderQueue.Clear();
|
||||
|
||||
Activate(false);
|
||||
}
|
||||
}
|
||||
|
@ -75,59 +76,34 @@ void RenderTarget::Clear(const Color& color)
|
|||
////////////////////////////////////////////////////////////
|
||||
void RenderTarget::Draw(const Drawable& object)
|
||||
{
|
||||
// Check whether we are called from the outside or from a previous call to Draw
|
||||
if (!myIsDrawing)
|
||||
// Save the current render states
|
||||
myRenderQueue.PushStates();
|
||||
|
||||
// Setup the viewport
|
||||
myRenderQueue.SetViewport(GetViewport(*myCurrentView));
|
||||
|
||||
// Setup the projection matrix
|
||||
myRenderQueue.SetProjection(myCurrentView->GetMatrix());
|
||||
|
||||
// Let the object draw itself
|
||||
object.Draw(*this, myRenderQueue);
|
||||
|
||||
// Restore the previous render states
|
||||
myRenderQueue.PopStates();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Make sure that what has been drawn so far is rendered
|
||||
////////////////////////////////////////////////////////////
|
||||
void RenderTarget::Flush()
|
||||
{
|
||||
if (Activate(true))
|
||||
{
|
||||
myIsDrawing = true;
|
||||
// Draw the whole render queue
|
||||
myRenderQueue.Render();
|
||||
|
||||
// Set our target as the current target for rendering
|
||||
if (Activate(true))
|
||||
{
|
||||
// Save the current render states and set the SFML ones
|
||||
if (myPreserveStates)
|
||||
{
|
||||
GLCheck(glMatrixMode(GL_MODELVIEW)); GLCheck(glPushMatrix());
|
||||
GLCheck(glMatrixMode(GL_PROJECTION)); GLCheck(glPushMatrix());
|
||||
GLCheck(glPushAttrib(GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT | GL_ENABLE_BIT |
|
||||
GL_TEXTURE_BIT | GL_TRANSFORM_BIT | GL_VIEWPORT_BIT));
|
||||
SetRenderStates();
|
||||
}
|
||||
|
||||
// Setup the viewport
|
||||
const FloatRect& viewport = myCurrentView->GetViewport();
|
||||
int left = static_cast<int>(0.5f + GetWidth() * viewport.Left);
|
||||
int top = static_cast<int>(0.5f + GetHeight() * (1.f - viewport.Bottom));
|
||||
int width = static_cast<int>(0.5f + GetWidth() * viewport.GetSize().x);
|
||||
int height = static_cast<int>(0.5f + GetHeight() * viewport.GetSize().y);
|
||||
GLCheck(glViewport(left, top, width, height));
|
||||
|
||||
// Setup the transform matrices
|
||||
GLCheck(glMatrixMode(GL_PROJECTION));
|
||||
GLCheck(glLoadMatrixf(myCurrentView->GetMatrix().Get4x4Elements()));
|
||||
GLCheck(glMatrixMode(GL_MODELVIEW));
|
||||
GLCheck(glLoadIdentity());
|
||||
|
||||
// Let the object draw itself
|
||||
object.Draw(*this);
|
||||
|
||||
// Restore render states
|
||||
if (myPreserveStates)
|
||||
{
|
||||
GLCheck(glMatrixMode(GL_PROJECTION)); GLCheck(glPopMatrix());
|
||||
GLCheck(glMatrixMode(GL_MODELVIEW)); GLCheck(glPopMatrix());
|
||||
GLCheck(glPopAttrib());
|
||||
}
|
||||
|
||||
// Deactivate rendering on this target
|
||||
Activate(false);
|
||||
}
|
||||
|
||||
myIsDrawing = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We are already called from a previous Draw : we don't need to set the states again, just draw the object
|
||||
object.Draw(*this);
|
||||
Activate(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -160,16 +136,48 @@ View& RenderTarget::GetDefaultView()
|
|||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Tell SFML to preserve external OpenGL states, at the expense of
|
||||
/// more CPU charge. Use this function if you don't want SFML
|
||||
/// to mess up your own OpenGL states (if any).
|
||||
/// Don't enable state preservation if not needed, as it will allow
|
||||
/// SFML to do internal optimizations and improve performances.
|
||||
/// This parameter is false by default
|
||||
/// Get the viewport of a view applied to this target
|
||||
////////////////////////////////////////////////////////////
|
||||
void RenderTarget::PreserveOpenGLStates(bool preserve)
|
||||
IntRect RenderTarget::GetViewport(const View& view) const
|
||||
{
|
||||
myPreserveStates = preserve;
|
||||
float width = static_cast<float>(GetWidth());
|
||||
float height = static_cast<float>(GetHeight());
|
||||
const FloatRect& viewport = view.GetViewport();
|
||||
|
||||
IntRect rect;
|
||||
rect.Left = static_cast<int>(0.5f + width * viewport.Left);
|
||||
rect.Top = static_cast<int>(0.5f + height * (1.f - viewport.Bottom));
|
||||
rect.Right = static_cast<int>(0.5f + width * viewport.Right);
|
||||
rect.Bottom = static_cast<int>(0.5f + height * (1.f - viewport.Top));
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Convert a point in window coordinates into view coordinates
|
||||
/// This version uses the current view of the window
|
||||
////////////////////////////////////////////////////////////
|
||||
sf::Vector2f RenderTarget::ConvertCoords(unsigned int x, unsigned int y) const
|
||||
{
|
||||
return ConvertCoords(x, y, GetView());
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Convert a point in window coordinates into view coordinates
|
||||
/// This version uses the given view
|
||||
////////////////////////////////////////////////////////////
|
||||
sf::Vector2f RenderTarget::ConvertCoords(unsigned int x, unsigned int y, const View& view) const
|
||||
{
|
||||
// First, convert from viewport coordinates to homogeneous coordinates
|
||||
Vector2f coords;
|
||||
IntRect viewport = GetViewport(view);
|
||||
coords.x = -1.f + 2.f * (static_cast<int>(x) - viewport.Left) / viewport.GetSize().x;
|
||||
coords.y = 1.f - 2.f * (static_cast<int>(y) - viewport.Top) / viewport.GetSize().y;
|
||||
|
||||
// Then transform by the inverse of the view matrix
|
||||
return view.GetInverseMatrix().Transform(coords);
|
||||
}
|
||||
|
||||
|
||||
|
@ -178,28 +186,12 @@ void RenderTarget::PreserveOpenGLStates(bool preserve)
|
|||
////////////////////////////////////////////////////////////
|
||||
void RenderTarget::Initialize()
|
||||
{
|
||||
if (Activate(true))
|
||||
{
|
||||
// Set the default rendering states
|
||||
SetRenderStates();
|
||||
// Setup the default view
|
||||
myDefaultView.Reset(FloatRect(0, 0, static_cast<float>(GetWidth()), static_cast<float>(GetHeight())));
|
||||
SetView(myDefaultView);
|
||||
|
||||
// Setup the default view
|
||||
myDefaultView.Reset(FloatRect(0, 0, static_cast<float>(GetWidth()), static_cast<float>(GetHeight())));
|
||||
SetView(myDefaultView);
|
||||
|
||||
Activate(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Set the OpenGL render states needed for the SFML rendering
|
||||
////////////////////////////////////////////////////////////
|
||||
void RenderTarget::SetRenderStates()
|
||||
{
|
||||
GLCheck(glDisable(GL_ALPHA_TEST));
|
||||
GLCheck(glDisable(GL_DEPTH_TEST));
|
||||
GLCheck(glDisable(GL_LIGHTING));
|
||||
// Clear the render queue
|
||||
myRenderQueue.Clear();
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -75,11 +75,7 @@ RenderWindow::~RenderWindow()
|
|||
////////////////////////////////////////////////////////////
|
||||
bool RenderWindow::Activate(bool active)
|
||||
{
|
||||
// For performances and consistency reasons, we only handle activation
|
||||
if (active)
|
||||
return SetActive();
|
||||
else
|
||||
return true;
|
||||
return SetActive(active);
|
||||
}
|
||||
|
||||
|
||||
|
@ -101,70 +97,6 @@ unsigned int RenderWindow::GetHeight() const
|
|||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Save the content of the window to an image
|
||||
////////////////////////////////////////////////////////////
|
||||
Image RenderWindow::Capture() const
|
||||
{
|
||||
// Get the window dimensions
|
||||
const unsigned int width = GetWidth();
|
||||
const unsigned int height = GetHeight();
|
||||
|
||||
// Set our window as the current target for rendering
|
||||
if (SetActive())
|
||||
{
|
||||
// Get pixels from the backbuffer
|
||||
std::vector<Uint8> pixels(width * height * 4);
|
||||
Uint8* ptr = &pixels[0];
|
||||
GLCheck(glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, ptr));
|
||||
|
||||
// Flip the pixels
|
||||
unsigned int pitch = width * 4;
|
||||
for (unsigned int y = 0; y < height / 2; ++y)
|
||||
std::swap_ranges(ptr + y * pitch, ptr + (y + 1) * pitch, ptr + (height - y - 1) * pitch);
|
||||
|
||||
// Create an image from the pixel buffer and return it
|
||||
return Image(width, height, ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Image(width, height, Color::White);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Convert a point in window coordinates into view coordinates
|
||||
/// This version uses the current view of the window
|
||||
////////////////////////////////////////////////////////////
|
||||
sf::Vector2f RenderWindow::ConvertCoords(unsigned int x, unsigned int y) const
|
||||
{
|
||||
return ConvertCoords(x, y, GetView());
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Convert a point in window coordinates into view coordinates
|
||||
/// This version uses the given view
|
||||
////////////////////////////////////////////////////////////
|
||||
sf::Vector2f RenderWindow::ConvertCoords(unsigned int x, unsigned int y, const View& view) const
|
||||
{
|
||||
// First, convert from viewport coordinates to homogeneous coordinates
|
||||
const FloatRect& viewport = view.GetViewport();
|
||||
int left = static_cast<int>(0.5f + GetWidth() * viewport.Left);
|
||||
int top = static_cast<int>(0.5f + GetHeight() * viewport.Top);
|
||||
int width = static_cast<int>(0.5f + GetWidth() * viewport.GetSize().x);
|
||||
int height = static_cast<int>(0.5f + GetHeight() * viewport.GetSize().y);
|
||||
|
||||
Vector2f coords;
|
||||
coords.x = -1.f + 2.f * (static_cast<int>(x) - left) / width;
|
||||
coords.y = 1.f - 2.f * (static_cast<int>(y) - top) / height;
|
||||
|
||||
// Then transform by the inverse of the view matrix
|
||||
return view.GetInverseMatrix().Transform(coords);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Called after the window has been created
|
||||
////////////////////////////////////////////////////////////
|
||||
|
@ -174,4 +106,14 @@ void RenderWindow::OnCreate()
|
|||
RenderTarget::Initialize();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Called before the window has been displayed
|
||||
////////////////////////////////////////////////////////////
|
||||
void RenderWindow::OnDisplay()
|
||||
{
|
||||
// Render the drawables drawn so far
|
||||
Flush();
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Graphics/Shape.hpp>
|
||||
#include <SFML/Graphics/GLCheck.hpp>
|
||||
#include <SFML/Graphics/RenderQueue.hpp>
|
||||
#include <math.h>
|
||||
|
||||
|
||||
|
@ -281,7 +281,7 @@ Shape Shape::Circle(const Vector2f& center, float radius, const Color& color, fl
|
|||
////////////////////////////////////////////////////////////
|
||||
/// /see Drawable::Render
|
||||
////////////////////////////////////////////////////////////
|
||||
void Shape::Render(RenderTarget&) const
|
||||
void Shape::Render(RenderTarget&, RenderQueue& queue) const
|
||||
{
|
||||
// Make sure the shape has at least 3 points (4 if we count the center)
|
||||
if (myPoints.size() < 4)
|
||||
|
@ -292,50 +292,69 @@ void Shape::Render(RenderTarget&) const
|
|||
const_cast<Shape*>(this)->Compile();
|
||||
|
||||
// Shapes only use color, no texture
|
||||
GLCheck(glDisable(GL_TEXTURE_2D));
|
||||
queue.SetTexture(NULL);
|
||||
|
||||
// Draw the shape
|
||||
if (myIsFillEnabled)
|
||||
{
|
||||
glBegin(GL_TRIANGLE_FAN);
|
||||
if (myPoints.size() == 4)
|
||||
{
|
||||
// Special case of a triangle
|
||||
queue.BeginBatch();
|
||||
queue.AddVertex(myPoints[1].Position.x, myPoints[1].Position.y, myPoints[1].Col);
|
||||
queue.AddVertex(myPoints[2].Position.x, myPoints[2].Position.y, myPoints[2].Col);
|
||||
queue.AddVertex(myPoints[3].Position.x, myPoints[3].Position.y, myPoints[3].Col);
|
||||
queue.AddTriangle(0, 1, 2);
|
||||
}
|
||||
else if (myPoints.size() == 5)
|
||||
{
|
||||
// Special case of a quad
|
||||
queue.BeginBatch();
|
||||
queue.AddVertex(myPoints[1].Position.x, myPoints[1].Position.y, myPoints[1].Col);
|
||||
queue.AddVertex(myPoints[2].Position.x, myPoints[2].Position.y, myPoints[2].Col);
|
||||
queue.AddVertex(myPoints[3].Position.x, myPoints[3].Position.y, myPoints[3].Col);
|
||||
queue.AddVertex(myPoints[4].Position.x, myPoints[4].Position.y, myPoints[4].Col);
|
||||
queue.AddTriangle(0, 1, 3);
|
||||
queue.AddTriangle(3, 1, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
// General case of a convex polygon
|
||||
queue.BeginBatch();
|
||||
for (std::vector<Point>::const_iterator i = myPoints.begin(); i != myPoints.end(); ++i)
|
||||
{
|
||||
Color color = i->Col * GetColor();
|
||||
glColor4ub(color.r, color.g, color.b, color.a);
|
||||
glVertex2f(i->Position.x, i->Position.y);
|
||||
}
|
||||
queue.AddVertex(i->Position.x, i->Position.y, i->Col);
|
||||
|
||||
for (std::size_t i = 1; i < myPoints.size() - 1; ++i)
|
||||
queue.AddTriangle(0, i, i + 1);
|
||||
|
||||
// Close the shape by duplicating the first point at the end
|
||||
Color color = myPoints[1].Col * GetColor();
|
||||
glColor4ub(color.r, color.g, color.b, color.a);
|
||||
glVertex2f(myPoints[1].Position.x, myPoints[1].Position.y);
|
||||
queue.AddTriangle(0, myPoints.size() - 1, 1);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
// Draw the outline
|
||||
if (myIsOutlineEnabled)
|
||||
if (myIsOutlineEnabled && (myOutline != 0))
|
||||
{
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
queue.BeginBatch();
|
||||
for (std::vector<Point>::const_iterator i = myPoints.begin() + 1; i != myPoints.end(); ++i)
|
||||
{
|
||||
for (std::size_t i = 1; i < myPoints.size(); ++i)
|
||||
{
|
||||
Color color = myPoints[i].OutlineCol * GetColor();
|
||||
glColor4ub(color.r, color.g, color.b, color.a);
|
||||
glVertex2f(myPoints[i].Position.x, myPoints[i].Position.y);
|
||||
glColor4ub(color.r, color.g, color.b, color.a);
|
||||
glVertex2f(myPoints[i].Position.x + myPoints[i].Normal.x * myOutline, myPoints[i].Position.y + myPoints[i].Normal.y * myOutline);
|
||||
}
|
||||
|
||||
// Close the shape by duplicating the first point at the end
|
||||
Color color = myPoints[1].OutlineCol * GetColor();
|
||||
glColor4ub(color.r, color.g, color.b, color.a);
|
||||
glVertex2f(myPoints[1].Position.x, myPoints[1].Position.y);
|
||||
glColor4ub(color.r, color.g, color.b, color.a);
|
||||
glVertex2f(myPoints[1].Position.x + myPoints[1].Normal.x * myOutline, myPoints[1].Position.y + myPoints[1].Normal.y * myOutline);
|
||||
Vector2f point1 = i->Position;
|
||||
Vector2f point2 = i->Position + i->Normal * myOutline;
|
||||
queue.AddVertex(point1.x, point1.y, i->OutlineCol);
|
||||
queue.AddVertex(point2.x, point2.y, i->OutlineCol);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
for (std::size_t i = 0; i < myPoints.size() - 2; ++i)
|
||||
{
|
||||
queue.AddTriangle(i * 2 + 0, i * 2 + 1, i * 2 + 2);
|
||||
queue.AddTriangle(i * 2 + 2, i * 2 + 1, i * 2 + 3);
|
||||
}
|
||||
|
||||
// Close the shape by duplicating the first point at the end
|
||||
unsigned int begin = 0;
|
||||
unsigned int last = (myPoints.size() - 2) * 2;
|
||||
queue.AddTriangle(last, last + 1, begin);
|
||||
queue.AddTriangle(begin, last + 1, begin + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -351,16 +370,17 @@ void Shape::Compile()
|
|||
Point center(Vector2f(0, 0), Color(0, 0, 0, 0));
|
||||
for (std::size_t i = 1; i < myPoints.size(); ++i)
|
||||
{
|
||||
center.Position += myPoints[i].Position / nbPoints;
|
||||
r += myPoints[i].Col.r / nbPoints;
|
||||
g += myPoints[i].Col.g / nbPoints;
|
||||
b += myPoints[i].Col.b / nbPoints;
|
||||
a += myPoints[i].Col.a / nbPoints;
|
||||
center.Position += myPoints[i].Position;
|
||||
r += myPoints[i].Col.r;
|
||||
g += myPoints[i].Col.g;
|
||||
b += myPoints[i].Col.b;
|
||||
a += myPoints[i].Col.a;
|
||||
}
|
||||
center.Col.r = static_cast<Uint8>(r);
|
||||
center.Col.g = static_cast<Uint8>(g);
|
||||
center.Col.b = static_cast<Uint8>(b);
|
||||
center.Col.a = static_cast<Uint8>(a);
|
||||
center.Position /= nbPoints;
|
||||
center.Col.r = static_cast<Uint8>(r / nbPoints);
|
||||
center.Col.g = static_cast<Uint8>(g / nbPoints);
|
||||
center.Col.b = static_cast<Uint8>(b / nbPoints);
|
||||
center.Col.a = static_cast<Uint8>(a / nbPoints);
|
||||
myPoints[0] = center;
|
||||
|
||||
// Compute the outline
|
||||
|
|
|
@ -27,7 +27,8 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Graphics/Sprite.hpp>
|
||||
#include <SFML/Graphics/Image.hpp>
|
||||
#include <SFML/Graphics/GLCheck.hpp>
|
||||
#include <SFML/Graphics/RenderQueue.hpp>
|
||||
#include <utility>
|
||||
|
||||
|
||||
namespace sf
|
||||
|
@ -181,50 +182,32 @@ Color Sprite::GetPixel(unsigned int x, unsigned int y) const
|
|||
////////////////////////////////////////////////////////////
|
||||
/// /see Drawable::Render
|
||||
////////////////////////////////////////////////////////////
|
||||
void Sprite::Render(RenderTarget&) const
|
||||
void Sprite::Render(RenderTarget&, RenderQueue& queue) const
|
||||
{
|
||||
// Get the sprite size
|
||||
float width = static_cast<float>(mySubRect.GetSize().x);
|
||||
float height = static_cast<float>(mySubRect.GetSize().y);
|
||||
|
||||
// Check if the image is valid
|
||||
// Check if the image is valid, and calculate the texture coordinates
|
||||
FloatRect coords;
|
||||
if (myImage && (myImage->GetWidth() > 0) && (myImage->GetHeight() > 0))
|
||||
{
|
||||
// Use the "offset trick" to get pixel-perfect rendering
|
||||
// see http://www.opengl.org/resources/faq/technical/transformations.htm#tran0030
|
||||
GLCheck(glTranslatef(0.375f, 0.375f, 0.f));
|
||||
|
||||
// Bind the texture
|
||||
myImage->Bind();
|
||||
|
||||
// Calculate the texture coordinates
|
||||
FloatRect texCoords = myImage->GetTexCoords(mySubRect);
|
||||
FloatRect rect(myIsFlippedX ? texCoords.Right : texCoords.Left,
|
||||
myIsFlippedY ? texCoords.Bottom : texCoords.Top,
|
||||
myIsFlippedX ? texCoords.Left : texCoords.Right,
|
||||
myIsFlippedY ? texCoords.Top : texCoords.Bottom);
|
||||
|
||||
// Draw the sprite's triangles
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(rect.Left, rect.Top); glVertex2f(0, 0);
|
||||
glTexCoord2f(rect.Left, rect.Bottom); glVertex2f(0, height);
|
||||
glTexCoord2f(rect.Right, rect.Bottom); glVertex2f(width, height);
|
||||
glTexCoord2f(rect.Right, rect.Top); glVertex2f(width, 0) ;
|
||||
glEnd();
|
||||
coords = myImage->GetTexCoords(mySubRect);
|
||||
if (myIsFlippedX) std::swap(coords.Left, coords.Right);
|
||||
if (myIsFlippedY) std::swap(coords.Top, coords.Bottom);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Disable texturing
|
||||
GLCheck(glDisable(GL_TEXTURE_2D));
|
||||
|
||||
// Draw the sprite's triangles
|
||||
glBegin(GL_QUADS);
|
||||
glVertex2f(0, 0);
|
||||
glVertex2f(0, height);
|
||||
glVertex2f(width, height);
|
||||
glVertex2f(width, 0);
|
||||
glEnd();
|
||||
}
|
||||
// Bind the texture
|
||||
queue.SetTexture(myImage);
|
||||
|
||||
// Draw the sprite's geometry
|
||||
queue.BeginBatch();
|
||||
queue.AddVertex(0, 0, coords.Left, coords.Top);
|
||||
queue.AddVertex(0, height, coords.Left, coords.Bottom);
|
||||
queue.AddVertex(width, height, coords.Right, coords.Bottom);
|
||||
queue.AddVertex(width, 0, coords.Right, coords.Top);
|
||||
queue.AddTriangle(0, 1, 3);
|
||||
queue.AddTriangle(3, 1, 2);
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -27,8 +27,7 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Graphics/String.hpp>
|
||||
#include <SFML/Graphics/Image.hpp>
|
||||
#include <SFML/Graphics/GLCheck.hpp>
|
||||
#include <locale>
|
||||
#include <SFML/Graphics/RenderQueue.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
|
@ -210,7 +209,7 @@ FloatRect String::GetRect() const
|
|||
////////////////////////////////////////////////////////////
|
||||
/// /see sfDrawable::Render
|
||||
////////////////////////////////////////////////////////////
|
||||
void String::Render(RenderTarget&) const
|
||||
void String::Render(RenderTarget&, RenderQueue& queue) const
|
||||
{
|
||||
// First get the internal UTF-32 string of the text
|
||||
const Unicode::UTF32String& text = myText;
|
||||
|
@ -222,10 +221,9 @@ void String::Render(RenderTarget&) const
|
|||
// Set the scaling factor to get the actual size
|
||||
float charSize = static_cast<float>(myFont->GetCharacterSize());
|
||||
float factor = mySize / charSize;
|
||||
GLCheck(glScalef(factor, factor, 1.f));
|
||||
|
||||
// Bind the font texture
|
||||
myFont->GetImage().Bind();
|
||||
queue.SetTexture(&myFont->GetImage());
|
||||
|
||||
// Initialize the rendering coordinates
|
||||
float x = 0.f;
|
||||
|
@ -239,7 +237,8 @@ void String::Render(RenderTarget&) const
|
|||
float italicCoeff = (myStyle & Italic) ? 0.208f : 0.f; // 12 degrees
|
||||
|
||||
// Draw one quad for each character
|
||||
glBegin(GL_QUADS);
|
||||
unsigned int index = 0;
|
||||
queue.BeginBatch();
|
||||
for (std::size_t i = 0; i < text.size(); ++i)
|
||||
{
|
||||
// Get the current character and its corresponding glyph
|
||||
|
@ -267,31 +266,67 @@ void String::Render(RenderTarget&) const
|
|||
}
|
||||
|
||||
// Draw a textured quad for the current character
|
||||
glTexCoord2f(coord.Left, coord.Top); glVertex2f(x + rect.Left - italicCoeff * rect.Top, y + rect.Top);
|
||||
glTexCoord2f(coord.Left, coord.Bottom); glVertex2f(x + rect.Left - italicCoeff * rect.Bottom, y + rect.Bottom);
|
||||
glTexCoord2f(coord.Right, coord.Bottom); glVertex2f(x + rect.Right - italicCoeff * rect.Bottom, y + rect.Bottom);
|
||||
glTexCoord2f(coord.Right, coord.Top); glVertex2f(x + rect.Right - italicCoeff * rect.Top, y + rect.Top);
|
||||
queue.AddVertex(factor * (x + rect.Left - italicCoeff * rect.Top), factor * (y + rect.Top), coord.Left, coord.Top);
|
||||
queue.AddVertex(factor * (x + rect.Left - italicCoeff * rect.Bottom), factor * (y + rect.Bottom), coord.Left, coord.Bottom);
|
||||
queue.AddVertex(factor * (x + rect.Right - italicCoeff * rect.Bottom), factor * (y + rect.Bottom), coord.Right, coord.Bottom);
|
||||
queue.AddVertex(factor * (x + rect.Right - italicCoeff * rect.Top), factor * (y + rect.Top), coord.Right, coord.Top);
|
||||
|
||||
// If we're using the bold style, we must render the character 4 more times,
|
||||
// slightly offseted, to simulate a higher weight
|
||||
if (myStyle & Bold)
|
||||
{
|
||||
static const float offsetsX[] = {-0.5f, 0.5f, 0.f, 0.f};
|
||||
static const float offsetsY[] = {0.f, 0.f, -0.5f, 0.5f};
|
||||
|
||||
for (int j = 0; j < 4; ++j)
|
||||
{
|
||||
glTexCoord2f(coord.Left, coord.Top); glVertex2f(x + offsetsX[j] + rect.Left - italicCoeff * rect.Top, y + offsetsY[j] + rect.Top);
|
||||
glTexCoord2f(coord.Left, coord.Bottom); glVertex2f(x + offsetsX[j] + rect.Left - italicCoeff * rect.Bottom, y + offsetsY[j] + rect.Bottom);
|
||||
glTexCoord2f(coord.Right, coord.Bottom); glVertex2f(x + offsetsX[j] + rect.Right - italicCoeff * rect.Bottom, y + offsetsY[j] + rect.Bottom);
|
||||
glTexCoord2f(coord.Right, coord.Top); glVertex2f(x + offsetsX[j] + rect.Right - italicCoeff * rect.Top, y + offsetsY[j] + rect.Top);
|
||||
}
|
||||
}
|
||||
queue.AddTriangle(index + 0, index + 1, index + 3);
|
||||
queue.AddTriangle(index + 3, index + 1, index + 2);
|
||||
index += 4;
|
||||
|
||||
// Advance to the next character
|
||||
x += advance;
|
||||
}
|
||||
glEnd();
|
||||
|
||||
// If we're using the bold style, we must render the string 4 more times,
|
||||
// slightly offseted, to simulate a higher weight
|
||||
if (myStyle & Bold)
|
||||
{
|
||||
float offset = mySize * 0.02f;
|
||||
static const float offsetsX[] = {-offset, offset, 0.f, 0.f};
|
||||
static const float offsetsY[] = {0.f, 0.f, -offset, offset};
|
||||
|
||||
for (int j = 0; j < 4; ++j)
|
||||
{
|
||||
index = 0;
|
||||
x = 0.f;
|
||||
y = charSize;
|
||||
|
||||
queue.BeginBatch();
|
||||
for (std::size_t i = 0; i < text.size(); ++i)
|
||||
{
|
||||
// Get the current character and its corresponding glyph
|
||||
Uint32 curChar = text[i];
|
||||
const Glyph& curGlyph = myFont->GetGlyph(curChar);
|
||||
int advance = curGlyph.Advance;
|
||||
const IntRect& rect = curGlyph.Rectangle;
|
||||
const FloatRect& coord = curGlyph.TexCoords;
|
||||
|
||||
// Handle special characters
|
||||
switch (curChar)
|
||||
{
|
||||
case L' ' : x += advance; continue;
|
||||
case L'\n' : y += charSize; x = 0; continue;
|
||||
case L'\t' : x += advance * 4; continue;
|
||||
case L'\v' : y += charSize * 4; continue;
|
||||
}
|
||||
|
||||
// Draw a textured quad for the current character
|
||||
queue.AddVertex(factor * (x + offsetsX[j] + rect.Left - italicCoeff * rect.Top), factor * (y + offsetsY[j] + rect.Top), coord.Left, coord.Top);
|
||||
queue.AddVertex(factor * (x + offsetsX[j] + rect.Left - italicCoeff * rect.Bottom), factor * (y + offsetsY[j] + rect.Bottom), coord.Left, coord.Bottom);
|
||||
queue.AddVertex(factor * (x + offsetsX[j] + rect.Right - italicCoeff * rect.Bottom), factor * (y + offsetsY[j] + rect.Bottom), coord.Right, coord.Bottom);
|
||||
queue.AddVertex(factor * (x + offsetsX[j] + rect.Right - italicCoeff * rect.Top), factor * (y + offsetsY[j] + rect.Top), coord.Right, coord.Top);
|
||||
|
||||
queue.AddTriangle(index + 0, index + 1, index + 3);
|
||||
queue.AddTriangle(index + 3, index + 1, index + 2);
|
||||
index += 4;
|
||||
|
||||
// Advance to the next character
|
||||
x += advance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the underlines if needed
|
||||
if (myStyle & Underlined)
|
||||
|
@ -304,16 +339,20 @@ void String::Render(RenderTarget&) const
|
|||
underlineCoords.push_back(y + 2);
|
||||
|
||||
// Draw the underlines as quads
|
||||
GLCheck(glDisable(GL_TEXTURE_2D));
|
||||
glBegin(GL_QUADS);
|
||||
index = 0;
|
||||
queue.SetTexture(NULL);
|
||||
queue.BeginBatch();
|
||||
for (std::size_t i = 0; i < underlineCoords.size(); i += 2)
|
||||
{
|
||||
glVertex2f(0, underlineCoords[i + 1]);
|
||||
glVertex2f(0, underlineCoords[i + 1] + thickness);
|
||||
glVertex2f(underlineCoords[i], underlineCoords[i + 1] + thickness);
|
||||
glVertex2f(underlineCoords[i], underlineCoords[i + 1]);
|
||||
queue.AddVertex(factor * (0), factor * (underlineCoords[i + 1]));
|
||||
queue.AddVertex(factor * (0), factor * (underlineCoords[i + 1] + thickness));
|
||||
queue.AddVertex(factor * (underlineCoords[i]), factor * (underlineCoords[i + 1] + thickness));
|
||||
queue.AddVertex(factor * (underlineCoords[i]), factor * (underlineCoords[i + 1]));
|
||||
|
||||
queue.AddTriangle(index + 0, index + 1, index + 3);
|
||||
queue.AddTriangle(index + 3, index + 1, index + 2);
|
||||
index += 4;
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -179,7 +179,8 @@ bool RenderImageImplPBuffer::Activate(bool active)
|
|||
}
|
||||
else
|
||||
{
|
||||
// We don't actually unbind the P-Buffer, for performances reasons
|
||||
// We don't actually unbind the P-Buffer,
|
||||
// for performances and consistency reasons
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -140,21 +140,17 @@ void Window::Create(VideoMode mode, const std::string& title, unsigned long styl
|
|||
delete myWindow;
|
||||
myWindow = priv::WindowImpl::New(mode, title, style);
|
||||
|
||||
{
|
||||
// Make sure another context is bound, so that:
|
||||
// - the context creation can request OpenGL extensions if necessary
|
||||
// - myContext can safely be destroyed (it's no longer bound)
|
||||
Context context;
|
||||
// Make sure another context is bound, so that:
|
||||
// - the context creation can request OpenGL extensions if necessary
|
||||
// - myContext can safely be destroyed (it's no longer bound)
|
||||
Context context;
|
||||
|
||||
// Recreate the context
|
||||
delete myContext;
|
||||
myContext = priv::ContextGL::New(myWindow, mode.BitsPerPixel, settings);
|
||||
// Recreate the context
|
||||
delete myContext;
|
||||
myContext = priv::ContextGL::New(myWindow, mode.BitsPerPixel, settings);
|
||||
|
||||
Initialize();
|
||||
}
|
||||
|
||||
// Activate the window's context
|
||||
SetActive();
|
||||
// Perform common initializations
|
||||
Initialize();
|
||||
}
|
||||
|
||||
|
||||
|
@ -167,21 +163,17 @@ void Window::Create(WindowHandle handle, const ContextSettings& settings)
|
|||
Close();
|
||||
myWindow = priv::WindowImpl::New(handle);
|
||||
|
||||
{
|
||||
// Make sure another context is bound, so that:
|
||||
// - the context creation can request OpenGL extensions if necessary
|
||||
// - myContext can safely be destroyed (it's no longer bound)
|
||||
Context context;
|
||||
// Make sure another context is bound, so that:
|
||||
// - the context creation can request OpenGL extensions if necessary
|
||||
// - myContext can safely be destroyed (it's no longer bound)
|
||||
Context context;
|
||||
|
||||
// Recreate the context
|
||||
delete myContext;
|
||||
myContext = priv::ContextGL::New(myWindow, VideoMode::GetDesktopMode().BitsPerPixel, settings);
|
||||
// Recreate the context
|
||||
delete myContext;
|
||||
myContext = priv::ContextGL::New(myWindow, VideoMode::GetDesktopMode().BitsPerPixel, settings);
|
||||
|
||||
Initialize();
|
||||
}
|
||||
|
||||
// Activate the window's context
|
||||
SetActive();
|
||||
// Perform common initializations
|
||||
Initialize();
|
||||
}
|
||||
|
||||
|
||||
|
@ -391,6 +383,9 @@ bool Window::SetActive(bool active) const
|
|||
////////////////////////////////////////////////////////////
|
||||
void Window::Display()
|
||||
{
|
||||
// Notify the derived class
|
||||
OnDisplay();
|
||||
|
||||
// Limit the framerate if needed
|
||||
if (myFramerateLimit > 0)
|
||||
{
|
||||
|
@ -404,8 +399,11 @@ void Window::Display()
|
|||
myClock.Reset();
|
||||
|
||||
// Display the backbuffer on screen
|
||||
if (SetActive())
|
||||
if (SetActive(true))
|
||||
{
|
||||
myContext->Display();
|
||||
SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -456,6 +454,15 @@ void Window::OnCreate()
|
|||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Called before the window has been displayed
|
||||
////////////////////////////////////////////////////////////
|
||||
void Window::OnDisplay()
|
||||
{
|
||||
// Nothing by default
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Receive an event from window
|
||||
////////////////////////////////////////////////////////////
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue