Removed all the automatic batching stuff and replaced it with a more straight-forward implementation using a state cache for optimizing performances

git-svn-id: https://sfml.svn.sourceforge.net/svnroot/sfml/branches/sfml2@1362 4e206d99-4929-0410-ac5d-dfc041789085
This commit is contained in:
LaurentGom 2010-01-19 20:39:32 +00:00
parent 8ba9495c02
commit c237305f9b
58 changed files with 890 additions and 2039 deletions

View file

@ -1,138 +0,0 @@
////////////////////////////////////////////////////////////
//
// 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/Shader.hpp>
#include <SFML/Graphics/GeometryRenderer.hpp>
#include <SFML/Graphics/GLCheck.hpp>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
Batch::Batch(const Image* texture, const Shader* shader, Blend::Mode blendMode, const IntRect& viewport) :
myTexture (texture),
myShader (shader),
myBlendMode(blendMode),
myViewport (viewport),
myStart (0),
myCount (0)
{
}
////////////////////////////////////////////////////////////
bool Batch::Matches(const Image* texture, const Shader* shader, Blend::Mode blendMode, const IntRect& viewport) const
{
return myTexture == texture &&
myShader == shader &&
myBlendMode == blendMode &&
myViewport.Left == viewport.Left &&
myViewport.Top == viewport.Top &&
myViewport.Right == viewport.Right &&
myViewport.Bottom == viewport.Bottom;
}
////////////////////////////////////////////////////////////
void Batch::Begin(Uint32 index)
{
myStart = index;
}
////////////////////////////////////////////////////////////
void Batch::End(Uint32 index)
{
myCount = index - myStart;
}
////////////////////////////////////////////////////////////
void Batch::Render(GeometryRenderer& renderer) 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));
switch (myBlendMode)
{
// Alpha blending
// glBlendFuncSeparateEXT is used when available to avoid an incorrect alpha value when the target
// is a RenderImage -- in this case the alpha value must be written directly to the target buffer
default :
case Blend::Alpha :
if (GLEW_EXT_blend_func_separate)
GLCheck(glBlendFuncSeparateEXT(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
else
GLCheck(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
break;
// Additive blending
case Blend::Add :
GLCheck(glBlendFunc(GL_SRC_ALPHA, GL_ONE));
break;
// Multiplicative blending
case Blend::Multiply :
GLCheck(glBlendFunc(GL_DST_COLOR, GL_ZERO));
break;
}
}
// Bind the texture
if (myTexture)
myTexture->Bind();
else
GLCheck(glDisable(GL_TEXTURE_2D));
// Bind the pixel shader
if (myShader)
myShader->Bind();
// Render the triangles
renderer.RenderTriangles(myStart, myCount);
// Disable the pixel shader
if (myShader)
myShader->Unbind();
}
} // namespace priv
} // namespace sf

View file

@ -1,117 +0,0 @@
////////////////////////////////////////////////////////////
//
// 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;
class Shader;
namespace priv
{
class GeometryRenderer;
////////////////////////////////////////////////////////////
/// \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 shader Pixel shader
/// \param blendMode Blending mode
/// \param viewport Target viewport
///
////////////////////////////////////////////////////////////
Batch(const Image* texture, const Shader* shader, Blend::Mode blendMode, const IntRect& viewport);
////////////////////////////////////////////////////////////
/// \brief Check if the batch matches a set of render states
///
/// \param texture Texture to use
/// \param shader Pixel shader
/// \param blendMode Blending mode
/// \param viewport Target viewport
///
////////////////////////////////////////////////////////////
bool Matches(const Image* texture, const Shader* shader, Blend::Mode blendMode, const IntRect& viewport) const;
////////////////////////////////////////////////////////////
/// \brief Setup the start index of the batch
///
/// \param index Start index
///
////////////////////////////////////////////////////////////
void Begin(Uint32 index);
////////////////////////////////////////////////////////////
/// \brief Setup the end index of the batch
///
/// \param index End index
///
////////////////////////////////////////////////////////////
void End(Uint32 index);
////////////////////////////////////////////////////////////
/// \brief Render the contents of the batch
///
/// \param renderer Renderer to use for rendering
///
////////////////////////////////////////////////////////////
void Render(GeometryRenderer& renderer) const;
private :
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
const Image* myTexture; ///< Texture used by the batch
const Shader* myShader; ///< Pixel shader used by the batch
Blend::Mode myBlendMode; ///< Blending mode used by the batch
IntRect myViewport; ///< Target viewport for the batch
Uint32 myStart; ///< Index of the first index to render with this batch
Uint32 myCount; ///< Number of indices to render with this batch
};
} // namespace priv
} // namespace sf
#endif // SFML_BATCH_HPP

View file

@ -26,7 +26,7 @@
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Drawable.hpp>
#include <SFML/Graphics/RenderQueue.hpp>
#include <SFML/Graphics/Renderer.hpp>
#include <SFML/Graphics/RenderTarget.hpp>
#include <math.h>
@ -366,19 +366,19 @@ const Matrix3& Drawable::GetInverseMatrix() const
////////////////////////////////////////////////////////////
/// Draw the object into the specified render target
////////////////////////////////////////////////////////////
void Drawable::Draw(RenderTarget& target, RenderQueue& queue) const
void Drawable::Draw(RenderTarget& target, Renderer& renderer) const
{
// Set the current model-view matrix
queue.ApplyModelView(GetMatrix());
renderer.ApplyModelView(GetMatrix());
// Set the current global color
queue.ApplyColor(myColor);
renderer.ApplyColor(myColor);
// Set the current alpha-blending mode
queue.SetBlendMode(myBlendMode);
renderer.SetBlendMode(myBlendMode);
// Let the derived class render the object geometry
Render(target, queue);
Render(target, renderer);
}
} // namespace sf

View file

@ -1,68 +0,0 @@
////////////////////////////////////////////////////////////
//
// 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

View file

@ -1,106 +0,0 @@
////////////////////////////////////////////////////////////
//
// 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 Uint32* 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(Uint32 start, Uint32 count) = 0;
};
} // namespace priv
} // namespace sf
#endif // SFML_GEOMETRYRENDERER_HPP

View file

@ -1,95 +0,0 @@
////////////////////////////////////////////////////////////
//
// 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 Uint32* indices, std::size_t)
{
// Store the geometry informations for later rendering
myVertices = vertices;
myIndices = indices;
}
////////////////////////////////////////////////////////////
void GeometryRendererIM::End()
{
// Nothing to do
}
////////////////////////////////////////////////////////////
void GeometryRendererIM::RenderTriangles(Uint32 start, Uint32 count)
{
// Caculate the bounds of the geometry range to render
const Uint32* begin = myIndices + start;
const Uint32* end = begin + count;
// Begin rendering
glBegin(GL_TRIANGLES);
// Send the vertices one by one
for (const Uint32* 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

View file

@ -1,108 +0,0 @@
////////////////////////////////////////////////////////////
//
// 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 Uint32* 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(Uint32 start, Uint32 count);
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
const float* myVertices; ///< Pointer to the vertices to render
const Uint32* myIndices; ///< Pointer to the indices to render
};
} // namespace priv
} // namespace sf
#endif // SFML_GEOMETRYRENDERERIM_HPP

View file

@ -1,97 +0,0 @@
////////////////////////////////////////////////////////////
//
// 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()
{
priv::EnsureGlewInit();
return GLEW_EXT_vertex_array != 0;
}
////////////////////////////////////////////////////////////
GeometryRendererVA::GeometryRendererVA() :
myIndices(NULL)
{
priv::EnsureGlewInit();
}
////////////////////////////////////////////////////////////
void GeometryRendererVA::Begin(const float* vertices, std::size_t verticesCount, const Uint32* 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 (GLEW_EXT_compiled_vertex_array)
GLCheck(glLockArraysEXT(0, static_cast<GLsizei>(verticesCount) / 8));
// Store indices for later use
myIndices = indices;
}
////////////////////////////////////////////////////////////
void GeometryRendererVA::End()
{
// Unlock the vertex array if it was locked
if (GLEW_EXT_compiled_vertex_array)
GLCheck(glUnlockArraysEXT());
}
////////////////////////////////////////////////////////////
void GeometryRendererVA::RenderTriangles(Uint32 start, Uint32 count)
{
GLCheck(glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(count), GL_UNSIGNED_INT, myIndices + start));
}
} // namespace priv
} // namespace sf

View file

@ -1,107 +0,0 @@
////////////////////////////////////////////////////////////
//
// 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 Uint32* 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(Uint32 start, Uint32 count);
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
const Uint32* myIndices; ///< Pointer to the indices to render
};
} // namespace priv
} // namespace sf
#endif // SFML_GEOMETRYRENDERERVA_HPP

View file

@ -1,127 +0,0 @@
////////////////////////////////////////////////////////////
//
// 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()
{
priv::EnsureGlewInit();
return GLEW_ARB_vertex_buffer_object != 0;
}
////////////////////////////////////////////////////////////
GeometryRendererVBO::GeometryRendererVBO() :
myVertexBufferSize(0),
myIndexBufferSize (0)
{
priv::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 Uint32* 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(Uint32), indices, GL_DYNAMIC_DRAW_ARB));
myIndexBufferSize = indicesCount;
}
else
{
GLCheck(glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, indicesCount * sizeof(Uint32), 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(Uint32 start, Uint32 count)
{
static const Uint32* pointer = NULL;
GLCheck(glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(count), GL_UNSIGNED_INT, pointer + start));
}
} // namespace priv
} // namespace sf

View file

@ -1,117 +0,0 @@
////////////////////////////////////////////////////////////
//
// 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 Uint32* 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(Uint32 start, Uint32 count);
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
GLuint myVertexBuffer; ///< Identifier of the vertex buffer
GLuint myIndexBuffer; ///< Identifier of the index buffer
std::size_t myVertexBufferSize; ///< Size of the vertex buffer
std::size_t myIndexBufferSize; ///< Size of the index buffer
};
} // namespace priv
} // namespace sf
#endif // SFML_GEOMETRYRENDERERVBO_HPP

View file

@ -354,9 +354,6 @@ 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())
{
@ -642,7 +639,7 @@ Image& Image::operator =(const Image& other)
std::swap(myArrayUpdated, temp.myArrayUpdated);
std::swap(myTextureUpdated, temp.myTextureUpdated);
std::swap(myPixelsFlipped, temp.myPixelsFlipped);
myPixels.swap(temp.myPixels);
std::swap(myPixels, temp.myPixels);
return *this;
}
@ -658,47 +655,39 @@ bool Image::CreateTexture()
return false;
// Adjust internal texture dimensions depending on NPOT textures support
unsigned int textureWidth = GetValidSize(myWidth);
unsigned int textureHeight = GetValidSize(myHeight);
myTextureWidth = GetValidSize(myWidth);
myTextureHeight = GetValidSize(myHeight);
// Check the maximum texture size
unsigned int maxSize = GetMaximumSize();
if ((textureWidth > maxSize) || (textureHeight > maxSize))
if ((myTextureWidth > maxSize) || (myTextureHeight > maxSize))
{
std::cerr << "Failed to create image, its internal size is too high "
<< "(" << textureWidth << "x" << textureHeight << ", "
<< "(" << myTextureWidth << "x" << myTextureHeight << ", "
<< "maximum is " << maxSize << "x" << maxSize << ")"
<< std::endl;
return false;
}
// Destroy the previous OpenGL texture if it already exists with another size
if ((textureWidth != myTextureWidth) || (textureHeight != myTextureHeight))
{
DestroyTexture();
myTextureWidth = textureWidth;
myTextureHeight = textureHeight;
}
// Create the OpenGL texture
// Create the OpenGL texture if it doesn't exist yet
if (!myTexture)
{
GLint previous;
GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous));
GLuint texture = 0;
GLuint texture;
GLCheck(glGenTextures(1, &texture));
GLCheck(glBindTexture(GL_TEXTURE_2D, texture));
GLCheck(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, myTextureWidth, myTextureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL));
GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP));
GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP));
GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, myIsSmooth ? GL_LINEAR : GL_NEAREST));
GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, myIsSmooth ? GL_LINEAR : GL_NEAREST));
myTexture = static_cast<unsigned int>(texture);
GLCheck(glBindTexture(GL_TEXTURE_2D, previous));
}
// Initialize the texture
GLint previous;
GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous));
GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture));
GLCheck(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, myTextureWidth, myTextureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL));
GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP));
GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP));
GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, myIsSmooth ? GL_LINEAR : GL_NEAREST));
GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, myIsSmooth ? GL_LINEAR : GL_NEAREST));
GLCheck(glBindTexture(GL_TEXTURE_2D, previous));
myTextureUpdated = false;
return true;

View file

@ -204,6 +204,9 @@ bool RenderImageImplPBuffer::UpdateTexture(unsigned int textureId)
{
if (Activate(true))
{
GLint previous;
GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous));
// Bind the texture
GLCheck(glEnable(GL_TEXTURE_2D));
GLCheck(glBindTexture(GL_TEXTURE_2D, textureId));
@ -211,8 +214,7 @@ bool RenderImageImplPBuffer::UpdateTexture(unsigned int textureId)
// Copy the rendered pixels to the image
GLCheck(glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, myWidth, myHeight));
// Deactivate the P-Buffer
Activate(false);
GLCheck(glBindTexture(GL_TEXTURE_2D, previous));
return true;
}

View file

@ -48,7 +48,6 @@ myRenderImage(NULL)
////////////////////////////////////////////////////////////
RenderImage::~RenderImage()
{
SetActive(false);
delete myRenderImage;
}
@ -77,12 +76,12 @@ bool RenderImage::Create(unsigned int width, unsigned int height, bool depthBuff
// Create the implementation
delete myRenderImage;
if (priv::RenderImageImplFBO::IsSupported())
/*if (priv::RenderImageImplFBO::IsSupported())
{
// Use FBO
myRenderImage = new priv::RenderImageImplFBO;
}
else if (priv::RenderImageImplPBuffer::IsSupported())
else*/ if (priv::RenderImageImplPBuffer::IsSupported())
{
// Use P-Buffer
myRenderImage = new priv::RenderImageImplPBuffer;
@ -132,9 +131,6 @@ bool RenderImage::SetActive(bool active)
////////////////////////////////////////////////////////////
void RenderImage::Display()
{
// Render everything that has been drawn so far
Flush();
// Update the target image
if (myRenderImage)
{

View file

@ -28,6 +28,7 @@
#include <SFML/Graphics/RenderImageImplFBO.hpp>
#include <SFML/Graphics/Image.hpp>
#include <SFML/Graphics/GLCheck.hpp>
#include <SFML/Window/Context.hpp>
#include <iostream>
@ -40,7 +41,8 @@ namespace priv
////////////////////////////////////////////////////////////
RenderImageImplFBO::RenderImageImplFBO() :
myFrameBuffer(0),
myDepthBuffer(0)
myDepthBuffer(0),
myContext (NULL)
{
}
@ -64,6 +66,9 @@ RenderImageImplFBO::~RenderImageImplFBO()
GLuint frameBuffer = static_cast<GLuint>(myFrameBuffer);
GLCheck(glDeleteFramebuffersEXT(1, &frameBuffer));
}
// Destroy the context
delete myContext;
}
@ -84,6 +89,10 @@ bool RenderImageImplFBO::IsSupported()
////////////////////////////////////////////////////////////
bool RenderImageImplFBO::Create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer)
{
// Create the context if not already done
if (!myContext)
myContext = new Context;
// Create the framebuffer object if not already done
if (!myFrameBuffer)
{
@ -132,9 +141,6 @@ bool RenderImageImplFBO::Create(unsigned int width, unsigned int height, unsigne
return false;
}
// Unbind the buffers
Activate(false);
return true;
}
@ -144,23 +150,12 @@ bool RenderImageImplFBO::Create(unsigned int width, unsigned int height, unsigne
////////////////////////////////////////////////////////////
bool RenderImageImplFBO::Activate(bool active)
{
if (active)
{
// Bind the buffers
GLCheck(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, myFrameBuffer));
GLCheck(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, myDepthBuffer));
}
else
{
// Unbind the buffers
GLCheck(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
GLCheck(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0));
}
if (myContext)
myContext->SetActive(active);
return true;
}
////////////////////////////////////////////////////////////
/// /see RenderImageImpl::UpdateTexture
////////////////////////////////////////////////////////////

View file

@ -33,6 +33,8 @@
namespace sf
{
class Context;
namespace priv
{
////////////////////////////////////////////////////////////
@ -88,6 +90,7 @@ private :
////////////////////////////////////////////////////////////
unsigned int myFrameBuffer; ///< OpenGL frame buffer object
unsigned int myDepthBuffer; ///< Optional depth buffer attached to the frame buffer
Context* myContext; ///< Needs a separate OpenGL context for not messing up the other ones
};
} // namespace priv

View file

@ -1,338 +0,0 @@
////////////////////////////////////////////////////////////
//
// 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)
{
// Use a union rather than reinterpret_cast, because it doesn't break strict-aliasing
// rules and results in a correct behaviour when compiling in optimized mode
union DoubleToInt
{
double d;
sf::Int32 i[2];
};
DoubleToInt u;
u.d = value + 6755399441055744.0;
#if defined(SFML_ENDIAN_LITTLE)
return u.i[0];
#else
return u.i[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::SetShader(const Shader* shader)
{
myCurrentShader = shader;
}
////////////////////////////////////////////////////////////
void RenderQueue::BeginBatch()
{
// Check if the current batch differs from the new render states
if (!myCurrentBatch || !myCurrentBatch->Matches(myCurrentTexture, myCurrentShader, myCurrentBlendMode, myCurrentViewport))
{
// Close the current batch
if (myCurrentBatch)
myCurrentBatch->End(myCurrentIndexCount);
// Create a new one
priv::Batch batch(myCurrentTexture, myCurrentShader, 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(std::size_t index0, std::size_t index1, std::size_t 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] = static_cast<Uint32>(index0 + myBaseIndex);
myIndices[myCurrentIndexCount + 1] = static_cast<Uint32>(index1 + myBaseIndex);
myIndices[myCurrentIndexCount + 2] = static_cast<Uint32>(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->Render(*myRenderer);
// 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()
{
myBatches.clear();
myCurrentBatch = NULL;
myCurrentVertexCount = 0;
myCurrentIndexCount = 0;
}
} // namespace sf

View file

@ -27,12 +27,22 @@
////////////////////////////////////////////////////////////
#include <SFML/Graphics/RenderTarget.hpp>
#include <SFML/Graphics/Drawable.hpp>
#include <SFML/Graphics/GLCheck.hpp>
#include <iostream>
namespace sf
{
////////////////////////////////////////////////////////////
/// Default constructor
////////////////////////////////////////////////////////////
RenderTarget::RenderTarget() :
myStatesSaved (false),
myViewHasChanged(false)
{
}
////////////////////////////////////////////////////////////
/// Destructor
////////////////////////////////////////////////////////////
@ -48,16 +58,7 @@ RenderTarget::~RenderTarget()
void RenderTarget::Clear(const Color& color)
{
if (Activate(true))
{
// 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);
}
myRenderer.Clear(color);
}
@ -66,20 +67,30 @@ void RenderTarget::Clear(const Color& color)
////////////////////////////////////////////////////////////
void RenderTarget::Draw(const Drawable& object)
{
// Save the current render states
myRenderQueue.PushStates();
if (Activate(true))
{
// Update the projection matrix and viewport if the current view has changed
// Note: we do the changes here and not directly in SetView in order to gather
// rendering commands, which is safer in multithreaded environments
if (myViewHasChanged)
{
myRenderer.SetProjection(myCurrentView.GetMatrix());
myRenderer.SetViewport(GetViewport(myCurrentView));
myViewHasChanged = false;
}
// Setup the shader
myRenderQueue.SetShader(NULL);
// Save the current render states
myRenderer.PushStates();
// Setup the viewport
myRenderQueue.SetViewport(GetViewport(myCurrentView));
// Setup the shader
myRenderer.SetShader(NULL);
// Let the object draw itself
object.Draw(*this, myRenderQueue);
// Let the object draw itself
object.Draw(*this, myRenderer);
// Restore the previous render states
myRenderQueue.PopStates();
// Restore the previous render states
myRenderer.PopStates();
}
}
@ -87,35 +98,30 @@ void RenderTarget::Draw(const Drawable& object)
/// Draw something into the target with a shader
////////////////////////////////////////////////////////////
void RenderTarget::Draw(const Drawable& object, const Shader& shader)
{
// Save the current render states
myRenderQueue.PushStates();
// Setup the shader
myRenderQueue.SetShader(&shader);
// Setup the viewport
myRenderQueue.SetViewport(GetViewport(myCurrentView));
// 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))
{
// Draw the whole render queue
myRenderQueue.Render();
// Update the projection matrix and viewport if the current view has changed
// Note: we do the changes here and not directly in SetView in order to gather
// rendering commands, which is safer in multithreaded environments
if (myViewHasChanged)
{
myRenderer.SetProjection(myCurrentView.GetMatrix());
myRenderer.SetViewport(GetViewport(myCurrentView));
myViewHasChanged = false;
}
Activate(false);
// Save the current render states
myRenderer.PushStates();
// Setup the shader
myRenderer.SetShader(&shader);
// Let the object draw itself
object.Draw(*this, myRenderer);
// Restore the previous render states
myRenderer.PopStates();
}
}
@ -127,9 +133,7 @@ void RenderTarget::SetView(const View& view)
{
// Save it
myCurrentView = view;
// Send the projection matrix to the render queue
myRenderQueue.SetProjection(view.GetMatrix());
myViewHasChanged = true;
}
@ -160,13 +164,10 @@ IntRect RenderTarget::GetViewport(const View& view) const
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;
return IntRect(static_cast<int>(0.5f + width * viewport.Left),
static_cast<int>(0.5f + height * (1.f - viewport.Bottom)),
static_cast<int>(0.5f + width * viewport.Right),
static_cast<int>(0.5f + height * (1.f - viewport.Top)));
}
@ -197,6 +198,39 @@ sf::Vector2f RenderTarget::ConvertCoords(unsigned int x, unsigned int y, const V
}
////////////////////////////////////////////////////////////
/// Save the current OpenGL render states and matrices
////////////////////////////////////////////////////////////
void RenderTarget::SaveGLStates()
{
if (Activate(true))
{
myRenderer.SaveGLStates();
myStatesSaved = true;
// Restore the render states and the current view, for SFML rendering
myRenderer.Initialize();
SetView(GetView());
}
}
////////////////////////////////////////////////////////////
/// Restore the previously saved OpenGL render states and matrices
////////////////////////////////////////////////////////////
void RenderTarget::RestoreGLStates()
{
if (myStatesSaved)
{
if (Activate(true))
{
myRenderer.RestoreGLStates();
myStatesSaved = false;
}
}
}
////////////////////////////////////////////////////////////
/// Called by the derived class when it's ready to be initialized
////////////////////////////////////////////////////////////
@ -206,8 +240,9 @@ void RenderTarget::Initialize()
myDefaultView.Reset(FloatRect(0, 0, static_cast<float>(GetWidth()), static_cast<float>(GetHeight())));
SetView(myDefaultView);
// Clear the render queue
myRenderQueue.Clear();
// Initialize the renderer
if (Activate(true))
myRenderer.Initialize();
}
} // namespace sf

View file

@ -63,8 +63,7 @@ RenderWindow::~RenderWindow()
////////////////////////////////////////////////////////////
bool RenderWindow::Activate(bool active)
{
// We only handle activation, for performances and consistency reasons
return active ? SetActive(active) : true;
return SetActive(active);
}
@ -91,10 +90,10 @@ void RenderWindow::OnCreate()
////////////////////////////////////////////////////////////
void RenderWindow::OnDisplay()
void RenderWindow::OnResize()
{
// Render the drawables drawn so far
Flush();
// Update the current view (recompute the viewport, which is stored in relative coordinates)
SetView(GetView());
}
} // namespace sf

View file

@ -0,0 +1,386 @@
////////////////////////////////////////////////////////////
//
// 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/Renderer.hpp>
#include <SFML/Graphics/Image.hpp>
#include <SFML/Graphics/Shader.hpp>
#include <SFML/Graphics/GLCheck.hpp>
////////////////////////////////////////////////////////////
// Private data
////////////////////////////////////////////////////////////
namespace
{
// Fast float to int conversion
inline sf::Int32 Round(double value)
{
// Use a union rather than reinterpret_cast, because it doesn't break strict-aliasing
// rules and results in a correct behaviour when compiling in optimized mode
union DoubleToInt
{
double d;
sf::Int32 i[2];
};
DoubleToInt u;
u.d = value + 6755399441055744.0;
#if defined(SFML_ENDIAN_LITTLE)
return u.i[0];
#else
return u.i[1];
#endif
}
}
namespace sf
{
////////////////////////////////////////////////////////////
Renderer::Renderer() :
myTextureIsValid (false),
myShaderIsValid (false),
myBlendModeIsValid(false),
myViewportIsValid (false)
{
myStates = &myStatesStack[0];
}
////////////////////////////////////////////////////////////
Renderer::~Renderer()
{
}
////////////////////////////////////////////////////////////
void Renderer::Initialize()
{
// Default render states
GLCheck(glDisable(GL_LIGHTING));
GLCheck(glDisable(GL_DEPTH_TEST));
GLCheck(glEnable(GL_ALPHA_TEST));
GLCheck(glAlphaFunc(GL_GREATER, 0));
// Default transform matrices
GLCheck(glMatrixMode(GL_MODELVIEW));
GLCheck(glLoadIdentity());
GLCheck(glMatrixMode(GL_PROJECTION));
GLCheck(glLoadIdentity());
// Invalidate the cached SFML states
myTextureIsValid = false;
myShaderIsValid = false;
myBlendModeIsValid = false;
myViewportIsValid = false;
}
////////////////////////////////////////////////////////////
void Renderer::SaveGLStates()
{
// Save render states
GLCheck(glPushAttrib(GL_ALL_ATTRIB_BITS));
//GLCheck(glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS));
// Save matrices
GLCheck(glMatrixMode(GL_MODELVIEW));
GLCheck(glPushMatrix());
GLCheck(glMatrixMode(GL_PROJECTION));
GLCheck(glPushMatrix());
}
////////////////////////////////////////////////////////////
void Renderer::RestoreGLStates()
{
// Restore render states
GLCheck(glPopAttrib());
//GLCheck(glPopClientAttrib());
// Restore matrices
GLCheck(glMatrixMode(GL_PROJECTION));
GLCheck(glPopMatrix());
GLCheck(glMatrixMode(GL_MODELVIEW));
GLCheck(glPopMatrix());
}
////////////////////////////////////////////////////////////
void Renderer::Clear(const Color& color)
{
GLCheck(glClearColor(color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f));
GLCheck(glClear(GL_COLOR_BUFFER_BIT));
}
////////////////////////////////////////////////////////////
void Renderer::PushStates()
{
myStates++;
*myStates = *(myStates - 1);
}
////////////////////////////////////////////////////////////
void Renderer::PopStates()
{
myStates--;
}
////////////////////////////////////////////////////////////
void Renderer::SetModelView(const Matrix3& matrix)
{
myStates->modelView = matrix;
}
////////////////////////////////////////////////////////////
void Renderer::ApplyModelView(const Matrix3& matrix)
{
myStates->modelView *= matrix;
}
////////////////////////////////////////////////////////////
void Renderer::SetProjection(const Matrix3& matrix)
{
myProjection = matrix;
}
////////////////////////////////////////////////////////////
void Renderer::ApplyProjection(const Matrix3& matrix)
{
myProjection *= matrix;
}
////////////////////////////////////////////////////////////
void Renderer::SetColor(const Color& color)
{
myStates->r = color.r / 255.f;
myStates->g = color.g / 255.f;
myStates->b = color.b / 255.f;
myStates->a = color.a / 255.f;
}
////////////////////////////////////////////////////////////
void Renderer::ApplyColor(const Color& color)
{
myStates->r *= color.r / 255.f;
myStates->g *= color.g / 255.f;
myStates->b *= color.b / 255.f;
myStates->a *= color.a / 255.f;
}
////////////////////////////////////////////////////////////
void Renderer::SetViewport(const IntRect& viewport)
{
if ((viewport.Left != myViewport.Left) || (viewport.Right != myViewport.Right) ||
(viewport.Top != myViewport.Top) || (viewport.Bottom != myViewport.Bottom) ||
!myViewportIsValid)
{
// Apply the new viewport
GLCheck(glViewport(viewport.Left, viewport.Top, viewport.GetSize().x, viewport.GetSize().y));
// Store it
myViewport = viewport;
myViewportIsValid = true;
// Store the half-size of the viewport for later computations
myViewportSize.x = myViewport.GetSize().x / 2.f;
myViewportSize.y = myViewport.GetSize().y / 2.f;
}
}
////////////////////////////////////////////////////////////
void Renderer::SetBlendMode(Blend::Mode mode)
{
if ((mode != myBlendMode) || !myBlendModeIsValid)
{
// Apply the new blending mode
if (mode == Blend::None)
{
GLCheck(glDisable(GL_BLEND));
}
else
{
GLCheck(glEnable(GL_BLEND));
switch (mode)
{
// Alpha blending
// glBlendFuncSeparateEXT is used when available to avoid an incorrect alpha value when the target
// is a RenderImage -- in this case the alpha value must be written directly to the target buffer
default :
case Blend::Alpha :
if (GLEW_EXT_blend_func_separate)
GLCheck(glBlendFuncSeparateEXT(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
else
GLCheck(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
break;
// Additive blending
case Blend::Add :
GLCheck(glBlendFunc(GL_SRC_ALPHA, GL_ONE));
break;
// Multiplicative blending
case Blend::Multiply :
GLCheck(glBlendFunc(GL_DST_COLOR, GL_ZERO));
break;
}
}
// Store it
myBlendMode = mode;
myBlendModeIsValid = true;
}
}
////////////////////////////////////////////////////////////
void Renderer::SetTexture(const Image* texture)
{
if ((texture != myTexture) || !myTextureIsValid)
{
// Apply the new texture
if (texture)
texture->Bind();
else
GLCheck(glDisable(GL_TEXTURE_2D));
// Store it
myTexture = texture;
myTextureIsValid = true;
}
}
////////////////////////////////////////////////////////////
void Renderer::SetShader(const Shader* shader)
{
if ((shader != myShader) || !myShaderIsValid)
{
// Apply the new shader
if (shader)
shader->Bind();
else if (myShaderIsValid && myShader)
myShader->Unbind();
// Store it
myShader = shader;
myShaderIsValid = false;
}
}
////////////////////////////////////////////////////////////
void Renderer::Begin(PrimitiveType type)
{
// Update the combined transform matrix
myTransform = myProjection * myStates->modelView;
// Begin rendering
switch (type)
{
case TriangleList : glBegin(GL_TRIANGLES); break;
case TriangleStrip : glBegin(GL_TRIANGLE_STRIP); break;
case TriangleFan : glBegin(GL_TRIANGLE_FAN); break;
case QuadList : glBegin(GL_QUADS); break;
default: break;
}
}
////////////////////////////////////////////////////////////
void Renderer::End()
{
// End rendering
glEnd();
}
////////////////////////////////////////////////////////////
void Renderer::AddVertex(float x, float y)
{
ProcessVertex(x, y, 0.f, 0.f, 1.f, 1.f, 1.f, 1.f);
}
////////////////////////////////////////////////////////////
void Renderer::AddVertex(float x, float y, float u, float v)
{
ProcessVertex(x, y, u, v, 1.f, 1.f, 1.f, 1.f);
}
////////////////////////////////////////////////////////////
void Renderer::AddVertex(float x, float y, const Color& color)
{
ProcessVertex(x, y, 0.f, 0.f, color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f);
}
////////////////////////////////////////////////////////////
void Renderer::AddVertex(float x, float y, float u, float v, const Color& color)
{
ProcessVertex(x, y, u, v, color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f);
}
////////////////////////////////////////////////////////////
void Renderer::ProcessVertex(float x, float y, float u, float v, float r, float g, float b, float a)
{
// Transform the vertex position by the current model-view-projection matrix
Vector2f position = myTransform.Transform(Vector2f(x, y));
// Round the vertex position so that it matches the
// viewport's pixels, and thus avoid rendering artifacts
// @todo remove and find a better solution :)
position.x = Round((position.x + 1.f) * myViewportSize.x) / myViewportSize.x - 1.f;
position.y = Round((position.y + 1.f) * myViewportSize.y) / myViewportSize.y - 1.f;
// Modulate the vertex color with the current global color
r *= myStates->r;
g *= myStates->g;
b *= myStates->b;
a *= myStates->a;
// Render the vertex
glColor4f(r, g, b, a);
glTexCoord2f(u, v);
glVertex2f(position.x, position.y);
}
} // namespace sf

View file

@ -218,20 +218,15 @@ void Shader::SetTexture(const std::string& name, const Image& texture)
int location = glGetUniformLocationARB(myShaderProgram, name.c_str());
if (location == -1)
{
std::cerr << "Texture \"" << name << "\" not found in Shader" << std::endl;
std::cerr << "Texture \"" << name << "\" not found in shader" << std::endl;
return;
}
// Store the texture for later use
if ((texture.GetWidth() > 0) && (texture.GetHeight() > 0))
{
if (&texture != &CurrentTexture)
myTextures[location] = &texture;
}
else
{
// An invalid size means that texture is Shader::CurrentTexture
myCurrentTexture = location;
}
}

View file

@ -26,7 +26,7 @@
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Shape.hpp>
#include <SFML/Graphics/RenderQueue.hpp>
#include <SFML/Graphics/Renderer.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&, RenderQueue& queue) const
void Shape::Render(RenderTarget&, Renderer& renderer) const
{
// Make sure the shape has at least 3 points (4 if we count the center)
if (myPoints.size() < 4)
@ -292,7 +292,7 @@ void Shape::Render(RenderTarget&, RenderQueue& queue) const
const_cast<Shape*>(this)->Compile();
// Shapes only use color, no texture
queue.SetTexture(NULL);
renderer.SetTexture(NULL);
// Draw the shape
if (myIsFillEnabled)
@ -300,61 +300,59 @@ void Shape::Render(RenderTarget&, RenderQueue& queue) const
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);
renderer.Begin(Renderer::TriangleList);
renderer.AddVertex(myPoints[1].Position.x, myPoints[1].Position.y, myPoints[1].Col);
renderer.AddVertex(myPoints[2].Position.x, myPoints[2].Position.y, myPoints[2].Col);
renderer.AddVertex(myPoints[3].Position.x, myPoints[3].Position.y, myPoints[3].Col);
renderer.End();
}
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);
renderer.Begin(Renderer::TriangleStrip);
renderer.AddVertex(myPoints[1].Position.x, myPoints[1].Position.y, myPoints[1].Col);
renderer.AddVertex(myPoints[2].Position.x, myPoints[2].Position.y, myPoints[2].Col);
renderer.AddVertex(myPoints[4].Position.x, myPoints[4].Position.y, myPoints[4].Col);
renderer.AddVertex(myPoints[3].Position.x, myPoints[3].Position.y, myPoints[3].Col);
renderer.End();
}
else
{
// General case of a convex polygon
queue.BeginBatch();
for (std::vector<Point>::const_iterator i = myPoints.begin(); i != myPoints.end(); ++i)
queue.AddVertex(i->Position.x, i->Position.y, i->Col);
renderer.Begin(Renderer::TriangleFan);
for (std::size_t i = 1; i < myPoints.size() - 1; ++i)
queue.AddTriangle(0, i, i + 1);
// General case of a convex polygon
for (std::vector<Point>::const_iterator i = myPoints.begin(); i != myPoints.end(); ++i)
renderer.AddVertex(i->Position.x, i->Position.y, i->Col);
// Close the shape by duplicating the first point at the end
queue.AddTriangle(0, myPoints.size() - 1, 1);
const Point& first = myPoints[1];
renderer.AddVertex(first.Position.x, first.Position.y, first.Col);
renderer.End();
}
}
// Draw the outline
if (myIsOutlineEnabled && (myOutline != 0))
{
queue.BeginBatch();
renderer.Begin(Renderer::TriangleStrip);
for (std::vector<Point>::const_iterator i = myPoints.begin() + 1; i != myPoints.end(); ++i)
{
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);
}
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);
renderer.AddVertex(point1.x, point1.y, i->OutlineCol);
renderer.AddVertex(point2.x, point2.y, i->OutlineCol);
}
// Close the shape by duplicating the first point at the end
std::size_t begin = 0;
std::size_t last = (myPoints.size() - 2) * 2;
queue.AddTriangle(last, last + 1, begin);
queue.AddTriangle(begin, last + 1, begin + 1);
const Point& first = myPoints[1];
Vector2f point1 = first.Position;
Vector2f point2 = first.Position + first.Normal * myOutline;
renderer.AddVertex(point1.x, point1.y, first.OutlineCol);
renderer.AddVertex(point2.x, point2.y, first.OutlineCol);
renderer.End();
}
}

View file

@ -27,7 +27,7 @@
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Sprite.hpp>
#include <SFML/Graphics/Image.hpp>
#include <SFML/Graphics/RenderQueue.hpp>
#include <SFML/Graphics/Renderer.hpp>
#include <utility>
@ -182,7 +182,7 @@ Color Sprite::GetPixel(unsigned int x, unsigned int y) const
////////////////////////////////////////////////////////////
/// /see Drawable::Render
////////////////////////////////////////////////////////////
void Sprite::Render(RenderTarget&, RenderQueue& queue) const
void Sprite::Render(RenderTarget&, Renderer& renderer) const
{
// Get the sprite size
float width = static_cast<float>(mySubRect.GetSize().x);
@ -198,16 +198,15 @@ void Sprite::Render(RenderTarget&, RenderQueue& queue) const
}
// Bind the texture
queue.SetTexture(myImage);
renderer.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);
renderer.Begin(Renderer::TriangleStrip);
renderer.AddVertex(0, 0, coords.Left, coords.Top);
renderer.AddVertex(width, 0, coords.Right, coords.Top);
renderer.AddVertex(0, height, coords.Left, coords.Bottom);
renderer.AddVertex(width, height, coords.Right, coords.Bottom);
renderer.End();
}
} // namespace sf

View file

@ -27,7 +27,7 @@
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Text.hpp>
#include <SFML/Graphics/Image.hpp>
#include <SFML/Graphics/RenderQueue.hpp>
#include <SFML/Graphics/Renderer.hpp>
namespace sf
@ -212,14 +212,14 @@ FloatRect Text::GetRect() const
////////////////////////////////////////////////////////////
/// /see Drawable::Render
////////////////////////////////////////////////////////////
void Text::Render(RenderTarget&, RenderQueue& queue) const
void Text::Render(RenderTarget&, Renderer& renderer) const
{
// No text or not font: nothing to render
if (!myFont || myString.IsEmpty())
return;
// Bind the font texture
queue.SetTexture(&myFont->GetImage(myCharacterSize));
renderer.SetTexture(&myFont->GetImage(myCharacterSize));
// Computes values related to the text style
bool bold = (myStyle & Bold) != 0;
@ -235,10 +235,12 @@ void Text::Render(RenderTarget&, RenderQueue& queue) const
float x = 0.f;
float y = static_cast<float>(myCharacterSize);
// Note:
// Here we use a Begin/End pair for each quad because
// the font's texture may change in a call to GetGlyph
// Draw one quad for each character
unsigned int index = 0;
Uint32 prevChar = 0;
queue.BeginBatch();
for (std::size_t i = 0; i < myString.GetSize(); ++i)
{
Uint32 curChar = myString[i];
@ -252,14 +254,13 @@ void Text::Render(RenderTarget&, RenderQueue& queue) const
{
float top = y + outlineOffset;
float bottom = top + outlineThick;
queue.AddVertex(0, top, outlineCoords.Left, outlineCoords.Top);
queue.AddVertex(0, bottom, outlineCoords.Left, outlineCoords.Bottom);
queue.AddVertex(x, bottom, outlineCoords.Right, outlineCoords.Bottom);
queue.AddVertex(x, top, outlineCoords.Right, outlineCoords.Top);
queue.AddTriangle(index + 0, index + 1, index + 3);
queue.AddTriangle(index + 3, index + 1, index + 2);
index += 4;
renderer.Begin(Renderer::QuadList);
renderer.AddVertex(0, top, outlineCoords.Left, outlineCoords.Top);
renderer.AddVertex(x, top, outlineCoords.Right, outlineCoords.Top);
renderer.AddVertex(x, bottom, outlineCoords.Right, outlineCoords.Bottom);
renderer.AddVertex(0, bottom, outlineCoords.Left, outlineCoords.Bottom);
renderer.End();
}
// Handle special characters
@ -278,14 +279,12 @@ void Text::Render(RenderTarget&, RenderQueue& queue) const
const FloatRect& coord = curGlyph.TexCoords;
// Draw a textured quad for the current character
queue.AddVertex(x + rect.Left - italicCoeff * rect.Top, y + rect.Top, coord.Left, coord.Top);
queue.AddVertex(x + rect.Left - italicCoeff * rect.Bottom, y + rect.Bottom, coord.Left, coord.Bottom);
queue.AddVertex(x + rect.Right - italicCoeff * rect.Bottom, y + rect.Bottom, coord.Right, coord.Bottom);
queue.AddVertex(x + rect.Right - italicCoeff * rect.Top, y + rect.Top, coord.Right, coord.Top);
queue.AddTriangle(index + 0, index + 1, index + 3);
queue.AddTriangle(index + 3, index + 1, index + 2);
index += 4;
renderer.Begin(Renderer::QuadList);
renderer.AddVertex(x + rect.Left - italicCoeff * rect.Top, y + rect.Top, coord.Left, coord.Top);
renderer.AddVertex(x + rect.Right - italicCoeff * rect.Top, y + rect.Top, coord.Right, coord.Top);
renderer.AddVertex(x + rect.Right - italicCoeff * rect.Bottom, y + rect.Bottom, coord.Right, coord.Bottom);
renderer.AddVertex(x + rect.Left - italicCoeff * rect.Bottom, y + rect.Bottom, coord.Left, coord.Bottom);
renderer.End();
// Advance to the next character
x += advance;
@ -296,14 +295,13 @@ void Text::Render(RenderTarget&, RenderQueue& queue) const
{
float top = y + outlineOffset;
float bottom = top + outlineThick;
queue.AddVertex(0, top, outlineCoords.Left, outlineCoords.Top);
queue.AddVertex(0, bottom, outlineCoords.Left, outlineCoords.Bottom);
queue.AddVertex(x, bottom, outlineCoords.Right, outlineCoords.Bottom);
queue.AddVertex(x, top, outlineCoords.Right, outlineCoords.Top);
queue.AddTriangle(index + 0, index + 1, index + 3);
queue.AddTriangle(index + 3, index + 1, index + 2);
index += 4;
renderer.Begin(Renderer::QuadList);
renderer.AddVertex(0, top, outlineCoords.Left, outlineCoords.Top);
renderer.AddVertex(x, top, outlineCoords.Right, outlineCoords.Top);
renderer.AddVertex(x, bottom, outlineCoords.Right, outlineCoords.Bottom);
renderer.AddVertex(0, bottom, outlineCoords.Left, outlineCoords.Bottom);
renderer.End();
}
}
@ -330,7 +328,7 @@ void Text::UpdateRect() const
float outlineThick = myCharacterSize * (bold ? 0.1f : 0.07f);
float charSize = static_cast<float>(myCharacterSize);
float space = static_cast<float>(myFont->GetGlyph(L' ', myCharacterSize, bold).Advance);
float lineSpacing = static_cast<float>(myFont->GetLineSpacing(myCharacterSize));
float lineSpacing = static_cast<float>(myFont->GetLineSpacing(myCharacterSize));
float curWidth = 0;
float curHeight = 0;
float width = 0;

View file

@ -195,6 +195,9 @@ bool RenderImageImplPBuffer::UpdateTexture(unsigned int textureId)
{
if (Activate(true))
{
GLint previous;
GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous));
// Bind the texture
GLCheck(glEnable(GL_TEXTURE_2D));
GLCheck(glBindTexture(GL_TEXTURE_2D, textureId));
@ -202,8 +205,7 @@ bool RenderImageImplPBuffer::UpdateTexture(unsigned int textureId)
// Copy the rendered pixels to the image
GLCheck(glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, myWidth, myHeight));
// Deactivate the P-Buffer
Activate(false);
GLCheck(glBindTexture(GL_TEXTURE_2D, previous));
return true;
}

View file

@ -147,13 +147,6 @@ void ContextGLX::UseVerticalSync(bool enabled)
}
////////////////////////////////////////////////////////////
bool ContextGLX::IsContextActive()
{
return glXGetCurrentContext() != NULL;
}
////////////////////////////////////////////////////////////
void ContextGLX::CreateContext(ContextGLX* shared, unsigned int bitsPerPixel, const ContextSettings& settings)
{
@ -201,8 +194,8 @@ void ContextGLX::CreateContext(ContextGLX* shared, unsigned int bitsPerPixel, co
glXGetConfig(myDisplay, &visuals[i], GLX_DEPTH_SIZE, &depth);
glXGetConfig(myDisplay, &visuals[i], GLX_STENCIL_SIZE, &stencil);
glXGetConfig(myDisplay, &visuals[i], GLX_SAMPLE_BUFFERS_ARB, &multiSampling);
glXGetConfig(myDisplay, &visuals[i], GLX_SAMPLES_ARB, &samples);
glXGetConfig(myDisplay, &visuals[i], GLX_SAMPLES_ARB, &samples);
// First check the mandatory parameters
if ((RGBA == 0) || (doubleBuffer == 0))
continue;
@ -283,10 +276,10 @@ void ContextGLX::CreateContext(ContextGLX* shared, unsigned int bitsPerPixel, co
glXGetConfig(myDisplay, bestVisual, GLX_DEPTH_SIZE, &depth);
glXGetConfig(myDisplay, bestVisual, GLX_STENCIL_SIZE, &stencil);
glXGetConfig(myDisplay, bestVisual, GLX_SAMPLE_BUFFERS_ARB, &multiSampling);
glXGetConfig(myDisplay, bestVisual, GLX_SAMPLES_ARB, &samples);
glXGetConfig(myDisplay, bestVisual, GLX_SAMPLES_ARB, &samples);
mySettings.DepthBits = static_cast<unsigned int>(depth);
mySettings.StencilBits = static_cast<unsigned int>(stencil);
mySettings.AntialiasingLevel = multiSampling ? samples : 0;
mySettings.AntialiasingLevel = multiSampling ? samples : 0;
// Change the target window's colormap so that it matches the context's one
::Window root = RootWindow(myDisplay, DefaultScreen(myDisplay));

View file

@ -98,14 +98,6 @@ public :
////////////////////////////////////////////////////////////
virtual void UseVerticalSync(bool enabled);
////////////////////////////////////////////////////////////
/// \brief Check if a context is active on the current thread
///
/// \return True if there's an active context, false otherwise
///
////////////////////////////////////////////////////////////
static bool IsContextActive();
private :
////////////////////////////////////////////////////////////

View file

@ -136,13 +136,6 @@ void ContextWGL::UseVerticalSync(bool enabled)
}
////////////////////////////////////////////////////////////
bool ContextWGL::IsContextActive()
{
return wglGetCurrentContext() != NULL;
}
////////////////////////////////////////////////////////////
void ContextWGL::CreateContext(ContextWGL* shared, unsigned int bitsPerPixel, const ContextSettings& settings)
{

View file

@ -97,14 +97,6 @@ public :
////////////////////////////////////////////////////////////
virtual void UseVerticalSync(bool enabled);
////////////////////////////////////////////////////////////
/// \brief Check if a context is active on the current thread
///
/// \return True if there's an active context, false otherwise
///
////////////////////////////////////////////////////////////
static bool IsContextActive();
private :
////////////////////////////////////////////////////////////

View file

@ -341,9 +341,6 @@ bool Window::SetActive(bool active) const
////////////////////////////////////////////////////////////
void Window::Display()
{
// Notify the derived class
OnDisplay();
// Limit the framerate if needed
if (myFramerateLimit > 0)
{
@ -399,7 +396,7 @@ void Window::OnCreate()
////////////////////////////////////////////////////////////
void Window::OnDisplay()
void Window::OnResize()
{
// Nothing by default
}
@ -418,6 +415,10 @@ void Window::OnEvent(const Event& event)
return;
}
// Notify resize events
if (event.Type == Event::Resized)
OnResize();
myEvents.push(event);
}