mirror of
https://github.com/luanti-org/luanti.git
synced 2025-09-15 18:57:08 +00:00
Implement support for FSAA in combination with post-processing (#15392)
- Actually it's MSAA I think, or perhaps the terms are equivalent - I've made it fit into the existing Irrlicht architecture, but that has resulted in code duplication compared to my original "hacky" approach - OpenGL 3.2+ and OpenGL ES 3.1+ are supported - EDT_OPENGL3 is not required, EDT_OPENGL works too - Helpful tutorial: https://learnopengl.com/Advanced-OpenGL/Anti-Aliasing, section "Off-screen MSAA" - This may be rough around the edges, but in general it works
This commit is contained in:
parent
a8ea165042
commit
9b6a399011
23 changed files with 290 additions and 42 deletions
|
@ -26,7 +26,7 @@ video::ITexture *TextureBuffer::getTexture(u8 index)
|
|||
}
|
||||
|
||||
|
||||
void TextureBuffer::setTexture(u8 index, core::dimension2du size, const std::string &name, video::ECOLOR_FORMAT format, bool clear)
|
||||
void TextureBuffer::setTexture(u8 index, core::dimension2du size, const std::string &name, video::ECOLOR_FORMAT format, bool clear, u8 msaa)
|
||||
{
|
||||
assert(index != NO_DEPTH_TEXTURE);
|
||||
|
||||
|
@ -41,9 +41,10 @@ void TextureBuffer::setTexture(u8 index, core::dimension2du size, const std::str
|
|||
definition.name = name;
|
||||
definition.format = format;
|
||||
definition.clear = clear;
|
||||
definition.msaa = msaa;
|
||||
}
|
||||
|
||||
void TextureBuffer::setTexture(u8 index, v2f scale_factor, const std::string &name, video::ECOLOR_FORMAT format, bool clear)
|
||||
void TextureBuffer::setTexture(u8 index, v2f scale_factor, const std::string &name, video::ECOLOR_FORMAT format, bool clear, u8 msaa)
|
||||
{
|
||||
assert(index != NO_DEPTH_TEXTURE);
|
||||
|
||||
|
@ -58,6 +59,7 @@ void TextureBuffer::setTexture(u8 index, v2f scale_factor, const std::string &na
|
|||
definition.name = name;
|
||||
definition.format = format;
|
||||
definition.clear = clear;
|
||||
definition.msaa = msaa;
|
||||
}
|
||||
|
||||
void TextureBuffer::reset(PipelineContext &context)
|
||||
|
@ -125,13 +127,19 @@ bool TextureBuffer::ensureTexture(video::ITexture **texture, const TextureDefini
|
|||
|
||||
if (definition.valid) {
|
||||
if (definition.clear) {
|
||||
// We're not able to clear a render target texture
|
||||
// We're not able to create a normal texture with MSAA
|
||||
// (could be solved by more refactoring in Irrlicht, but not needed for now)
|
||||
sanity_check(definition.msaa < 1);
|
||||
|
||||
video::IImage *image = m_driver->createImage(definition.format, size);
|
||||
// Cannot use image->fill because it's not implemented for all formats.
|
||||
std::memset(image->getData(), 0, image->getDataSizeFromFormat(definition.format, size.Width, size.Height));
|
||||
*texture = m_driver->addTexture(definition.name.c_str(), image);
|
||||
image->drop();
|
||||
}
|
||||
else {
|
||||
} else if (definition.msaa > 0) {
|
||||
*texture = m_driver->addRenderTargetTextureMs(size, definition.msaa, definition.name.c_str(), definition.format);
|
||||
} else {
|
||||
*texture = m_driver->addRenderTargetTexture(size, definition.name.c_str(), definition.format);
|
||||
}
|
||||
}
|
||||
|
@ -189,6 +197,12 @@ void TextureBufferOutput::activate(PipelineContext &context)
|
|||
RenderTarget::activate(context);
|
||||
}
|
||||
|
||||
video::IRenderTarget *TextureBufferOutput::getIrrRenderTarget(PipelineContext &context)
|
||||
{
|
||||
activate(context); // Needed to make sure that render_target is set up.
|
||||
return render_target;
|
||||
}
|
||||
|
||||
u8 DynamicSource::getTextureCount()
|
||||
{
|
||||
assert(isConfigured());
|
||||
|
|
|
@ -117,7 +117,7 @@ public:
|
|||
* @param name unique name of the texture
|
||||
* @param format color format
|
||||
*/
|
||||
void setTexture(u8 index, core::dimension2du size, const std::string& name, video::ECOLOR_FORMAT format, bool clear = false);
|
||||
void setTexture(u8 index, core::dimension2du size, const std::string& name, video::ECOLOR_FORMAT format, bool clear = false, u8 msaa = 0);
|
||||
|
||||
/**
|
||||
* Configure relative-size texture for the specific index
|
||||
|
@ -127,7 +127,7 @@ public:
|
|||
* @param name unique name of the texture
|
||||
* @param format color format
|
||||
*/
|
||||
void setTexture(u8 index, v2f scale_factor, const std::string& name, video::ECOLOR_FORMAT format, bool clear = false);
|
||||
void setTexture(u8 index, v2f scale_factor, const std::string& name, video::ECOLOR_FORMAT format, bool clear = false, u8 msaa = 0);
|
||||
|
||||
virtual u8 getTextureCount() override { return m_textures.size(); }
|
||||
virtual video::ITexture *getTexture(u8 index) override;
|
||||
|
@ -146,6 +146,7 @@ private:
|
|||
core::dimension2du size;
|
||||
std::string name;
|
||||
video::ECOLOR_FORMAT format;
|
||||
u8 msaa;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -174,6 +175,9 @@ public:
|
|||
TextureBufferOutput(TextureBuffer *buffer, const std::vector<u8> &texture_map, u8 depth_stencil);
|
||||
virtual ~TextureBufferOutput() override;
|
||||
void activate(PipelineContext &context) override;
|
||||
|
||||
video::IRenderTarget *getIrrRenderTarget(PipelineContext &context);
|
||||
|
||||
private:
|
||||
static const u8 NO_DEPTH_TEXTURE = 255;
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "client/shader.h"
|
||||
#include "client/tile.h"
|
||||
#include "settings.h"
|
||||
#include "mt_opengl.h"
|
||||
|
||||
PostProcessingStep::PostProcessingStep(u32 _shader_id, const std::vector<u8> &_texture_map) :
|
||||
shader_id(_shader_id), texture_map(_texture_map)
|
||||
|
@ -102,21 +103,45 @@ RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep
|
|||
static const u8 TEXTURE_EXPOSURE_2 = 4;
|
||||
static const u8 TEXTURE_FXAA = 5;
|
||||
static const u8 TEXTURE_VOLUME = 6;
|
||||
|
||||
static const u8 TEXTURE_MSAA_COLOR = 7;
|
||||
static const u8 TEXTURE_MSAA_DEPTH = 8;
|
||||
|
||||
static const u8 TEXTURE_SCALE_DOWN = 10;
|
||||
static const u8 TEXTURE_SCALE_UP = 20;
|
||||
|
||||
// Super-sampling is simply rendering into a larger texture.
|
||||
// Downscaling is done by the final step when rendering to the screen.
|
||||
const std::string antialiasing = g_settings->get("antialiasing");
|
||||
const bool enable_bloom = g_settings->getBool("enable_bloom");
|
||||
const bool enable_volumetric_light = g_settings->getBool("enable_volumetric_lighting") && enable_bloom;
|
||||
const bool enable_auto_exposure = g_settings->getBool("enable_auto_exposure");
|
||||
|
||||
const std::string antialiasing = g_settings->get("antialiasing");
|
||||
const u16 antialiasing_scale = MYMAX(2, g_settings->getU16("fsaa"));
|
||||
|
||||
// This code only deals with MSAA in combination with post-processing. MSAA without
|
||||
// post-processing works via a flag at OpenGL context creation instead.
|
||||
// To make MSAA work with post-processing, we need multisample texture support,
|
||||
// which has higher OpenGL (ES) version requirements.
|
||||
// Note: This is not about renderbuffer objects, but about textures,
|
||||
// since that's what we use and what Irrlicht allows us to use.
|
||||
|
||||
const bool msaa_available = driver->queryFeature(video::EVDF_TEXTURE_MULTISAMPLE);
|
||||
const bool enable_msaa = antialiasing == "fsaa" && msaa_available;
|
||||
if (antialiasing == "fsaa" && !msaa_available)
|
||||
warningstream << "Ignoring configured FSAA. FSAA is not supported in "
|
||||
<< "combination with post-processing by the current video driver." << std::endl;
|
||||
|
||||
const bool enable_ssaa = antialiasing == "ssaa";
|
||||
const bool enable_fxaa = antialiasing == "fxaa";
|
||||
const bool enable_volumetric_light = g_settings->getBool("enable_volumetric_lighting") && enable_bloom;
|
||||
|
||||
// Super-sampling is simply rendering into a larger texture.
|
||||
// Downscaling is done by the final step when rendering to the screen.
|
||||
if (enable_ssaa) {
|
||||
u16 ssaa_scale = MYMAX(2, g_settings->getU16("fsaa"));
|
||||
scale *= ssaa_scale;
|
||||
scale *= antialiasing_scale;
|
||||
}
|
||||
|
||||
if (enable_msaa) {
|
||||
buffer->setTexture(TEXTURE_MSAA_COLOR, scale, "3d_render_msaa", color_format, false, antialiasing_scale);
|
||||
buffer->setTexture(TEXTURE_MSAA_DEPTH, scale, "3d_depthmap_msaa", depth_format, false, antialiasing_scale);
|
||||
}
|
||||
|
||||
buffer->setTexture(TEXTURE_COLOR, scale, "3d_render", color_format);
|
||||
|
@ -125,7 +150,14 @@ RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep
|
|||
buffer->setTexture(TEXTURE_DEPTH, scale, "3d_depthmap", depth_format);
|
||||
|
||||
// attach buffer to the previous step
|
||||
previousStep->setRenderTarget(pipeline->createOwned<TextureBufferOutput>(buffer, std::vector<u8> { TEXTURE_COLOR }, TEXTURE_DEPTH));
|
||||
if (enable_msaa) {
|
||||
TextureBufferOutput *msaa = pipeline->createOwned<TextureBufferOutput>(buffer, std::vector<u8> { TEXTURE_MSAA_COLOR }, TEXTURE_MSAA_DEPTH);
|
||||
previousStep->setRenderTarget(msaa);
|
||||
TextureBufferOutput *normal = pipeline->createOwned<TextureBufferOutput>(buffer, std::vector<u8> { TEXTURE_COLOR }, TEXTURE_DEPTH);
|
||||
pipeline->addStep<ResolveMSAAStep>(msaa, normal);
|
||||
} else {
|
||||
previousStep->setRenderTarget(pipeline->createOwned<TextureBufferOutput>(buffer, std::vector<u8> { TEXTURE_COLOR }, TEXTURE_DEPTH));
|
||||
}
|
||||
|
||||
// shared variables
|
||||
u32 shader_id;
|
||||
|
@ -234,3 +266,9 @@ RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep
|
|||
|
||||
return effect;
|
||||
}
|
||||
|
||||
void ResolveMSAAStep::run(PipelineContext &context)
|
||||
{
|
||||
context.device->getVideoDriver()->blitRenderTarget(msaa_fbo->getIrrRenderTarget(context),
|
||||
target_fbo->getIrrRenderTarget(context));
|
||||
}
|
||||
|
|
|
@ -44,4 +44,18 @@ private:
|
|||
void configureMaterial();
|
||||
};
|
||||
|
||||
|
||||
class ResolveMSAAStep : public TrivialRenderStep
|
||||
{
|
||||
public:
|
||||
ResolveMSAAStep(TextureBufferOutput *_msaa_fbo, TextureBufferOutput *_target_fbo) :
|
||||
msaa_fbo(_msaa_fbo), target_fbo(_target_fbo) {};
|
||||
void run(PipelineContext &context) override;
|
||||
|
||||
private:
|
||||
TextureBufferOutput *msaa_fbo;
|
||||
TextureBufferOutput *target_fbo;
|
||||
};
|
||||
|
||||
|
||||
RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep, v2f scale, Client *client);
|
||||
|
|
|
@ -179,7 +179,10 @@ RenderingEngine::RenderingEngine(MyEventReceiver *receiver)
|
|||
|
||||
// bpp, fsaa, vsync
|
||||
bool vsync = g_settings->getBool("vsync");
|
||||
bool enable_fsaa = g_settings->get("antialiasing") == "fsaa";
|
||||
// Don't enable MSAA in OpenGL context creation if post-processing is enabled,
|
||||
// the post-processing pipeline handles it.
|
||||
bool enable_fsaa = g_settings->get("antialiasing") == "fsaa" &&
|
||||
!g_settings->getBool("enable_post_processing");
|
||||
u16 fsaa = enable_fsaa ? MYMAX(2, g_settings->getU16("fsaa")) : 0;
|
||||
|
||||
// Determine driver
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue