Files
vibe3_physics/source/gpu/gpu_sprite_batch.hpp
Sergio Valor 74d954df1e fix: corregir límite de sprites en SHAPE mode con muchas bolas
GpuSpriteBatch::init() ahora acepta capacidad dinámica para soportar
--custom-balls N con N > 200000. El buffer se dimensiona a (N+1) quads,
reservando siempre un slot para el overlay. addFullscreenOverlay() calcula
overlay_index_count_ desde el delta real de indices_ en lugar de fijarlo
a 6 incondicionalmente. Engine calcula la capacidad correcta al init.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 00:14:28 +01:00

89 lines
3.5 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#pragma once
#include <SDL3/SDL_gpu.h>
#include <vector>
#include <cstdint>
// ---------------------------------------------------------------------------
// GpuVertex — 8-float vertex layout sent to the GPU.
// Position is in NDC (pre-transformed on CPU), UV in [0,1], color in [0,1].
// ---------------------------------------------------------------------------
struct GpuVertex {
float x, y; // NDC position (1..1)
float u, v; // Texture coords (0..1)
float r, g, b, a; // RGBA color (0..1)
};
// ============================================================================
// GpuSpriteBatch — Accumulates sprite quads, uploads them in one copy pass.
//
// Usage per frame:
// batch.beginFrame();
// batch.addBackground(...); // Must be first (bg indices = [0..5])
// batch.addSprite(...) × N;
// batch.uploadBatch(device, cmd); // Copy pass
// // Then in render pass: bind buffers, draw bg with white tex, draw sprites.
// ============================================================================
class GpuSpriteBatch {
public:
// Default maximum sprites (background + UI overlay each count as one sprite)
static constexpr int DEFAULT_MAX_SPRITES = 200000;
bool init(SDL_GPUDevice* device, int max_sprites = DEFAULT_MAX_SPRITES);
void destroy(SDL_GPUDevice* device);
void beginFrame();
// Add the full-screen background gradient quad.
// top_* and bot_* are RGB in [0,1].
void addBackground(float screen_w, float screen_h,
float top_r, float top_g, float top_b,
float bot_r, float bot_g, float bot_b);
// Add a sprite quad (pixel coordinates).
// scale: uniform scale around the quad centre.
void addSprite(float x, float y, float w, float h,
float r, float g, float b, float a,
float scale,
float screen_w, float screen_h);
// Add a full-screen overlay quad (e.g. UI surface, NDC 1..1).
void addFullscreenOverlay();
// Upload CPU vectors to GPU buffers via a copy pass.
// Returns false if the batch is empty.
bool uploadBatch(SDL_GPUDevice* device, SDL_GPUCommandBuffer* cmd_buf);
SDL_GPUBuffer* vertexBuffer() const { return vertex_buf_; }
SDL_GPUBuffer* indexBuffer() const { return index_buf_; }
int bgIndexCount() const { return bg_index_count_; }
int overlayIndexOffset() const { return overlay_index_offset_; }
int overlayIndexCount() const { return overlay_index_count_; }
int spriteIndexOffset() const { return sprite_index_offset_; }
int spriteIndexCount() const { return sprite_index_count_; }
bool isEmpty() const { return vertices_.empty(); }
private:
void toNDC(float px, float py, float screen_w, float screen_h,
float& ndx, float& ndy) const;
void pushQuad(float ndx0, float ndy0, float ndx1, float ndy1,
float u0, float v0, float u1, float v1,
float r, float g, float b, float a);
std::vector<GpuVertex> vertices_;
std::vector<uint32_t> indices_;
SDL_GPUBuffer* vertex_buf_ = nullptr;
SDL_GPUBuffer* index_buf_ = nullptr;
SDL_GPUTransferBuffer* vertex_transfer_ = nullptr;
SDL_GPUTransferBuffer* index_transfer_ = nullptr;
int bg_index_count_ = 0;
int sprite_index_offset_ = 0;
int sprite_index_count_ = 0;
int overlay_index_offset_ = 0;
int overlay_index_count_ = 0;
int max_sprites_ = DEFAULT_MAX_SPRITES;
};