Skip to content

Commit

Permalink
instanced rendering - render multiple instances
Browse files Browse the repository at this point in the history
  • Loading branch information
goopey7 committed Dec 27, 2023
1 parent 1d70f27 commit 08f9312
Show file tree
Hide file tree
Showing 8 changed files with 54 additions and 24 deletions.
10 changes: 7 additions & 3 deletions game/GameApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ void GameApp::init()

// TODO dynamically load and unload meshes and handle instances etc
scene->createEntity("Viking Room").addComponent<goop::MeshComponent>("res/viking_room.obj");
scene->createEntity("Viking Room1").addComponent<goop::MeshComponent>("res/viking_room.obj");
glm::mat4& transform =
scene->getEntity("Viking Room1").getComponent<goop::TransformComponent>().transform;
transform = glm::translate(transform, glm::vec3(0.0f, -2.0f, -2.0f));
scene->createEntity("Cow").addComponent<goop::MeshComponent>("res/cow.obj");

/* TODO -------------
Expand All @@ -32,8 +36,8 @@ void GameApp::init()

void GameApp::update(float dt)
{
glm::mat4& transform =
scene->getEntity("Viking Room").getComponent<goop::TransformComponent>().transform;
//glm::mat4& transform =
// scene->getEntity("Viking Room").getComponent<goop::TransformComponent>().transform;

transform = glm::rotate(transform, dt, glm::vec3(0.0f, 1.0f, 0.0f));
//transform = glm::rotate(transform, dt, glm::vec3(0.0f, 1.0f, 0.0f));
}
5 changes: 3 additions & 2 deletions goop/Core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ Core::Core(int argc, char** argv) : app(createGame(argc, argv, &scene))
sys::gWindow->initialize();
sys::gWindow->openWindow(1280, 720, "Goop", GOOP_WINDOW_DEFAULT);
sys::gRenderer->initialize();
sys::gRenderer->setScene(&scene);
rm->initialize();
app->init();

Expand Down Expand Up @@ -59,7 +60,7 @@ void Core::run()

#ifdef GOOP_APPTYPE_EDITOR
ImVec2 viewportSize = app->getViewportSize();
sys::gRenderer->render(&scene, viewportSize.x, viewportSize.y);
sys::gRenderer->render(viewportSize.x, viewportSize.y);
#endif
app->gui();

Expand All @@ -80,7 +81,7 @@ void Core::run()
}

#ifndef GOOP_APPTYPE_EDITOR
sys::gRenderer->render(&scene);
sys::gRenderer->render();
#endif

sys::gRenderer->endFrame();
Expand Down
6 changes: 4 additions & 2 deletions goop/sys/Renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,17 @@ class Renderer : public Subsystem
virtual void beginFrame() = 0;
virtual void endFrame() = 0;
#ifdef GOOP_APPTYPE_EDITOR
virtual void render(Scene* scene, float width = -1.f, float height = -1.f) = 0;
virtual void render(float width = -1.f, float height = -1.f) = 0;
#else
virtual void render(Scene* scene) = 0;
virtual void render() = 0;
#endif
virtual void addToRenderQueue(uint32_t mesh, MeshLoader* meshLoader);
bool isMeshQueueEmpty() const { return meshQueue.empty(); }

virtual ImTextureID getViewTexture() const = 0;

void setScene(Scene* scene) { this->scene = scene; }

protected:
std::queue<uint32_t> meshQueue;
MeshLoader* meshLoader;
Expand Down
7 changes: 7 additions & 0 deletions goop/sys/ResourceManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,14 @@ int ResourceManager::initialize()

bool ResourceManager::loadMesh(MeshComponent& mesh)
{
if (loadedMeshes[mesh.path] != 0)
{
std::cout << "Mesh " << mesh.path << " already loaded" << std::endl;
mesh.id = loadedMeshes[mesh.path];
return true;
}
mesh.id = meshLoader->load(mesh.path);
loadedMeshes[mesh.path] = mesh.id;
std::cout << "Loaded mesh " << mesh.path << " with id " << mesh.id << std::endl;
return true;
}
Expand Down
2 changes: 2 additions & 0 deletions goop/sys/ResourceManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <goop/sys/MeshLoader.h>
#include <goop/sys/Subsystem.h>
#include <goop/Components.h>
#include <map>
#include <string>

namespace goop::sys
Expand All @@ -26,5 +27,6 @@ class ResourceManager : public Subsystem
private:
std::unique_ptr<MeshLoader> meshLoader;
std::unique_ptr<Sfx> sfx;
std::map<std::string, uint32_t> loadedMeshes;
};
} // namespace goop::sys
7 changes: 4 additions & 3 deletions goop/sys/platform/vulkan/Buffers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,11 +121,12 @@ void Buffers::updateBuffers(uint32_t currentFrame, const Vertex* vertices, uint3
{
createVertexBuffer(currentFrame, vertices, vertexCount);
std::vector<Instance> instancesToRender;
for (auto& [index, instances] : *instances)
for (int i = 0; i < instances->size(); i++)
{
instanceOffsets[currentFrame].push_back(instancesToRender.size());
instancesToRender.insert(instancesToRender.end(), instances.begin(), instances.end());
instanceCounts[currentFrame].push_back(instances.size());
instancesToRender.insert(instancesToRender.end(), instances->at(i).begin(),
instances->at(i).end());
instanceCounts[currentFrame].push_back(instances->at(i).size());
}
createInstanceBuffer(currentFrame, instancesToRender.data(), instancesToRender.size());
createIndexBuffer(currentFrame, indices, indexCount);
Expand Down
37 changes: 25 additions & 12 deletions goop/sys/platform/vulkan/Renderer_Vulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,7 @@ void Renderer_Vulkan::updateUniformBuffer(Scene* scene, uint32_t currentFrame)
{
UniformBufferObject ubo{};

TransformComponent& transform =
scene->getEntity("Viking Room").getComponent<goop::TransformComponent>();

ubo.model = transform.transform;
ubo.model = glm::mat4(1.f);

ubo.view =
glm::lookAt(glm::vec3(2.f, 2.f, 2.f), glm::vec3(0.f, 0.f, 0.f), glm::vec3(0.f, 1.f, 0.f));
Expand Down Expand Up @@ -162,7 +159,7 @@ void Renderer_Vulkan::addToRenderQueue(uint32_t mesh, MeshLoader* meshLoader)

void Renderer_Vulkan::updateBuffers()
{
if (meshLoader != nullptr)
if (meshLoader != nullptr && scene != nullptr)
{
oldQueue = meshQueue;
std::vector<Vertex> vertices;
Expand All @@ -173,6 +170,14 @@ void Renderer_Vulkan::updateBuffers()

std::map<uint32_t, uint32_t> instanceCounts;

std::vector<Entity> entitiesToRender;
auto view = scene->view<MeshComponent>();

for (auto entity : view)
{
entitiesToRender.push_back(goop::Entity(entity, scene));
}

while (!meshQueue.empty())
{
uint32_t id = meshQueue.front();
Expand All @@ -193,7 +198,12 @@ void Renderer_Vulkan::updateBuffers()
indexCounts.push_back(mesh.indices.size());
}

instances[id].push_back({glm::mat4(1.f)});
// find an entity to render who has the corresponding mesh ID
auto entity =
std::find_if(entitiesToRender.begin(), entitiesToRender.end(),
[id](Entity& e) { return e.getComponent<MeshComponent>().id == id; });
instances[id].push_back({entity->getComponent<TransformComponent>().transform});
entitiesToRender.erase(entity);

meshQueue.pop();
}
Expand Down Expand Up @@ -225,7 +235,7 @@ void Renderer_Vulkan::recreateSwapchain()
}

#ifndef GOOP_APPTYPE_EDITOR
void Renderer_Vulkan::render(Scene* scene)
void Renderer_Vulkan::render()
{
vkDeviceWaitIdle(*ctx);
buffers->swapBuffers(currentFrame);
Expand Down Expand Up @@ -367,12 +377,15 @@ void Renderer_Vulkan::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_
buffers->getIndexBuffer(currentFrame) != nullptr)
{
// for each different instance, render all instances of that mesh
size_t uniqueInstances = buffers->getNumUniqueInstances(currentFrame);
for (size_t i = 0; i < buffers->getNumUniqueInstances(currentFrame); i++)
{
vkCmdDrawIndexed(commandBuffer, buffers->getIndexCount(currentFrame, i),
buffers->getInstanceCount(currentFrame, i),
buffers->getIndexOffset(currentFrame, i), 0,
buffers->getInstanceOffsets(currentFrame, i));
int instanceCount = buffers->getInstanceCount(currentFrame, i);
int instanceOffset = buffers->getInstanceOffsets(currentFrame, i);
int indexCount = buffers->getIndexCount(currentFrame, i);
int indexOffset = buffers->getIndexOffset(currentFrame, i);
vkCmdDrawIndexed(commandBuffer, indexCount, instanceCount, indexOffset, 0,
instanceOffset);
}
}

Expand Down Expand Up @@ -528,7 +541,7 @@ void Renderer_Vulkan::renderFrame(uint32_t imageIndex)
updateBuffers();
}

void Renderer_Vulkan::render(Scene* scene, float width, float height)
void Renderer_Vulkan::render(float width, float height)
{
// wait for the fence to signal that the frame is finished
sync->waitForFrame(currentFrame);
Expand Down
4 changes: 2 additions & 2 deletions goop/sys/platform/vulkan/Renderer_Vulkan.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ class Renderer_Vulkan : public Renderer
// Renderer interface
void beginFrame() final;
#ifdef GOOP_APPTYPE_EDITOR
void render(Scene* scene, float width = -1.f, float height = -1.f) final;
void render(float width = -1.f, float height = -1.f) final;
#else
void render(Scene* scene) final;
void render() final;
#endif
void endFrame() final;
void addToRenderQueue(uint32_t mesh, MeshLoader* meshLoader) final;
Expand Down

0 comments on commit 08f9312

Please sign in to comment.