9#include <unordered_map>
12#include "spdlog/spdlog.h"
20 :
RenderPass(
device), _layerComposition(layerComposition), _scene(scene), _renderer(renderer)
27 _renderActions.push_back(renderAction);
31 void RenderPassForward::updateClears()
33 if (_renderActions.empty()) {
37 const auto* ra = _renderActions.front();
38 const auto* cameraComp = ra ? ra->camera :
nullptr;
39 const auto* camera = cameraComp ? cameraComp->camera() :
nullptr;
46 const bool clearColor = ra->clearColor;
47 const bool clearDepth = ra->clearDepth;
48 const bool clearStencil = ra->clearStencil;
51 const auto clear = camera->clearColor();
58 const float clearDepthValue = 1.0f;
65 const int clearStencilValue = 0;
75 spdlog::error(
"RenderPassForward parity violation: before() called twice without matching after()");
76 assert(!_beforeCalled &&
"RenderPassForward::before called while pass is already active");
79 _executeCalled =
false;
86 device()->setHdrPass(
true);
89 refreshCameraUseFlags();
91 if (!validateRenderActionOrder()) {
92 spdlog::error(
"RenderPassForward parity violation: invalid render action ordering");
93 assert(
false &&
"Invalid render action order");
98 for (
const auto* ra : _renderActions) {
99 if (ra && ra->firstCameraUse && _scene) {
100 _scene->fire(
"prerender", ra->camera);
105 void RenderPassForward::renderRenderAction(
RenderAction* renderAction,
const bool firstRenderAction)
107 (void)firstRenderAction;
108 if (!_beforeCalled) {
109 spdlog::error(
"RenderPassForward parity violation: renderRenderAction() called before before()");
110 assert(_beforeCalled &&
"Render action executed outside pass lifecycle");
112 if (!renderAction || !renderAction->
camera || !_renderer) {
117 auto* layer = renderAction->
layer;
124 _renderer->renderForwardLayer(camera, target, layer, renderAction->
transparent);
127 _scene->fire(
"postrender:layer", renderAction->
camera, layer, renderAction->
transparent);
133 if (!_beforeCalled) {
134 spdlog::error(
"RenderPassForward parity violation: execute() called before before()");
135 assert(_beforeCalled &&
"RenderPassForward::execute requires before()");
137 _executeCalled =
true;
139 for (
size_t i = 0; i < _renderActions.size(); ++i) {
140 auto* ra = _renderActions[i];
141 if (!ra || !_layerComposition || !_layerComposition->isEnabled(ra->layer, ra->transparent)) {
144 renderRenderAction(ra, i == 0);
150 if (!_beforeCalled) {
151 spdlog::error(
"RenderPassForward parity violation: after() called before before()");
152 assert(_beforeCalled &&
"RenderPassForward::after requires before()");
154 if (!_executeCalled) {
155 spdlog::error(
"RenderPassForward parity violation: after() called before execute()");
156 assert(_executeCalled &&
"RenderPassForward::after requires execute()");
159 for (
const auto* ra : _renderActions) {
160 if (ra && ra->lastCameraUse && _scene) {
161 _scene->fire(
"postrender", ra->camera);
167 device()->setHdrPass(
false);
170 _beforeCalled =
false;
171 _executeCalled =
false;
174 void RenderPassForward::refreshCameraUseFlags()
176 for (
size_t i = 0; i < _renderActions.size(); ++i) {
177 auto* ra = _renderActions[i];
178 if (!ra || !ra->camera) {
182 const auto* camera = ra->camera;
183 bool hasPreviousForCamera =
false;
184 bool hasNextForCamera =
false;
186 for (
size_t j = 0; j < i; ++j) {
187 if (_renderActions[j] && _renderActions[j]->camera == camera) {
188 hasPreviousForCamera =
true;
193 for (
size_t j = i + 1; j < _renderActions.size(); ++j) {
194 if (_renderActions[j] && _renderActions[j]->camera == camera) {
195 hasNextForCamera =
true;
200 ra->firstCameraUse = !hasPreviousForCamera;
201 ra->lastCameraUse = !hasNextForCamera;
205 bool RenderPassForward::validateRenderActionOrder()
const
207 std::unordered_map<const CameraComponent*, bool> activeCameraSpan;
209 for (
const auto* ra : _renderActions) {
210 if (!ra || !ra->camera || !ra->layer) {
214 const auto* camera = ra->camera;
215 const bool isActive = activeCameraSpan.contains(camera) && activeCameraSpan.at(camera);
217 if (ra->firstCameraUse && isActive) {
220 if (!ra->firstCameraUse && !isActive) {
224 if (ra->firstCameraUse) {
225 activeCameraSpan[camera] =
true;
228 if (ra->lastCameraUse) {
229 if (!activeCameraSpan.contains(camera) || !activeCameraSpan[camera]) {
232 activeCameraSpan[camera] =
false;
236 for (
const auto& [camera, active] : activeCameraSpan) {
EventHandler * fire(const std::string &name, Args &&... args)
void addRenderAction(RenderAction *renderAction)
RenderPassForward(const std::shared_ptr< GraphicsDevice > &device, LayerComposition *layerComposition, Scene *scene, Renderer *renderer)
void setClearColor(const Color *color=nullptr)
void setClearDepth(const float *depthValue=nullptr)
void setClearStencil(const int *stencilValue=nullptr)
std::shared_ptr< GraphicsDevice > device() const
RenderPass(const std::shared_ptr< GraphicsDevice > &device)
Container for the scene graph, lighting environment, fog, skybox, and layer composition.
std::shared_ptr< RenderTarget > renderTarget