diff options
Diffstat (limited to 'source/Renderer.cpp')
-rw-r--r-- | source/Renderer.cpp | 130 |
1 files changed, 116 insertions, 14 deletions
diff --git a/source/Renderer.cpp b/source/Renderer.cpp index dec24ea..f96c3a0 100644 --- a/source/Renderer.cpp +++ b/source/Renderer.cpp @@ -1,19 +1,43 @@ #include "Renderer.hpp" -RenderObject::RenderObject(GpuMesh* mesh, Material* material) { +#include <cassert> + +RenderObject::RenderObject() + : mVao{ GL_NONE } { +} + +RenderObject::~RenderObject() { + DeleteGLObjects(); +} + +GLuint RenderObject::GetGLVao() const { + return mVao; +} + +void RenderObject::RebuildIfNecessary() { + if (mVao != GL_NONE) { + return; + } + + assert(mIndexBuf != nullptr); + assert(mVertexFormat != nullptr); + glGenVertexArrays(1, &mVao); glBindVertexArray(mVao); - auto& vf = mesh->vertFormat; - auto& vBindings = mesh->vertBufBindings.bindings; - auto& shaderInfo = material->GetShader()->GetInfo(); + auto& vBindings = mVertexBufBinding.bindings; + auto& shaderInfo = mMaterial->GetShader()->GetInfo(); // Setup vertex buffers - for (auto& elm : vf->elements) { + for (auto& elm : mVertexFormat->elements) { assert(elm.bindingIndex < vBindings.size()); auto& buffer = vBindings[elm.bindingIndex]; - int index = material->GetShader()->GetInfo().FindInputLocation(elm.semantic); + int index = shaderInfo.FindInputLocation(elm.semantic); + if (index == -1) { + continue; + } + glBindBuffer(GL_ARRAY_BUFFER, buffer->handle); glEnableVertexAttribArray(index); glVertexAttribPointer( @@ -21,23 +45,101 @@ RenderObject::RenderObject(GpuMesh* mesh, Material* material) { Tags::VectorLenOf(elm.type), Tags::FindGLType(elm.type), Tags::IsNormalized(elm.type), - vf->vertexSize, + mVertexFormat->vertexSize, (void*)(uintptr_t)elm.offset); } // Setup index buffer - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->indexBuf->handle); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuf->handle); glBindVertexArray(GL_NONE); } -RenderObject::~RenderObject() { - glDeleteVertexArrays(1, &mVao); +void RenderObject::SetMaterial(Material* material) { + mMaterial.Attach(material); + DeleteGLObjects(); +} + +void RenderObject::UpdateIndexBuffer(GpuIndexBuffer* indexBuffer) { + mIndexBuf.Attach(indexBuffer); + DeleteGLObjects(); +} + +void RenderObject::UpdateVertexFormat(VertexFormat* vertexFormat) { + mVertexFormat.Attach(vertexFormat); + DeleteGLObjects(); +} + +void RenderObject::UpdateVertexBufferBindings(BufferBindings** bindingsOut) { + *bindingsOut = &mVertexBufBinding; + DeleteGLObjects(); +} + +void RenderObject::SetFormat(VertexFormat* vertexFormat, Tags::IndexType indexFormat) { + mIndexBuf.Attach(new GpuIndexBuffer()); + mIndexBuf->indexType = indexFormat; + mIndexBuf->count = 0; + + mVertexFormat.Attach(vertexFormat); + mVertexBufBinding.Clear(); + for (auto& element : vertexFormat->elements) { + if (mVertexBufBinding.GetBinding(element.bindingIndex) == nullptr) { + mVertexBufBinding.SetBinding(element.bindingIndex, new GpuVertexBuffer()); + } + } +} + +void RenderObject::DeleteGLObjects() { + if (mVao != GL_NONE) { + glDeleteVertexArrays(1, &mVao); + mVao = GL_NONE; + } +} + +void Renderer::BeginFrame(Camera& camera, float currentTime, float deltaTime) { + assert(mInsideFrame == false); + mInsideFrame = true; + mFrame_Cam = &camera; + mFrame_Transform = camera.CalcProjectionMatrix() * camera.CalcViewMatrix(); + mFrame_Time = currentTime; + mFrame_DeltaTime = deltaTime; +} + +void Renderer::EndFrame() { + assert(mInsideFrame == true); + mInsideFrame = false; } -void Renderer::Draw(RenderObject& object) { - auto indexType = object.GetMesh()->indexBuf->indexType; +void Renderer::Draw(const RenderObject* objects, size_t count) { + using namespace Tags; + + assert(mInsideFrame); + + // TODO shader grouping + // TODO material grouping + for (size_t i = 0; i < count; ++i) { + auto& object = objects[i]; + auto indexBuffer = object.GetIndexBuffer(); + auto mat = object.GetMaterial(); + auto shader = mat->GetShader(); - glBindVertexArray(object.GetGLVao()); - glDrawElements(GL_TRIANGLES, 0, Tags::FindGLType(indexType), 0); + glUseProgram(shader->GetProgram()); + + // Autofill uniforms + if (shader->autofillLoc_Transform != kInvalidLocation) { + glUniformMatrix4fv(shader->autofillLoc_Transform, 1, GL_FALSE, &mFrame_Transform[0][0]); + } + if (shader->autofillLoc_Time != kInvalidLocation) { + glUniform1f(shader->autofillLoc_Time, mFrame_Time); + } + if (shader->autofillLoc_DeltaTime != kInvalidLocation) { + glUniform1f(shader->autofillLoc_DeltaTime, mFrame_DeltaTime); + } + + // Material uniforms + mat->UseUniforms(); + + glBindVertexArray(object.GetGLVao()); + glDrawElements(GL_TRIANGLES, indexBuffer->count, indexBuffer->GetIndexTypeGL(), 0); + } } |