Files
fs2open.github.com/code/graphics/util/UniformBufferManager.cpp
T
asarium 0d188fe076 Use deferred shader for applying directional lights
This moves all lighting operations into the deferred shading phase of
the rendering pipeline. Previously, directional lights were applied to
all objects while they were being rendered. This was probably done to
avoid doing multiple full screen passes later but caused some problems
since the color information in the G-buffers was not correct for doing
later lighting operations.

This was especially noticable in dark scenes where point lights would
appear to ignore the color of the rendered objects. This should be fixed
with these changes.

I did some performance testing and to my surprise this actually improves
performance in very demanding scenes. My guess would be that applying
the shadows while rendering the objects caused a lot of overdraw which
is not the case anymore since shadows are only computed for visible
pixels. In simple scenes the opposite happens which leads to decreased
performance in those cases but in my opinion the improvement in
demanding scenes outweights this performance decrease.
2018-02-25 12:43:45 +01:00

88 lines
2.2 KiB
C++

#include "UniformBufferManager.h"
#include "uniform_structs.h"
namespace {
size_t getElementSize(uniform_block_type type) {
switch (type) {
case uniform_block_type::Lights:
return sizeof(graphics::deferred_light_data);
case uniform_block_type::ModelData:
return sizeof(graphics::model_uniform_data);
case uniform_block_type::NanoVGData:
return sizeof(graphics::nanovg_draw_data);
case uniform_block_type::DecalInfo:
return sizeof(graphics::decal_info);
case uniform_block_type::NUM_BLOCK_TYPES:
default:
Assertion(false, "Invalid block type encountered!");
return 0;
}
}
size_t getHeaderSize(uniform_block_type type) {
switch (type) {
case uniform_block_type::Lights:
return sizeof(graphics::deferred_global_data);
case uniform_block_type::DecalInfo:
return sizeof(graphics::decal_globals);
case uniform_block_type::ModelData:
case uniform_block_type::NanoVGData:
return 0;
case uniform_block_type::NUM_BLOCK_TYPES:
default:
Assertion(false, "Invalid block type encountered!");
return 0;
}
}
}
namespace graphics {
namespace util {
UniformBufferManager::UniformBufferManager(uniform_block_type uniform_type) : _type(uniform_type) {
}
UniformBuffer* UniformBufferManager::getBuffer() {
if (!_retiredBuffers.empty()) {
// Reuse one of the free buffers
auto buffer = _retiredBuffers.back();
// Sanity check
Assertion(!buffer->isInUse(), "Retired buffer is in use!");
_retiredBuffers.pop_back();
_usedBuffers.push_back(buffer);
return buffer;
}
// No free buffers available, create a new one
std::unique_ptr<UniformBuffer> buffer(new UniformBuffer(getElementSize(_type), getHeaderSize(_type)));
auto ptr = buffer.get();
_buffers.push_back(std::move(buffer));
_usedBuffers.push_back(ptr);
return ptr;
}
void UniformBufferManager::retireBuffers() {
GR_DEBUG_SCOPE("Retiring buffers of buffer manager");
for (auto& buffer : _usedBuffers) {
if (!buffer->isInUse()) {
// This buffer will be retired soon so add it to the list before removing it from the used list
_retiredBuffers.push_back(buffer);
}
}
// Remove the buffers from the list
_usedBuffers.erase(std::remove_if(_usedBuffers.begin(), _usedBuffers.end(), [](UniformBuffer* buffer) {
return !buffer->isInUse();
}), _usedBuffers.end());
}
}
}