mirror of
https://github.com/luanti-org/luanti.git
synced 2025-09-15 18:57:08 +00:00
Improve bloom effect (#12916)
* Remove the built-in exposure factor of 2.5 * Add physics-based bloom (https://learnopengl.com/Guest-Articles/2022/Phys.-Based-Bloom) * Add luminance scaling for bloom layer to simulate HDR * Add setting to control bloom strength
This commit is contained in:
parent
fb3085a2c5
commit
9b24041394
15 changed files with 195 additions and 59 deletions
|
@ -432,6 +432,8 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter
|
|||
bool m_bloom_enabled;
|
||||
CachedPixelShaderSetting<float> m_bloom_intensity_pixel;
|
||||
float m_bloom_intensity;
|
||||
CachedPixelShaderSetting<float> m_bloom_strength_pixel;
|
||||
float m_bloom_strength;
|
||||
CachedPixelShaderSetting<float> m_bloom_radius_pixel;
|
||||
float m_bloom_radius;
|
||||
|
||||
|
@ -444,8 +446,10 @@ public:
|
|||
m_user_exposure_factor = g_settings->getFloat("exposure_factor", 0.1f, 10.0f);
|
||||
if (name == "bloom_intensity")
|
||||
m_bloom_intensity = g_settings->getFloat("bloom_intensity", 0.01f, 1.0f);
|
||||
if (name == "bloom_strength_factor")
|
||||
m_bloom_strength = RenderingEngine::BASE_BLOOM_STRENGTH * g_settings->getFloat("bloom_strength_factor", 0.1f, 10.0f);
|
||||
if (name == "bloom_radius")
|
||||
m_bloom_radius = g_settings->getFloat("bloom_radius", 1.0f, 64.0f);
|
||||
m_bloom_radius = g_settings->getFloat("bloom_radius", 0.1f, 8.0f);
|
||||
}
|
||||
|
||||
static void settingsCallback(const std::string &name, void *userdata)
|
||||
|
@ -479,17 +483,20 @@ public:
|
|||
m_texel_size0("texelSize0"),
|
||||
m_exposure_factor_pixel("exposureFactor"),
|
||||
m_bloom_intensity_pixel("bloomIntensity"),
|
||||
m_bloom_strength_pixel("bloomStrength"),
|
||||
m_bloom_radius_pixel("bloomRadius")
|
||||
{
|
||||
g_settings->registerChangedCallback("enable_fog", settingsCallback, this);
|
||||
g_settings->registerChangedCallback("exposure_factor", settingsCallback, this);
|
||||
g_settings->registerChangedCallback("bloom_intensity", settingsCallback, this);
|
||||
g_settings->registerChangedCallback("bloom_strength_factor", settingsCallback, this);
|
||||
g_settings->registerChangedCallback("bloom_radius", settingsCallback, this);
|
||||
m_fog_enabled = g_settings->getBool("enable_fog");
|
||||
m_user_exposure_factor = g_settings->getFloat("exposure_factor", 0.1f, 10.0f);
|
||||
m_bloom_enabled = g_settings->getBool("enable_bloom");
|
||||
m_bloom_intensity = g_settings->getFloat("bloom_intensity", 0.01f, 1.0f);
|
||||
m_bloom_radius = g_settings->getFloat("bloom_radius", 1.0f, 64.0f);
|
||||
m_bloom_strength = RenderingEngine::BASE_BLOOM_STRENGTH * g_settings->getFloat("bloom_strength_factor", 0.1f, 10.0f);
|
||||
m_bloom_radius = g_settings->getFloat("bloom_radius", 0.1f, 8.0f);
|
||||
}
|
||||
|
||||
~GameGlobalShaderConstantSetter()
|
||||
|
@ -567,14 +574,15 @@ public:
|
|||
|
||||
m_texel_size0.set(m_texel_size0_values.data(), services);
|
||||
|
||||
float exposure_factor = RenderingEngine::DEFAULT_EXPOSURE_FACTOR * m_user_exposure_factor;
|
||||
float exposure_factor = m_user_exposure_factor;
|
||||
if (std::isnan(exposure_factor))
|
||||
exposure_factor = RenderingEngine::DEFAULT_EXPOSURE_FACTOR;
|
||||
exposure_factor = 1.0f;
|
||||
m_exposure_factor_pixel.set(&exposure_factor, services);
|
||||
|
||||
if (m_bloom_enabled) {
|
||||
m_bloom_intensity_pixel.set(&m_bloom_intensity, services);
|
||||
m_bloom_radius_pixel.set(&m_bloom_radius, services);
|
||||
m_bloom_strength_pixel.set(&m_bloom_strength, services);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -390,9 +390,10 @@ public:
|
|||
* @return RenderStep* Pointer to the created step for further configuration.
|
||||
*/
|
||||
template<typename T, typename... Args>
|
||||
RenderStep *addStep(Args&&... args) {
|
||||
T *addStep(Args&&... args) {
|
||||
T* result = own(std::make_unique<T>(std::forward<Args>(args)...));
|
||||
return addStep(result);
|
||||
addStep(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
RenderSource *getInput();
|
||||
|
|
|
@ -115,8 +115,8 @@ RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep
|
|||
static const u8 TEXTURE_COLOR = 0;
|
||||
static const u8 TEXTURE_DEPTH = 1;
|
||||
static const u8 TEXTURE_BLOOM = 2;
|
||||
static const u8 TEXTURE_BLUR = 3;
|
||||
static const u8 TEXTURE_BLUR_SECONDARY = 4;
|
||||
static const u8 TEXTURE_BLOOM_DOWN = 10;
|
||||
static const u8 TEXTURE_BLOOM_UP = 20;
|
||||
|
||||
buffer->setTexture(TEXTURE_COLOR, scale, "3d_render", color_format);
|
||||
buffer->setTexture(TEXTURE_DEPTH, scale, "3d_depthmap", depth_format);
|
||||
|
@ -124,39 +124,56 @@ RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep
|
|||
// attach buffer to the previous step
|
||||
previousStep->setRenderTarget(pipeline->createOwned<TextureBufferOutput>(buffer, std::vector<u8> { TEXTURE_COLOR }, TEXTURE_DEPTH));
|
||||
|
||||
// shared variables
|
||||
u32 shader_id;
|
||||
|
||||
// post-processing stage
|
||||
// set up bloom
|
||||
if (g_settings->getBool("enable_bloom")) {
|
||||
|
||||
buffer->setTexture(TEXTURE_BLUR, scale * 0.5, "blur", color_format);
|
||||
buffer->setTexture(TEXTURE_BLOOM, scale * 0.5, "bloom", color_format);
|
||||
u8 bloom_input_texture = TEXTURE_BLOOM;
|
||||
|
||||
if (g_settings->getBool("enable_bloom_dedicated_texture")) {
|
||||
buffer->setTexture(TEXTURE_BLUR_SECONDARY, scale * 0.5, "blur2", color_format);
|
||||
bloom_input_texture = TEXTURE_BLUR_SECONDARY;
|
||||
|
||||
buffer->setTexture(TEXTURE_BLOOM, scale, "bloom", color_format);
|
||||
|
||||
const u8 MIPMAP_LEVELS = 4;
|
||||
v2f downscale = scale * 0.5;
|
||||
for (u8 i = 0; i < MIPMAP_LEVELS; i++) {
|
||||
buffer->setTexture(TEXTURE_BLOOM_DOWN + i, downscale, std::string("bloom_down") + std::to_string(i), color_format);
|
||||
buffer->setTexture(TEXTURE_BLOOM_UP + i, downscale, std::string("bloom_up") + std::to_string(i), color_format);
|
||||
downscale *= 0.5;
|
||||
}
|
||||
|
||||
// get bright spots
|
||||
u32 shader_id = client->getShaderSource()->getShader("extract_bloom", TILE_MATERIAL_PLAIN, NDT_MESH);
|
||||
RenderStep *extract_bloom = pipeline->addStep<PostProcessingStep>(shader_id, std::vector<u8> { TEXTURE_COLOR });
|
||||
extract_bloom->setRenderSource(buffer);
|
||||
extract_bloom->setRenderTarget(pipeline->createOwned<TextureBufferOutput>(buffer, bloom_input_texture));
|
||||
// horizontal blur
|
||||
shader_id = client->getShaderSource()->getShader("blur_h", TILE_MATERIAL_PLAIN, NDT_MESH);
|
||||
RenderStep *blur_h = pipeline->addStep<PostProcessingStep>(shader_id, std::vector<u8> { bloom_input_texture });
|
||||
blur_h->setRenderSource(buffer);
|
||||
blur_h->setRenderTarget(pipeline->createOwned<TextureBufferOutput>(buffer, TEXTURE_BLUR));
|
||||
// vertical blur
|
||||
shader_id = client->getShaderSource()->getShader("blur_v", TILE_MATERIAL_PLAIN, NDT_MESH);
|
||||
RenderStep *blur_v = pipeline->addStep<PostProcessingStep>(shader_id, std::vector<u8> { TEXTURE_BLUR });
|
||||
blur_v->setRenderSource(buffer);
|
||||
blur_v->setRenderTarget(pipeline->createOwned<TextureBufferOutput>(buffer, TEXTURE_BLOOM));
|
||||
extract_bloom->setRenderTarget(pipeline->createOwned<TextureBufferOutput>(buffer, TEXTURE_BLOOM));
|
||||
|
||||
// downsample
|
||||
shader_id = client->getShaderSource()->getShader("bloom_downsample", TILE_MATERIAL_PLAIN, NDT_MESH);
|
||||
u8 source = TEXTURE_BLOOM;
|
||||
for (u8 i = 0; i < MIPMAP_LEVELS; i++) {
|
||||
auto step = pipeline->addStep<PostProcessingStep>(shader_id, std::vector<u8> { source });
|
||||
step->setRenderSource(buffer);
|
||||
step->setBilinearFilter(0, true);
|
||||
step->setRenderTarget(pipeline->createOwned<TextureBufferOutput>(buffer, TEXTURE_BLOOM_DOWN + i));
|
||||
source = TEXTURE_BLOOM_DOWN + i;
|
||||
}
|
||||
|
||||
// upsample
|
||||
shader_id = client->getShaderSource()->getShader("bloom_upsample", TILE_MATERIAL_PLAIN, NDT_MESH);
|
||||
for (u8 i = MIPMAP_LEVELS - 1; i > 0; i--) {
|
||||
auto step = pipeline->addStep<PostProcessingStep>(shader_id, std::vector<u8> { u8(TEXTURE_BLOOM_DOWN + i - 1), source });
|
||||
step->setRenderSource(buffer);
|
||||
step->setBilinearFilter(0, true);
|
||||
step->setBilinearFilter(1, true);
|
||||
step->setRenderTarget(pipeline->createOwned<TextureBufferOutput>(buffer, u8(TEXTURE_BLOOM_UP + i - 1)));
|
||||
source = TEXTURE_BLOOM_UP + i - 1;
|
||||
}
|
||||
}
|
||||
|
||||
// final post-processing
|
||||
u32 shader_id = client->getShaderSource()->getShader("second_stage", TILE_MATERIAL_PLAIN, NDT_MESH);
|
||||
PostProcessingStep *effect = pipeline->createOwned<PostProcessingStep>(shader_id, std::vector<u8> { TEXTURE_COLOR, TEXTURE_BLOOM });
|
||||
shader_id = client->getShaderSource()->getShader("second_stage", TILE_MATERIAL_PLAIN, NDT_MESH);
|
||||
PostProcessingStep *effect = pipeline->createOwned<PostProcessingStep>(shader_id, std::vector<u8> { TEXTURE_COLOR, TEXTURE_BLOOM_UP });
|
||||
pipeline->addStep(effect);
|
||||
effect->setBilinearFilter(1, true); // apply filter to the bloom
|
||||
effect->setRenderSource(buffer);
|
||||
|
|
|
@ -56,6 +56,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#endif
|
||||
|
||||
RenderingEngine *RenderingEngine::s_singleton = nullptr;
|
||||
const float RenderingEngine::BASE_BLOOM_STRENGTH = 8.0f;
|
||||
|
||||
|
||||
static gui::GUISkin *createSkin(gui::IGUIEnvironment *environment,
|
||||
|
|
|
@ -46,9 +46,7 @@ class RenderingCore;
|
|||
class RenderingEngine
|
||||
{
|
||||
public:
|
||||
/// Default color factor before applying effects like bloom or tomemapping
|
||||
/// this is derived from tonemapping code and tuned empirically
|
||||
static constexpr float DEFAULT_EXPOSURE_FACTOR = 2.5f;
|
||||
static const float BASE_BLOOM_STRENGTH;
|
||||
|
||||
RenderingEngine(IEventReceiver *eventReceiver);
|
||||
~RenderingEngine();
|
||||
|
|
|
@ -273,9 +273,9 @@ void set_default_settings()
|
|||
settings->setDefault("exposure_factor", "1.0");
|
||||
settings->setDefault("enable_bloom", "false");
|
||||
settings->setDefault("enable_bloom_debug", "false");
|
||||
settings->setDefault("enable_bloom_dedicated_texture", "false");
|
||||
settings->setDefault("bloom_strength_factor", "1.0");
|
||||
settings->setDefault("bloom_intensity", "0.05");
|
||||
settings->setDefault("bloom_radius", "16");
|
||||
settings->setDefault("bloom_radius", "1");
|
||||
|
||||
// Effects Shadows
|
||||
settings->setDefault("enable_dynamic_shadows", "false");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue