Optimize Glow with local memory

This commit is contained in:
clayjohn 2020-09-19 15:02:32 -07:00
parent 5b6a22e275
commit 63a34b93aa
16 changed files with 201 additions and 160 deletions

View file

@ -18,24 +18,24 @@
<link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link>
</tutorials>
<methods>
<method name="is_glow_level_enabled" qualifiers="const">
<return type="bool">
<method name="get_glow_level" qualifiers="const">
<return type="float">
</return>
<argument index="0" name="idx" type="int">
</argument>
<description>
Returns [code]true[/code] if the glow level [code]idx[/code] is specified, [code]false[/code] otherwise.
Returns the intensity of the glow level [code]idx[/code].
</description>
</method>
<method name="set_glow_level_enabled">
<method name="set_glow_level">
<return type="void">
</return>
<argument index="0" name="idx" type="int">
</argument>
<argument index="1" name="enabled" type="bool">
<argument index="1" name="intensity" type="float">
</argument>
<description>
Enables or disables the glow level at index [code]idx[/code]. Each level relies on the previous level. This means that enabling higher glow levels will slow down the glow effect rendering, even if previous levels aren't enabled.
Sets the intensity of the glow level [code]idx[/code]. A value above [code]0.0[/code] enables the level. Each level relies on the previous level. This means that enabling higher glow levels will slow down the glow effect rendering, even if previous levels aren't enabled.
</description>
</method>
</methods>
@ -132,33 +132,36 @@
The lower threshold of the HDR glow. When using the GLES2 renderer (which doesn't support HDR), this needs to be below [code]1.0[/code] for glow to be visible. A value of [code]0.9[/code] works well in this case.
</member>
<member name="glow_intensity" type="float" setter="set_glow_intensity" getter="get_glow_intensity" default="0.8">
The glow intensity. When using the GLES2 renderer, this should be increased to 1.5 to compensate for the lack of HDR rendering.
The overall brightness multiplier of the glow effect. When using the GLES2 renderer, this should be increased to 1.5 to compensate for the lack of HDR rendering.
</member>
<member name="glow_levels/1" type="bool" setter="set_glow_level_enabled" getter="is_glow_level_enabled" default="false">
If [code]true[/code], the 1st level of glow is enabled. This is the most "local" level (least blurry).
<member name="glow_levels/1" type="float" setter="set_glow_level" getter="get_glow_level" default="0.0">
The intensity of the 1st level of glow. This is the most "local" level (least blurry).
</member>
<member name="glow_levels/2" type="bool" setter="set_glow_level_enabled" getter="is_glow_level_enabled" default="false">
If [code]true[/code], the 2th level of glow is enabled.
<member name="glow_levels/2" type="float" setter="set_glow_level" getter="get_glow_level" default="0.0">
The intensity of the 2nd level of glow.
</member>
<member name="glow_levels/3" type="bool" setter="set_glow_level_enabled" getter="is_glow_level_enabled" default="true">
If [code]true[/code], the 3th level of glow is enabled.
<member name="glow_levels/3" type="float" setter="set_glow_level" getter="get_glow_level" default="1.0">
The intensity of the 3rd level of glow.
</member>
<member name="glow_levels/4" type="bool" setter="set_glow_level_enabled" getter="is_glow_level_enabled" default="false">
If [code]true[/code], the 4th level of glow is enabled.
<member name="glow_levels/4" type="float" setter="set_glow_level" getter="get_glow_level" default="0.0">
The intensity of the 4th level of glow.
</member>
<member name="glow_levels/5" type="bool" setter="set_glow_level_enabled" getter="is_glow_level_enabled" default="true">
If [code]true[/code], the 5th level of glow is enabled.
<member name="glow_levels/5" type="float" setter="set_glow_level" getter="get_glow_level" default="1.0">
The intensity of the 5th level of glow.
</member>
<member name="glow_levels/6" type="bool" setter="set_glow_level_enabled" getter="is_glow_level_enabled" default="false">
If [code]true[/code], the 6th level of glow is enabled.
<member name="glow_levels/6" type="float" setter="set_glow_level" getter="get_glow_level" default="0.0">
The intensity of the 6th level of glow.
</member>
<member name="glow_levels/7" type="bool" setter="set_glow_level_enabled" getter="is_glow_level_enabled" default="false">
If [code]true[/code], the 7th level of glow is enabled. This is the most "global" level (blurriest).
<member name="glow_levels/7" type="float" setter="set_glow_level" getter="get_glow_level" default="0.0">
The intensity of the 7th level of glow. This is the most "global" level (blurriest).
</member>
<member name="glow_mix" type="float" setter="set_glow_mix" getter="get_glow_mix" default="0.05">
</member>
<member name="glow_normalized" type="bool" setter="set_glow_normalized" getter="is_glow_normalized" default="false">
If [code]true[/code], glow levels will be normalized so that summed together their intensities equal [code]1.0[/code].
</member>
<member name="glow_strength" type="float" setter="set_glow_strength" getter="get_glow_strength" default="1.0">
The glow strength. When using the GLES2 renderer, this should be increased to 1.3 to compensate for the lack of HDR rendering.
The strength of the glow effect. This applies as the glow is blurred across the screen and increases the distance and intensity of the blur. When using the GLES2 renderer, this should be increased to 1.3 to compensate for the lack of HDR rendering.
</member>
<member name="reflected_light_source" type="int" setter="set_reflection_source" getter="get_reflection_source" enum="Environment.ReflectionSource" default="0">
</member>

View file

@ -718,7 +718,7 @@
</argument>
<argument index="1" name="enable" type="bool">
</argument>
<argument index="2" name="level_flags" type="int">
<argument index="2" name="levels" type="PackedFloat32Array">
</argument>
<argument index="3" name="intensity" type="float">
</argument>

View file

@ -80,7 +80,7 @@ public:
void environment_set_canvas_max_layer(RID p_env, int p_max_layer) override {}
void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG, const Color &p_ao_color = Color()) override {}
void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap) override {}
void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap) override {}
void environment_glow_set_use_bicubic_upscale(bool p_enable) override {}
void environment_glow_set_use_high_quality(bool p_enable) override {}

View file

@ -578,22 +578,28 @@ bool Environment::is_glow_enabled() const {
return glow_enabled;
}
void Environment::set_glow_level_enabled(int p_level, bool p_enabled) {
void Environment::set_glow_level(int p_level, float p_intensity) {
ERR_FAIL_INDEX(p_level, RS::MAX_GLOW_LEVELS);
if (p_enabled) {
glow_levels |= (1 << p_level);
} else {
glow_levels &= ~(1 << p_level);
}
glow_levels.write[p_level] = p_intensity;
_update_glow();
}
bool Environment::is_glow_level_enabled(int p_level) const {
float Environment::get_glow_level(int p_level) const {
ERR_FAIL_INDEX_V(p_level, RS::MAX_GLOW_LEVELS, false);
return glow_levels & (1 << p_level);
return glow_levels[p_level];
}
void Environment::set_glow_normalized(bool p_normalized) {
glow_normalize_levels = p_normalized;
_update_glow();
}
bool Environment::is_glow_normalized() const {
return glow_normalize_levels;
}
void Environment::set_glow_intensity(float p_intensity) {
@ -670,10 +676,24 @@ float Environment::get_glow_hdr_luminance_cap() const {
}
void Environment::_update_glow() {
Vector<float> normalized_levels;
if (glow_normalize_levels) {
normalized_levels.resize(7);
float size = 0.0;
for (int i = 0; i < glow_levels.size(); i++) {
size += glow_levels[i];
}
for (int i = 0; i < glow_levels.size(); i++) {
normalized_levels.write[i] = glow_levels[i] / size;
}
} else {
normalized_levels = glow_levels;
}
RS::get_singleton()->environment_set_glow(
environment,
glow_enabled,
glow_levels,
normalized_levels,
glow_intensity,
glow_strength,
glow_mix,
@ -1162,8 +1182,10 @@ void Environment::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_glow_enabled", "enabled"), &Environment::set_glow_enabled);
ClassDB::bind_method(D_METHOD("is_glow_enabled"), &Environment::is_glow_enabled);
ClassDB::bind_method(D_METHOD("set_glow_level_enabled", "idx", "enabled"), &Environment::set_glow_level_enabled);
ClassDB::bind_method(D_METHOD("is_glow_level_enabled", "idx"), &Environment::is_glow_level_enabled);
ClassDB::bind_method(D_METHOD("set_glow_level", "idx", "intensity"), &Environment::set_glow_level);
ClassDB::bind_method(D_METHOD("get_glow_level", "idx"), &Environment::get_glow_level);
ClassDB::bind_method(D_METHOD("set_glow_normalized", "normalize"), &Environment::set_glow_normalized);
ClassDB::bind_method(D_METHOD("is_glow_normalized"), &Environment::is_glow_normalized);
ClassDB::bind_method(D_METHOD("set_glow_intensity", "intensity"), &Environment::set_glow_intensity);
ClassDB::bind_method(D_METHOD("get_glow_intensity"), &Environment::get_glow_intensity);
ClassDB::bind_method(D_METHOD("set_glow_strength", "strength"), &Environment::set_glow_strength);
@ -1183,13 +1205,14 @@ void Environment::_bind_methods() {
ADD_GROUP("Glow", "glow_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "glow_enabled"), "set_glow_enabled", "is_glow_enabled");
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "glow_levels/1"), "set_glow_level_enabled", "is_glow_level_enabled", 0);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "glow_levels/2"), "set_glow_level_enabled", "is_glow_level_enabled", 1);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "glow_levels/3"), "set_glow_level_enabled", "is_glow_level_enabled", 2);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "glow_levels/4"), "set_glow_level_enabled", "is_glow_level_enabled", 3);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "glow_levels/5"), "set_glow_level_enabled", "is_glow_level_enabled", 4);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "glow_levels/6"), "set_glow_level_enabled", "is_glow_level_enabled", 5);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "glow_levels/7"), "set_glow_level_enabled", "is_glow_level_enabled", 6);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "glow_levels/1", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_glow_level", "get_glow_level", 0);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "glow_levels/2", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_glow_level", "get_glow_level", 1);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "glow_levels/3", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_glow_level", "get_glow_level", 2);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "glow_levels/4", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_glow_level", "get_glow_level", 3);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "glow_levels/5", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_glow_level", "get_glow_level", 4);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "glow_levels/6", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_glow_level", "get_glow_level", 5);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "glow_levels/7", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_glow_level", "get_glow_level", 6);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "glow_normalized"), "set_glow_normalized", "is_glow_normalized");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "glow_intensity", PROPERTY_HINT_RANGE, "0.0,8.0,0.01"), "set_glow_intensity", "get_glow_intensity");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "glow_strength", PROPERTY_HINT_RANGE, "0.0,2.0,0.01"), "set_glow_strength", "get_glow_strength");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "glow_mix", PROPERTY_HINT_RANGE, "0.0,1.0,0.001"), "set_glow_mix", "get_glow_mix");
@ -1329,6 +1352,16 @@ Environment::Environment() {
environment = RS::get_singleton()->environment_create();
set_camera_feed_id(bg_camera_feed_id);
glow_levels.resize(7);
glow_levels.write[0] = 0.0;
glow_levels.write[1] = 0.0;
glow_levels.write[2] = 1.0;
glow_levels.write[3] = 0.0;
glow_levels.write[4] = 1.0;
glow_levels.write[5] = 0.0;
glow_levels.write[6] = 0.0;
_update_ambient_light();
_update_tonemap();
_update_ssr();

View file

@ -171,7 +171,8 @@ private:
// Glow
bool glow_enabled = false;
int glow_levels = (1 << 2) | (1 << 4);
Vector<float> glow_levels;
bool glow_normalize_levels = false;
float glow_intensity = 0.8;
float glow_strength = 1.0;
float glow_mix = 0.05;
@ -332,8 +333,10 @@ public:
// Glow
void set_glow_enabled(bool p_enabled);
bool is_glow_enabled() const;
void set_glow_level_enabled(int p_level, bool p_enabled);
bool is_glow_level_enabled(int p_level) const;
void set_glow_level(int p_level, float p_intensity);
float get_glow_level(int p_level) const;
void set_glow_normalized(bool p_normalized);
bool is_glow_normalized() const;
void set_glow_intensity(float p_intensity);
float get_glow_intensity() const;
void set_glow_strength(float p_strength);

View file

@ -84,7 +84,7 @@ public:
virtual void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id) = 0;
#endif
virtual void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap) = 0;
virtual void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap) = 0;
virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) = 0;
virtual void environment_glow_set_use_high_quality(bool p_enable) = 0;

View file

@ -389,14 +389,14 @@ void RasterizerEffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_texture,
RD::get_singleton()->compute_list_end();
}
void RasterizerEffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_texture, RID p_back_texture, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_treshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) {
void RasterizerEffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_treshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) {
zeromem(&copy.push_constant, sizeof(CopyPushConstant));
CopyMode copy_mode = p_first_pass && p_auto_exposure.is_valid() ? COPY_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE : COPY_MODE_GAUSSIAN_GLOW;
uint32_t base_flags = 0;
int32_t x_groups = (p_size.width - 1) / 8 + 1;
int32_t y_groups = (p_size.height - 1) / 8 + 1;
int32_t x_groups = (p_size.width + 7) / 8;
int32_t y_groups = (p_size.height + 7) / 8;
copy.push_constant.section[2] = p_size.x;
copy.push_constant.section[3] = p_size.y;
@ -411,29 +411,15 @@ void RasterizerEffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_texture,
copy.push_constant.glow_auto_exposure_grey = p_auto_exposure_grey; //unused also
//HORIZONTAL
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[copy_mode]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_texture), 3);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_back_texture), 3);
if (p_auto_exposure.is_valid() && p_first_pass) {
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_auto_exposure), 1);
}
copy.push_constant.flags = base_flags | COPY_FLAG_HORIZONTAL | (p_first_pass ? COPY_FLAG_GLOW_FIRST_PASS : 0) | (p_high_quality ? COPY_FLAG_HIGH_QUALITY_GLOW : 0);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
RD::get_singleton()->compute_list_add_barrier(compute_list);
copy_mode = COPY_MODE_GAUSSIAN_GLOW;
//VERTICAL
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[copy_mode]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_texture), 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_back_texture), 3);
copy.push_constant.flags = base_flags;
copy.push_constant.flags = base_flags | (p_first_pass ? COPY_FLAG_GLOW_FIRST_PASS : 0) | (p_high_quality ? COPY_FLAG_HIGH_QUALITY_GLOW : 0);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
@ -692,7 +678,13 @@ void RasterizerEffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer,
tonemap.push_constant.use_glow = p_settings.use_glow;
tonemap.push_constant.glow_intensity = p_settings.glow_intensity;
tonemap.push_constant.glow_level_flags = p_settings.glow_level_flags;
tonemap.push_constant.glow_levels[0] = p_settings.glow_levels[0]; // clean this up to just pass by pointer or something
tonemap.push_constant.glow_levels[1] = p_settings.glow_levels[1];
tonemap.push_constant.glow_levels[2] = p_settings.glow_levels[2];
tonemap.push_constant.glow_levels[3] = p_settings.glow_levels[3];
tonemap.push_constant.glow_levels[4] = p_settings.glow_levels[4];
tonemap.push_constant.glow_levels[5] = p_settings.glow_levels[5];
tonemap.push_constant.glow_levels[6] = p_settings.glow_levels[6];
tonemap.push_constant.glow_texture_size[0] = p_settings.glow_texture_size.x;
tonemap.push_constant.glow_texture_size[1] = p_settings.glow_texture_size.y;
tonemap.push_constant.glow_mode = p_settings.glow_mode;

View file

@ -175,14 +175,16 @@ class RasterizerEffectsRD {
uint32_t tonemapper;
uint32_t glow_texture_size[2];
float glow_intensity;
uint32_t glow_level_flags;
uint32_t pad3;
uint32_t glow_mode;
float glow_levels[7];
float exposure;
float white;
float auto_exposure_grey;
uint32_t pad2;
float pixel_size[2];
uint32_t use_fxaa;
@ -607,7 +609,7 @@ public:
void copy_depth_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, float p_z_near, float p_z_far);
void copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_uv_rect, RD::DrawListID p_draw_list, bool p_flip_y = false, bool p_panorama = false);
void gaussian_blur(RID p_source_rd_texture, RID p_texture, RID p_back_texture, const Rect2i &p_region, bool p_8bit_dst = false);
void gaussian_glow(RID p_source_rd_texture, RID p_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_treshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
void gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_treshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
void cubemap_roughness(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size);
void make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size);
@ -627,7 +629,7 @@ public:
GlowMode glow_mode = GLOW_MODE_ADD;
float glow_intensity = 1.0;
uint32_t glow_level_flags = 0;
float glow_levels[7] = { 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0 };
Vector2i glow_texture_size;
bool glow_use_bicubic_upscale = false;
RID glow_texture;

View file

@ -2932,11 +2932,12 @@ void RasterizerSceneRD::environment_set_tonemap(RID p_env, RS::EnvironmentToneMa
env->auto_exp_scale = p_auto_exp_scale;
}
void RasterizerSceneRD::environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap) {
void RasterizerSceneRD::environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap) {
Environment *env = environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);
ERR_FAIL_COND_MSG(p_levels.size() != 7, "Size of array of glow levels must be 7");
env->glow_enabled = p_enable;
env->glow_levels = p_level_flags;
env->glow_levels = p_levels;
env->glow_intensity = p_intensity;
env->glow_strength = p_strength;
env->glow_mix = p_mix;
@ -5237,25 +5238,21 @@ void RasterizerSceneRD::_render_buffers_post_process_and_tonemap(RID p_render_bu
}
int max_glow_level = -1;
int glow_mask = 0;
if (can_use_effects && env && env->glow_enabled) {
/* see that blur textures are allocated */
if (rb->blur[0].texture.is_null()) {
if (rb->blur[1].texture.is_null()) {
_allocate_blur_textures(rb);
_render_buffers_uniform_set_changed(p_render_buffers);
}
for (int i = 0; i < RS::MAX_GLOW_LEVELS; i++) {
if (env->glow_levels & (1 << i)) {
if (env->glow_levels[i] > 0.0) {
if (i >= rb->blur[1].mipmaps.size()) {
max_glow_level = rb->blur[1].mipmaps.size() - 1;
glow_mask |= 1 << max_glow_level;
} else {
max_glow_level = i;
glow_mask |= (1 << i);
}
}
}
@ -5269,9 +5266,9 @@ void RasterizerSceneRD::_render_buffers_post_process_and_tonemap(RID p_render_bu
if (env->auto_exposure && rb->luminance.current.is_valid()) {
luminance_texture = rb->luminance.current;
}
storage->get_effects()->gaussian_glow(rb->texture, rb->blur[0].mipmaps[i + 1].texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale);
storage->get_effects()->gaussian_glow(rb->texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale);
} else {
storage->get_effects()->gaussian_glow(rb->blur[1].mipmaps[i - 1].texture, rb->blur[0].mipmaps[i + 1].texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality);
storage->get_effects()->gaussian_glow(rb->blur[1].mipmaps[i - 1].texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality);
}
}
}
@ -5294,7 +5291,9 @@ void RasterizerSceneRD::_render_buffers_post_process_and_tonemap(RID p_render_bu
tonemap.use_glow = true;
tonemap.glow_mode = RasterizerEffectsRD::TonemapSettings::GlowMode(env->glow_blend_mode);
tonemap.glow_intensity = env->glow_blend_mode == RS::ENV_GLOW_BLEND_MODE_MIX ? env->glow_mix : env->glow_intensity;
tonemap.glow_level_flags = glow_mask;
for (int i = 0; i < RS::MAX_GLOW_LEVELS; i++) {
tonemap.glow_levels[i] = env->glow_levels[i];
}
tonemap.glow_texture_size.x = rb->blur[1].mipmaps[0].width;
tonemap.glow_texture_size.y = rb->blur[1].mipmaps[0].height;
tonemap.glow_use_bicubic_upscale = glow_bicubic_upscale;

View file

@ -721,7 +721,7 @@ private:
/// Glow
bool glow_enabled = false;
int glow_levels = (1 << 2) | (1 << 4);
Vector<float> glow_levels;
float glow_intensity = 0.8;
float glow_strength = 1.0;
float glow_bloom = 0.0;
@ -1530,7 +1530,7 @@ public:
bool is_environment(RID p_env) const;
void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap);
void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap);
void environment_glow_set_use_bicubic_upscale(bool p_enable);
void environment_glow_set_use_high_quality(bool p_enable);

View file

@ -58,12 +58,20 @@ layout(rgba8, set = 3, binding = 0) uniform restrict writeonly image2D dest_buff
layout(rgba32f, set = 3, binding = 0) uniform restrict writeonly image2D dest_buffer;
#endif
#ifdef MODE_GAUSSIAN_GLOW
shared vec4 local_cache[256];
shared vec4 temp_cache[128];
#endif
void main() {
// Pixel being shaded
ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
#ifndef MODE_GAUSSIAN_GLOW // Glow needs the extra threads
if (any(greaterThanEqual(pos, params.section.zw))) { //too large, do nothing
return;
}
#endif
#ifdef MODE_MIPMAP
@ -104,70 +112,69 @@ void main() {
#ifdef MODE_GAUSSIAN_GLOW
//Glow uses larger sigma 1 for a more rounded blur effect
// First pass copy texture into 16x16 local memory for every 8x8 thread block
vec2 quad_center_uv = clamp(vec2(gl_GlobalInvocationID.xy + gl_LocalInvocationID.xy - 3.5) / params.section.zw, vec2(0.5 / params.section.zw), vec2(1.0 - 1.5 / params.section.zw));
uint dest_index = gl_LocalInvocationID.x * 2 + gl_LocalInvocationID.y * 2 * 16;
#define GLOW_ADD(m_ofs, m_mult) \
{ \
ivec2 ofs = base_pos + m_ofs; \
if (all(greaterThanEqual(ofs, section_begin)) && all(lessThan(ofs, section_end))) { \
color += texelFetch(source_color, ofs, 0) * m_mult; \
} \
if (bool(params.flags & FLAG_HIGH_QUALITY_GLOW)) {
vec2 quad_offset_uv = clamp((vec2(gl_GlobalInvocationID.xy + gl_LocalInvocationID.xy - 3.0)) / params.section.zw, vec2(0.5 / params.section.zw), vec2(1.0 - 1.5 / params.section.zw));
local_cache[dest_index] = (textureLod(source_color, quad_center_uv, 0) + textureLod(source_color, quad_offset_uv, 0)) * 0.5;
local_cache[dest_index + 1] = (textureLod(source_color, quad_center_uv + vec2(1.0 / params.section.z, 0.0), 0) + textureLod(source_color, quad_offset_uv + vec2(1.0 / params.section.z, 0.0), 0)) * 0.5;
local_cache[dest_index + 16] = (textureLod(source_color, quad_center_uv + vec2(0.0, 1.0 / params.section.w), 0) + textureLod(source_color, quad_offset_uv + vec2(0.0, 1.0 / params.section.w), 0)) * 0.5;
local_cache[dest_index + 16 + 1] = (textureLod(source_color, quad_center_uv + vec2(1.0 / params.section.zw), 0) + textureLod(source_color, quad_offset_uv + vec2(1.0 / params.section.zw), 0)) * 0.5;
} else {
local_cache[dest_index] = textureLod(source_color, quad_center_uv, 0);
local_cache[dest_index + 1] = textureLod(source_color, quad_center_uv + vec2(1.0 / params.section.z, 0.0), 0);
local_cache[dest_index + 16] = textureLod(source_color, quad_center_uv + vec2(0.0, 1.0 / params.section.w), 0);
local_cache[dest_index + 16 + 1] = textureLod(source_color, quad_center_uv + vec2(1.0 / params.section.zw), 0);
}
memoryBarrierShared();
barrier();
// Horizontal pass. Needs to copy into 8x16 chunk of local memory so vertical pass has full resolution
uint read_index = gl_LocalInvocationID.x + gl_LocalInvocationID.y * 32 + 4;
vec4 color_top = vec4(0.0);
color_top += local_cache[read_index] * 0.174938;
color_top += local_cache[read_index + 1] * 0.165569;
color_top += local_cache[read_index + 2] * 0.140367;
color_top += local_cache[read_index + 3] * 0.106595;
color_top += local_cache[read_index - 1] * 0.165569;
color_top += local_cache[read_index - 2] * 0.140367;
color_top += local_cache[read_index - 3] * 0.106595;
vec4 color_bottom = vec4(0.0);
color_bottom += local_cache[read_index + 16] * 0.174938;
color_bottom += local_cache[read_index + 1 + 16] * 0.165569;
color_bottom += local_cache[read_index + 2 + 16] * 0.140367;
color_bottom += local_cache[read_index + 3 + 16] * 0.106595;
color_bottom += local_cache[read_index - 1 + 16] * 0.165569;
color_bottom += local_cache[read_index - 2 + 16] * 0.140367;
color_bottom += local_cache[read_index - 3 + 16] * 0.106595;
// rotate samples to take advantage of cache coherency
uint write_index = gl_LocalInvocationID.y * 2 + gl_LocalInvocationID.x * 16;
temp_cache[write_index] = color_top;
temp_cache[write_index + 1] = color_bottom;
memoryBarrierShared();
barrier();
// Vertical pass
uint index = gl_LocalInvocationID.y + gl_LocalInvocationID.x * 16 + 4;
vec4 color = vec4(0.0);
if (bool(params.flags & FLAG_HORIZONTAL)) {
ivec2 base_pos = ((pos + params.section.xy) << 1) + ivec2(1);
ivec2 section_begin = params.section.xy << 1;
ivec2 section_end = section_begin + (params.section.zw << 1);
color += temp_cache[index] * 0.174938;
color += temp_cache[index + 1] * 0.165569;
color += temp_cache[index + 2] * 0.140367;
color += temp_cache[index + 3] * 0.106595;
color += temp_cache[index - 1] * 0.165569;
color += temp_cache[index - 2] * 0.140367;
color += temp_cache[index - 3] * 0.106595;
if (bool(params.flags & FLAG_HIGH_QUALITY_GLOW)) {
//Sample from two lines to capture single pixel features
GLOW_ADD(ivec2(0, 0), 0.152781);
GLOW_ADD(ivec2(1, 0), 0.144599);
GLOW_ADD(ivec2(2, 0), 0.122589);
GLOW_ADD(ivec2(3, 0), 0.093095);
GLOW_ADD(ivec2(4, 0), 0.063327);
GLOW_ADD(ivec2(-1, 0), 0.144599);
GLOW_ADD(ivec2(-2, 0), 0.122589);
GLOW_ADD(ivec2(-3, 0), 0.093095);
GLOW_ADD(ivec2(-4, 0), 0.063327);
GLOW_ADD(ivec2(0, 1), 0.152781);
GLOW_ADD(ivec2(1, 1), 0.144599);
GLOW_ADD(ivec2(2, 1), 0.122589);
GLOW_ADD(ivec2(3, 1), 0.093095);
GLOW_ADD(ivec2(4, 1), 0.063327);
GLOW_ADD(ivec2(-1, 1), 0.144599);
GLOW_ADD(ivec2(-2, 1), 0.122589);
GLOW_ADD(ivec2(-3, 1), 0.093095);
GLOW_ADD(ivec2(-4, 1), 0.063327);
color *= 0.5;
} else {
GLOW_ADD(ivec2(0, 0), 0.174938);
GLOW_ADD(ivec2(1, 0), 0.165569);
GLOW_ADD(ivec2(2, 0), 0.140367);
GLOW_ADD(ivec2(3, 0), 0.106595);
GLOW_ADD(ivec2(-1, 0), 0.165569);
GLOW_ADD(ivec2(-2, 0), 0.140367);
GLOW_ADD(ivec2(-3, 0), 0.106595);
}
color *= params.glow_strength;
} else {
ivec2 base_pos = pos + params.section.xy;
ivec2 section_begin = params.section.xy;
ivec2 section_end = section_begin + params.section.zw;
GLOW_ADD(ivec2(0, 0), 0.288713);
GLOW_ADD(ivec2(0, 1), 0.233062);
GLOW_ADD(ivec2(0, 2), 0.122581);
GLOW_ADD(ivec2(0, -1), 0.233062);
GLOW_ADD(ivec2(0, -2), 0.122581);
color *= params.glow_strength;
}
#undef GLOW_ADD
color *= params.glow_strength;
if (bool(params.flags & FLAG_GLOW_FIRST_PASS)) {
#ifdef GLOW_USE_AUTO_EXPOSURE

View file

@ -37,12 +37,14 @@ layout(push_constant, binding = 1, std430) uniform Params {
uvec2 glow_texture_size;
float glow_intensity;
uint glow_level_flags;
uint pad3;
uint glow_mode;
float glow_levels[7];
float exposure;
float white;
float auto_exposure_grey;
uint pad2;
vec2 pixel_size;
bool use_fxaa;
@ -186,32 +188,32 @@ vec3 apply_tonemapping(vec3 color, float white) { // inputs are LINEAR, always o
vec3 gather_glow(sampler2D tex, vec2 uv) { // sample all selected glow levels
vec3 glow = vec3(0.0f);
if (bool(params.glow_level_flags & (1 << 0))) {
glow += GLOW_TEXTURE_SAMPLE(tex, uv, 0).rgb;
if (params.glow_levels[0] > 0.0001) {
glow += GLOW_TEXTURE_SAMPLE(tex, uv, 0).rgb * params.glow_levels[0];
}
if (bool(params.glow_level_flags & (1 << 1))) {
glow += GLOW_TEXTURE_SAMPLE(tex, uv, 1).rgb;
if (params.glow_levels[1] > 0.0001) {
glow += GLOW_TEXTURE_SAMPLE(tex, uv, 1).rgb * params.glow_levels[1];
}
if (bool(params.glow_level_flags & (1 << 2))) {
glow += GLOW_TEXTURE_SAMPLE(tex, uv, 2).rgb;
if (params.glow_levels[2] > 0.0001) {
glow += GLOW_TEXTURE_SAMPLE(tex, uv, 2).rgb * params.glow_levels[2];
}
if (bool(params.glow_level_flags & (1 << 3))) {
glow += GLOW_TEXTURE_SAMPLE(tex, uv, 3).rgb;
if (params.glow_levels[3] > 0.0001) {
glow += GLOW_TEXTURE_SAMPLE(tex, uv, 3).rgb * params.glow_levels[3];
}
if (bool(params.glow_level_flags & (1 << 4))) {
glow += GLOW_TEXTURE_SAMPLE(tex, uv, 4).rgb;
if (params.glow_levels[4] > 0.0001) {
glow += GLOW_TEXTURE_SAMPLE(tex, uv, 4).rgb * params.glow_levels[4];
}
if (bool(params.glow_level_flags & (1 << 5))) {
glow += GLOW_TEXTURE_SAMPLE(tex, uv, 5).rgb;
if (params.glow_levels[5] > 0.0001) {
glow += GLOW_TEXTURE_SAMPLE(tex, uv, 5).rgb * params.glow_levels[5];
}
if (bool(params.glow_level_flags & (1 << 6))) {
glow += GLOW_TEXTURE_SAMPLE(tex, uv, 6).rgb;
if (params.glow_levels[6] > 0.0001) {
glow += GLOW_TEXTURE_SAMPLE(tex, uv, 6).rgb * params.glow_levels[6];
}
return glow;

View file

@ -581,7 +581,7 @@ public:
BIND9(environment_set_ssao, RID, bool, float, float, float, float, float, EnvironmentSSAOBlur, float)
BIND2(environment_set_ssao_quality, EnvironmentSSAOQuality, bool)
BIND11(environment_set_glow, RID, bool, int, float, float, float, float, EnvironmentGlowBlendMode, float, float, float)
BIND11(environment_set_glow, RID, bool, Vector<float>, float, float, float, float, EnvironmentGlowBlendMode, float, float, float)
BIND1(environment_glow_set_use_bicubic_upscale, bool)
BIND1(environment_glow_set_use_high_quality, bool)

View file

@ -492,7 +492,7 @@ public:
FUNC1(environment_set_sdfgi_ray_count, EnvironmentSDFGIRayCount)
FUNC1(environment_set_sdfgi_frames_to_converge, EnvironmentSDFGIFramesToConverge)
FUNC11(environment_set_glow, RID, bool, int, float, float, float, float, EnvironmentGlowBlendMode, float, float, float)
FUNC11(environment_set_glow, RID, bool, Vector<float>, float, float, float, float, EnvironmentGlowBlendMode, float, float, float)
FUNC1(environment_glow_set_use_bicubic_upscale, bool)
FUNC1(environment_glow_set_use_high_quality, bool)

View file

@ -1747,7 +1747,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("environment_set_bg_energy", "env", "energy"), &RenderingServer::environment_set_bg_energy);
ClassDB::bind_method(D_METHOD("environment_set_canvas_max_layer", "env", "max_layer"), &RenderingServer::environment_set_canvas_max_layer);
ClassDB::bind_method(D_METHOD("environment_set_ambient_light", "env", "color", "ambient", "energy", "sky_contibution", "reflection_source", "ao_color"), &RenderingServer::environment_set_ambient_light, DEFVAL(RS::ENV_AMBIENT_SOURCE_BG), DEFVAL(1.0), DEFVAL(0.0), DEFVAL(RS::ENV_REFLECTION_SOURCE_BG), DEFVAL(Color()));
ClassDB::bind_method(D_METHOD("environment_set_glow", "env", "enable", "level_flags", "intensity", "strength", "mix", "bloom_threshold", "blend_mode", "hdr_bleed_threshold", "hdr_bleed_scale", "hdr_luminance_cap"), &RenderingServer::environment_set_glow);
ClassDB::bind_method(D_METHOD("environment_set_glow", "env", "enable", "levels", "intensity", "strength", "mix", "bloom_threshold", "blend_mode", "hdr_bleed_threshold", "hdr_bleed_scale", "hdr_luminance_cap"), &RenderingServer::environment_set_glow);
ClassDB::bind_method(D_METHOD("environment_set_tonemap", "env", "tone_mapper", "exposure", "white", "auto_exposure", "min_luminance", "max_luminance", "auto_exp_speed", "auto_exp_grey"), &RenderingServer::environment_set_tonemap);
ClassDB::bind_method(D_METHOD("environment_set_adjustment", "env", "enable", "brightness", "contrast", "saturation", "ramp"), &RenderingServer::environment_set_adjustment);
ClassDB::bind_method(D_METHOD("environment_set_ssr", "env", "enable", "max_steps", "fade_in", "fade_out", "depth_tolerance"), &RenderingServer::environment_set_ssr);

View file

@ -832,7 +832,7 @@ public:
ENV_GLOW_BLEND_MODE_MIX,
};
virtual void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap) = 0;
virtual void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap) = 0;
virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) = 0;
virtual void environment_glow_set_use_high_quality(bool p_enable) = 0;