Add texture coordinate type to sf::RenderStates

This commit is contained in:
Corentin Schreiber 2021-07-04 07:47:48 +01:00 committed by Chris Thrasher
parent b234ede61e
commit ebf485737f
14 changed files with 119 additions and 37 deletions

View File

@ -0,0 +1,43 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2023 Laurent Gomila (laurent@sfml-dev.org)
//
// 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.
//
////////////////////////////////////////////////////////////
#pragma once
namespace sf
{
////////////////////////////////////////////////////////////
/// \ingroup graphics
/// \brief Types of texture coordinates that can be used for rendering
///
/// \see sf::Texture::bind
///
////////////////////////////////////////////////////////////
enum class CoordinateType
{
Normalized, //!< Texture coordinates in range [0 .. 1]
Pixels //!< Texture coordinates in range [0 .. size]
};
} // namespace sf

View File

@ -30,6 +30,7 @@
#include <SFML/Graphics/Export.hpp>
#include <SFML/Graphics/BlendMode.hpp>
#include <SFML/Graphics/CoordinateType.hpp>
#include <SFML/Graphics/Transform.hpp>
@ -95,11 +96,16 @@ struct SFML_GRAPHICS_API RenderStates
///
/// \param theBlendMode Blend mode to use
/// \param theTransform Transform to use
/// \param theCoordinateType Texture coordinate type to use
/// \param theTexture Texture to use
/// \param theShader Shader to use
///
////////////////////////////////////////////////////////////
RenderStates(const BlendMode& theBlendMode, const Transform& theTransform, const Texture* theTexture, const Shader* theShader);
RenderStates(const BlendMode& theBlendMode,
const Transform& theTransform,
CoordinateType theCoordinateType,
const Texture* theTexture,
const Shader* theShader);
////////////////////////////////////////////////////////////
// Static member data
@ -112,6 +118,7 @@ struct SFML_GRAPHICS_API RenderStates
////////////////////////////////////////////////////////////
BlendMode blendMode{BlendAlpha}; //!< Blending mode
Transform transform; //!< Transform
CoordinateType coordinateType{CoordinateType::Pixels}; //!< Texture coordinate type
const Texture* texture{}; //!< Texture
const Shader* shader{}; //!< Shader
};
@ -123,10 +130,11 @@ struct SFML_GRAPHICS_API RenderStates
/// \class sf::RenderStates
/// \ingroup graphics
///
/// There are four global states that can be applied to
/// There are five global states that can be applied to
/// the drawn objects:
/// \li the blend mode: how pixels of the object are blended with the background
/// \li the transform: how the object is positioned/rotated/scaled
/// \li the texture coordinate type: how texture coordinates are interpreted
/// \li the texture: what image is mapped to the object
/// \li the shader: what custom effect is applied to the object
///

View File

@ -31,6 +31,7 @@
#include <SFML/Graphics/BlendMode.hpp>
#include <SFML/Graphics/Color.hpp>
#include <SFML/Graphics/CoordinateType.hpp>
#include <SFML/Graphics/PrimitiveType.hpp>
#include <SFML/Graphics/Rect.hpp>
#include <SFML/Graphics/RenderStates.hpp>
@ -463,9 +464,10 @@ private:
/// \brief Apply a new texture
///
/// \param texture Texture to apply
/// \param coordinateType The texture coordinate type to use
///
////////////////////////////////////////////////////////////
void applyTexture(const Texture* texture);
void applyTexture(const Texture* texture, CoordinateType coordinateType = CoordinateType::Pixels);
////////////////////////////////////////////////////////////
/// \brief Apply a new shader
@ -514,6 +516,7 @@ private:
bool scissorEnabled; //!< Is scissor testing enabled?
BlendMode lastBlendMode; //!< Cached blending mode
std::uint64_t lastTextureId; //!< Cached texture
CoordinateType lastCoordinateType; //!< Texture coordinate type
bool texCoordsArrayEnabled; //!< Is GL_TEXTURE_COORD_ARRAY client state enabled?
bool useVertexCache; //!< Did we previously use the vertex cache?
std::array<Vertex, 4> vertexCache; //!< Pre-transformed vertices cache

View File

@ -29,6 +29,7 @@
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Export.hpp>
#include <SFML/Graphics/CoordinateType.hpp>
#include <SFML/Graphics/Rect.hpp>
#include <SFML/Window/GlResource.hpp>
@ -52,16 +53,6 @@ class Image;
class SFML_GRAPHICS_API Texture : GlResource
{
public:
////////////////////////////////////////////////////////////
/// \brief Types of texture coordinates that can be used for rendering
///
////////////////////////////////////////////////////////////
enum CoordinateType
{
Normalized, //!< Texture coordinates in range [0 .. 1]
Pixels //!< Texture coordinates in range [0 .. size]
};
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
@ -578,7 +569,7 @@ public:
/// \param coordinateType Type of texture coordinates to use
///
////////////////////////////////////////////////////////////
static void bind(const Texture* texture, CoordinateType coordinateType = Normalized);
static void bind(const Texture* texture, CoordinateType coordinateType = CoordinateType::Normalized);
////////////////////////////////////////////////////////////
/// \brief Get the maximum texture size allowed

View File

@ -7,6 +7,7 @@ set(SRC
${INCROOT}/BlendMode.hpp
${INCROOT}/Color.hpp
${INCROOT}/Color.inl
${INCROOT}/CoordinateType.hpp
${INCROOT}/Export.hpp
${SRCROOT}/Font.cpp
${INCROOT}/Font.hpp

View File

@ -71,10 +71,12 @@ RenderStates::RenderStates(const Shader* theShader) : shader(theShader)
////////////////////////////////////////////////////////////
RenderStates::RenderStates(const BlendMode& theBlendMode,
const Transform& theTransform,
CoordinateType theCoordinateType,
const Texture* theTexture,
const Shader* theShader) :
blendMode(theBlendMode),
transform(theTransform),
coordinateType(theCoordinateType),
texture(theTexture),
shader(theShader)
{

View File

@ -676,11 +676,12 @@ void RenderTarget::applyTransform(const Transform& transform)
////////////////////////////////////////////////////////////
void RenderTarget::applyTexture(const Texture* texture)
void RenderTarget::applyTexture(const Texture* texture, CoordinateType coordinateType)
{
Texture::bind(texture, Texture::Pixels);
Texture::bind(texture, coordinateType);
m_cache.lastTextureId = texture ? texture->m_cacheId : 0;
m_cache.lastCoordinateType = coordinateType;
}
@ -740,13 +741,13 @@ void RenderTarget::setupDraw(bool useVertexCache, const RenderStates& states)
// This saves us from having to call glFlush() in
// RenderTextureImplFBO which can be quite costly
// See: https://www.khronos.org/opengl/wiki/Memory_Model
applyTexture(states.texture);
applyTexture(states.texture, states.coordinateType);
}
else
{
const std::uint64_t textureId = states.texture ? states.texture->m_cacheId : 0;
if (textureId != m_cache.lastTextureId)
applyTexture(states.texture);
if (textureId != m_cache.lastTextureId || states.coordinateType != m_cache.lastCoordinateType)
applyTexture(states.texture, states.coordinateType);
}
// Apply the shader

View File

@ -236,6 +236,7 @@ void Shape::draw(RenderTarget& target, const RenderStates& states) const
RenderStates statesCopy(states);
statesCopy.transform *= getTransform();
statesCopy.coordinateType = CoordinateType::Pixels;
// Render the inside
statesCopy.texture = m_texture;

View File

@ -132,6 +132,7 @@ void Sprite::draw(RenderTarget& target, const RenderStates& states) const
statesCopy.transform *= getTransform();
statesCopy.texture = m_texture;
statesCopy.coordinateType = CoordinateType::Pixels;
target.draw(m_vertices.data(), m_vertices.size(), PrimitiveType::TriangleStrip, statesCopy);
}

View File

@ -356,6 +356,7 @@ void Text::draw(RenderTarget& target, const RenderStates& states) const
statesCopy.transform *= getTransform();
statesCopy.texture = &m_font->getTexture(m_characterSize);
statesCopy.coordinateType = CoordinateType::Pixels;
// Only draw the outline if there is something to draw
if (m_outlineThickness != 0)

View File

@ -862,7 +862,7 @@ void Texture::bind(const Texture* texture, CoordinateType coordinateType)
glCheck(glBindTexture(GL_TEXTURE_2D, texture->m_texture));
// Check if we need to define a special texture matrix
if ((coordinateType == Pixels) || texture->m_pixelsFlipped)
if ((coordinateType == CoordinateType::Pixels) || texture->m_pixelsFlipped)
{
// clang-format off
GLfloat matrix[16] = {1.f, 0.f, 0.f, 0.f,
@ -873,7 +873,7 @@ void Texture::bind(const Texture* texture, CoordinateType coordinateType)
// If non-normalized coordinates (= pixels) are requested, we need to
// setup scale factors that convert the range [0 .. size] to [0 .. 1]
if (coordinateType == Pixels)
if (coordinateType == CoordinateType::Pixels)
{
matrix[0] = 1.f / static_cast<float>(texture->m_actualSize.x);
matrix[5] = 1.f / static_cast<float>(texture->m_actualSize.y);
@ -889,11 +889,17 @@ void Texture::bind(const Texture* texture, CoordinateType coordinateType)
// Load the matrix
glCheck(glMatrixMode(GL_TEXTURE));
glCheck(glLoadMatrixf(matrix));
}
else
{
// Reset the texture matrix
glCheck(glMatrixMode(GL_TEXTURE));
glCheck(glLoadIdentity());
}
// Go back to model-view mode (sf::RenderTarget relies on it)
glCheck(glMatrixMode(GL_MODELVIEW));
}
}
else
{
// Bind no texture

View File

@ -85,6 +85,7 @@ set(GRAPHICS_SRC
Graphics/CircleShape.test.cpp
Graphics/Color.test.cpp
Graphics/ConvexShape.test.cpp
Graphics/CoordinateType.test.cpp
Graphics/Drawable.test.cpp
Graphics/Font.test.cpp
Graphics/Glyph.test.cpp

View File

@ -0,0 +1,16 @@
#include <SFML/Graphics/CoordinateType.hpp>
#include <catch2/catch_test_macros.hpp>
#include <type_traits>
TEST_CASE("[Graphics] sf::CoordinateType")
{
SECTION("Type traits")
{
STATIC_CHECK(std::is_copy_constructible_v<sf::CoordinateType>);
STATIC_CHECK(std::is_copy_assignable_v<sf::CoordinateType>);
STATIC_CHECK(std::is_nothrow_move_constructible_v<sf::CoordinateType>);
STATIC_CHECK(std::is_nothrow_move_assignable_v<sf::CoordinateType>);
}
}

View File

@ -22,6 +22,7 @@ TEST_CASE("[Graphics] sf::RenderStates")
const sf::RenderStates renderStates;
CHECK(renderStates.blendMode == sf::BlendMode());
CHECK(renderStates.transform == sf::Transform());
CHECK(renderStates.coordinateType == sf::CoordinateType::Pixels);
CHECK(renderStates.texture == nullptr);
CHECK(renderStates.shader == nullptr);
}
@ -37,6 +38,7 @@ TEST_CASE("[Graphics] sf::RenderStates")
const sf::RenderStates renderStates(blendMode);
CHECK(renderStates.blendMode == blendMode);
CHECK(renderStates.transform == sf::Transform());
CHECK(renderStates.coordinateType == sf::CoordinateType::Pixels);
CHECK(renderStates.texture == nullptr);
CHECK(renderStates.shader == nullptr);
}
@ -47,6 +49,7 @@ TEST_CASE("[Graphics] sf::RenderStates")
const sf::RenderStates renderStates(transform);
CHECK(renderStates.blendMode == sf::BlendMode());
CHECK(renderStates.transform == transform);
CHECK(renderStates.coordinateType == sf::CoordinateType::Pixels);
CHECK(renderStates.texture == nullptr);
CHECK(renderStates.shader == nullptr);
}
@ -57,6 +60,7 @@ TEST_CASE("[Graphics] sf::RenderStates")
const sf::RenderStates renderStates(texture);
CHECK(renderStates.blendMode == sf::BlendMode());
CHECK(renderStates.transform == sf::Transform());
CHECK(renderStates.coordinateType == sf::CoordinateType::Pixels);
CHECK(renderStates.texture == texture);
CHECK(renderStates.shader == nullptr);
}
@ -67,6 +71,7 @@ TEST_CASE("[Graphics] sf::RenderStates")
const sf::RenderStates renderStates(shader);
CHECK(renderStates.blendMode == sf::BlendMode());
CHECK(renderStates.transform == sf::Transform());
CHECK(renderStates.coordinateType == sf::CoordinateType::Pixels);
CHECK(renderStates.texture == nullptr);
CHECK(renderStates.shader == shader);
}
@ -80,9 +85,10 @@ TEST_CASE("[Graphics] sf::RenderStates")
sf::BlendMode::DstAlpha,
sf::BlendMode::Max);
const sf::Transform transform(10, 2, 3, 4, 50, 40, 30, 20, 10);
const sf::RenderStates renderStates(blendMode, transform, nullptr, nullptr);
const sf::RenderStates renderStates(blendMode, transform, sf::CoordinateType::Normalized, nullptr, nullptr);
CHECK(renderStates.blendMode == blendMode);
CHECK(renderStates.transform == transform);
CHECK(renderStates.coordinateType == sf::CoordinateType::Normalized);
CHECK(renderStates.texture == nullptr);
CHECK(renderStates.shader == nullptr);
}
@ -92,6 +98,7 @@ TEST_CASE("[Graphics] sf::RenderStates")
{
CHECK(sf::RenderStates::Default.blendMode == sf::BlendMode());
CHECK(sf::RenderStates::Default.transform == sf::Transform());
CHECK(sf::RenderStates::Default.coordinateType == sf::CoordinateType::Pixels);
CHECK(sf::RenderStates::Default.texture == nullptr);
CHECK(sf::RenderStates::Default.shader == nullptr);
}