Scale color output in the mobile renderer to provide HDR support

This commit is contained in:
Bastiaan Olij 2021-07-26 21:31:15 +10:00
parent 2d446771d6
commit d22163c657
18 changed files with 94 additions and 50 deletions

View file

@ -812,6 +812,7 @@ void EffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer, const Tone
tonemap.push_constant.exposure = p_settings.exposure;
tonemap.push_constant.white = p_settings.white;
tonemap.push_constant.auto_exposure_grey = p_settings.auto_exposure_grey;
tonemap.push_constant.luminance_multiplier = p_settings.luminance_multiplier;
tonemap.push_constant.use_color_correction = p_settings.use_color_correction;
@ -864,6 +865,7 @@ void EffectsRD::tonemapper(RD::DrawListID p_subpass_draw_list, RID p_source_colo
tonemap.push_constant.use_color_correction = p_settings.use_color_correction;
tonemap.push_constant.use_debanding = p_settings.use_debanding;
tonemap.push_constant.luminance_multiplier = p_settings.luminance_multiplier;
RD::get_singleton()->draw_list_bind_render_pipeline(p_subpass_draw_list, tonemap.pipelines[mode].get_render_pipeline(RD::INVALID_ID, p_dst_format_id, false, RD::get_singleton()->draw_list_get_current_pass()));
RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, _get_uniform_set_for_input(p_source_color), 0);

View file

@ -255,7 +255,7 @@ private:
float exposure; // 4 - 84
float white; // 4 - 88
float auto_exposure_grey; // 4 - 92
uint32_t pad2; // 4 - 96
float luminance_multiplier; // 4 - 96
float pixel_size[2]; // 8 - 104
uint32_t use_fxaa; // 4 - 108
@ -308,7 +308,7 @@ private:
float exposure_adjust;
float min_luminance;
float max_luminance;
float pad[1];
uint32_t pad1;
};
struct LuminanceReduceFragment {
@ -818,6 +818,7 @@ public:
bool use_auto_exposure = false;
float auto_exposure_grey = 0.5;
RID exposure_texture;
float luminance_multiplier = 1.0;
bool use_bcs = false;
float brightness = 1.0;

View file

@ -271,6 +271,12 @@ bool RenderForwardMobile::free(RID p_rid) {
/* Render functions */
float RenderForwardMobile::_render_buffers_get_luminance_multiplier() {
// On mobile renderer we need to multiply source colors by 2 due to using a UNORM buffer
// and multiplying by the output color during 3D rendering by 0.5
return 2.0;
}
RD::DataFormat RenderForwardMobile::_render_buffers_get_color_format() {
// Using 32bit buffers enables AFBC on mobile devices which should have a definite performance improvement (MALI G710 and newer support this on 64bit RTs)
return RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32;
@ -631,7 +637,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
RID sky_rid = env->sky;
if (sky_rid.is_valid()) {
sky.update(env, projection, p_render_data->cam_transform, time);
sky.update(env, projection, p_render_data->cam_transform, time, _render_buffers_get_luminance_multiplier());
radiance_texture = sky.sky_get_radiance_texture_rd(sky_rid);
} else {
// do not try to draw sky if invalid
@ -750,9 +756,9 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
CameraMatrix correction;
correction.set_depth_correction(true);
CameraMatrix projection = correction * p_render_data->cam_projection;
sky.draw(draw_list, env, framebuffer, 1, &projection, p_render_data->cam_transform, time);
sky.draw(draw_list, env, framebuffer, 1, &projection, p_render_data->cam_transform, time, _render_buffers_get_luminance_multiplier());
} else {
sky.draw(draw_list, env, framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time);
sky.draw(draw_list, env, framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time, _render_buffers_get_luminance_multiplier());
}
RD::get_singleton()->draw_command_end_label(); // Draw Sky Subpass

View file

@ -202,6 +202,7 @@ protected:
}
};
virtual float _render_buffers_get_luminance_multiplier() override;
virtual RD::DataFormat _render_buffers_get_color_format() override;
virtual bool _render_buffers_can_be_storage() override;

View file

@ -665,6 +665,8 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
actions.global_buffer_array_variable = "global_variables.data";
actions.instance_uniform_index_variable = "draw_call.instance_uniforms_ofs";
actions.apply_luminance_multiplier = true; // apply luminance multiplier to screen texture
compiler.initialize(actions);
}

View file

@ -2237,6 +2237,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
}
}
tonemap.luminance_multiplier = _render_buffers_get_luminance_multiplier();
tonemap.view_count = p_render_data->view_count;
storage->get_effects()->tonemapper(rb->texture, storage->render_target_get_rd_framebuffer(rb->render_target), tonemap);
@ -2301,6 +2302,7 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr
tonemap.use_debanding = rb->use_debanding;
tonemap.texture_size = Vector2i(rb->width, rb->height);
tonemap.luminance_multiplier = _render_buffers_get_luminance_multiplier();
tonemap.view_count = p_render_data->view_count;
storage->get_effects()->tonemapper(draw_list, p_source_texture, RD::get_singleton()->framebuffer_get_format(p_framebuffer), tonemap);
@ -2573,6 +2575,10 @@ float RendererSceneRenderRD::render_buffers_get_volumetric_fog_detail_spread(RID
return rb->volumetric_fog->spread;
}
float RendererSceneRenderRD::_render_buffers_get_luminance_multiplier() {
return 1.0;
}
RD::DataFormat RendererSceneRenderRD::_render_buffers_get_color_format() {
return RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
}

View file

@ -1190,6 +1190,7 @@ public:
/* render buffers */
virtual float _render_buffers_get_luminance_multiplier();
virtual RD::DataFormat _render_buffers_get_color_format();
virtual bool _render_buffers_can_be_storage();
virtual RID render_buffers_create() override;

View file

@ -259,7 +259,7 @@ static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_basis, float *p_ar
p_array[11] = 0;
}
void RendererSceneSkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const CameraMatrix *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position) {
void RendererSceneSkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const CameraMatrix *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position, float p_luminance_multiplier) {
SkyPushConstant sky_push_constant;
memset(&sky_push_constant, 0, sizeof(SkyPushConstant));
@ -276,6 +276,7 @@ void RendererSceneSkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_
sky_push_constant.position[2] = p_position.z;
sky_push_constant.multiplier = p_multiplier;
sky_push_constant.time = p_time;
sky_push_constant.luminance_multiplier = p_luminance_multiplier;
store_transform_3x3(p_orientation, sky_push_constant.orientation);
RenderingDevice::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(p_fb);
@ -1191,7 +1192,7 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b
RD::get_singleton()->buffer_update(sky_scene_state.uniform_buffer, 0, sizeof(SkySceneState::UBO), &sky_scene_state.ubo);
}
void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform, double p_time) {
void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {
ERR_FAIL_COND(!p_env);
Sky *sky = get_sky(p_env->sky);
@ -1283,7 +1284,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES, sky_shader.default_shader_rd);
cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[2].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
_render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[2].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, multiplier, p_transform.origin);
_render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[2].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, multiplier, p_transform.origin, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
RD::get_singleton()->draw_command_end_label();
@ -1302,7 +1303,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_CUBEMAP_HALF_RES, sky_shader.default_shader_rd);
cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[1].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
_render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[1].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, multiplier, p_transform.origin);
_render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[1].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, multiplier, p_transform.origin, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
RD::get_singleton()->draw_command_end_label();
@ -1317,7 +1318,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_CUBEMAP, sky_shader.default_shader_rd);
cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[0].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
_render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[0].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, multiplier, p_transform.origin);
_render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[0].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, multiplier, p_transform.origin, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
RD::get_singleton()->draw_command_end_label();
@ -1435,7 +1436,7 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
clear_colors.push_back(Color(0.0, 0.0, 0.0));
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->quarter_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors);
_render_sky(draw_list, p_time, sky->quarter_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin);
_render_sky(draw_list, p_time, sky->quarter_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, 1.0);
RD::get_singleton()->draw_list_end();
}
@ -1448,7 +1449,7 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
clear_colors.push_back(Color(0.0, 0.0, 0.0));
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->half_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors);
_render_sky(draw_list, p_time, sky->half_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin);
_render_sky(draw_list, p_time, sky->half_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, 1.0);
RD::get_singleton()->draw_list_end();
}
@ -1462,11 +1463,11 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
}
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_fb, RD::INITIAL_ACTION_CONTINUE, p_can_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, p_can_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ);
_render_sky(draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin);
_render_sky(draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, 1.0);
RD::get_singleton()->draw_list_end();
}
void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time) {
void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {
ERR_FAIL_COND(!p_env);
ERR_FAIL_COND(p_view_count == 0);
@ -1542,7 +1543,7 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u
clear_colors.push_back(Color(0.0, 0.0, 0.0));
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->quarter_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors);
_render_sky(draw_list, p_time, sky->quarter_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin);
_render_sky(draw_list, p_time, sky->quarter_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
@ -1555,12 +1556,12 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u
clear_colors.push_back(Color(0.0, 0.0, 0.0));
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->half_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors);
_render_sky(draw_list, p_time, sky->half_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin);
_render_sky(draw_list, p_time, sky->half_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
}
void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironmentRD *p_env, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time) {
void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironmentRD *p_env, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {
ERR_FAIL_COND(!p_env);
ERR_FAIL_COND(p_view_count == 0);
@ -1636,7 +1637,7 @@ void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironme
texture_uniform_set = sky_scene_state.fog_only_texture_uniform_set;
}
_render_sky(p_draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin);
_render_sky(p_draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, p_luminance_multiplier);
}
void RendererSceneSkyRD::invalidate_sky(Sky *p_sky) {

View file

@ -100,7 +100,8 @@ private:
float position[3]; // 12 - 92
float multiplier; // 4 - 96
float time; // 4 - 100
float pad[3]; // 12 - 112 // Using pad to align on 16 bytes
float luminance_multiplier; // 4 - 104
float pad[2]; // 8 - 112 // Using pad to align on 16 bytes
// 128 is the max size of a push constant. We can replace "pad" but we can't add any more.
};
@ -138,7 +139,7 @@ private:
virtual ~SkyShaderData();
};
void _render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const CameraMatrix *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position);
void _render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const CameraMatrix *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position, float p_luminance_multiplier);
public:
struct SkySceneState {
@ -293,10 +294,10 @@ public:
~RendererSceneSkyRD();
void setup(RendererSceneEnvironmentRD *p_env, RID p_render_buffers, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render);
void update(RendererSceneEnvironmentRD *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform, double p_time);
void draw(RendererSceneEnvironmentRD *p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time);
void update_res_buffers(RendererSceneEnvironmentRD *p_env, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time);
void draw(RD::DrawListID p_draw_list, RendererSceneEnvironmentRD *p_env, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time);
void update(RendererSceneEnvironmentRD *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0);
void draw(RendererSceneEnvironmentRD *p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time); // only called by clustered renderer
void update_res_buffers(RendererSceneEnvironmentRD *p_env, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0);
void draw(RD::DrawListID p_draw_list, RendererSceneEnvironmentRD *p_env, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0);
void invalidate_sky(Sky *p_sky);
void update_dirty_skys();

View file

@ -1165,6 +1165,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
SL::VariableNode *vnode = (SL::VariableNode *)onode->arguments[0];
bool is_texture_func = false;
bool is_screen_texture = false;
if (onode->op == SL::OP_STRUCT) {
code += _mkid(vnode->name);
} else if (onode->op == SL::OP_CONSTRUCT) {
@ -1197,6 +1198,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
const SL::VariableNode *varnode = static_cast<const SL::VariableNode *>(onode->arguments[i]);
StringName texture_uniform = varnode->name;
is_screen_texture = (texture_uniform == "SCREEN_TEXTURE");
String sampler_name;
@ -1236,6 +1238,9 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
}
}
code += ")";
if (is_screen_texture && actions.apply_luminance_multiplier) {
code = "(" + code + " * vec4(vec3(sc_luminance_multiplier), 1.0))";
}
} break;
case SL::OP_INDEX: {
code += _dump_node_code(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);

View file

@ -95,6 +95,7 @@ public:
String global_buffer_array_variable;
String instance_uniform_index_variable;
uint32_t base_varying_index = 0;
bool apply_luminance_multiplier = false;
};
private:

View file

@ -38,6 +38,8 @@ layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure;
layout(location = 0) out vec4 frag_color;
void main() {
// We do not apply our color scale for our mobile renderer here, we'll leave our colors at half brightness and apply scale in the tonemap raster.
#ifdef MODE_MIPMAP
vec2 pix_size = blur.pixel_size;

View file

@ -6,6 +6,6 @@ layout(push_constant, binding = 1, std430) uniform PushConstant {
float exposure_adjust;
float min_luminance;
float max_luminance;
float pad;
uint pad1;
}
settings;

View file

@ -374,6 +374,9 @@ layout(constant_id = 9) const uint sc_directional_penumbra_shadow_samples = 4;
layout(constant_id = 10) const bool sc_decal_use_mipmaps = true;
layout(constant_id = 11) const bool sc_projector_use_mipmaps = true;
// not used in clustered renderer but we share some code with the mobile renderer that requires this.
const float sc_luminance_multiplier = 1.0;
#include "scene_forward_clustered_inc.glsl"
/* Varyings */

View file

@ -969,7 +969,7 @@ void reflection_process(uint ref_index, vec3 vertex, vec3 normal, float roughnes
vec4 reflection;
reflection.rgb = textureLod(samplerCubeArray(reflection_atlas, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(local_ref_vec, reflections.data[ref_index].index), roughness * MAX_ROUGHNESS_LOD).rgb;
reflection.rgb = textureLod(samplerCubeArray(reflection_atlas, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(local_ref_vec, reflections.data[ref_index].index), roughness * MAX_ROUGHNESS_LOD).rgb * sc_luminance_multiplier;
if (reflections.data[ref_index].exterior) {
reflection.rgb = mix(specular_light, reflection.rgb, blend);

View file

@ -401,6 +401,8 @@ layout(constant_id = 14) const bool sc_disable_fog = false;
#endif //!MODE_RENDER_DEPTH
layout(constant_id = 15) const float sc_luminance_multiplier = 2.0;
/* Include our forward mobile UBOs definitions etc. */
#include "scene_forward_mobile_inc.glsl"
@ -1551,12 +1553,15 @@ void main() {
frag_color = vec4(albedo, alpha);
#else // MODE_UNSHADED
frag_color = vec4(emission + ambient_light + diffuse_light + specular_light, alpha);
//frag_color = vec4(1.0);
#endif // MODE_UNSHADED
// Draw "fixed" fog before volumetric fog to ensure volumetric fog can appear in front of the sky.
frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a);
// On mobile we use a UNORM buffer with 10bpp which results in a range from 0.0 - 1.0 resulting in HDR breaking
// We divide by sc_luminance_multiplier to support a range from 0.0 - 2.0 both increasing precision on bright and darker images
frag_color.rgb = frag_color.rgb / sc_luminance_multiplier;
#endif //MODE_MULTIPLE_RENDER_TARGETS
#endif //MODE_RENDER_DEPTH

View file

@ -17,6 +17,8 @@ layout(push_constant, binding = 1, std430) uniform Params {
vec4 projections[MAX_VIEWS];
vec4 position_multiplier;
float time;
float luminance_multiplier;
float pad[2];
}
params;
@ -55,6 +57,8 @@ layout(push_constant, binding = 1, std430) uniform Params {
vec4 projections[MAX_VIEWS];
vec4 position_multiplier;
float time;
float luminance_multiplier;
float pad[2];
}
params;
@ -199,17 +203,17 @@ void main() {
vec3 inverted_cube_normal = cube_normal;
inverted_cube_normal.z *= -1.0;
#ifdef USES_HALF_RES_COLOR
half_res_color = texture(samplerCube(half_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), inverted_cube_normal);
half_res_color = texture(samplerCube(half_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), inverted_cube_normal) * params.luminance_multiplier;
#endif
#ifdef USES_QUARTER_RES_COLOR
quarter_res_color = texture(samplerCube(quarter_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), inverted_cube_normal);
quarter_res_color = texture(samplerCube(quarter_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), inverted_cube_normal) * params.luminance_multiplier;
#endif
#else
#ifdef USES_HALF_RES_COLOR
half_res_color = textureLod(sampler2D(half_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0);
half_res_color = textureLod(sampler2D(half_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0) * params.luminance_multiplier;
#endif
#ifdef USES_QUARTER_RES_COLOR
quarter_res_color = textureLod(sampler2D(quarter_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0);
quarter_res_color = textureLod(sampler2D(quarter_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0) * params.luminance_multiplier;
#endif
#endif
@ -246,4 +250,7 @@ void main() {
if (!AT_CUBEMAP_PASS && !AT_HALF_RES_PASS && !AT_QUARTER_RES_PASS) {
frag_color.a = 0.0;
}
// For mobile renderer we're dividing by 2.0 as we're using a UNORM buffer
frag_color.rgb = frag_color.rgb / params.luminance_multiplier;
}

View file

@ -71,7 +71,7 @@ layout(push_constant, binding = 1, std430) uniform Params {
float exposure;
float white;
float auto_exposure_grey;
uint pad2;
float luminance_multiplier;
vec2 pixel_size;
bool use_fxaa;
@ -298,15 +298,15 @@ vec3 do_fxaa(vec3 color, float exposure, vec2 uv_interp) {
const float FXAA_SPAN_MAX = 8.0;
#ifdef MULTIVIEW
vec3 rgbNW = textureLod(source_color, vec3(uv_interp + vec2(-1.0, -1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure;
vec3 rgbNE = textureLod(source_color, vec3(uv_interp + vec2(1.0, -1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure;
vec3 rgbSW = textureLod(source_color, vec3(uv_interp + vec2(-1.0, 1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure;
vec3 rgbSE = textureLod(source_color, vec3(uv_interp + vec2(1.0, 1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure;
vec3 rgbNW = textureLod(source_color, vec3(uv_interp + vec2(-1.0, -1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure * params.luminance_multiplier;
vec3 rgbNE = textureLod(source_color, vec3(uv_interp + vec2(1.0, -1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure * params.luminance_multiplier;
vec3 rgbSW = textureLod(source_color, vec3(uv_interp + vec2(-1.0, 1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure * params.luminance_multiplier;
vec3 rgbSE = textureLod(source_color, vec3(uv_interp + vec2(1.0, 1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure * params.luminance_multiplier;
#else
vec3 rgbNW = textureLod(source_color, uv_interp + vec2(-1.0, -1.0) * params.pixel_size, 0.0).xyz * exposure;
vec3 rgbNE = textureLod(source_color, uv_interp + vec2(1.0, -1.0) * params.pixel_size, 0.0).xyz * exposure;
vec3 rgbSW = textureLod(source_color, uv_interp + vec2(-1.0, 1.0) * params.pixel_size, 0.0).xyz * exposure;
vec3 rgbSE = textureLod(source_color, uv_interp + vec2(1.0, 1.0) * params.pixel_size, 0.0).xyz * exposure;
vec3 rgbNW = textureLod(source_color, uv_interp + vec2(-1.0, -1.0) * params.pixel_size, 0.0).xyz * exposure * params.luminance_multiplier;
vec3 rgbNE = textureLod(source_color, uv_interp + vec2(1.0, -1.0) * params.pixel_size, 0.0).xyz * exposure * params.luminance_multiplier;
vec3 rgbSW = textureLod(source_color, uv_interp + vec2(-1.0, 1.0) * params.pixel_size, 0.0).xyz * exposure * params.luminance_multiplier;
vec3 rgbSE = textureLod(source_color, uv_interp + vec2(1.0, 1.0) * params.pixel_size, 0.0).xyz * exposure * params.luminance_multiplier;
#endif
vec3 rgbM = color;
vec3 luma = vec3(0.299, 0.587, 0.114);
@ -333,11 +333,11 @@ vec3 do_fxaa(vec3 color, float exposure, vec2 uv_interp) {
params.pixel_size;
#ifdef MULTIVIEW
vec3 rgbA = 0.5 * exposure * (textureLod(source_color, vec3(uv_interp + dir * (1.0 / 3.0 - 0.5), ViewIndex), 0.0).xyz + textureLod(source_color, vec3(uv_interp + dir * (2.0 / 3.0 - 0.5), ViewIndex), 0.0).xyz);
vec3 rgbB = rgbA * 0.5 + 0.25 * exposure * (textureLod(source_color, vec3(uv_interp + dir * -0.5, ViewIndex), 0.0).xyz + textureLod(source_color, vec3(uv_interp + dir * 0.5, ViewIndex), 0.0).xyz);
vec3 rgbA = 0.5 * exposure * (textureLod(source_color, vec3(uv_interp + dir * (1.0 / 3.0 - 0.5), ViewIndex), 0.0).xyz + textureLod(source_color, vec3(uv_interp + dir * (2.0 / 3.0 - 0.5), ViewIndex), 0.0).xyz) * params.luminance_multiplier;
vec3 rgbB = rgbA * 0.5 + 0.25 * exposure * (textureLod(source_color, vec3(uv_interp + dir * -0.5, ViewIndex), 0.0).xyz + textureLod(source_color, vec3(uv_interp + dir * 0.5, ViewIndex), 0.0).xyz) * params.luminance_multiplier;
#else
vec3 rgbA = 0.5 * exposure * (textureLod(source_color, uv_interp + dir * (1.0 / 3.0 - 0.5), 0.0).xyz + textureLod(source_color, uv_interp + dir * (2.0 / 3.0 - 0.5), 0.0).xyz);
vec3 rgbB = rgbA * 0.5 + 0.25 * exposure * (textureLod(source_color, uv_interp + dir * -0.5, 0.0).xyz + textureLod(source_color, uv_interp + dir * 0.5, 0.0).xyz);
vec3 rgbA = 0.5 * exposure * (textureLod(source_color, uv_interp + dir * (1.0 / 3.0 - 0.5), 0.0).xyz + textureLod(source_color, uv_interp + dir * (2.0 / 3.0 - 0.5), 0.0).xyz) * params.luminance_multiplier;
vec3 rgbB = rgbA * 0.5 + 0.25 * exposure * (textureLod(source_color, uv_interp + dir * -0.5, 0.0).xyz + textureLod(source_color, uv_interp + dir * 0.5, 0.0).xyz) * params.luminance_multiplier;
#endif
float lumaB = dot(rgbB, luma);
@ -364,11 +364,11 @@ vec3 screen_space_dither(vec2 frag_coord) {
void main() {
#ifdef SUBPASS
// SUBPASS and MULTIVIEW can be combined but in that case we're already reading from the correct layer
vec3 color = subpassLoad(input_color).rgb;
vec3 color = subpassLoad(input_color).rgb * params.luminance_multiplier;
#elif defined(MULTIVIEW)
vec3 color = textureLod(source_color, vec3(uv_interp, ViewIndex), 0.0f).rgb;
vec3 color = textureLod(source_color, vec3(uv_interp, ViewIndex), 0.0f).rgb * params.luminance_multiplier;
#else
vec3 color = textureLod(source_color, uv_interp, 0.0f).rgb;
vec3 color = textureLod(source_color, uv_interp, 0.0f).rgb * params.luminance_multiplier;
#endif
// Exposure
@ -377,7 +377,7 @@ void main() {
#ifndef SUBPASS
if (params.use_auto_exposure) {
exposure *= 1.0 / (texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / params.auto_exposure_grey);
exposure *= 1.0 / (texelFetch(source_auto_exposure, ivec2(0, 0), 0).r * params.luminance_multiplier / params.auto_exposure_grey);
}
#endif
@ -386,7 +386,7 @@ void main() {
// Early Tonemap & SRGB Conversion
#ifndef SUBPASS
if (params.use_glow && params.glow_mode == GLOW_MODE_MIX) {
vec3 glow = gather_glow(source_glow, uv_interp);
vec3 glow = gather_glow(source_glow, uv_interp) * params.luminance_multiplier;
color.rgb = mix(color.rgb, glow, params.glow_intensity);
}
@ -411,7 +411,7 @@ void main() {
// Glow
if (params.use_glow && params.glow_mode != GLOW_MODE_MIX) {
vec3 glow = gather_glow(source_glow, uv_interp) * params.glow_intensity;
vec3 glow = gather_glow(source_glow, uv_interp) * params.glow_intensity * params.luminance_multiplier;
// high dynamic range -> SRGB
glow = apply_tonemapping(glow, params.white);