// Copyright (c) 2023 Dominic Masters // // This software is released under the MIT License. // https://opensource.org/licenses/MIT #include "assert/assert.hpp" #include "RenderPipeline.hpp" #include "game/Game.hpp" #include "scene/Scene.hpp" #include "component/display/Camera.hpp" #include "component/display/IRenderableComponent.hpp" using namespace Dawn; RenderPipeline::RenderPipeline() { } void RenderPipeline::render( const std::shared_ptr game ) { assertNotNull(game, "Game cannot be null"); auto scene = game->getCurrentScene(); if(!scene) return; this->renderScene(game, scene); } void RenderPipeline::renderScene( const std::shared_ptr game, const std::shared_ptr scene ) { assertNotNull(game, "Game cannot be null"); assertNotNull(scene, "Scene cannot be null"); // TODO: Render Subscenes First // Get a list of all cameras in the scene auto cameras = scene->findComponents(); auto backBuffer = scene->getGame()->renderHost.getBackBufferRenderTarget(); std::shared_ptr backbufferCamera = nullptr; for(auto camera : cameras) { auto rt = camera->getRenderTarget(); // Is this camera the backbuffer camera? if(rt == backBuffer) { backbufferCamera = camera; continue; } // Render scene with this camera renderSceneCamera(game, scene, camera, rt); } if(backbufferCamera) { // Render the backbuffer camera renderSceneCamera(game, scene, backbufferCamera, backBuffer); } } void RenderPipeline::renderSceneCamera( const std::shared_ptr game, const std::shared_ptr scene, const std::shared_ptr camera, const std::shared_ptr renderTarget ) { assertNotNull(game, "Game cannot be null"); assertNotNull(scene, "Scene cannot be null"); assertNotNull(camera, "Camera cannot be null"); assertNotNull(renderTarget, "RenderTarget cannot be null"); struct RenderPassContext ctx = { game, scene, camera, renderTarget }; // Get list of renderables std::vector> renderPasses; auto renderables = scene->findComponents(); for(auto renderable : renderables) { auto rp = renderable->getPasses(ctx); renderPasses.insert(renderPasses.end(), rp.begin(), rp.end()); } auto rp = renderPasses[0]; rp->bind(); // TODO: Make clearing the buffers editable! renderTarget->bind(); renderTarget->clear( RENDER_TARGET_CLEAR_COLOR | RENDER_TARGET_CLEAR_DEPTH ); rp->bind(); for(auto renderPass : renderPasses) { renderPass->bind(); renderPass->setData(); renderPass->upload(); renderPass->draw(); } } RenderPipeline::~RenderPipeline() { }