1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414
|
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2025 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
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Export.hpp>
#include <SFML/Graphics/Drawable.hpp>
#include <SFML/Graphics/PrimitiveType.hpp>
#include <SFML/Graphics/RenderStates.hpp>
#include <SFML/Window/GlResource.hpp>
#include <cstddef>
namespace sf
{
class RenderTarget;
struct Vertex;
////////////////////////////////////////////////////////////
/// \brief Vertex buffer storage for one or more 2D primitives
///
////////////////////////////////////////////////////////////
class SFML_GRAPHICS_API VertexBuffer : public Drawable, private GlResource
{
public:
////////////////////////////////////////////////////////////
/// \brief Usage specifiers
///
/// If data is going to be updated once or more every frame,
/// set the usage to Stream. If data is going to be set once
/// and used for a long time without being modified, set the
/// usage to Static. For everything else Dynamic should be a
/// good compromise.
///
////////////////////////////////////////////////////////////
enum class Usage
{
Stream, //!< Constantly changing data
Dynamic, //!< Occasionally changing data
Static //!< Rarely changing data
};
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// Creates an empty vertex buffer.
///
////////////////////////////////////////////////////////////
VertexBuffer() = default;
////////////////////////////////////////////////////////////
/// \brief Construct a `VertexBuffer` with a specific `PrimitiveType`
///
/// Creates an empty vertex buffer and sets its primitive type to \p type.
///
/// \param type Type of primitive
///
////////////////////////////////////////////////////////////
explicit VertexBuffer(PrimitiveType type);
////////////////////////////////////////////////////////////
/// \brief Construct a `VertexBuffer` with a specific usage specifier
///
/// Creates an empty vertex buffer and sets its usage to \p usage.
///
/// \param usage Usage specifier
///
////////////////////////////////////////////////////////////
explicit VertexBuffer(Usage usage);
////////////////////////////////////////////////////////////
/// \brief Construct a `VertexBuffer` with a specific `PrimitiveType` and usage specifier
///
/// Creates an empty vertex buffer and sets its primitive type
/// to \p type and usage to \p usage.
///
/// \param type Type of primitive
/// \param usage Usage specifier
///
////////////////////////////////////////////////////////////
VertexBuffer(PrimitiveType type, Usage usage);
////////////////////////////////////////////////////////////
/// \brief Copy constructor
///
/// \param copy instance to copy
///
////////////////////////////////////////////////////////////
VertexBuffer(const VertexBuffer& copy);
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
~VertexBuffer() override;
////////////////////////////////////////////////////////////
/// \brief Create the vertex buffer
///
/// Creates the vertex buffer and allocates enough graphics
/// memory to hold `vertexCount` vertices. Any previously
/// allocated memory is freed in the process.
///
/// In order to deallocate previously allocated memory pass 0
/// as `vertexCount`. Don't forget to recreate with a non-zero
/// value when graphics memory should be allocated again.
///
/// \param vertexCount Number of vertices worth of memory to allocate
///
/// \return `true` if creation was successful
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool create(std::size_t vertexCount);
////////////////////////////////////////////////////////////
/// \brief Return the vertex count
///
/// \return Number of vertices in the vertex buffer
///
////////////////////////////////////////////////////////////
[[nodiscard]] std::size_t getVertexCount() const;
////////////////////////////////////////////////////////////
/// \brief Update the whole buffer from an array of vertices
///
/// The vertex array is assumed to have the same size as
/// the created buffer.
///
/// No additional check is performed on the size of the vertex
/// array. Passing invalid arguments will lead to undefined
/// behavior.
///
/// This function does nothing if `vertices` is null or if the
/// buffer was not previously created.
///
/// \param vertices Array of vertices to copy to the buffer
///
/// \return `true` if the update was successful
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool update(const Vertex* vertices);
////////////////////////////////////////////////////////////
/// \brief Update a part of the buffer from an array of vertices
///
/// `offset` is specified as the number of vertices to skip
/// from the beginning of the buffer.
///
/// If `offset` is 0 and `vertexCount` is equal to the size of
/// the currently created buffer, its whole contents are replaced.
///
/// If `offset` is 0 and `vertexCount` is greater than the
/// size of the currently created buffer, a new buffer is created
/// containing the vertex data.
///
/// If `offset` is 0 and `vertexCount` is less than the size of
/// the currently created buffer, only the corresponding region
/// is updated.
///
/// If `offset` is not 0 and `offset` + `vertexCount` is greater
/// than the size of the currently created buffer, the update fails.
///
/// No additional check is performed on the size of the vertex
/// array. Passing invalid arguments will lead to undefined
/// behavior.
///
/// \param vertices Array of vertices to copy to the buffer
/// \param vertexCount Number of vertices to copy
/// \param offset Offset in the buffer to copy to
///
/// \return `true` if the update was successful
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool update(const Vertex* vertices, std::size_t vertexCount, unsigned int offset);
////////////////////////////////////////////////////////////
/// \brief Copy the contents of another buffer into this buffer
///
/// \param vertexBuffer Vertex buffer whose contents to copy into this vertex buffer
///
/// \return `true` if the copy was successful
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool update(const VertexBuffer& vertexBuffer);
////////////////////////////////////////////////////////////
/// \brief Overload of assignment operator
///
/// \param right Instance to assign
///
/// \return Reference to self
///
////////////////////////////////////////////////////////////
VertexBuffer& operator=(const VertexBuffer& right);
////////////////////////////////////////////////////////////
/// \brief Swap the contents of this vertex buffer with those of another
///
/// \param right Instance to swap with
///
////////////////////////////////////////////////////////////
void swap(VertexBuffer& right) noexcept;
////////////////////////////////////////////////////////////
/// \brief Get the underlying OpenGL handle of the vertex buffer.
///
/// You shouldn't need to use this function, unless you have
/// very specific stuff to implement that SFML doesn't support,
/// or implement a temporary workaround until a bug is fixed.
///
/// \return OpenGL handle of the vertex buffer or 0 if not yet created
///
////////////////////////////////////////////////////////////
[[nodiscard]] unsigned int getNativeHandle() const;
////////////////////////////////////////////////////////////
/// \brief Set the type of primitives to draw
///
/// This function defines how the vertices must be interpreted
/// when it's time to draw them.
///
/// The default primitive type is `sf::PrimitiveType::Points`.
///
/// \param type Type of primitive
///
////////////////////////////////////////////////////////////
void setPrimitiveType(PrimitiveType type);
////////////////////////////////////////////////////////////
/// \brief Get the type of primitives drawn by the vertex buffer
///
/// \return Primitive type
///
////////////////////////////////////////////////////////////
[[nodiscard]] PrimitiveType getPrimitiveType() const;
////////////////////////////////////////////////////////////
/// \brief Set the usage specifier of this vertex buffer
///
/// This function provides a hint about how this vertex buffer is
/// going to be used in terms of data update frequency.
///
/// After changing the usage specifier, the vertex buffer has
/// to be updated with new data for the usage specifier to
/// take effect.
///
/// The default usage type is `sf::VertexBuffer::Usage::Stream`.
///
/// \param usage Usage specifier
///
////////////////////////////////////////////////////////////
void setUsage(Usage usage);
////////////////////////////////////////////////////////////
/// \brief Get the usage specifier of this vertex buffer
///
/// \return Usage specifier
///
////////////////////////////////////////////////////////////
[[nodiscard]] Usage getUsage() const;
////////////////////////////////////////////////////////////
/// \brief Bind a vertex buffer for rendering
///
/// This function is not part of the graphics API, it mustn't be
/// used when drawing SFML entities. It must be used only if you
/// mix `sf::VertexBuffer` with OpenGL code.
///
/// \code
/// sf::VertexBuffer vb1, vb2;
/// ...
/// sf::VertexBuffer::bind(&vb1);
/// // draw OpenGL stuff that use vb1...
/// sf::VertexBuffer::bind(&vb2);
/// // draw OpenGL stuff that use vb2...
/// sf::VertexBuffer::bind(nullptr);
/// // draw OpenGL stuff that use no vertex buffer...
/// \endcode
///
/// \param vertexBuffer Pointer to the vertex buffer to bind, can be null to use no vertex buffer
///
////////////////////////////////////////////////////////////
static void bind(const VertexBuffer* vertexBuffer);
////////////////////////////////////////////////////////////
/// \brief Tell whether or not the system supports vertex buffers
///
/// This function should always be called before using
/// the vertex buffer features. If it returns `false`, then
/// any attempt to use `sf::VertexBuffer` will fail.
///
/// \return `true` if vertex buffers are supported, `false` otherwise
///
////////////////////////////////////////////////////////////
[[nodiscard]] static bool isAvailable();
private:
////////////////////////////////////////////////////////////
/// \brief Draw the vertex buffer to a render target
///
/// \param target Render target to draw to
/// \param states Current render states
///
////////////////////////////////////////////////////////////
void draw(RenderTarget& target, RenderStates states) const override;
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
unsigned int m_buffer{}; //!< Internal buffer identifier
std::size_t m_size{}; //!< Size in Vertices of the currently allocated buffer
PrimitiveType m_primitiveType{PrimitiveType::Points}; //!< Type of primitives to draw
Usage m_usage{Usage::Stream}; //!< How this vertex buffer is to be used
};
////////////////////////////////////////////////////////////
/// \brief Swap the contents of one vertex buffer with those of another
///
/// \param left First instance to swap
/// \param right Second instance to swap
///
////////////////////////////////////////////////////////////
SFML_GRAPHICS_API void swap(VertexBuffer& left, VertexBuffer& right) noexcept;
} // namespace sf
////////////////////////////////////////////////////////////
/// \class sf::VertexBuffer
/// \ingroup graphics
///
/// `sf::VertexBuffer` is a simple wrapper around a dynamic
/// buffer of vertices and a primitives type.
///
/// Unlike `sf::VertexArray`, the vertex data is stored in
/// graphics memory.
///
/// In situations where a large amount of vertex data would
/// have to be transferred from system memory to graphics memory
/// every frame, using `sf::VertexBuffer` can help. By using a
/// `sf::VertexBuffer`, data that has not been changed between frames
/// does not have to be re-transferred from system to graphics
/// memory as would be the case with `sf::VertexArray`. If data transfer
/// is a bottleneck, this can lead to performance gains.
///
/// Using `sf::VertexBuffer`, the user also has the ability to only modify
/// a portion of the buffer in graphics memory. This way, a large buffer
/// can be allocated at the start of the application and only the
/// applicable portions of it need to be updated during the course of
/// the application. This allows the user to take full control of data
/// transfers between system and graphics memory if they need to.
///
/// In special cases, the user can make use of multiple threads to update
/// vertex data in multiple distinct regions of the buffer simultaneously.
/// This might make sense when e.g. the position of multiple objects has to
/// be recalculated very frequently. The computation load can be spread
/// across multiple threads as long as there are no other data dependencies.
///
/// Simultaneous updates to the vertex buffer are not guaranteed to be
/// carried out by the driver in any specific order. Updating the same
/// region of the buffer from multiple threads will not cause undefined
/// behavior, however the final state of the buffer will be unpredictable.
///
/// Simultaneous updates of distinct non-overlapping regions of the buffer
/// are also not guaranteed to complete in a specific order. However, in
/// this case the user can make sure to synchronize the writer threads at
/// well-defined points in their code. The driver will make sure that all
/// pending data transfers complete before the vertex buffer is sourced
/// by the rendering pipeline.
///
/// It inherits `sf::Drawable`, but unlike other drawables it
/// is not transformable.
///
/// Example:
/// \code
/// std::array<sf::Vertex, 15> vertices;
/// ...
/// sf::VertexBuffer triangles(sf::PrimitiveType::Triangles);
/// triangles.create(vertices.size());
/// triangles.update(vertices.data());
/// ...
/// window.draw(triangles);
/// \endcode
///
/// \see `sf::Vertex`, `sf::VertexArray`
///
////////////////////////////////////////////////////////////
|