Batch Rendering & IndexBuffers & RendererProgram
This commit is contained in:
parent
2f560239cb
commit
a3092c476c
19 changed files with 263 additions and 52 deletions
|
@ -24,5 +24,4 @@
|
|||
#define BIT(x) 1 << x
|
||||
|
||||
#define LT_ENGINE_ASSERT(x, ...) { if(!(x)) { LT_ENGINE_CRITICAL(__VA_ARGS__); __debugbreak(); } }
|
||||
#define LT_CLIENT_ASSERT(x, ...) { if(!(x)) { LT_CLIENT_CRITICAL(__VA_ARGS__); __debugbreak(); } }
|
||||
|
||||
#define LT_CLIENT_ASSERT(x, ...) { if(!(x)) { LT_CLIENT_CRITICAL(__VA_ARGS__); __debugbreak(); } }
|
|
@ -41,7 +41,9 @@ namespace Light {
|
|||
m_Window->PollEvents();
|
||||
|
||||
// Rendering
|
||||
m_Window->GetGfxContext()->GetRenderer()->Draw();
|
||||
m_Window->GetGfxContext()->GetRenderer()->BeginScene();
|
||||
m_LayerStack.OnRender();
|
||||
m_Window->GetGfxContext()->GetRenderer()->EndScene();
|
||||
|
||||
// Buffer updates
|
||||
m_Window->GetGfxContext()->GetRenderCommand()->SwapBuffers();
|
||||
|
|
|
@ -27,12 +27,15 @@ namespace Light {
|
|||
}
|
||||
}
|
||||
|
||||
IndexBuffer* IndexBuffer::Create(unsigned int count, unsigned int* indices)
|
||||
IndexBuffer* IndexBuffer::Create(unsigned int count, unsigned int* indices, void* sharedContext)
|
||||
{
|
||||
switch (GraphicsContext::GetGraphicsAPI())
|
||||
{
|
||||
case GraphicsAPI::OpenGL:
|
||||
return new glIndexBuffer(count, indices);
|
||||
case GraphicsAPI::DirectX: LT_WIN(
|
||||
return new dxIndexBuffer(count, indices, sharedContext);
|
||||
)
|
||||
default:
|
||||
LT_ENGINE_ASSERT(false, "IndexBuffer::Create: invalid/unsupported GraphicsAPI {}", GraphicsContext::GetGraphicsAPI());
|
||||
return nullptr;
|
||||
|
|
|
@ -9,6 +9,9 @@ namespace Light {
|
|||
public:
|
||||
static VertexBuffer* Create(unsigned int stride, unsigned int count, float* vertices, void* sharedContext);
|
||||
|
||||
virtual void* Map() = 0;
|
||||
virtual void UnMap() = 0;
|
||||
|
||||
virtual void Bind() = 0;
|
||||
virtual void UnBind() = 0;
|
||||
|
||||
|
@ -19,7 +22,7 @@ namespace Light {
|
|||
class IndexBuffer
|
||||
{
|
||||
public:
|
||||
static IndexBuffer* Create(unsigned int count, unsigned int* indices);
|
||||
static IndexBuffer* Create(unsigned int count, unsigned int* indices, void* sharedContext);
|
||||
|
||||
virtual void Bind() = 0;
|
||||
virtual void UnBind() = 0;
|
||||
|
|
|
@ -7,24 +7,36 @@
|
|||
|
||||
namespace Light {
|
||||
|
||||
Renderer* Renderer::m_Context;
|
||||
Renderer* Renderer::s_Context;
|
||||
|
||||
Renderer::Renderer(std::shared_ptr<RenderCommand> renderCommand, void* sharedContext)
|
||||
: m_RenderCommand(renderCommand), m_SharedContext(sharedContext)
|
||||
{
|
||||
m_Context = this;
|
||||
s_Context = this;
|
||||
|
||||
m_Shader = std::unique_ptr<Shader>(Shader::Create("res/vertex.vertex", "res/fragment.fragment", m_SharedContext));
|
||||
// QUADRENDERER //
|
||||
unsigned int offset = 0;
|
||||
unsigned int* indices = new unsigned int[LT_MAX_QUAD * 6];
|
||||
|
||||
float vertices[] =
|
||||
for (int i = 0; i < LT_MAX_QUAD * 6; i += 6)
|
||||
{
|
||||
0.0f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f,
|
||||
0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f,
|
||||
};
|
||||
indices[i + 0] = offset + 0;
|
||||
indices[i + 1] = offset + 1;
|
||||
indices[i + 2] = offset + 2;
|
||||
|
||||
m_VertexBuffer = std::unique_ptr<VertexBuffer>(VertexBuffer::Create(6 * sizeof(float), (2 + 4) * 3, vertices, m_SharedContext));
|
||||
m_VertexLayout = std::unique_ptr<VertexLayout>(VertexLayout::Create(m_VertexBuffer.get(), m_Shader.get(), { { "POSITION", VertexElementType::Float2 },{ "COLOR", VertexElementType::Float4 } }, m_SharedContext));
|
||||
indices[i + 3] = offset + 2;
|
||||
indices[i + 4] = offset + 3;
|
||||
indices[i + 5] = offset + 0;
|
||||
|
||||
offset += 4;
|
||||
}
|
||||
|
||||
m_QuadRenderer.shader = std::unique_ptr<Shader>(Shader::Create("res/vertex.vertex", "res/fragment.fragment", m_SharedContext));
|
||||
m_QuadRenderer.vertexBuffer = std::unique_ptr<VertexBuffer>(VertexBuffer::Create(sizeof(QuadRendererProgram::QuadVertexData), LT_MAX_QUAD * 4, nullptr, m_SharedContext));
|
||||
m_QuadRenderer.vertexLayout = std::unique_ptr<VertexLayout>(VertexLayout::Create(m_QuadRenderer.vertexBuffer.get(), m_QuadRenderer.shader.get(), { { "POSITION", VertexElementType::Float3 },{ "COLOR", VertexElementType::Float4 } }, m_SharedContext));
|
||||
m_QuadRenderer.indexBuffer = std::unique_ptr<IndexBuffer>(IndexBuffer::Create(LT_MAX_QUAD * 6, indices, m_SharedContext));
|
||||
delete[] indices;
|
||||
// QUADRENDERER //
|
||||
}
|
||||
|
||||
Renderer* Renderer::Create(std::shared_ptr<RenderCommand> renderCommand, void* sharedContext)
|
||||
|
@ -32,14 +44,63 @@ namespace Light {
|
|||
return new Renderer(renderCommand, sharedContext);
|
||||
}
|
||||
|
||||
void Renderer::Draw()
|
||||
void Renderer::DrawQuad(const glm::vec3& position, const glm::vec2& size, const glm::vec4& tint)
|
||||
{
|
||||
m_Shader->Bind();
|
||||
m_VertexBuffer->Bind();
|
||||
m_VertexLayout->Bind();
|
||||
s_Context->DrawQuadImpl(position, size, tint);
|
||||
}
|
||||
|
||||
m_RenderCommand->Draw(3u);
|
||||
void Renderer::DrawQuadImpl(const glm::vec3& position, const glm::vec2& size, const glm::vec4& tint)
|
||||
{
|
||||
// check
|
||||
if (m_QuadRenderer.mapCurrent + 4 >= m_QuadRenderer.mapEnd)
|
||||
{
|
||||
LT_ENGINE_WARN("Render::DrawQuad: max calls per frame exceeded the limit: {}", LT_MAX_QUAD);
|
||||
|
||||
EndScene();
|
||||
m_QuadRenderer.Map();
|
||||
}
|
||||
|
||||
// local
|
||||
const float xMin = position.x;
|
||||
const float yMin = position.y;
|
||||
const float xMax = position.x + size.x;
|
||||
const float yMax = position.y + size.y;
|
||||
|
||||
// TOP LEFT
|
||||
m_QuadRenderer.mapCurrent->position = { xMin, yMin, position.z };
|
||||
m_QuadRenderer.mapCurrent->tint = glm::vec4(1.0f, 0.1f, 0.1f, 1.0f);
|
||||
m_QuadRenderer.mapCurrent++;
|
||||
|
||||
// TOP RIGHT
|
||||
m_QuadRenderer.mapCurrent->position = { xMax, yMin, position.z };
|
||||
m_QuadRenderer.mapCurrent->tint = glm::vec4(0.1f, 1.0f, 0.1f, 1.0f);
|
||||
m_QuadRenderer.mapCurrent++;
|
||||
|
||||
// BOTTOM RIGHT
|
||||
m_QuadRenderer.mapCurrent->position = { xMax, yMax, position.z };
|
||||
m_QuadRenderer.mapCurrent->tint = glm::vec4(0.3f, 0.3f, 0.3f, 1.0f);
|
||||
m_QuadRenderer.mapCurrent++;
|
||||
|
||||
// BOTTOM LEFT
|
||||
m_QuadRenderer.mapCurrent->position = { xMin, yMax, position.z };
|
||||
m_QuadRenderer.mapCurrent->tint = glm::vec4(0.1f, 0.1f, 1.0f, 1.0f);
|
||||
m_QuadRenderer.mapCurrent++;
|
||||
|
||||
// advance
|
||||
m_QuadRenderer.quadCount++;
|
||||
}
|
||||
|
||||
|
||||
void Renderer::BeginScene()
|
||||
{
|
||||
m_QuadRenderer.Map();
|
||||
}
|
||||
|
||||
void Renderer::EndScene()
|
||||
{
|
||||
m_QuadRenderer.Bind();
|
||||
m_RenderCommand->DrawIndexed(m_QuadRenderer.quadCount * 6);
|
||||
m_QuadRenderer.quadCount = 0;
|
||||
}
|
||||
|
||||
}
|
|
@ -6,31 +6,80 @@
|
|||
#include "Buffers.h"
|
||||
#include "VertexLayout.h"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#define LT_MAX_QUAD 124
|
||||
|
||||
namespace Light {
|
||||
|
||||
class RenderCommand;
|
||||
|
||||
struct RendererProgram
|
||||
{
|
||||
virtual void Map() = 0;
|
||||
virtual void Bind() = 0;
|
||||
};
|
||||
|
||||
class Renderer
|
||||
{
|
||||
private:
|
||||
static Renderer* m_Context;
|
||||
struct QuadRendererProgram : RendererProgram
|
||||
{
|
||||
// graphics context
|
||||
std::shared_ptr<Shader> shader;
|
||||
std::shared_ptr<VertexLayout> vertexLayout;
|
||||
std::shared_ptr<VertexBuffer> vertexBuffer;
|
||||
std::shared_ptr<IndexBuffer> indexBuffer;
|
||||
|
||||
// buffer data
|
||||
struct QuadVertexData
|
||||
{
|
||||
glm::vec3 position;
|
||||
glm::vec4 tint;
|
||||
};
|
||||
|
||||
QuadVertexData* mapCurrent = nullptr;
|
||||
QuadVertexData* mapEnd = nullptr;
|
||||
unsigned int quadCount = 0u;
|
||||
|
||||
// functions
|
||||
void Map()
|
||||
{
|
||||
mapCurrent = (QuadVertexData*)vertexBuffer->Map();
|
||||
mapEnd = mapCurrent + LT_MAX_QUAD * 4;
|
||||
}
|
||||
|
||||
void Bind()
|
||||
{
|
||||
vertexBuffer->UnMap();
|
||||
shader->Bind();
|
||||
vertexLayout->Bind();
|
||||
vertexBuffer->Bind();
|
||||
indexBuffer->Bind();
|
||||
}
|
||||
};
|
||||
|
||||
static Renderer* s_Context;
|
||||
|
||||
QuadRendererProgram m_QuadRenderer;
|
||||
|
||||
std::shared_ptr<RenderCommand> m_RenderCommand;
|
||||
|
||||
std::unique_ptr<Shader> m_Shader;
|
||||
std::unique_ptr<VertexBuffer> m_VertexBuffer;
|
||||
std::unique_ptr<VertexLayout> m_VertexLayout;
|
||||
|
||||
void* m_SharedContext;
|
||||
public:
|
||||
static Renderer* Create(std::shared_ptr<RenderCommand> renderCommand, void* sharedContext);
|
||||
|
||||
void Draw();
|
||||
static void DrawQuad(const glm::vec3& position, const glm::vec2& size, const glm::vec4& tint);
|
||||
|
||||
void BeginScene();
|
||||
void EndScene();
|
||||
|
||||
private:
|
||||
Renderer(std::shared_ptr<RenderCommand> renderCommand, void* sharedContext);
|
||||
|
||||
void DrawQuadImpl(const glm::vec3& position, const glm::vec2& size, const glm::vec4& tint);
|
||||
};
|
||||
|
||||
}
|
|
@ -33,6 +33,8 @@ namespace Light {
|
|||
virtual void OnUpdate(float deltaTime) {}
|
||||
virtual void OnUserInterfaceUpdate() {}
|
||||
|
||||
virtual void OnRender() {}
|
||||
|
||||
// Mouse events
|
||||
virtual bool OnMouseMoved(const MouseMovedEvent& event) { return false; }
|
||||
virtual bool OnButtonPressed(const ButtonPressedEvent& event) { return false; }
|
||||
|
|
|
@ -35,6 +35,12 @@ namespace Light {
|
|||
(*it)->OnUserInterfaceUpdate();
|
||||
}
|
||||
|
||||
void LayerStack::OnRender()
|
||||
{
|
||||
for (auto it = m_Begin; it != m_End; it++)
|
||||
(*it)->OnRender();
|
||||
}
|
||||
|
||||
void LayerStack::OnEvent(const Event& event)
|
||||
{
|
||||
switch (event.GetEventType())
|
||||
|
|
|
@ -30,6 +30,8 @@ namespace Light {
|
|||
void OnUpdate(float deltaTime);
|
||||
void OnUserInterfaceUpdate();
|
||||
|
||||
void OnRender();
|
||||
|
||||
void OnEvent(const Event& event);
|
||||
|
||||
inline bool IsEmpty() { return m_Layers.empty(); }
|
||||
|
|
|
@ -17,8 +17,6 @@ namespace Light {
|
|||
m_DeviceContext = dxContext->deviceContext;
|
||||
|
||||
D3D11_BUFFER_DESC desc = { 0 };
|
||||
D3D11_SUBRESOURCE_DATA sd = { 0 };
|
||||
|
||||
|
||||
desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
||||
desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
|
@ -27,15 +25,24 @@ namespace Light {
|
|||
desc.ByteWidth = count * stride;
|
||||
desc.StructureByteStride = stride;
|
||||
|
||||
sd.pSysMem = vertices;
|
||||
|
||||
DXC(m_Device->CreateBuffer(&desc, &sd, &m_Buffer));
|
||||
DXC(m_Device->CreateBuffer(&desc, nullptr, &m_Buffer));
|
||||
}
|
||||
|
||||
dxVertexBuffer::~dxVertexBuffer()
|
||||
{
|
||||
}
|
||||
|
||||
void* dxVertexBuffer::Map()
|
||||
{
|
||||
m_DeviceContext->Map(m_Buffer.Get(), NULL, D3D11_MAP_WRITE_DISCARD, NULL, &m_Map);
|
||||
return m_Map.pData;
|
||||
}
|
||||
|
||||
void dxVertexBuffer::UnMap()
|
||||
{
|
||||
m_DeviceContext->Unmap(m_Buffer.Get(), NULL);
|
||||
}
|
||||
|
||||
void dxVertexBuffer::Bind()
|
||||
{
|
||||
static const unsigned int offset = 0u;
|
||||
|
@ -46,4 +53,41 @@ namespace Light {
|
|||
{
|
||||
}
|
||||
|
||||
|
||||
dxIndexBuffer::dxIndexBuffer(unsigned int count, unsigned int* indices, void* sharedContext)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
dxSharedContext* dxContext = static_cast<dxSharedContext*>(sharedContext);
|
||||
LT_ENGINE_ASSERT(dxContext, "dxShader::dxShader: invalid dxContext");
|
||||
|
||||
m_Device = dxContext->device;
|
||||
m_DeviceContext = dxContext->deviceContext;
|
||||
|
||||
D3D11_BUFFER_DESC bufferDesc = { 0 };
|
||||
D3D11_SUBRESOURCE_DATA sd = { 0 };
|
||||
bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
|
||||
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
|
||||
bufferDesc.ByteWidth = count * sizeof(unsigned int);
|
||||
bufferDesc.StructureByteStride = sizeof(unsigned int);
|
||||
|
||||
sd.pSysMem = indices;
|
||||
|
||||
DXC(m_Device->CreateBuffer(&bufferDesc, &sd, &m_Buffer));
|
||||
}
|
||||
|
||||
dxIndexBuffer::~dxIndexBuffer()
|
||||
{
|
||||
}
|
||||
|
||||
void dxIndexBuffer::Bind()
|
||||
{
|
||||
m_DeviceContext->IASetIndexBuffer(m_Buffer.Get(), DXGI_FORMAT_R32_UINT, 0u);
|
||||
}
|
||||
|
||||
void dxIndexBuffer::UnBind()
|
||||
{
|
||||
}
|
||||
|
||||
}
|
|
@ -17,11 +17,31 @@ namespace Light {
|
|||
Microsoft::WRL::ComPtr<ID3D11Device> m_Device;
|
||||
Microsoft::WRL::ComPtr<ID3D11DeviceContext> m_DeviceContext;
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE m_Map;
|
||||
|
||||
unsigned int m_Stride;
|
||||
public:
|
||||
dxVertexBuffer(unsigned int count, unsigned int stride, float* vertices, void* sharedContext);
|
||||
~dxVertexBuffer();
|
||||
|
||||
void* Map() override;
|
||||
void UnMap() override;
|
||||
|
||||
void Bind() override;
|
||||
void UnBind() override;
|
||||
};
|
||||
|
||||
class dxIndexBuffer : public IndexBuffer
|
||||
{
|
||||
private:
|
||||
Microsoft::WRL::ComPtr<ID3D11Buffer> m_Buffer;
|
||||
|
||||
Microsoft::WRL::ComPtr<ID3D11Device> m_Device;
|
||||
Microsoft::WRL::ComPtr<ID3D11DeviceContext> m_DeviceContext;
|
||||
public:
|
||||
dxIndexBuffer(unsigned int count, unsigned int* indices, void* sharedContext);
|
||||
~dxIndexBuffer();
|
||||
|
||||
void Bind() override;
|
||||
void UnBind() override;
|
||||
};
|
||||
|
|
|
@ -8,8 +8,7 @@ namespace Light {
|
|||
glVertexBuffer::glVertexBuffer(unsigned int count, float* vertices)
|
||||
{
|
||||
glCreateBuffers(1, &m_BufferID);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_BufferID);
|
||||
glBufferData(GL_ARRAY_BUFFER, count * sizeof(float), vertices, GL_STATIC_DRAW);
|
||||
glNamedBufferData(m_BufferID, count * sizeof(float), vertices, GL_DYNAMIC_DRAW);
|
||||
}
|
||||
|
||||
glVertexBuffer::~glVertexBuffer()
|
||||
|
@ -17,6 +16,16 @@ namespace Light {
|
|||
glDeleteBuffers(1, &m_BufferID);
|
||||
}
|
||||
|
||||
void* glVertexBuffer::Map()
|
||||
{
|
||||
return glMapNamedBuffer(m_BufferID, GL_WRITE_ONLY);
|
||||
}
|
||||
|
||||
void glVertexBuffer::UnMap()
|
||||
{
|
||||
glUnmapNamedBuffer(m_BufferID);
|
||||
}
|
||||
|
||||
void glVertexBuffer::Bind()
|
||||
{
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_BufferID);
|
||||
|
@ -30,9 +39,7 @@ namespace Light {
|
|||
glIndexBuffer::glIndexBuffer(unsigned int count, unsigned int* indices)
|
||||
{
|
||||
glCreateBuffers(1, &m_BufferID);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_BufferID);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, count * sizeof(unsigned int), indices, GL_STATIC_DRAW);
|
||||
|
||||
glNamedBufferData(m_BufferID, count * sizeof(unsigned int), indices, GL_STATIC_DRAW);
|
||||
}
|
||||
|
||||
glIndexBuffer::~glIndexBuffer()
|
||||
|
|
|
@ -14,6 +14,9 @@ namespace Light {
|
|||
glVertexBuffer(unsigned int count, float* vertices);
|
||||
~glVertexBuffer();
|
||||
|
||||
void* Map() override;
|
||||
void UnMap() override;
|
||||
|
||||
void Bind() override;
|
||||
void UnBind() override;
|
||||
};
|
||||
|
|
|
@ -28,7 +28,7 @@ namespace Light {
|
|||
glfwSetWindowUserPointer(m_Handle, &m_EventCallback);
|
||||
BindGlfwEvents();
|
||||
|
||||
m_GraphicsContext = std::unique_ptr<GraphicsContext>(GraphicsContext::Create(GraphicsAPI::DirectX, m_Handle));
|
||||
m_GraphicsContext = std::unique_ptr<GraphicsContext>(GraphicsContext::Create(GraphicsAPI::OpenGL, m_Handle));
|
||||
LT_ENGINE_ASSERT(m_GraphicsContext, "wWindow::wWindow: graphics context creation failed");
|
||||
}
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@ Size=400,400
|
|||
Collapsed=0
|
||||
|
||||
[Window][Dear ImGui Demo]
|
||||
Pos=-3,-1
|
||||
Size=244,247
|
||||
Pos=1,-3
|
||||
Size=405,290
|
||||
Collapsed=0
|
||||
|
||||
[Window][Dear ImGui Metrics/Debugger]
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
float4 main(float4 Color : COLOR) : SV_Target
|
||||
#version 440 core
|
||||
|
||||
in vec4 fragColor;
|
||||
|
||||
out vec4 FragmentColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
return Color;
|
||||
FragmentColor = fragColor;
|
||||
}
|
|
@ -1,13 +1,12 @@
|
|||
struct VertexOut
|
||||
{
|
||||
float4 Color : COLOR;
|
||||
float4 Position : SV_Position;
|
||||
};
|
||||
#version 440 core
|
||||
|
||||
VertexOut main(float2 InPosition : POSITION, float4 InColor : COLOR)
|
||||
layout(location = 0) in vec3 a_Position;
|
||||
layout(location = 1) in vec4 a_Color;
|
||||
|
||||
out vec4 fragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
VertexOut vso;
|
||||
vso.Position = float4(InPosition.x, InPosition.y, 0.0f, 1.0f);
|
||||
vso.Color = InColor;
|
||||
return vso;
|
||||
gl_Position = vec4(a_Position, 1.0);
|
||||
fragColor = a_Color;
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
#define LIGHT_ENTRY_POINT
|
||||
#include <LightEngine.h>
|
||||
|
||||
#include "SandboxLayer.h"
|
||||
#include "SandboxLayer.h"
|
||||
|
||||
class Sandbox : public Light::Application
|
||||
{
|
||||
|
|
|
@ -5,4 +5,9 @@ class SandboxLayer : public Light::Layer
|
|||
public:
|
||||
SandboxLayer(const std::string& name): Light::Layer(name) {}
|
||||
|
||||
void OnRender() override
|
||||
{
|
||||
Light::Renderer::DrawQuad(glm::vec3(-0.5f, -0.5f, 0.0f), glm::vec2(1.f, 1.f), glm::vec4(1.12f, 1.41f, 1.72f, 1.0f));
|
||||
}
|
||||
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue