#pragma once #include "RcPtr.hpp" #include "SmallVector.hpp" #include #include #include #include namespace Tags { /// Vertex element semantics, used to identify the meaning of vertex buffer contents enum VertexElementSemantic { /// Position, typically VET_Float3 VES_Position = 1, /// Blending weights VES_BlendWeights = 2, /// Blending indices VES_BlendIndices = 3, /// Normal, typically VET_Float3 VES_Normal = 4, /// Colour, typically VET_Ubyte4 VES_Colour = 5, /// Secondary colour. Generally free for custom data. Means specular with OpenGL FFP. VES_Colour2 = 6, /// Texture coordinates, typically VET_Float2 VES_Texture_coordinates = 7, /// Binormal (Y axis if normal is Z) VES_Binormal = 8, /// Tangent (X axis if normal is Z) VES_Tangent = 9, /// The number of VertexElementSemantic elements (note - the first value VES_Position is 1) VES_COUNT = 9, }; enum VertexElementType { VET_Float1, VET_Float2, VET_Float3, VET_Float4, VET_Short2, VET_Short4, VET_Ubyte4, // the following are not universally supported on all hardware: VET_Double1, VET_Double2, VET_Double3, VET_Double4, VET_Ushort2, VET_Ushort4, VET_Int1, VET_Int2, VET_Int3, VET_Int4, VET_Uint1, VET_Uint2, VET_Uint3, VET_Uint4, VET_Byte4, /// signed bytes VET_NORM_BEGIN, VET_Byte4Norm = VET_NORM_BEGIN, /// signed bytes (normalized to -1..1) VET_Ubyte4Norm, /// unsigned bytes (normalized to 0..1) VET_Short2Norm, /// signed shorts (normalized to -1..1) VET_Short4Norm, VET_Ushort2Norm, /// unsigned shorts (normalized to 0..1) VET_Ushort4Norm, VET_NORM_END = VET_Ushort4Norm, }; int SizeOf(VertexElementType type); bool IsNormalized(VertexElementType type); enum IndexType { IT_16Bit, IT_32Bit, }; int SizeOf(IndexType type); } // namespace Tags struct GpuVertexBuffer : public RefCounted { GLuint handle; int sizeInBytes; GpuVertexBuffer(); ~GpuVertexBuffer(); void Upload(const std::byte* data, size_t sizeInBytes); }; struct GpuIndexBuffer : public RefCounted { GLuint handle; Tags::IndexType indexType; int sizeInBytes; GpuIndexBuffer(); ~GpuIndexBuffer(); void Upload(const std::byte* data, size_t count); void Upload(const std::byte* data, Tags::IndexType type, size_t count); }; struct BufferBindings : public RefCounted { SmallVector, 4> bindings; int GetMaxBindingIndex() const; /// Safe. Returns nullptr if the index is not bound to any buffers. GpuVertexBuffer* GetBinding(int index) const; /// Adds or updates a buffer binding. Setting a binding to nullptr effectively removes the binding. void SetBinding(int index, GpuVertexBuffer* buffer); void Clear(); }; struct VertexElementFormat { int offset; int bindingIndex; Tags::VertexElementType type; Tags::VertexElementSemantic semantic; int GetStride() const; auto operator<=>(const VertexElementFormat&) const = default; }; struct VertexFormat : public RefCounted { std::vector elements; int vertexSize = 0; const std::vector& GetElements() { return elements; } void AddElement(VertexElementFormat element); void RemoveElement(int index); void Sort(); void CompactBindingIndex(); }; class GpuMesh : public RefCounted { public: RcPtr vertFormat; RcPtr vertBufBindings; RcPtr indexBuf; public: GpuMesh(VertexFormat* vertexFormat, BufferBindings* bindings, GpuIndexBuffer* indexBuffer); bool IsEmpty() const; void SetVertex(VertexFormat* vertexFormat, BufferBindings* bindings); VertexFormat* GetVertexFormat() const; BufferBindings* GetVertexBufferBindings() const; void SetIndex(GpuIndexBuffer* buffer); GpuIndexBuffer* GetIndexBuffer() const; };