mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-10 17:46:53 -10:00
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.
88 lines
2.2 KiB
C++
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());
|
|
}
|
|
|
|
}
|
|
}
|