use pipelines to replace vertexArray

This commit is contained in:
2025-12-15 11:01:30 +08:00
parent 0f7eb7cc95
commit 57ca6c30f5
25 changed files with 755 additions and 489 deletions

View File

@ -1,6 +1,6 @@
Scene: Scene Name Scene: Scene Name
Environment: Environment:
AssetPath: assets\env\birchwood_4k.hdr AssetPath: assets/env/birchwood_4k.hdr
Light: Light:
Direction: [-0.5, -0.5, 1] Direction: [-0.5, -0.5, 1]
Radiance: [1, 1, 1] Radiance: [1, 1, 1]
@ -20,7 +20,7 @@ Entities:
Type: 1 Type: 1
Data: 5 Data: 5
MeshComponent: MeshComponent:
AssetPath: assets\meshes\Sphere1m.fbx AssetPath: assets/meshes/Sphere1m.fbx
- Entity: 5178862374589434728 - Entity: 5178862374589434728
TagComponent: TagComponent:
Tag: Camera Tag: Camera
@ -63,4 +63,4 @@ Entities:
Type: 6 Type: 6
Data: [0, 0, 0] Data: [0, 0, 0]
MeshComponent: MeshComponent:
AssetPath: assets\meshes\TestScene.fbx AssetPath: assets/meshes/TestScene.fbx

View File

@ -21,13 +21,14 @@
// ImGui // ImGui
#include "imgui.h" #include "imgui.h"
#include "Prism/Renderer/Buffer.h"
#include "Prism/Renderer/Renderer.h" #include "Prism/Renderer/Renderer.h"
#include "Prism/Renderer/SceneRenderer.h" #include "Prism/Renderer/SceneRenderer.h"
#include "Prism/Renderer/RenderPass.h" #include "Prism/Renderer/RenderPass.h"
#include "Prism/Renderer/Shader.h" #include "Prism/Renderer/Shader.h"
#include "Prism/Renderer/Texture.h" #include "Prism/Renderer/Texture.h"
#include "Prism/Renderer/FrameBuffer.h" #include "Prism/Renderer/FrameBuffer.h"
#include "Prism//Renderer/VertexBuffer.h"
#include "Prism//Renderer/IndexBuffer.h"
#include "Prism/Renderer/Shader.h" #include "Prism/Renderer/Shader.h"
#include "Prism/Renderer/Mesh.h" #include "Prism/Renderer/Mesh.h"
#include "Prism/Renderer/Camera.h" #include "Prism/Renderer/Camera.h"

View File

@ -1,127 +0,0 @@
//
// Created by sfd on 25-11-22.
//
#include "OpenGLBuffer.h"
#include "Prism/Renderer/Renderer.h"
namespace Prism
{
static GLenum OpenGLUsage(VertexBufferUsage usage)
{
switch (usage)
{
case VertexBufferUsage::Static: return GL_STATIC_DRAW;
case VertexBufferUsage::Dynamic: return GL_DYNAMIC_DRAW;
}
PM_CORE_ASSERT(false, "Unknown vertex buffer usage");
return 0;
}
// ******************************************
// Vertex
// ******************************************
OpenGLVertexBuffer::OpenGLVertexBuffer(void* data, const uint32_t size, const VertexBufferUsage usage)
: m_Size(size), m_Usage(usage)
{
m_LocalData = Buffer::Copy(data, size);
Ref<OpenGLVertexBuffer> instance = this;
Renderer::Submit([instance]() mutable {
glCreateBuffers(1, &instance->m_RendererID);
glNamedBufferData(instance->m_RendererID, instance->m_Size, instance->m_LocalData.Data, OpenGLUsage(instance->m_Usage));
});
}
OpenGLVertexBuffer::OpenGLVertexBuffer(const uint32_t size, const VertexBufferUsage usage)
: m_Size(size), m_Usage(usage)
{
Ref<OpenGLVertexBuffer> instance = this;
Renderer::Submit([instance]() mutable {
glCreateBuffers(1, &instance->m_RendererID);
glNamedBufferData(instance->m_RendererID, instance->m_Size, nullptr, OpenGLUsage(instance->m_Usage));
});
}
OpenGLVertexBuffer::~OpenGLVertexBuffer()
{
GLuint rendererID = m_RendererID;
Renderer::Submit([rendererID](){
glDeleteBuffers(1, &rendererID);
});
}
void OpenGLVertexBuffer::SetData(void* buffer, uint32_t size, uint32_t offset)
{
m_LocalData = Buffer::Copy(buffer, size);
m_Size = size;
Ref<OpenGLVertexBuffer> instance = this;
Renderer::Submit([instance, offset]() {
glNamedBufferSubData(instance->m_RendererID, offset, instance->m_Size, instance->m_LocalData.Data);
});
}
void OpenGLVertexBuffer::Bind() const
{
Ref<const OpenGLVertexBuffer> instance = this;
Renderer::Submit([instance]() {
glBindBuffer(GL_ARRAY_BUFFER, instance->m_RendererID);
});
}
OpenGLIndexBuffer::OpenGLIndexBuffer(const uint32_t size)
: m_Size(size)
{
Renderer::Submit([this]()
{
glCreateBuffers(1, &m_RendererID);
glNamedBufferData(m_RendererID, m_Size, nullptr, GL_DYNAMIC_DRAW);
});
}
// ******************************************
// IndexBuffer
// ******************************************
OpenGLIndexBuffer::OpenGLIndexBuffer(void* data, const uint32_t size)
: m_Size(size)
{
m_LocalData = Buffer::Copy(data, size);
Ref<OpenGLIndexBuffer> instance = this;
Renderer::Submit([instance]() mutable {
glCreateBuffers(1, &instance->m_RendererID);
glNamedBufferData(instance->m_RendererID, instance->m_Size, instance->m_LocalData.Data, GL_STATIC_DRAW);
});
}
OpenGLIndexBuffer::~OpenGLIndexBuffer()
{
const GLuint rendererID = m_RendererID;
Renderer::Submit([rendererID](){
glDeleteBuffers(1, &rendererID);
});
}
void OpenGLIndexBuffer::SetData(void* data, uint32_t size, uint32_t offset)
{
m_LocalData = Buffer::Copy(data, size);
m_Size = size;
Renderer::Submit([this, offset](){
glNamedBufferSubData(m_RendererID, offset, m_Size, m_LocalData.Data);
});
}
void OpenGLIndexBuffer::Bind() const
{
Ref<const OpenGLIndexBuffer> instance = this;
Renderer::Submit([instance]() {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, instance->m_RendererID);
});
}
}

View File

@ -1,69 +0,0 @@
//
// Created by sfd on 25-11-22.
//
#ifndef OPENGLBUFFER_H
#define OPENGLBUFFER_H
#include "glad/glad.h"
#include "Prism/Core/Buffer.h"
#include "Prism/Renderer/Buffer.h"
namespace Prism
{
// ******************************************
// Vertex
// ******************************************
class OpenGLVertexBuffer : public VertexBuffer
{
public:
OpenGLVertexBuffer(void* data, uint32_t size, VertexBufferUsage usage = VertexBufferUsage::Static);
OpenGLVertexBuffer(uint32_t size, VertexBufferUsage usage = VertexBufferUsage::Dynamic);
virtual ~OpenGLVertexBuffer();
void SetData(void* buffer, uint32_t size, uint32_t offset = 0) override;
void Bind() const override;
virtual const BufferLayout& GetLayout() const override { return m_Layout; }
virtual void SetLayout(const BufferLayout& layout) override { m_Layout = layout; }
uint32_t GetSize() const override { return m_Size; }
RendererID GetRendererID() const override { return m_RendererID; }
private:
RendererID m_RendererID = 0;
uint32_t m_Size;
VertexBufferUsage m_Usage;
BufferLayout m_Layout;
Buffer m_LocalData;
};
// ******************************************
// IndexBuffer
// ******************************************
class OpenGLIndexBuffer : public IndexBuffer
{
public:
OpenGLIndexBuffer(uint32_t size);
OpenGLIndexBuffer(void* data, uint32_t size);
virtual ~OpenGLIndexBuffer();
virtual void SetData(void* data, uint32_t size, uint32_t offset = 0);
virtual void Bind() const;
virtual uint32_t GetCount() const { return m_Size / sizeof(uint32_t); }
virtual uint32_t GetSize() const { return m_Size; }
virtual RendererID GetRendererID() const { return m_RendererID; }
private:
RendererID m_RendererID = 0;
uint32_t m_Size;
Buffer m_LocalData;
};
}
#endif //OPENGLBUFFER_H

View File

@ -0,0 +1,62 @@
//
// Created by sfd on 2025/12/15.
//
#include "OpenGLIndexBuffer.h"
#include "glad/glad.h"
#include "Prism/Renderer/Renderer.h"
namespace Prism {
OpenGLIndexBuffer::OpenGLIndexBuffer(void* data, uint32_t size)
: m_RendererID(0), m_Size(size)
{
m_LocalData = Buffer::Copy(data, size);
Ref<OpenGLIndexBuffer> instance = this;
Renderer::Submit([instance]() mutable {
glCreateBuffers(1, &instance->m_RendererID);
glNamedBufferData(instance->m_RendererID, instance->m_Size, instance->m_LocalData.Data, GL_STATIC_DRAW);
});
}
OpenGLIndexBuffer::OpenGLIndexBuffer(uint32_t size)
: m_Size(size)
{
// m_LocalData = Buffer(size);
Ref<OpenGLIndexBuffer> instance = this;
Renderer::Submit([instance]() mutable {
glCreateBuffers(1, &instance->m_RendererID);
glNamedBufferData(instance->m_RendererID, instance->m_Size, nullptr, GL_DYNAMIC_DRAW);
});
}
OpenGLIndexBuffer::~OpenGLIndexBuffer()
{
GLuint rendererID = m_RendererID;
Renderer::Submit([rendererID]() {
glDeleteBuffers(1, &rendererID);
});
}
void OpenGLIndexBuffer::SetData(void* data, uint32_t size, uint32_t offset)
{
m_LocalData = Buffer::Copy(data, size);
m_Size = size;
Ref<OpenGLIndexBuffer> instance = this;
Renderer::Submit([instance, offset]() {
glNamedBufferSubData(instance->m_RendererID, offset, instance->m_Size, instance->m_LocalData.Data);
});
}
void OpenGLIndexBuffer::Bind() const
{
Ref<const OpenGLIndexBuffer> instance = this;
Renderer::Submit([instance]() {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, instance->m_RendererID);
});
}
}

View File

@ -0,0 +1,35 @@
//
// Created by sfd on 2025/12/15.
//
#ifndef PRISM_OPENGLINDEXBUFFER_H
#define PRISM_OPENGLINDEXBUFFER_H
#include "Prism/Core/Buffer.h"
#include "Prism/Renderer/IndexBuffer.h"
namespace Prism {
class OpenGLIndexBuffer : public IndexBuffer
{
public:
OpenGLIndexBuffer(uint32_t size);
OpenGLIndexBuffer(void* data, uint32_t size);
virtual ~OpenGLIndexBuffer();
void SetData(void* data, uint32_t size, uint32_t offset = 0) override;
void Bind() const override;
uint32_t GetCount() const override { return m_Size / sizeof(uint32_t); }
uint32_t GetSize() const override { return m_Size; }
RendererID GetRendererID() const override { return m_RendererID; }
private:
RendererID m_RendererID = 0;
uint32_t m_Size;
Buffer m_LocalData;
};
}
#endif //PRISM_OPENGLINDEXBUFFER_H

View File

@ -0,0 +1,129 @@
//
// Created by sfd on 2025/12/15.
//
#include "OpenGLPipeline.h"
#include "glad/glad.h"
#include "Prism/Renderer/Pipeline.h"
#include "Prism/Renderer/Renderer.h"
#include "Prism/Renderer/VertexBuffer.h"
namespace Prism {
static GLenum ShaderDataTypeToOpenGLBaseType(ShaderDataType type)
{
switch (type)
{
case ShaderDataType::Float: return GL_FLOAT;
case ShaderDataType::Float2: return GL_FLOAT;
case ShaderDataType::Float3: return GL_FLOAT;
case ShaderDataType::Float4: return GL_FLOAT;
case ShaderDataType::Mat3: return GL_FLOAT;
case ShaderDataType::Mat4: return GL_FLOAT;
case ShaderDataType::Int: return GL_INT;
case ShaderDataType::Int2: return GL_INT;
case ShaderDataType::Int3: return GL_INT;
case ShaderDataType::Int4: return GL_INT;
case ShaderDataType::Bool: return GL_BOOL;
}
PM_CORE_ASSERT(false, "Unknown ShaderDataType!");
return 0;
}
OpenGLPipeline::OpenGLPipeline(const PipelineSpecification& spec)
: m_Specification(spec)
{
OpenGLPipeline::Invalidate();
}
OpenGLPipeline::~OpenGLPipeline()
{
GLuint rendererID = m_VertexArrayRendererID;
Renderer::Submit([rendererID]()
{
glDeleteVertexArrays(1, &rendererID);
});
}
void OpenGLPipeline::Invalidate()
{
PM_CORE_ASSERT(m_Specification.Layout.GetElements().size(), "Layout is empty!");
Ref<OpenGLPipeline> instance = this;
Renderer::Submit([instance]() mutable
{
auto& vertexArrayRendererID = instance->m_VertexArrayRendererID;
if (vertexArrayRendererID)
glDeleteVertexArrays(1, &vertexArrayRendererID);
glGenVertexArrays(1, &vertexArrayRendererID);
glBindVertexArray(vertexArrayRendererID);
#if 0
const auto& layout = instance->m_Specification.Layout;
uint32_t attribIndex = 0;
for (const auto& element : layout)
{
auto glBaseType = ShaderDataTypeToOpenGLBaseType(element.Type);
glEnableVertexAttribArray(attribIndex);
if (glBaseType == GL_INT)
{
glVertexAttribIPointer(attribIndex,
element.GetComponentCount(),
glBaseType,
layout.GetStride(),
(const void*)(intptr_t)element.Offset);
}
else
{
glVertexAttribPointer(attribIndex,
element.GetComponentCount(),
glBaseType,
element.Normalized ? GL_TRUE : GL_FALSE,
layout.GetStride(),
(const void*)(intptr_t)element.Offset);
}
attribIndex++;
}
#endif
glBindVertexArray(0);
});
}
void OpenGLPipeline::Bind()
{
Ref<OpenGLPipeline> instance = this;
Renderer::Submit([instance]()
{
glBindVertexArray(instance->m_VertexArrayRendererID);
const auto& layout = instance->m_Specification.Layout;
uint32_t attribIndex = 0;
for (const auto& element : layout)
{
auto glBaseType = ShaderDataTypeToOpenGLBaseType(element.Type);
glEnableVertexAttribArray(attribIndex);
if (glBaseType == GL_INT)
{
glVertexAttribIPointer(attribIndex,
element.GetComponentCount(),
glBaseType,
layout.GetStride(),
(const void*)(intptr_t)element.Offset);
}
else
{
glVertexAttribPointer(attribIndex,
element.GetComponentCount(),
glBaseType,
element.Normalized ? GL_TRUE : GL_FALSE,
layout.GetStride(),
(const void*)(intptr_t)element.Offset);
}
attribIndex++;
}
});
}
}

View File

@ -0,0 +1,31 @@
//
// Created by sfd on 2025/12/15.
//
#ifndef PRISM_OPENGLPIPELINE_H
#define PRISM_OPENGLPIPELINE_H
#include "Prism/Renderer/Pipeline.h"
namespace Prism {
class OpenGLPipeline : public Pipeline
{
public:
OpenGLPipeline(const PipelineSpecification& spec);
virtual ~OpenGLPipeline();
virtual PipelineSpecification& GetSpecification() { return m_Specification; }
virtual const PipelineSpecification& GetSpecification() const { return m_Specification; }
virtual void Invalidate() override;
virtual void Bind() override;
private:
PipelineSpecification m_Specification;
uint32_t m_VertexArrayRendererID = 0;
};
}
#endif //PRISM_OPENGLPIPELINE_H

View File

@ -4,7 +4,6 @@
#include "OpenGLVertexArray.h" #include "OpenGLVertexArray.h"
#include "OpenGLBuffer.h"
#include "glad/glad.h" #include "glad/glad.h"
#include "Prism/Renderer/Renderer.h" #include "Prism/Renderer/Renderer.h"

View File

@ -0,0 +1,71 @@
//
// Created by sfd on 2025/12/15.
//
#include "OpenGLVertexBuffer.h"
#include "glad/glad.h"
#include "Prism/Renderer/Renderer.h"
namespace Prism {
static GLenum OpenGLUsage(VertexBufferUsage usage)
{
switch (usage)
{
case VertexBufferUsage::Static: return GL_STATIC_DRAW;
case VertexBufferUsage::Dynamic: return GL_DYNAMIC_DRAW;
}
PM_CORE_ASSERT(false, "Unknown vertex buffer usage");
return 0;
}
OpenGLVertexBuffer::OpenGLVertexBuffer(void* data, const uint32_t size, const VertexBufferUsage usage)
: m_Size(size), m_Usage(usage)
{
m_LocalData = Buffer::Copy(data, size);
Ref<OpenGLVertexBuffer> instance = this;
Renderer::Submit([instance]() mutable {
glCreateBuffers(1, &instance->m_RendererID);
glNamedBufferData(instance->m_RendererID, instance->m_Size, instance->m_LocalData.Data, OpenGLUsage(instance->m_Usage));
});
}
OpenGLVertexBuffer::OpenGLVertexBuffer(const uint32_t size, const VertexBufferUsage usage)
: m_Size(size), m_Usage(usage)
{
Ref<OpenGLVertexBuffer> instance = this;
Renderer::Submit([instance]() mutable {
glCreateBuffers(1, &instance->m_RendererID);
glNamedBufferData(instance->m_RendererID, instance->m_Size, nullptr, OpenGLUsage(instance->m_Usage));
});
}
OpenGLVertexBuffer::~OpenGLVertexBuffer()
{
GLuint rendererID = m_RendererID;
Renderer::Submit([rendererID](){
glDeleteBuffers(1, &rendererID);
});
}
void OpenGLVertexBuffer::SetData(void* buffer, uint32_t size, uint32_t offset)
{
m_LocalData = Buffer::Copy(buffer, size);
m_Size = size;
Ref<OpenGLVertexBuffer> instance = this;
Renderer::Submit([instance, offset]() {
glNamedBufferSubData(instance->m_RendererID, offset, instance->m_Size, instance->m_LocalData.Data);
});
}
void OpenGLVertexBuffer::Bind() const
{
Ref<const OpenGLVertexBuffer> instance = this;
Renderer::Submit([instance]() {
glBindBuffer(GL_ARRAY_BUFFER, instance->m_RendererID);
});
}
}

View File

@ -0,0 +1,41 @@
//
// Created by sfd on 2025/12/15.
//
#ifndef PRISM_OPENGLVERTEXBUFFER_H
#define PRISM_OPENGLVERTEXBUFFER_H
#include "Prism/Core/Buffer.h"
#include "Prism/Renderer/VertexBuffer.h"
namespace Prism {
class OpenGLVertexBuffer : public VertexBuffer
{
public:
OpenGLVertexBuffer(void* data, uint32_t size, VertexBufferUsage usage = VertexBufferUsage::Static);
OpenGLVertexBuffer(uint32_t size, VertexBufferUsage usage = VertexBufferUsage::Dynamic);
~OpenGLVertexBuffer() override;
void SetData(void* data, uint32_t size, uint32_t offset = 0) override;
void Bind() const override;
virtual const VertexBufferLayout& GetLayout() const override { return m_Layout; }
virtual void SetLayout(const VertexBufferLayout& layout) override { m_Layout = layout; }
uint32_t GetSize() const override { return m_Size; }
RendererID GetRendererID() const override { return m_RendererID; }
private:
RendererID m_RendererID = 0;
uint32_t m_Size;
VertexBufferUsage m_Usage;
VertexBufferLayout m_Layout;
Buffer m_LocalData;
};
}
#endif //PRISM_OPENGLVERTEXBUFFER_H

View File

@ -1,56 +0,0 @@
//
// Created by sfd on 25-11-22.
//
#include "Buffer.h"
#include "Prism/Platform/OpenGL/OpenGLBuffer.h"
namespace Prism
{
Ref<VertexBuffer> VertexBuffer::Create(void* data, uint32_t size, VertexBufferUsage usage)
{
switch (RendererAPI::Current())
{
case RendererAPIType::None: return nullptr;
case RendererAPIType::OpenGL: return Ref<OpenGLVertexBuffer>::Create(data, size, usage);
}
PM_CORE_ASSERT(false, "Unknown RendererAPI");
return nullptr;
}
Ref<VertexBuffer> VertexBuffer::Create(uint32_t size, VertexBufferUsage usage)
{
switch (RendererAPI::Current())
{
case RendererAPIType::None: return nullptr;
case RendererAPIType::OpenGL: return Ref<OpenGLVertexBuffer>::Create(size, usage);
}
PM_CORE_ASSERT(false, "Unknown RendererAPI");
return nullptr;
}
Ref<IndexBuffer> IndexBuffer::Create(uint32_t size)
{
switch (RendererAPI::Current())
{
case RendererAPIType::None: return nullptr;
case RendererAPIType::OpenGL: return Ref<OpenGLIndexBuffer>::Create(size);
}
PM_CORE_ASSERT(false, "Unknown RendererAPI");
return nullptr;
}
Ref<IndexBuffer> IndexBuffer::Create(void* data, uint32_t size)
{
switch (RendererAPI::Current())
{
case RendererAPIType::None: return nullptr;
case RendererAPIType::OpenGL: return Ref<OpenGLIndexBuffer>::Create(data, size);
}
PM_CORE_ASSERT(false, "Unknown RendererAPI");
return nullptr;
}
}

View File

@ -1,160 +0,0 @@
//
// Created by sfd on 25-11-22.
//
#ifndef RENDERER_BUFFER_H
#define RENDERER_BUFFER_H
#include "RendererAPI.h"
#include "Prism/Core/Ref.h"
namespace Prism
{
enum class ShaderDataType
{
None = 0, Float, Float2, Float3, Float4, Mat3, Mat4, Int, Int2, Int3, Int4, Bool
};
static uint32_t ShaderDataTypeSize(ShaderDataType type)
{
switch (type)
{
case ShaderDataType::Float: return 4;
case ShaderDataType::Float2: return 4 * 2;
case ShaderDataType::Float3: return 4 * 3;
case ShaderDataType::Float4: return 4 * 4;
case ShaderDataType::Mat3: return 4 * 3 * 3;
case ShaderDataType::Mat4: return 4 * 4 * 4;
case ShaderDataType::Int: return 4;
case ShaderDataType::Int2: return 4 * 2;
case ShaderDataType::Int3: return 4 * 3;
case ShaderDataType::Int4: return 4 * 4;
case ShaderDataType::Bool: return 1;
}
PM_CORE_ASSERT(false, "Unknown ShaderDataType!");
return 0;
}
struct BufferElement
{
std::string Name;
ShaderDataType Type;
uint32_t Size;
uint32_t Offset;
bool Normalized;
BufferElement() = default;
BufferElement(ShaderDataType type, const std::string& name, bool normalized = false)
: Name(name), Type(type), Size(ShaderDataTypeSize(type)), Offset(0), Normalized(normalized)
{
}
uint32_t GetComponentCount() const
{
switch (Type)
{
case ShaderDataType::Float: return 1;
case ShaderDataType::Float2: return 2;
case ShaderDataType::Float3: return 3;
case ShaderDataType::Float4: return 4;
case ShaderDataType::Mat3: return 3 * 3;
case ShaderDataType::Mat4: return 4 * 4;
case ShaderDataType::Int: return 1;
case ShaderDataType::Int2: return 2;
case ShaderDataType::Int3: return 3;
case ShaderDataType::Int4: return 4;
case ShaderDataType::Bool: return 1;
}
PM_CORE_ASSERT(false, "Unknown ShaderDataType!");
return 0;
}
};
class BufferLayout
{
public:
BufferLayout() {}
BufferLayout(const std::initializer_list<BufferElement>& elements)
: m_Elements(elements)
{
CalculateOffsetsAndStride();
}
inline uint32_t GetStride() const { return m_Stride; }
inline const std::vector<BufferElement>& GetElements() const { return m_Elements; }
std::vector<BufferElement>::iterator begin() { return m_Elements.begin(); }
std::vector<BufferElement>::iterator end() { return m_Elements.end(); }
std::vector<BufferElement>::const_iterator begin() const { return m_Elements.begin(); }
std::vector<BufferElement>::const_iterator end() const { return m_Elements.end(); }
private:
void CalculateOffsetsAndStride()
{
uint32_t offset = 0;
m_Stride = 0;
for (auto& element : m_Elements)
{
element.Offset = offset;
offset += element.Size;
m_Stride += element.Size;
}
}
private:
std::vector<BufferElement> m_Elements;
uint32_t m_Stride = 0;
};
enum class VertexBufferUsage
{
None = 0, Static = 1, Dynamic = 2
};
class PRISM_API VertexBuffer : public RefCounted
{
public:
virtual ~VertexBuffer() {}
static Ref<VertexBuffer> Create(void* data, uint32_t size, VertexBufferUsage usage = VertexBufferUsage::Static);
static Ref<VertexBuffer> Create(uint32_t size, VertexBufferUsage usage = VertexBufferUsage::Dynamic);
virtual void SetData(void* buffer, uint32_t size, uint32_t offset = 0) = 0;
virtual void Bind() const = 0;
virtual const BufferLayout& GetLayout() const = 0;
virtual void SetLayout(const BufferLayout& layout) = 0;
virtual unsigned int GetSize() const = 0;
virtual RendererID GetRendererID() const = 0;
};
class PRISM_API IndexBuffer : public RefCounted
{
public:
virtual ~IndexBuffer() {}
static Ref<IndexBuffer> Create(uint32_t size);
static Ref<IndexBuffer> Create(void* data, uint32_t size = 0);
virtual void SetData(void* buffer, uint32_t size, uint32_t offset = 0) = 0;
virtual void Bind() const = 0;
virtual uint32_t GetCount() const = 0;
virtual unsigned int GetSize() const = 0;
virtual RendererID GetRendererID() const = 0;
};
}
#endif //RENDERER_BUFFER_H

View File

@ -0,0 +1,33 @@
//
// Created by sfd on 2025/12/15.
//
#include "IndexBuffer.h"
#include "Prism/Platform/OpenGL/OpenGLIndexBuffer.h"
namespace Prism {
Ref<IndexBuffer> IndexBuffer::Create(uint32_t size)
{
switch (RendererAPI::Current())
{
case RendererAPIType::None: return nullptr;
case RendererAPIType::OpenGL: return Ref<OpenGLIndexBuffer>::Create(size);
}
PM_CORE_ASSERT(false, "Unknown RendererAPI");
return nullptr;
}
Ref<IndexBuffer> IndexBuffer::Create(void* data, uint32_t size)
{
switch (RendererAPI::Current())
{
case RendererAPIType::None: return nullptr;
case RendererAPIType::OpenGL: return Ref<OpenGLIndexBuffer>::Create(data, size);
}
PM_CORE_ASSERT(false, "Unknown RendererAPI");
return nullptr;
}
}

View File

@ -0,0 +1,32 @@
//
// Created by sfd on 2025/12/15.
//
#ifndef PRISM_INDEXBUFFER_H
#define PRISM_INDEXBUFFER_H
#include "RendererAPI.h"
#include "Prism/Core/Ref.h"
namespace Prism {
class IndexBuffer : public RefCounted {
public:
virtual ~IndexBuffer() {
}
virtual void SetData(void *buffer, uint32_t size, uint32_t offset = 0) = 0;
virtual void Bind() const = 0;
virtual uint32_t GetCount() const = 0;
virtual uint32_t GetSize() const = 0;
virtual RendererID GetRendererID() const = 0;
static Ref<IndexBuffer> Create(uint32_t size);
static Ref<IndexBuffer> Create(void *data, uint32_t size = 0);
};
}
#endif //PRISM_INDEXBUFFER_H

View File

@ -475,11 +475,11 @@ namespace Prism
PM_MESH_LOG("------------------------"); PM_MESH_LOG("------------------------");
} }
m_VertexArray = VertexArray::Create(); VertexBufferLayout vertexBufferLayout;
if (m_IsAnimated) if (m_IsAnimated)
{ {
auto vb = VertexBuffer::Create(m_AnimatedVertices.data(), (uint32_t)m_AnimatedVertices.size() * sizeof(AnimatedVertex)); m_VertexBuffer = VertexBuffer::Create(m_AnimatedVertices.data(), (uint32_t)m_AnimatedVertices.size() * sizeof(AnimatedVertex));
vb->SetLayout({ vertexBufferLayout = {
{ ShaderDataType::Float3, "a_Position" }, { ShaderDataType::Float3, "a_Position" },
{ ShaderDataType::Float3, "a_Normal" }, { ShaderDataType::Float3, "a_Normal" },
{ ShaderDataType::Float3, "a_Tangent" }, { ShaderDataType::Float3, "a_Tangent" },
@ -487,24 +487,24 @@ namespace Prism
{ ShaderDataType::Float2, "a_TexCoord" }, { ShaderDataType::Float2, "a_TexCoord" },
{ ShaderDataType::Int4, "a_BoneIDs" }, { ShaderDataType::Int4, "a_BoneIDs" },
{ ShaderDataType::Float4, "a_BoneWeights" }, { ShaderDataType::Float4, "a_BoneWeights" },
}); };
m_VertexArray->AddVertexBuffer(vb);
}else }else
{ {
auto vb = VertexBuffer::Create(m_StaticVertices.data(), (uint32_t)m_StaticVertices.size() * sizeof(Vertex)); m_VertexBuffer = VertexBuffer::Create(m_StaticVertices.data(), (uint32_t)m_StaticVertices.size() * sizeof(Vertex));
vb->SetLayout({ vertexBufferLayout = {
{ ShaderDataType::Float3, "a_Position" }, { ShaderDataType::Float3, "a_Position" },
{ ShaderDataType::Float3, "a_Normal" }, { ShaderDataType::Float3, "a_Normal" },
{ ShaderDataType::Float3, "a_Tangent" }, { ShaderDataType::Float3, "a_Tangent" },
{ ShaderDataType::Float3, "a_Binormal" }, { ShaderDataType::Float3, "a_Binormal" },
{ ShaderDataType::Float2, "a_TexCoord" }, { ShaderDataType::Float2, "a_TexCoord" },
}); };
m_VertexArray->AddVertexBuffer(vb);
} }
auto ib = IndexBuffer::Create(m_Indices.data(), (uint32_t)m_Indices.size() * sizeof(Index)); m_IndexBuffer = IndexBuffer::Create(m_Indices.data(), (uint32_t)m_Indices.size() * sizeof(Index));
m_VertexArray->SetIndexBuffer(ib);
PipelineSpecification pipelineSpecification;
pipelineSpecification.Layout = vertexBufferLayout;
m_Pipeline = Pipeline::Create(pipelineSpecification);
} }
Mesh::~Mesh() = default; Mesh::~Mesh() = default;

View File

@ -8,6 +8,7 @@
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include "Material.h" #include "Material.h"
#include "Pipeline.h"
#include "Shader.h" #include "Shader.h"
#include "VertexArray.h" #include "VertexArray.h"
#include "Prism/Core/TimeStep.h" #include "Prism/Core/TimeStep.h"
@ -145,7 +146,10 @@ namespace Prism
uint32_t m_BoneCount = 0; uint32_t m_BoneCount = 0;
std::vector<BoneInfo> m_BoneInfo; std::vector<BoneInfo> m_BoneInfo;
Ref<VertexArray> m_VertexArray; // Ref<VertexArray> m_VertexArray;
Ref<Pipeline> m_Pipeline;
Ref<VertexBuffer> m_VertexBuffer;
Ref<IndexBuffer> m_IndexBuffer;
std::vector<Vertex> m_StaticVertices; std::vector<Vertex> m_StaticVertices;

View File

@ -0,0 +1,21 @@
//
// Created by sfd on 2025/12/15.
//
#include "Pipeline.h"
#include "Prism/Platform/OpenGL/OpenGLPipeline.h"
namespace Prism {
Ref<Pipeline> Pipeline::Create(const PipelineSpecification& spec)
{
switch (RendererAPI::Current())
{
case RendererAPIType::None: return nullptr;
case RendererAPIType::OpenGL: return Ref<OpenGLPipeline>::Create(spec);
}
PM_CORE_ASSERT(false, "Unknown RendererAPI");
return nullptr;
}
}

View File

@ -0,0 +1,36 @@
//
// Created by sfd on 2025/12/15.
//
#ifndef PRISM_PIPELINE_H
#define PRISM_PIPELINE_H
#include "Shader.h"
#include "VertexBuffer.h"
#include "Prism/Core/Ref.h"
namespace Prism {
struct PipelineSpecification
{
Ref<Prism::Shader> Shader;
VertexBufferLayout Layout;
};
class Pipeline : public RefCounted
{
public:
virtual ~Pipeline() = default;
virtual PipelineSpecification& GetSpecification() = 0;
virtual const PipelineSpecification& GetSpecification() const = 0;
virtual void Invalidate() = 0;
// TEMP: remove this when render command buffers are a thing
virtual void Bind() = 0;
static Ref<Pipeline> Create(const PipelineSpecification& spec);
};
}
#endif //PRISM_PIPELINE_H

View File

@ -17,7 +17,7 @@ namespace Prism
class PRISM_API RenderPass : public RefCounted class PRISM_API RenderPass : public RefCounted
{ {
public: public:
virtual ~RenderPass() {} virtual ~RenderPass() = default;
virtual RenderPassSpecification& GetSpecification() = 0; virtual RenderPassSpecification& GetSpecification() = 0;

View File

@ -19,7 +19,10 @@ namespace Prism
Ref<RenderPass> m_ActiveRenderPass; Ref<RenderPass> m_ActiveRenderPass;
RenderCommandQueue m_CommandQueue; RenderCommandQueue m_CommandQueue;
Ref<ShaderLibrary> m_ShaderLibrary; Ref<ShaderLibrary> m_ShaderLibrary;
Ref<VertexArray> m_FullscreenQuadVertexArray;
Ref<VertexBuffer> m_FullscreenQuadVertexBuffer;
Ref<IndexBuffer> m_FullscreenQuadIndexBuffer;
Ref<Pipeline> m_FullscreenQuadPipeline;
}; };
static RendererData s_Data; static RendererData s_Data;
@ -45,16 +48,16 @@ namespace Prism
0, 1, 2, 2, 3, 0 0, 1, 2, 2, 3, 0
}; };
s_Data.m_FullscreenQuadVertexArray = VertexArray::Create();
auto quadVB = VertexBuffer::Create(fullScreenQuadVertex, sizeof(float) * sizeof(fullScreenQuadVertex)); PipelineSpecification pipelineSpecification;
quadVB->SetLayout({ pipelineSpecification.Layout = {
{ ShaderDataType::Float3, "a_Position" }, { ShaderDataType::Float3, "a_Position" },
{ ShaderDataType::Float2, "a_TexCoord" } { ShaderDataType::Float2, "a_TexCoord" }
}); };
s_Data.m_FullscreenQuadPipeline = Pipeline::Create(pipelineSpecification);
auto quadIB = IndexBuffer::Create(fullScreenQuadIndices, sizeof(fullScreenQuadIndices) * sizeof(uint32_t)); s_Data.m_FullscreenQuadVertexBuffer = VertexBuffer::Create(fullScreenQuadVertex, sizeof(fullScreenQuadVertex[0]) * sizeof(fullScreenQuadVertex));
s_Data.m_FullscreenQuadVertexArray->AddVertexBuffer(quadVB); s_Data.m_FullscreenQuadIndexBuffer = IndexBuffer::Create(fullScreenQuadIndices, sizeof(fullScreenQuadIndices[0]) * sizeof(fullScreenQuadIndices));
s_Data.m_FullscreenQuadVertexArray->SetIndexBuffer(quadIB);
Renderer2D::Init(); Renderer2D::Init();
} }
@ -141,7 +144,10 @@ namespace Prism
shader->SetMat4("u_Transform", transform); shader->SetMat4("u_Transform", transform);
} }
s_Data.m_FullscreenQuadVertexArray->Bind(); s_Data.m_FullscreenQuadVertexBuffer->Bind();
s_Data.m_FullscreenQuadPipeline->Bind();
s_Data.m_FullscreenQuadIndexBuffer->Bind();
Renderer::DrawIndexed(6, PrimitiveType::Triangles, depthTest); Renderer::DrawIndexed(6, PrimitiveType::Triangles, depthTest);
} }
@ -154,7 +160,10 @@ namespace Prism
depthTest = material->GetFlag(MaterialFlag::DepthTest); depthTest = material->GetFlag(MaterialFlag::DepthTest);
} }
s_Data.m_FullscreenQuadVertexArray->Bind(); s_Data.m_FullscreenQuadVertexBuffer->Bind();
s_Data.m_FullscreenQuadPipeline->Bind();
s_Data.m_FullscreenQuadIndexBuffer->Bind();
Renderer::DrawIndexed(6, PrimitiveType::Triangles, depthTest); Renderer::DrawIndexed(6, PrimitiveType::Triangles, depthTest);
} }
@ -164,7 +173,9 @@ namespace Prism
// auto shader = material->GetShader(); // auto shader = material->GetShader();
// TODO: Sort this out // TODO: Sort this out
mesh->m_VertexArray->Bind(); mesh->m_VertexBuffer->Bind();
mesh->m_Pipeline->Bind();
mesh->m_IndexBuffer->Bind();
const auto& materials = mesh->GetMaterials(); const auto& materials = mesh->GetMaterials();
for (Submesh& submesh : mesh->m_Submeshes) for (Submesh& submesh : mesh->m_Submeshes)

View File

@ -38,8 +38,10 @@ namespace Prism
static constexpr uint32_t MaxLineIndices = MaxLines * 6; static constexpr uint32_t MaxLineIndices = MaxLines * 6;
// Quad // Quad
Ref<VertexArray> QuadVertexArray; Ref<Pipeline> QuadPipeline;
Ref<VertexBuffer> QuadVertexBuffer; Ref<VertexBuffer> QuadVertexBuffer;
Ref<IndexBuffer> QuadIndexBuffer;
Ref<Shader> TextureShader; Ref<Shader> TextureShader;
Ref<Texture2D> WhiteTexture; Ref<Texture2D> WhiteTexture;
@ -54,8 +56,9 @@ namespace Prism
// Lines // Lines
Ref<VertexArray> LineVertexArray; Ref<Pipeline> LinePipeline;
Ref<VertexBuffer> LineVertexBuffer; Ref<VertexBuffer> LineVertexBuffer;
Ref<IndexBuffer> LineIndexBuffer;
Ref<Shader> LineShader; Ref<Shader> LineShader;
uint32_t LineIndexCount = 0; uint32_t LineIndexCount = 0;
@ -74,18 +77,18 @@ namespace Prism
void Renderer2D::Init() void Renderer2D::Init()
{ {
s_Data.QuadVertexArray = VertexArray::Create(); {
PipelineSpecification pipelineSpecification;
s_Data.QuadVertexBuffer = VertexBuffer::Create(s_Data.MaxVertices * sizeof(QuadVertex)); pipelineSpecification.Layout = {
s_Data.QuadVertexBuffer->SetLayout({
{ ShaderDataType::Float3, "a_Position" }, { ShaderDataType::Float3, "a_Position" },
{ ShaderDataType::Float4, "a_Color" }, { ShaderDataType::Float4, "a_Color" },
{ ShaderDataType::Float2, "a_TexCoord" }, { ShaderDataType::Float2, "a_TexCoord" },
{ ShaderDataType::Float, "a_TexIndex" }, { ShaderDataType::Float, "a_TexIndex" },
{ ShaderDataType::Float, "a_TilingFactor" } { ShaderDataType::Float, "a_TilingFactor" }
}); };
s_Data.QuadVertexArray->AddVertexBuffer(s_Data.QuadVertexBuffer); s_Data.QuadPipeline = Pipeline::Create(pipelineSpecification);
s_Data.QuadVertexBuffer = VertexBuffer::Create(s_Data.MaxVertices * sizeof(QuadVertex));
s_Data.QuadVertexBufferBase = new QuadVertex[s_Data.MaxVertices]; s_Data.QuadVertexBufferBase = new QuadVertex[s_Data.MaxVertices];
uint32_t* quadIndices = new uint32_t[s_Data.MaxIndices]; uint32_t* quadIndices = new uint32_t[s_Data.MaxIndices];
@ -104,9 +107,9 @@ namespace Prism
offset += 4; offset += 4;
} }
Ref<IndexBuffer> quadIB = IndexBuffer::Create(quadIndices, s_Data.MaxIndices); s_Data.QuadIndexBuffer = IndexBuffer::Create(quadIndices, s_Data.MaxIndices);
s_Data.QuadVertexArray->SetIndexBuffer(quadIB);
delete[] quadIndices; delete[] quadIndices;
}
s_Data.WhiteTexture = Texture2D::Create(TextureFormat::RGBA, 1, 1); s_Data.WhiteTexture = Texture2D::Create(TextureFormat::RGBA, 1, 1);
uint32_t whiteTextureData = 0xffffffff; uint32_t whiteTextureData = 0xffffffff;
@ -125,26 +128,27 @@ namespace Prism
s_Data.QuadVertexPositions[3] = { -0.5f, 0.5f, 0.0f, 1.0f }; s_Data.QuadVertexPositions[3] = { -0.5f, 0.5f, 0.0f, 1.0f };
// Lines // Lines
{
s_Data.LineShader = Shader::Create("assets/shaders/Renderer2D_Line.glsl"); s_Data.LineShader = Shader::Create("assets/shaders/Renderer2D_Line.glsl");
s_Data.LineVertexArray = VertexArray::Create();
s_Data.LineVertexBuffer = VertexBuffer::Create(s_Data.MaxLineVertices * sizeof(LineVertex)); PipelineSpecification pipelineSpecification;
s_Data.LineVertexBuffer->SetLayout({ pipelineSpecification.Layout = {
{ ShaderDataType::Float3, "a_Position" }, { ShaderDataType::Float3, "a_Position" },
{ ShaderDataType::Float4, "a_Color" } { ShaderDataType::Float4, "a_Color" }
}); };
s_Data.LineVertexArray->AddVertexBuffer(s_Data.LineVertexBuffer); s_Data.LinePipeline = Pipeline::Create(pipelineSpecification);
s_Data.LineVertexBuffer = VertexBuffer::Create(s_Data.MaxLineVertices * sizeof(LineVertex));
s_Data.LineVertexBufferBase = new LineVertex[s_Data.MaxLineVertices]; s_Data.LineVertexBufferBase = new LineVertex[s_Data.MaxLineVertices];
uint32_t* lineIndices = new uint32_t[s_Data.MaxLineIndices]; uint32_t* lineIndices = new uint32_t[s_Data.MaxLineIndices];
for (uint32_t i = 0; i < s_Data.MaxLineIndices; i++) for (uint32_t i = 0; i < s_Data.MaxLineIndices; i++)
lineIndices[i] = i; lineIndices[i] = i;
Ref<IndexBuffer> lineIB = IndexBuffer::Create(lineIndices, s_Data.MaxLineIndices); s_Data.LineIndexBuffer = IndexBuffer::Create(lineIndices, s_Data.MaxLineIndices);
s_Data.LineVertexArray->SetIndexBuffer(lineIB);
delete[] lineIndices; delete[] lineIndices;
} }
}
void Renderer2D::Shutdown() void Renderer2D::Shutdown()
{ {
@ -180,7 +184,9 @@ namespace Prism
for (uint32_t i = 0; i < s_Data.TextureSlotIndex; i++) for (uint32_t i = 0; i < s_Data.TextureSlotIndex; i++)
s_Data.TextureSlots[i]->Bind(i); s_Data.TextureSlots[i]->Bind(i);
s_Data.QuadVertexArray->Bind(); s_Data.QuadVertexBuffer->Bind();
s_Data.QuadPipeline->Bind();
s_Data.QuadIndexBuffer->Bind();
Renderer::DrawIndexed(s_Data.QuadIndexCount, PrimitiveType::Triangles, s_Data.DepthTest); Renderer::DrawIndexed(s_Data.QuadIndexCount, PrimitiveType::Triangles, s_Data.DepthTest);
s_Data.Stats.DrawCalls++; s_Data.Stats.DrawCalls++;
} }
@ -193,7 +199,9 @@ namespace Prism
s_Data.LineShader->Bind(); s_Data.LineShader->Bind();
s_Data.LineShader->SetMat4("u_ViewProjection", s_Data.CameraViewProj); s_Data.LineShader->SetMat4("u_ViewProjection", s_Data.CameraViewProj);
s_Data.LineVertexArray->Bind(); s_Data.LineVertexBuffer->Bind();
s_Data.LinePipeline->Bind();
s_Data.LineIndexBuffer->Bind();
Renderer::SetLineThickness(1.0f); Renderer::SetLineThickness(1.0f);
Renderer::DrawIndexed(s_Data.LineIndexCount, PrimitiveType::Lines, s_Data.DepthTest); Renderer::DrawIndexed(s_Data.LineIndexCount, PrimitiveType::Lines, s_Data.DepthTest);
s_Data.Stats.DrawCalls++; s_Data.Stats.DrawCalls++;

View File

@ -4,7 +4,9 @@
#ifndef VERTEXARRAY_H #ifndef VERTEXARRAY_H
#define VERTEXARRAY_H #define VERTEXARRAY_H
#include "Buffer.h" #include "IndexBuffer.h"
#include "VertexBuffer.h"
#include "Prism/Core/Ref.h"
namespace Prism namespace Prism

View File

@ -0,0 +1,33 @@
//
// Created by sfd on 2025/12/15.
//
#include "VertexBuffer.h"
#include "Prism/Platform/OpenGL/OpenGLVertexBuffer.h"
namespace Prism {
Ref<VertexBuffer> VertexBuffer::Create(void* data, uint32_t size, VertexBufferUsage usage)
{
switch (RendererAPI::Current())
{
case RendererAPIType::None: return nullptr;
case RendererAPIType::OpenGL: return Ref<OpenGLVertexBuffer>::Create(data, size, usage);
}
PM_CORE_ASSERT(false, "Unknown RendererAPI");
return nullptr;
}
Ref<VertexBuffer> VertexBuffer::Create(uint32_t size, VertexBufferUsage usage)
{
switch (RendererAPI::Current())
{
case RendererAPIType::None: return nullptr;
case RendererAPIType::OpenGL: return Ref<OpenGLVertexBuffer>::Create(size, usage);
}
PM_CORE_ASSERT(false, "Unknown RendererAPI");
return nullptr;
}
}

View File

@ -0,0 +1,129 @@
//
// Created by sfd on 2025/12/15.
//
#ifndef PRISM_VERTEXBUFFER_H
#define PRISM_VERTEXBUFFER_H
#include "RendererAPI.h"
#include "Prism/Core/Ref.h"
namespace Prism {
enum class ShaderDataType {
None = 0, Float, Float2, Float3, Float4, Mat3, Mat4, Int, Int2, Int3, Int4, Bool
};
static uint32_t ShaderDataTypeSize(const ShaderDataType type) {
switch (type) {
case ShaderDataType::Float: return 4;
case ShaderDataType::Float2: return 4 * 2;
case ShaderDataType::Float3: return 4 * 3;
case ShaderDataType::Float4: return 4 * 4;
case ShaderDataType::Mat3: return 4 * 3 * 3;
case ShaderDataType::Mat4: return 4 * 4 * 4;
case ShaderDataType::Int: return 4;
case ShaderDataType::Int2: return 4 * 2;
case ShaderDataType::Int3: return 4 * 3;
case ShaderDataType::Int4: return 4 * 4;
case ShaderDataType::Bool: return 1;
}
PM_CORE_ASSERT(false, "Unknown ShaderDataType!");
return 0;
}
struct VertexBufferElement {
std::string Name;
ShaderDataType Type;
uint32_t Size;
uint32_t Offset;
bool Normalized;
VertexBufferElement() = default;
VertexBufferElement(const ShaderDataType type, const std::string &name, const bool normalized = false)
: Name(name), Type(type), Size(ShaderDataTypeSize(type)), Offset(0), Normalized(normalized) {
}
uint32_t GetComponentCount() const {
switch (Type) {
case ShaderDataType::Float: return 1;
case ShaderDataType::Float2: return 2;
case ShaderDataType::Float3: return 3;
case ShaderDataType::Float4: return 4;
case ShaderDataType::Mat3: return 3 * 3;
case ShaderDataType::Mat4: return 4 * 4;
case ShaderDataType::Int: return 1;
case ShaderDataType::Int2: return 2;
case ShaderDataType::Int3: return 3;
case ShaderDataType::Int4: return 4;
case ShaderDataType::Bool: return 1;
}
PM_CORE_ASSERT(false, "Unknown ShaderDataType!");
return 0;
}
};
class VertexBufferLayout {
public:
VertexBufferLayout() {
}
VertexBufferLayout(const std::initializer_list<VertexBufferElement> &elements)
: m_Elements(elements) {
CalculateOffsetsAndStride();
}
inline uint32_t GetStride() const { return m_Stride; }
inline const std::vector<VertexBufferElement> &GetElements() const { return m_Elements; }
std::vector<VertexBufferElement>::iterator begin() { return m_Elements.begin(); }
std::vector<VertexBufferElement>::iterator end() { return m_Elements.end(); }
std::vector<VertexBufferElement>::const_iterator begin() const { return m_Elements.begin(); }
std::vector<VertexBufferElement>::const_iterator end() const { return m_Elements.end(); }
private:
void CalculateOffsetsAndStride() {
uint32_t offset = 0;
m_Stride = 0;
for (auto &element: m_Elements) {
element.Offset = offset;
offset += element.Size;
m_Stride += element.Size;
}
}
private:
std::vector<VertexBufferElement> m_Elements;
uint32_t m_Stride = 0;
};
enum class VertexBufferUsage {
None = 0, Static = 1, Dynamic = 2
};
class VertexBuffer : public RefCounted {
public:
virtual ~VertexBuffer() {
}
virtual void SetData(void *buffer, uint32_t size, uint32_t offset = 0) = 0;
virtual void Bind() const = 0;
virtual const VertexBufferLayout &GetLayout() const = 0;
virtual void SetLayout(const VertexBufferLayout &layout) = 0;
virtual unsigned int GetSize() const = 0;
virtual RendererID GetRendererID() const = 0;
static Ref<VertexBuffer> Create(void *data, uint32_t size, VertexBufferUsage usage = VertexBufferUsage::Static);
static Ref<VertexBuffer> Create(uint32_t size, VertexBufferUsage usage = VertexBufferUsage::Dynamic);
};
}
#endif //PRISM_VERTEXBUFFER_H