Browse Source

-Refactored post processing, re-added glow and added a mix blend mode.

Juan Linietsky 5 years ago
parent
commit
b859e69919

+ 36 - 11
scene/resources/environment.cpp

@@ -312,6 +312,14 @@ void Environment::_validate_property(PropertyInfo &property) const {
 		}
 		}
 	}
 	}
 
 
+	if (property.name == "glow_intensity" && glow_blend_mode == GLOW_BLEND_MODE_MIX) {
+		property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL;
+	}
+
+	if (property.name == "glow_mix" && glow_blend_mode != GLOW_BLEND_MODE_MIX) {
+		property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL;
+	}
+
 	if (property.name == "background_color") {
 	if (property.name == "background_color") {
 		if (bg_mode != BG_COLOR && ambient_source != AMBIENT_SOURCE_COLOR) {
 		if (bg_mode != BG_COLOR && ambient_source != AMBIENT_SOURCE_COLOR) {
 			property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL;
 			property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL;
@@ -571,7 +579,7 @@ float Environment::get_ssao_edge_sharpness() const {
 void Environment::set_glow_enabled(bool p_enabled) {
 void Environment::set_glow_enabled(bool p_enabled) {
 
 
 	glow_enabled = p_enabled;
 	glow_enabled = p_enabled;
-	VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale);
+	VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale);
 	_change_notify();
 	_change_notify();
 }
 }
 
 
@@ -589,7 +597,7 @@ void Environment::set_glow_level(int p_level, bool p_enabled) {
 	else
 	else
 		glow_levels &= ~(1 << p_level);
 		glow_levels &= ~(1 << p_level);
 
 
-	VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale);
+	VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale);
 }
 }
 bool Environment::is_glow_level_enabled(int p_level) const {
 bool Environment::is_glow_level_enabled(int p_level) const {
 
 
@@ -602,7 +610,7 @@ void Environment::set_glow_intensity(float p_intensity) {
 
 
 	glow_intensity = p_intensity;
 	glow_intensity = p_intensity;
 
 
-	VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale);
+	VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale);
 }
 }
 float Environment::get_glow_intensity() const {
 float Environment::get_glow_intensity() const {
 
 
@@ -612,18 +620,28 @@ float Environment::get_glow_intensity() const {
 void Environment::set_glow_strength(float p_strength) {
 void Environment::set_glow_strength(float p_strength) {
 
 
 	glow_strength = p_strength;
 	glow_strength = p_strength;
-	VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale);
+	VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale);
 }
 }
 float Environment::get_glow_strength() const {
 float Environment::get_glow_strength() const {
 
 
 	return glow_strength;
 	return glow_strength;
 }
 }
 
 
+void Environment::set_glow_mix(float p_mix) {
+
+	glow_mix = p_mix;
+	VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale);
+}
+float Environment::get_glow_mix() const {
+
+	return glow_mix;
+}
+
 void Environment::set_glow_bloom(float p_threshold) {
 void Environment::set_glow_bloom(float p_threshold) {
 
 
 	glow_bloom = p_threshold;
 	glow_bloom = p_threshold;
 
 
-	VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale);
+	VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale);
 }
 }
 float Environment::get_glow_bloom() const {
 float Environment::get_glow_bloom() const {
 
 
@@ -634,7 +652,8 @@ void Environment::set_glow_blend_mode(GlowBlendMode p_mode) {
 
 
 	glow_blend_mode = p_mode;
 	glow_blend_mode = p_mode;
 
 
-	VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale);
+	VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale);
+	_change_notify();
 }
 }
 Environment::GlowBlendMode Environment::get_glow_blend_mode() const {
 Environment::GlowBlendMode Environment::get_glow_blend_mode() const {
 
 
@@ -645,7 +664,7 @@ void Environment::set_glow_hdr_bleed_threshold(float p_threshold) {
 
 
 	glow_hdr_bleed_threshold = p_threshold;
 	glow_hdr_bleed_threshold = p_threshold;
 
 
-	VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale);
+	VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale);
 }
 }
 float Environment::get_glow_hdr_bleed_threshold() const {
 float Environment::get_glow_hdr_bleed_threshold() const {
 
 
@@ -656,7 +675,7 @@ void Environment::set_glow_hdr_luminance_cap(float p_amount) {
 
 
 	glow_hdr_luminance_cap = p_amount;
 	glow_hdr_luminance_cap = p_amount;
 
 
-	VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale);
+	VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale);
 }
 }
 float Environment::get_glow_hdr_luminance_cap() const {
 float Environment::get_glow_hdr_luminance_cap() const {
 
 
@@ -667,7 +686,7 @@ void Environment::set_glow_hdr_bleed_scale(float p_scale) {
 
 
 	glow_hdr_bleed_scale = p_scale;
 	glow_hdr_bleed_scale = p_scale;
 
 
-	VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale);
+	VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale);
 }
 }
 float Environment::get_glow_hdr_bleed_scale() const {
 float Environment::get_glow_hdr_bleed_scale() const {
 
 
@@ -677,7 +696,7 @@ float Environment::get_glow_hdr_bleed_scale() const {
 void Environment::set_glow_bicubic_upscale(bool p_enable) {
 void Environment::set_glow_bicubic_upscale(bool p_enable) {
 
 
 	glow_bicubic_upscale = p_enable;
 	glow_bicubic_upscale = p_enable;
-	VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale);
+	VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale);
 }
 }
 
 
 bool Environment::is_glow_bicubic_upscale_enabled() const {
 bool Environment::is_glow_bicubic_upscale_enabled() const {
@@ -1224,6 +1243,9 @@ void Environment::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("set_glow_strength", "strength"), &Environment::set_glow_strength);
 	ClassDB::bind_method(D_METHOD("set_glow_strength", "strength"), &Environment::set_glow_strength);
 	ClassDB::bind_method(D_METHOD("get_glow_strength"), &Environment::get_glow_strength);
 	ClassDB::bind_method(D_METHOD("get_glow_strength"), &Environment::get_glow_strength);
 
 
+	ClassDB::bind_method(D_METHOD("set_glow_mix", "mix"), &Environment::set_glow_mix);
+	ClassDB::bind_method(D_METHOD("get_glow_mix"), &Environment::get_glow_mix);
+
 	ClassDB::bind_method(D_METHOD("set_glow_bloom", "amount"), &Environment::set_glow_bloom);
 	ClassDB::bind_method(D_METHOD("set_glow_bloom", "amount"), &Environment::set_glow_bloom);
 	ClassDB::bind_method(D_METHOD("get_glow_bloom"), &Environment::get_glow_bloom);
 	ClassDB::bind_method(D_METHOD("get_glow_bloom"), &Environment::get_glow_bloom);
 
 
@@ -1253,9 +1275,10 @@ void Environment::_bind_methods() {
 	ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "glow_levels/7"), "set_glow_level", "is_glow_level_enabled", 6);
 	ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "glow_levels/7"), "set_glow_level", "is_glow_level_enabled", 6);
 
 
 	ADD_PROPERTY(PropertyInfo(Variant::REAL, "glow_intensity", PROPERTY_HINT_RANGE, "0.0,8.0,0.01"), "set_glow_intensity", "get_glow_intensity");
 	ADD_PROPERTY(PropertyInfo(Variant::REAL, "glow_intensity", PROPERTY_HINT_RANGE, "0.0,8.0,0.01"), "set_glow_intensity", "get_glow_intensity");
+	ADD_PROPERTY(PropertyInfo(Variant::REAL, "glow_mix", PROPERTY_HINT_RANGE, "0.0,1.0,0.001"), "set_glow_mix", "get_glow_mix");
 	ADD_PROPERTY(PropertyInfo(Variant::REAL, "glow_strength", PROPERTY_HINT_RANGE, "0.0,2.0,0.01"), "set_glow_strength", "get_glow_strength");
 	ADD_PROPERTY(PropertyInfo(Variant::REAL, "glow_strength", PROPERTY_HINT_RANGE, "0.0,2.0,0.01"), "set_glow_strength", "get_glow_strength");
 	ADD_PROPERTY(PropertyInfo(Variant::REAL, "glow_bloom", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"), "set_glow_bloom", "get_glow_bloom");
 	ADD_PROPERTY(PropertyInfo(Variant::REAL, "glow_bloom", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"), "set_glow_bloom", "get_glow_bloom");
-	ADD_PROPERTY(PropertyInfo(Variant::INT, "glow_blend_mode", PROPERTY_HINT_ENUM, "Additive,Screen,Softlight,Replace"), "set_glow_blend_mode", "get_glow_blend_mode");
+	ADD_PROPERTY(PropertyInfo(Variant::INT, "glow_blend_mode", PROPERTY_HINT_ENUM, "Additive,Screen,Softlight,Replace,Mix"), "set_glow_blend_mode", "get_glow_blend_mode");
 	ADD_PROPERTY(PropertyInfo(Variant::REAL, "glow_hdr_threshold", PROPERTY_HINT_RANGE, "0.0,4.0,0.01"), "set_glow_hdr_bleed_threshold", "get_glow_hdr_bleed_threshold");
 	ADD_PROPERTY(PropertyInfo(Variant::REAL, "glow_hdr_threshold", PROPERTY_HINT_RANGE, "0.0,4.0,0.01"), "set_glow_hdr_bleed_threshold", "get_glow_hdr_bleed_threshold");
 	ADD_PROPERTY(PropertyInfo(Variant::REAL, "glow_hdr_luminance_cap", PROPERTY_HINT_RANGE, "0.0,256.0,0.01"), "set_glow_hdr_luminance_cap", "get_glow_hdr_luminance_cap");
 	ADD_PROPERTY(PropertyInfo(Variant::REAL, "glow_hdr_luminance_cap", PROPERTY_HINT_RANGE, "0.0,256.0,0.01"), "set_glow_hdr_luminance_cap", "get_glow_hdr_luminance_cap");
 	ADD_PROPERTY(PropertyInfo(Variant::REAL, "glow_hdr_scale", PROPERTY_HINT_RANGE, "0.0,4.0,0.01"), "set_glow_hdr_bleed_scale", "get_glow_hdr_bleed_scale");
 	ADD_PROPERTY(PropertyInfo(Variant::REAL, "glow_hdr_scale", PROPERTY_HINT_RANGE, "0.0,4.0,0.01"), "set_glow_hdr_bleed_scale", "get_glow_hdr_bleed_scale");
@@ -1304,6 +1327,7 @@ void Environment::_bind_methods() {
 	BIND_ENUM_CONSTANT(GLOW_BLEND_MODE_SCREEN);
 	BIND_ENUM_CONSTANT(GLOW_BLEND_MODE_SCREEN);
 	BIND_ENUM_CONSTANT(GLOW_BLEND_MODE_SOFTLIGHT);
 	BIND_ENUM_CONSTANT(GLOW_BLEND_MODE_SOFTLIGHT);
 	BIND_ENUM_CONSTANT(GLOW_BLEND_MODE_REPLACE);
 	BIND_ENUM_CONSTANT(GLOW_BLEND_MODE_REPLACE);
+	BIND_ENUM_CONSTANT(GLOW_BLEND_MODE_MIX);
 
 
 	BIND_ENUM_CONSTANT(TONE_MAPPER_LINEAR);
 	BIND_ENUM_CONSTANT(TONE_MAPPER_LINEAR);
 	BIND_ENUM_CONSTANT(TONE_MAPPER_REINHARDT);
 	BIND_ENUM_CONSTANT(TONE_MAPPER_REINHARDT);
@@ -1387,6 +1411,7 @@ Environment::Environment() :
 	glow_levels = (1 << 2) | (1 << 4);
 	glow_levels = (1 << 2) | (1 << 4);
 	glow_intensity = 0.8;
 	glow_intensity = 0.8;
 	glow_strength = 1.0;
 	glow_strength = 1.0;
+	glow_mix = 0.05;
 	glow_bloom = 0.0;
 	glow_bloom = 0.0;
 	glow_blend_mode = GLOW_BLEND_MODE_SOFTLIGHT;
 	glow_blend_mode = GLOW_BLEND_MODE_SOFTLIGHT;
 	glow_hdr_bleed_threshold = 1.0;
 	glow_hdr_bleed_threshold = 1.0;

+ 5 - 0
scene/resources/environment.h

@@ -77,6 +77,7 @@ public:
 		GLOW_BLEND_MODE_SCREEN,
 		GLOW_BLEND_MODE_SCREEN,
 		GLOW_BLEND_MODE_SOFTLIGHT,
 		GLOW_BLEND_MODE_SOFTLIGHT,
 		GLOW_BLEND_MODE_REPLACE,
 		GLOW_BLEND_MODE_REPLACE,
+		GLOW_BLEND_MODE_MIX,
 	};
 	};
 
 
 	enum DOFBlurQuality {
 	enum DOFBlurQuality {
@@ -154,6 +155,7 @@ private:
 	int glow_levels;
 	int glow_levels;
 	float glow_intensity;
 	float glow_intensity;
 	float glow_strength;
 	float glow_strength;
+	float glow_mix;
 	float glow_bloom;
 	float glow_bloom;
 	GlowBlendMode glow_blend_mode;
 	GlowBlendMode glow_blend_mode;
 	float glow_hdr_bleed_threshold;
 	float glow_hdr_bleed_threshold;
@@ -333,6 +335,9 @@ public:
 	void set_glow_strength(float p_strength);
 	void set_glow_strength(float p_strength);
 	float get_glow_strength() const;
 	float get_glow_strength() const;
 
 
+	void set_glow_mix(float p_mix);
+	float get_glow_mix() const;
+
 	void set_glow_bloom(float p_threshold);
 	void set_glow_bloom(float p_threshold);
 	float get_glow_bloom() const;
 	float get_glow_bloom() const;
 
 

+ 1 - 1
servers/visual/rasterizer.h

@@ -77,7 +77,7 @@ public:
 
 
 	virtual void environment_set_dof_blur_near(RID p_env, bool p_enable, float p_distance, float p_transition, float p_far_amount, VS::EnvironmentDOFBlurQuality p_quality) = 0;
 	virtual void environment_set_dof_blur_near(RID p_env, bool p_enable, float p_distance, float p_transition, float p_far_amount, VS::EnvironmentDOFBlurQuality p_quality) = 0;
 	virtual void environment_set_dof_blur_far(RID p_env, bool p_enable, float p_distance, float p_transition, float p_far_amount, VS::EnvironmentDOFBlurQuality p_quality) = 0;
 	virtual void environment_set_dof_blur_far(RID p_env, bool p_enable, float p_distance, float p_transition, float p_far_amount, VS::EnvironmentDOFBlurQuality p_quality) = 0;
-	virtual void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_bloom_threshold, VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale) = 0;
+	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, VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale) = 0;
 	virtual void environment_set_fog(RID p_env, bool p_enable, float p_begin, float p_end, RID p_gradient_texture) = 0;
 	virtual void environment_set_fog(RID p_env, bool p_enable, float p_begin, float p_end, RID p_gradient_texture) = 0;
 
 
 	virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance, bool p_roughness) = 0;
 	virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance, bool p_roughness) = 0;

+ 59 - 3
servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp

@@ -45,7 +45,7 @@ static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_basis, float *p_ar
 	p_array[11] = 0;
 	p_array[11] = 0;
 }
 }
 
 
-RID RasterizerEffectsRD::_get_uniform_set_from_texture(RID p_texture) {
+RID RasterizerEffectsRD::_get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps) {
 
 
 	if (texture_to_uniform_set_cache.has(p_texture)) {
 	if (texture_to_uniform_set_cache.has(p_texture)) {
 		RID uniform_set = texture_to_uniform_set_cache[p_texture];
 		RID uniform_set = texture_to_uniform_set_cache[p_texture];
@@ -58,7 +58,7 @@ RID RasterizerEffectsRD::_get_uniform_set_from_texture(RID p_texture) {
 	RD::Uniform u;
 	RD::Uniform u;
 	u.type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
 	u.type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
 	u.binding = 0;
 	u.binding = 0;
-	u.ids.push_back(default_sampler);
+	u.ids.push_back(p_use_mipmaps ? default_mipmap_sampler : default_sampler);
 	u.ids.push_back(p_texture);
 	u.ids.push_back(p_texture);
 	uniforms.push_back(u);
 	uniforms.push_back(u);
 	//any thing with the same configuration (one texture in binding 0 for set 0), is good
 	//any thing with the same configuration (one texture in binding 0 for set 0), is good
@@ -147,6 +147,55 @@ void RasterizerEffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_framebuff
 	RD::get_singleton()->draw_list_end();
 	RD::get_singleton()->draw_list_end();
 }
 }
 
 
+void RasterizerEffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength, 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) {
+
+	zeromem(&blur.push_constant, sizeof(BlurPushConstant));
+
+	BlurMode blur_mode = p_first_pass && p_auto_exposure.is_valid() ? BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE : BLUR_MODE_GAUSSIAN_GLOW;
+	uint32_t base_flags = 0;
+
+	blur.push_constant.pixel_size[0] = p_pixel_size.x;
+	blur.push_constant.pixel_size[1] = p_pixel_size.y;
+
+	blur.push_constant.glow_strength = p_strength;
+	blur.push_constant.glow_bloom = p_bloom;
+	blur.push_constant.glow_hdr_threshold = p_hdr_bleed_treshold;
+	blur.push_constant.glow_hdr_scale = p_hdr_bleed_scale;
+	blur.push_constant.glow_exposure = p_exposure;
+	blur.push_constant.glow_white = 0; //actually unused
+	blur.push_constant.glow_luminance_cap = p_luminance_cap;
+	blur.push_constant.glow_auto_exposure_grey = 0; //unused also
+
+	//HORIZONTAL
+	RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer_half, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+	RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer_half)));
+	RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
+	if (p_auto_exposure.is_valid() && p_first_pass) {
+		RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_auto_exposure), 1);
+	}
+	RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
+
+	blur.push_constant.flags = base_flags | BLUR_FLAG_HORIZONTAL | (p_first_pass ? BLUR_FLAG_GLOW_FIRST_PASS : 0);
+	RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur.push_constant, sizeof(BlurPushConstant));
+
+	RD::get_singleton()->draw_list_draw(draw_list, true);
+	RD::get_singleton()->draw_list_end();
+
+	blur_mode = BLUR_MODE_GAUSSIAN_GLOW;
+
+	//VERTICAL
+	draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+	RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
+	RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_rd_texture_half), 0);
+	RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
+
+	blur.push_constant.flags = base_flags;
+	RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur.push_constant, sizeof(BlurPushConstant));
+
+	RD::get_singleton()->draw_list_draw(draw_list, true);
+	RD::get_singleton()->draw_list_end();
+}
+
 void RasterizerEffectsRD::cubemap_roughness(RID p_source_rd_texture, bool p_source_is_panorama, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness) {
 void RasterizerEffectsRD::cubemap_roughness(RID p_source_rd_texture, bool p_source_is_panorama, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness) {
 
 
 	zeromem(&roughness.push_constant, sizeof(CubemapRoughnessPushConstant));
 	zeromem(&roughness.push_constant, sizeof(CubemapRoughnessPushConstant));
@@ -241,6 +290,7 @@ void RasterizerEffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer,
 	tonemap.push_constant.glow_level_flags = p_settings.glow_level_flags;
 	tonemap.push_constant.glow_level_flags = p_settings.glow_level_flags;
 	tonemap.push_constant.glow_texture_size[0] = p_settings.glow_texture_size.x;
 	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_texture_size[1] = p_settings.glow_texture_size.y;
+	tonemap.push_constant.glow_mode = p_settings.glow_mode;
 
 
 	TonemapMode mode = p_settings.glow_use_bicubic_upscale ? TONEMAP_MODE_BICUBIC_GLOW_FILTER : TONEMAP_MODE_NORMAL;
 	TonemapMode mode = p_settings.glow_use_bicubic_upscale ? TONEMAP_MODE_BICUBIC_GLOW_FILTER : TONEMAP_MODE_NORMAL;
 
 
@@ -256,7 +306,7 @@ void RasterizerEffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer,
 	RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, tonemap.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dst_framebuffer)));
 	RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, tonemap.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dst_framebuffer)));
 	RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_color), 0);
 	RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_color), 0);
 	RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_settings.exposure_texture), 1);
 	RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_settings.exposure_texture), 1);
-	RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_settings.glow_texture), 2);
+	RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_settings.glow_texture, true), 2);
 	RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_settings.color_correction_texture), 3);
 	RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_settings.color_correction_texture), 3);
 	RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
 	RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
 
 
@@ -361,6 +411,12 @@ RasterizerEffectsRD::RasterizerEffectsRD() {
 
 
 	default_sampler = RD::get_singleton()->sampler_create(sampler);
 	default_sampler = RD::get_singleton()->sampler_create(sampler);
 
 
+	sampler.min_filter = RD::SAMPLER_FILTER_LINEAR;
+	sampler.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+	sampler.max_lod = 1e20;
+
+	default_mipmap_sampler = RD::get_singleton()->sampler_create(sampler);
+
 	{ //create index array for copy shaders
 	{ //create index array for copy shaders
 		PoolVector<uint8_t> pv;
 		PoolVector<uint8_t> pv;
 		pv.resize(6 * 4);
 		pv.resize(6 * 4);

+ 8 - 2
servers/visual/rasterizer_rd/rasterizer_effects_rd.h

@@ -198,17 +198,22 @@ class RasterizerEffectsRD {
 	} copy;
 	} copy;
 
 
 	RID default_sampler;
 	RID default_sampler;
+	RID default_mipmap_sampler;
 	RID index_buffer;
 	RID index_buffer;
 	RID index_array;
 	RID index_array;
 
 
 	Map<RID, RID> texture_to_uniform_set_cache;
 	Map<RID, RID> texture_to_uniform_set_cache;
 
 
-	RID _get_uniform_set_from_texture(RID p_texture);
+	RID _get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps = false);
 
 
 public:
 public:
+	//TODO must re-do most of the shaders in compute
+
 	void region_copy(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_region);
 	void region_copy(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_region);
 	void copy_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, bool p_flip_y = false);
 	void copy_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, bool p_flip_y = false);
 	void gaussian_blur(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, const Rect2 &p_region);
 	void gaussian_blur(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, const Rect2 &p_region);
+	void gaussian_glow(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength = 1.0, 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());
+
 	void cubemap_roughness(RID p_source_rd_texture, bool p_source_is_panorama, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness);
 	void cubemap_roughness(RID p_source_rd_texture, bool p_source_is_panorama, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness);
 	void render_panorama(RD::DrawListID p_list, RenderingDevice::FramebufferFormatID p_fb_format, RID p_panorama, const CameraMatrix &p_camera, const Basis &p_orientation, float p_alpha, float p_multipler);
 	void render_panorama(RD::DrawListID p_list, RenderingDevice::FramebufferFormatID p_fb_format, RID p_panorama, const CameraMatrix &p_camera, const Basis &p_orientation, float p_alpha, float p_multipler);
 	void make_mipmap(RID p_source_rd_texture, RID p_framebuffer_half, const Vector2 &p_pixel_size);
 	void make_mipmap(RID p_source_rd_texture, RID p_framebuffer_half, const Vector2 &p_pixel_size);
@@ -221,7 +226,8 @@ public:
 			GLOW_MODE_ADD,
 			GLOW_MODE_ADD,
 			GLOW_MODE_SCREEN,
 			GLOW_MODE_SCREEN,
 			GLOW_MODE_SOFTLIGHT,
 			GLOW_MODE_SOFTLIGHT,
-			GLOW_MODE_REPLACE
+			GLOW_MODE_REPLACE,
+			GLOW_MODE_MIX
 		};
 		};
 
 
 		GlowMode glow_mode = GLOW_MODE_ADD;
 		GlowMode glow_mode = GLOW_MODE_ADD;

+ 34 - 204
servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.cpp

@@ -536,34 +536,20 @@ void RasterizerSceneForwardRD::RenderBufferDataForward::clear() {
 		color_fb = RID();
 		color_fb = RID();
 	}
 	}
 
 
-	if (color.is_valid()) {
-		RD::get_singleton()->free(color);
-		color = RID();
-	}
-
 	if (depth.is_valid()) {
 	if (depth.is_valid()) {
 		RD::get_singleton()->free(depth);
 		RD::get_singleton()->free(depth);
 		depth = RID();
 		depth = RID();
 	}
 	}
 }
 }
 
 
-void RasterizerSceneForwardRD::RenderBufferDataForward::configure(RID p_render_target, int p_width, int p_height, VS::ViewportMSAA p_msaa) {
+void RasterizerSceneForwardRD::RenderBufferDataForward::configure(RID p_color_buffer, int p_width, int p_height, VS::ViewportMSAA p_msaa) {
 	clear();
 	clear();
 
 
 	width = p_width;
 	width = p_width;
 	height = p_height;
 	height = p_height;
 
 
-	render_target = p_render_target;
+	color = p_color_buffer;
 
 
-	{
-		RD::TextureFormat tf;
-		tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
-		tf.width = p_width;
-		tf.height = p_height;
-		tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
-
-		color = RD::get_singleton()->texture_create(tf, RD::TextureView());
-	}
 	{
 	{
 		RD::TextureFormat tf;
 		RD::TextureFormat tf;
 		tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT;
 		tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT;
@@ -576,7 +562,7 @@ void RasterizerSceneForwardRD::RenderBufferDataForward::configure(RID p_render_t
 
 
 	{
 	{
 		Vector<RID> fb;
 		Vector<RID> fb;
-		fb.push_back(color);
+		fb.push_back(p_color_buffer);
 		fb.push_back(depth);
 		fb.push_back(depth);
 
 
 		color_fb = RD::get_singleton()->framebuffer_create(fb);
 		color_fb = RD::get_singleton()->framebuffer_create(fb);
@@ -589,7 +575,7 @@ void RasterizerSceneForwardRD::RenderBufferDataForward::configure(RID p_render_t
 	}
 	}
 	{
 	{
 		Vector<RID> fb;
 		Vector<RID> fb;
-		fb.push_back(color);
+		fb.push_back(p_color_buffer);
 
 
 		color_only_fb = RD::get_singleton()->framebuffer_create(fb);
 		color_only_fb = RD::get_singleton()->framebuffer_create(fb);
 	}
 	}
@@ -951,7 +937,7 @@ void RasterizerSceneForwardRD::_render_list(RenderingDevice::DrawListID p_draw_l
 	}
 	}
 }
 }
 
 
-void RasterizerSceneForwardRD::_setup_environment(RID p_render_target, RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y) {
+void RasterizerSceneForwardRD::_setup_environment(RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color) {
 
 
 	//CameraMatrix projection = p_cam_projection;
 	//CameraMatrix projection = p_cam_projection;
 	//projection.flip_y(); // Vulkan and modern APIs use Y-Down
 	//projection.flip_y(); // Vulkan and modern APIs use Y-Down
@@ -981,7 +967,7 @@ void RasterizerSceneForwardRD::_setup_environment(RID p_render_target, RID p_env
 	//time global variables
 	//time global variables
 	scene_state.ubo.time = time;
 	scene_state.ubo.time = time;
 
 
-	if (debug_draw == VS::VIEWPORT_DEBUG_DRAW_UNSHADED) {
+	if (get_debug_draw_mode() == VS::VIEWPORT_DEBUG_DRAW_UNSHADED) {
 
 
 		scene_state.ubo.use_ambient_light = true;
 		scene_state.ubo.use_ambient_light = true;
 		scene_state.ubo.ambient_light_color_energy[0] = 1;
 		scene_state.ubo.ambient_light_color_energy[0] = 1;
@@ -1004,7 +990,7 @@ void RasterizerSceneForwardRD::_setup_environment(RID p_render_target, RID p_env
 		//ambient
 		//ambient
 		if (ambient_src == VS::ENV_AMBIENT_SOURCE_BG && (env_bg == VS::ENV_BG_CLEAR_COLOR || env_bg == VS::ENV_BG_COLOR)) {
 		if (ambient_src == VS::ENV_AMBIENT_SOURCE_BG && (env_bg == VS::ENV_BG_CLEAR_COLOR || env_bg == VS::ENV_BG_COLOR)) {
 
 
-			Color color = (p_render_target.is_valid() && env_bg == VS::ENV_BG_CLEAR_COLOR) ? (p_render_target.is_valid() ? storage->render_target_get_clear_request_color(p_render_target) : Color(0, 0, 0)) : environment_get_bg_color(p_environment);
+			Color color = env_bg == VS::ENV_BG_CLEAR_COLOR ? p_default_bg_color : environment_get_bg_color(p_environment);
 			color = color.to_linear();
 			color = color.to_linear();
 
 
 			scene_state.ubo.ambient_light_color_energy[0] = color.r * bg_energy;
 			scene_state.ubo.ambient_light_color_energy[0] = color.r * bg_energy;
@@ -1039,138 +1025,21 @@ void RasterizerSceneForwardRD::_setup_environment(RID p_render_target, RID p_env
 
 
 	} else {
 	} else {
 
 
-		if (p_reflection_probe.is_valid() && !storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_reflection_probe))) {
-			scene_state.ubo.use_ambient_light = true;
-			Color clear_color = storage->get_default_clear_color();
-			clear_color = clear_color.to_linear();
-			scene_state.ubo.ambient_light_color_energy[0] = clear_color.r;
-			scene_state.ubo.ambient_light_color_energy[1] = clear_color.g;
-			scene_state.ubo.ambient_light_color_energy[2] = clear_color.b;
-			scene_state.ubo.ambient_light_color_energy[3] = 1.0;
-
-		} else if (p_render_target.is_valid()) {
+		if (p_reflection_probe.is_valid() && storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_reflection_probe))) {
+			scene_state.ubo.use_ambient_light = false;
+		} else {
 			scene_state.ubo.use_ambient_light = true;
 			scene_state.ubo.use_ambient_light = true;
-			Color clear_color = storage->render_target_get_clear_request_color(p_render_target);
+			Color clear_color = p_default_bg_color;
 			clear_color = clear_color.to_linear();
 			clear_color = clear_color.to_linear();
 			scene_state.ubo.ambient_light_color_energy[0] = clear_color.r;
 			scene_state.ubo.ambient_light_color_energy[0] = clear_color.r;
 			scene_state.ubo.ambient_light_color_energy[1] = clear_color.g;
 			scene_state.ubo.ambient_light_color_energy[1] = clear_color.g;
 			scene_state.ubo.ambient_light_color_energy[2] = clear_color.b;
 			scene_state.ubo.ambient_light_color_energy[2] = clear_color.b;
 			scene_state.ubo.ambient_light_color_energy[3] = 1.0;
 			scene_state.ubo.ambient_light_color_energy[3] = 1.0;
-		} else {
-			scene_state.ubo.use_ambient_light = false;
 		}
 		}
 
 
 		scene_state.ubo.use_ambient_cubemap = false;
 		scene_state.ubo.use_ambient_cubemap = false;
 		scene_state.ubo.use_reflection_cubemap = false;
 		scene_state.ubo.use_reflection_cubemap = false;
 	}
 	}
-#if 0
-	//bg and ambient
-	if (p_environment.is_valid()) {
-
-		state.ubo_data.bg_energy = env->bg_energy;
-		state.ubo_data.ambient_energy = env->ambient_energy;
-		Color linear_ambient_color = env->ambient_color.to_linear();
-		state.ubo_data.ambient_light_color[0] = linear_ambient_color.r;
-		state.ubo_data.ambient_light_color[1] = linear_ambient_color.g;
-		state.ubo_data.ambient_light_color[2] = linear_ambient_color.b;
-		state.ubo_data.ambient_light_color[3] = linear_ambient_color.a;
-
-		Color bg_color;
-
-		switch (env->bg_mode) {
-			case VS::ENV_BG_CLEAR_COLOR: {
-				bg_color = storage->frame.clear_request_color.to_linear();
-			} break;
-			case VS::ENV_BG_COLOR: {
-				bg_color = env->bg_color.to_linear();
-			} break;
-			default: {
-				bg_color = Color(0, 0, 0, 1);
-			} break;
-		}
-
-		state.ubo_data.bg_color[0] = bg_color.r;
-		state.ubo_data.bg_color[1] = bg_color.g;
-		state.ubo_data.bg_color[2] = bg_color.b;
-		state.ubo_data.bg_color[3] = bg_color.a;
-
-		//use the inverse of our sky_orientation, we may need to skip this if we're using a reflection probe?
-		sky_orientation = Transform(env->sky_orientation, Vector3(0.0, 0.0, 0.0)).affine_inverse();
-
-		state.env_radiance_data.ambient_contribution = env->ambient_sky_contribution;
-		state.ubo_data.ambient_occlusion_affect_light = env->ssao_light_affect;
-		state.ubo_data.ambient_occlusion_affect_ssao = env->ssao_ao_channel_affect;
-
-		//fog
-
-		Color linear_fog = env->fog_color.to_linear();
-		state.ubo_data.fog_color_enabled[0] = linear_fog.r;
-		state.ubo_data.fog_color_enabled[1] = linear_fog.g;
-		state.ubo_data.fog_color_enabled[2] = linear_fog.b;
-		state.ubo_data.fog_color_enabled[3] = (!p_no_fog && env->fog_enabled) ? 1.0 : 0.0;
-		state.ubo_data.fog_density = linear_fog.a;
-
-		Color linear_sun = env->fog_sun_color.to_linear();
-		state.ubo_data.fog_sun_color_amount[0] = linear_sun.r;
-		state.ubo_data.fog_sun_color_amount[1] = linear_sun.g;
-		state.ubo_data.fog_sun_color_amount[2] = linear_sun.b;
-		state.ubo_data.fog_sun_color_amount[3] = env->fog_sun_amount;
-		state.ubo_data.fog_depth_enabled = env->fog_depth_enabled;
-		state.ubo_data.fog_depth_begin = env->fog_depth_begin;
-		state.ubo_data.fog_depth_end = env->fog_depth_end;
-		state.ubo_data.fog_depth_curve = env->fog_depth_curve;
-		state.ubo_data.fog_transmit_enabled = env->fog_transmit_enabled;
-		state.ubo_data.fog_transmit_curve = env->fog_transmit_curve;
-		state.ubo_data.fog_height_enabled = env->fog_height_enabled;
-		state.ubo_data.fog_height_min = env->fog_height_min;
-		state.ubo_data.fog_height_max = env->fog_height_max;
-		state.ubo_data.fog_height_curve = env->fog_height_curve;
-
-	} else {
-		state.ubo_data.bg_energy = 1.0;
-		state.ubo_data.ambient_energy = 1.0;
-		//use from clear color instead, since there is no ambient
-		Color linear_ambient_color = storage->frame.clear_request_color.to_linear();
-		state.ubo_data.ambient_light_color[0] = linear_ambient_color.r;
-		state.ubo_data.ambient_light_color[1] = linear_ambient_color.g;
-		state.ubo_data.ambient_light_color[2] = linear_ambient_color.b;
-		state.ubo_data.ambient_light_color[3] = linear_ambient_color.a;
-
-		state.ubo_data.bg_color[0] = linear_ambient_color.r;
-		state.ubo_data.bg_color[1] = linear_ambient_color.g;
-		state.ubo_data.bg_color[2] = linear_ambient_color.b;
-		state.ubo_data.bg_color[3] = linear_ambient_color.a;
-
-		state.env_radiance_data.ambient_contribution = 0;
-		state.ubo_data.ambient_occlusion_affect_light = 0;
-
-		state.ubo_data.fog_color_enabled[3] = 0.0;
-	}
-
-	{
-		//directional shadow
-
-		state.ubo_data.shadow_directional_pixel_size[0] = 1.0 / directional_shadow.size;
-		state.ubo_data.shadow_directional_pixel_size[1] = 1.0 / directional_shadow.size;
-
-		glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4);
-		glBindTexture(GL_TEXTURE_2D, directional_shadow.depth);
-		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
-		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LESS);
-	}
-
-	glBindBuffer(GL_UNIFORM_BUFFER, state.scene_ubo);
-	glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(State::SceneDataUBO), &state.ubo_data);
-	glBindBuffer(GL_UNIFORM_BUFFER, 0);
-
-	//fill up environment
-
-	store_transform(sky_orientation * p_cam_transform, state.env_radiance_data.transform);
-
-	glBindBuffer(GL_UNIFORM_BUFFER, state.env_radiance_ubo);
-	glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(State::EnvironmentRadianceUBO), &state.env_radiance_data);
-	glBindBuffer(GL_UNIFORM_BUFFER, 0);
-#endif
 
 
 	RD::get_singleton()->buffer_update(scene_state.uniform_buffer, 0, sizeof(SceneState::UBO), &scene_state.ubo, true);
 	RD::get_singleton()->buffer_update(scene_state.uniform_buffer, 0, sizeof(SceneState::UBO), &scene_state.ubo, true);
 }
 }
@@ -1181,12 +1050,12 @@ void RasterizerSceneForwardRD::_add_geometry(InstanceBase *p_instance, uint32_t
 
 
 	m_src = p_instance->material_override.is_valid() ? p_instance->material_override : p_material;
 	m_src = p_instance->material_override.is_valid() ? p_instance->material_override : p_material;
 
 
-	if (unlikely(debug_draw != VS::VIEWPORT_DEBUG_DRAW_DISABLED)) {
-		if (debug_draw == VS::VIEWPORT_DEBUG_DRAW_OVERDRAW) {
+	if (unlikely(get_debug_draw_mode() != VS::VIEWPORT_DEBUG_DRAW_DISABLED)) {
+		if (get_debug_draw_mode() == VS::VIEWPORT_DEBUG_DRAW_OVERDRAW) {
 			m_src = overdraw_material;
 			m_src = overdraw_material;
-		} else if (debug_draw == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME) {
+		} else if (get_debug_draw_mode() == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME) {
 			m_src = wireframe_material;
 			m_src = wireframe_material;
-		} else if (debug_draw == VS::VIEWPORT_DEBUG_DRAW_LIGHTING) {
+		} else if (get_debug_draw_mode() == VS::VIEWPORT_DEBUG_DRAW_LIGHTING) {
 			m_src = default_material;
 			m_src = default_material;
 		}
 		}
 	}
 	}
@@ -1756,9 +1625,12 @@ void RasterizerSceneForwardRD::_setup_lights(RID *p_light_cull_result, int p_lig
 	}
 	}
 }
 }
 
 
-void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {
+void RasterizerSceneForwardRD::_render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color) {
 
 
-	RenderBufferDataForward *render_buffer = (RenderBufferDataForward *)p_buffer_data;
+	RenderBufferDataForward *render_buffer = NULL;
+	if (p_render_buffer.is_valid()) {
+		render_buffer = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffer);
+	}
 
 
 	//first of all, make a new render pass
 	//first of all, make a new render pass
 	render_pass++;
 	render_pass++;
@@ -1788,7 +1660,7 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co
 
 
 	RENDER_TIMESTAMP("Setup 3D Scene");
 	RENDER_TIMESTAMP("Setup 3D Scene");
 
 
-	if (debug_draw == VS::VIEWPORT_DEBUG_DRAW_UNSHADED) {
+	if (get_debug_draw_mode() == VS::VIEWPORT_DEBUG_DRAW_UNSHADED) {
 		p_light_cull_count = 0;
 		p_light_cull_count = 0;
 		p_reflection_probe_cull_count = 0;
 		p_reflection_probe_cull_count = 0;
 		p_gi_probe_cull_count = 0;
 		p_gi_probe_cull_count = 0;
@@ -1816,7 +1688,6 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co
 	scene_state.ubo.viewport_size[0] = vp_he.x;
 	scene_state.ubo.viewport_size[0] = vp_he.x;
 	scene_state.ubo.viewport_size[1] = vp_he.y;
 	scene_state.ubo.viewport_size[1] = vp_he.y;
 
 
-	RID render_target;
 	Size2 screen_pixel_size;
 	Size2 screen_pixel_size;
 	RID opaque_framebuffer;
 	RID opaque_framebuffer;
 	RID depth_framebuffer;
 	RID depth_framebuffer;
@@ -1825,7 +1696,6 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co
 	if (render_buffer) {
 	if (render_buffer) {
 		screen_pixel_size.width = 1.0 / render_buffer->width;
 		screen_pixel_size.width = 1.0 / render_buffer->width;
 		screen_pixel_size.height = 1.0 / render_buffer->height;
 		screen_pixel_size.height = 1.0 / render_buffer->height;
-		render_target = render_buffer->render_target;
 
 
 		opaque_framebuffer = render_buffer->color_fb;
 		opaque_framebuffer = render_buffer->color_fb;
 		depth_framebuffer = render_buffer->depth_fb;
 		depth_framebuffer = render_buffer->depth_fb;
@@ -1851,7 +1721,7 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co
 	_setup_lights(p_light_cull_result, p_light_cull_count, p_cam_transform.affine_inverse(), p_shadow_atlas, using_shadows);
 	_setup_lights(p_light_cull_result, p_light_cull_count, p_cam_transform.affine_inverse(), p_shadow_atlas, using_shadows);
 	_setup_reflections(p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_cam_transform.affine_inverse(), p_environment);
 	_setup_reflections(p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_cam_transform.affine_inverse(), p_environment);
 	_setup_gi_probes(p_gi_probe_cull_result, p_gi_probe_cull_count, p_cam_transform);
 	_setup_gi_probes(p_gi_probe_cull_result, p_gi_probe_cull_count, p_cam_transform);
-	_setup_environment(render_target, p_environment, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_pixel_size, p_shadow_atlas, !p_reflection_probe.is_valid());
+	_setup_environment(p_environment, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_pixel_size, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color);
 
 
 	render_list.clear();
 	render_list.clear();
 	_fill_render_list(p_cull_result, p_cull_count, PASS_MODE_COLOR, render_buffer == nullptr);
 	_fill_render_list(p_cull_result, p_cull_count, PASS_MODE_COLOR, render_buffer == nullptr);
@@ -1862,14 +1732,14 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co
 	Color clear_color;
 	Color clear_color;
 	bool keep_color = false;
 	bool keep_color = false;
 
 
-	if (debug_draw == VS::VIEWPORT_DEBUG_DRAW_OVERDRAW) {
+	if (get_debug_draw_mode() == VS::VIEWPORT_DEBUG_DRAW_OVERDRAW) {
 		clear_color = Color(0, 0, 0, 1); //in overdraw mode, BG should always be black
 		clear_color = Color(0, 0, 0, 1); //in overdraw mode, BG should always be black
 	} else if (is_environment(p_environment)) {
 	} else if (is_environment(p_environment)) {
 		VS::EnvironmentBG bg_mode = environment_get_background(p_environment);
 		VS::EnvironmentBG bg_mode = environment_get_background(p_environment);
 		float bg_energy = environment_get_bg_energy(p_environment);
 		float bg_energy = environment_get_bg_energy(p_environment);
 		switch (bg_mode) {
 		switch (bg_mode) {
 			case VS::ENV_BG_CLEAR_COLOR: {
 			case VS::ENV_BG_CLEAR_COLOR: {
-				clear_color = render_target.is_valid() ? storage->render_target_get_clear_request_color(render_target) : environment_get_bg_color(p_environment);
+				clear_color = p_default_bg_color;
 				clear_color.r *= bg_energy;
 				clear_color.r *= bg_energy;
 				clear_color.g *= bg_energy;
 				clear_color.g *= bg_energy;
 				clear_color.b *= bg_energy;
 				clear_color.b *= bg_energy;
@@ -1896,14 +1766,12 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co
 			case VS::ENV_BG_CAMERA_FEED: {
 			case VS::ENV_BG_CAMERA_FEED: {
 
 
 			} break;
 			} break;
+			default: {
+			}
 		}
 		}
 	} else {
 	} else {
 
 
-		if (p_reflection_probe.is_valid() && !storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_reflection_probe))) {
-			clear_color = storage->get_default_clear_color();
-		} else if (render_target.is_valid()) {
-			clear_color = storage->render_target_get_clear_request_color(render_target);
-		}
+		clear_color = p_default_bg_color;
 	}
 	}
 
 
 	_setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), radiance_cubemap, p_shadow_atlas, p_reflection_atlas);
 	_setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), radiance_cubemap, p_shadow_atlas, p_reflection_atlas);
@@ -1913,7 +1781,7 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co
 	_fill_instances(render_list.elements, render_list.element_count, false);
 	_fill_instances(render_list.elements, render_list.element_count, false);
 
 
 	bool can_continue = true; //unless the middle buffers are needed
 	bool can_continue = true; //unless the middle buffers are needed
-	bool debug_giprobes = debug_draw == VS::VIEWPORT_DEBUG_DRAW_GI_PROBE_ALBEDO || debug_draw == VS::VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING || debug_draw == VS::VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION;
+	bool debug_giprobes = get_debug_draw_mode() == VS::VIEWPORT_DEBUG_DRAW_GI_PROBE_ALBEDO || get_debug_draw_mode() == VS::VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING || get_debug_draw_mode() == VS::VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION;
 	bool using_separate_specular = false;
 	bool using_separate_specular = false;
 
 
 	bool depth_pre_pass = depth_framebuffer.is_valid();
 	bool depth_pre_pass = depth_framebuffer.is_valid();
@@ -1944,7 +1812,7 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co
 		CameraMatrix cm = (dc * p_cam_projection) * CameraMatrix(p_cam_transform.affine_inverse());
 		CameraMatrix cm = (dc * p_cam_projection) * CameraMatrix(p_cam_transform.affine_inverse());
 		RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(opaque_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ);
 		RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(opaque_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ);
 		for (int i = 0; i < p_gi_probe_cull_count; i++) {
 		for (int i = 0; i < p_gi_probe_cull_count; i++) {
-			_debug_giprobe(p_gi_probe_cull_result[i], draw_list, opaque_framebuffer, cm, debug_draw == VS::VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING, debug_draw == VS::VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION, 1.0);
+			_debug_giprobe(p_gi_probe_cull_result[i], draw_list, opaque_framebuffer, cm, get_debug_draw_mode() == VS::VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING, get_debug_draw_mode() == VS::VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION, 1.0);
 		}
 		}
 		RD::get_singleton()->draw_list_end();
 		RD::get_singleton()->draw_list_end();
 	}
 	}
@@ -1992,44 +1860,10 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co
 		return;
 		return;
 	}
 	}
 
 
-	RasterizerEffectsRD *effects = storage->get_effects();
+	RENDER_TIMESTAMP("Tonemap");
 
 
-	{
-		RENDER_TIMESTAMP("Tonemap");
-		//tonemap
-		RasterizerEffectsRD::TonemapSettings tonemap;
-
-		tonemap.color_correction_texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
-		tonemap.exposure_texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE);
-		tonemap.glow_texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK);
-
-		if (is_environment(p_environment)) {
-			tonemap.tonemap_mode = environment_get_tonemapper(p_environment);
-			tonemap.white = environment_get_white(p_environment);
-			tonemap.exposure = environment_get_exposure(p_environment);
-		}
-		effects->tonemapper(render_buffer->color, storage->render_target_get_rd_framebuffer(render_buffer->render_target), tonemap);
-	}
-
-	storage->render_target_disable_clear_request(render_buffer->render_target);
-
-	if (render_buffer && debug_draw == VS::VIEWPORT_DEBUG_DRAW_SHADOW_ATLAS) {
-		if (p_shadow_atlas.is_valid()) {
-			RID shadow_atlas_texture = shadow_atlas_get_texture(p_shadow_atlas);
-			Size2 rtsize = storage->render_target_get_size(render_buffer->render_target);
-
-			effects->copy_to_rect(shadow_atlas_texture, storage->render_target_get_rd_framebuffer(render_buffer->render_target), Rect2(Vector2(), rtsize / 2));
-		}
-	}
-
-	if (render_buffer && debug_draw == VS::VIEWPORT_DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS) {
-		if (directional_shadow_get_texture().is_valid()) {
-			RID shadow_atlas_texture = directional_shadow_get_texture();
-			Size2 rtsize = storage->render_target_get_size(render_buffer->render_target);
-
-			effects->copy_to_rect(shadow_atlas_texture, storage->render_target_get_rd_framebuffer(render_buffer->render_target), Rect2(Vector2(), rtsize / 2));
-		}
-	}
+	render_buffers_post_process_and_tonemap(p_render_buffer, p_environment);
+	render_buffers_debug_draw(p_render_buffer, p_shadow_atlas);
 
 
 #if 0
 #if 0
 	_post_process(env, p_cam_projection);
 	_post_process(env, p_cam_projection);
@@ -2101,7 +1935,7 @@ void RasterizerSceneForwardRD::_render_shadow(RID p_framebuffer, InstanceBase **
 	scene_state.ubo.z_far = p_zfar;
 	scene_state.ubo.z_far = p_zfar;
 	scene_state.ubo.dual_paraboloid_side = p_use_dp_flip ? -1 : 1;
 	scene_state.ubo.dual_paraboloid_side = p_use_dp_flip ? -1 : 1;
 
 
-	_setup_environment(RID(), RID(), p_projection, p_transform, RID(), true, Vector2(1, 1), RID(), true);
+	_setup_environment(RID(), p_projection, p_transform, RID(), true, Vector2(1, 1), RID(), true, Color());
 
 
 	render_list.clear();
 	render_list.clear();
 
 
@@ -2137,7 +1971,7 @@ void RasterizerSceneForwardRD::_render_material(const Transform &p_cam_transform
 	scene_state.ubo.z_far = 0;
 	scene_state.ubo.z_far = 0;
 	scene_state.ubo.dual_paraboloid_side = 0;
 	scene_state.ubo.dual_paraboloid_side = 0;
 
 
-	_setup_environment(RID(), RID(), p_cam_projection, p_cam_transform, RID(), true, Vector2(1, 1), RID(), false);
+	_setup_environment(RID(), p_cam_projection, p_cam_transform, RID(), true, Vector2(1, 1), RID(), false, Color());
 
 
 	render_list.clear();
 	render_list.clear();
 
 
@@ -2395,10 +2229,6 @@ void RasterizerSceneForwardRD::set_time(double p_time) {
 	time = p_time;
 	time = p_time;
 }
 }
 
 
-void RasterizerSceneForwardRD::set_debug_draw_mode(VS::ViewportDebugDraw p_debug_draw) {
-	debug_draw = p_debug_draw;
-}
-
 RasterizerSceneForwardRD::RasterizerSceneForwardRD(RasterizerStorageRD *p_storage) :
 RasterizerSceneForwardRD::RasterizerSceneForwardRD(RasterizerStorageRD *p_storage) :
 		RasterizerSceneRD(p_storage) {
 		RasterizerSceneRD(p_storage) {
 	singleton = this;
 	singleton = this;

+ 3 - 8
servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h

@@ -194,10 +194,8 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
 		RID color_only_fb;
 		RID color_only_fb;
 		int width, height;
 		int width, height;
 
 
-		RID render_target;
-
 		void clear();
 		void clear();
-		virtual void configure(RID p_render_target, int p_width, int p_height, VS::ViewportMSAA p_msaa);
+		virtual void configure(RID p_color_buffer, int p_width, int p_height, VS::ViewportMSAA p_msaa);
 
 
 		~RenderBufferDataForward();
 		~RenderBufferDataForward();
 	};
 	};
@@ -525,7 +523,7 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
 		PASS_MODE_DEPTH_MATERIAL,
 		PASS_MODE_DEPTH_MATERIAL,
 	};
 	};
 
 
-	void _setup_environment(RID p_render_target, RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y);
+	void _setup_environment(RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color);
 	void _setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, RID p_shadow_atlas, bool p_using_shadows);
 	void _setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, RID p_shadow_atlas, bool p_using_shadows);
 	void _setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, RID p_environment);
 	void _setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, RID p_environment);
 	void _setup_gi_probes(RID *p_gi_probe_probe_cull_result, int p_gi_probe_probe_cull_count, const Transform &p_camera_transform);
 	void _setup_gi_probes(RID *p_gi_probe_probe_cull_result, int p_gi_probe_probe_cull_count, const Transform &p_camera_transform);
@@ -539,16 +537,13 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
 
 
 	void _draw_sky(RD::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_fb_format, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform, float p_alpha);
 	void _draw_sky(RD::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_fb_format, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform, float p_alpha);
 
 
-	VS::ViewportDebugDraw debug_draw = VS::VIEWPORT_DEBUG_DRAW_DISABLED;
-
 protected:
 protected:
-	virtual void _render_scene(RenderBufferData *p_buffer_data, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
+	virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color);
 	virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip);
 	virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip);
 	virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region);
 	virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region);
 
 
 public:
 public:
 	virtual void set_time(double p_time);
 	virtual void set_time(double p_time);
-	virtual void set_debug_draw_mode(VS::ViewportDebugDraw p_debug_draw);
 
 
 	virtual bool free(RID p_rid);
 	virtual bool free(RID p_rid);
 
 

+ 238 - 42
servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp

@@ -468,46 +468,21 @@ void RasterizerSceneRD::environment_set_tonemap(RID p_env, VS::EnvironmentToneMa
 	env->auto_exp_scale = p_auto_exp_scale;
 	env->auto_exp_scale = p_auto_exp_scale;
 }
 }
 
 
-VS::EnvironmentToneMapper RasterizerSceneRD::environment_get_tonemapper(RID p_env) const {
-	Environent *env = environment_owner.getornull(p_env);
-	ERR_FAIL_COND_V(!env, VS::ENV_TONE_MAPPER_LINEAR);
-	return env->tone_mapper;
-}
-float RasterizerSceneRD::environment_get_exposure(RID p_env) const {
-	Environent *env = environment_owner.getornull(p_env);
-	ERR_FAIL_COND_V(!env, 0);
-	return env->exposure;
-}
-float RasterizerSceneRD::environment_get_white(RID p_env) const {
-	Environent *env = environment_owner.getornull(p_env);
-	ERR_FAIL_COND_V(!env, 0);
-	return env->white;
-}
-bool RasterizerSceneRD::environment_get_auto_exposure(RID p_env) const {
-	Environent *env = environment_owner.getornull(p_env);
-	ERR_FAIL_COND_V(!env, false);
-	return env->auto_exposure;
-}
-float RasterizerSceneRD::environment_get_min_luminance(RID p_env) const {
-	Environent *env = environment_owner.getornull(p_env);
-	ERR_FAIL_COND_V(!env, 0);
-	return env->min_luminance;
-}
-float RasterizerSceneRD::environment_get_max_luminance(RID p_env) const {
-	Environent *env = environment_owner.getornull(p_env);
-	ERR_FAIL_COND_V(!env, 0);
-	return env->max_luminance;
-}
-float RasterizerSceneRD::environment_get_auto_exposure_scale(RID p_env) const {
-	Environent *env = environment_owner.getornull(p_env);
-	ERR_FAIL_COND_V(!env, 0);
-	return env->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, VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale) {
 
 
-float RasterizerSceneRD::environment_get_auto_exposure_speed(RID p_env) const {
 	Environent *env = environment_owner.getornull(p_env);
 	Environent *env = environment_owner.getornull(p_env);
-	ERR_FAIL_COND_V(!env, 0);
-	return env->auto_exp_speed;
+	ERR_FAIL_COND(!env);
+	env->glow_enabled = p_enable;
+	env->glow_levels = p_level_flags;
+	env->glow_intensity = p_intensity;
+	env->glow_strength = p_strength;
+	env->glow_mix = p_mix;
+	env->glow_bloom = p_bloom_threshold;
+	env->glow_blend_mode = p_blend_mode;
+	env->glow_hdr_bleed_threshold = p_hdr_bleed_threshold;
+	env->glow_hdr_bleed_scale = p_hdr_bleed_scale;
+	env->glow_hdr_luminance_cap = p_hdr_luminance_cap;
+	env->glow_bicubic_upscale = p_bicubic_upscale;
 }
 }
 
 
 bool RasterizerSceneRD::is_environment(RID p_env) const {
 bool RasterizerSceneRD::is_environment(RID p_env) const {
@@ -2181,6 +2156,198 @@ RID RasterizerSceneRD::render_buffers_create() {
 	return render_buffers_owner.make_rid(rb);
 	return render_buffers_owner.make_rid(rb);
 }
 }
 
 
+void RasterizerSceneRD::_allocate_blur_textures(RenderBuffers *rb) {
+	ERR_FAIL_COND(!rb->blur[0].texture.is_null());
+
+	uint32_t mipmaps_required = Image::get_image_required_mipmaps(rb->width, rb->height, Image::FORMAT_RGBAH);
+
+	RD::TextureFormat tf;
+	tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+	tf.width = rb->width;
+	tf.height = rb->height;
+	tf.type = RD::TEXTURE_TYPE_2D;
+	tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
+	tf.mipmaps = mipmaps_required;
+
+	rb->blur[0].texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
+	//the second one is smaller (only used for separatable part of blur)
+	tf.width >>= 1;
+	tf.height >>= 1;
+	tf.mipmaps--;
+	rb->blur[1].texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
+
+	int base_width = rb->width;
+	int base_height = rb->height;
+
+	for (uint32_t i = 0; i < mipmaps_required; i++) {
+
+		RenderBuffers::Blur::Mipmap mm;
+		mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->blur[0].texture, 0, i);
+		{
+			Vector<RID> fbs;
+			fbs.push_back(mm.texture);
+			mm.framebuffer = RD::get_singleton()->framebuffer_create(fbs);
+		}
+
+		mm.width = base_width;
+		mm.height = base_height;
+
+		rb->blur[0].mipmaps.push_back(mm);
+
+		if (i > 0) {
+
+			mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->blur[1].texture, 0, i - 1);
+			{
+				Vector<RID> fbs;
+				fbs.push_back(mm.texture);
+				mm.framebuffer = RD::get_singleton()->framebuffer_create(fbs);
+			}
+
+			rb->blur[1].mipmaps.push_back(mm);
+		}
+
+		base_width = MAX(1, base_width >> 1);
+		base_height = MAX(1, base_height >> 1);
+	}
+}
+
+void RasterizerSceneRD::_free_render_buffer_data(RenderBuffers *rb) {
+
+	if (rb->texture.is_valid()) {
+		RD::get_singleton()->free(rb->texture);
+	}
+
+	for (int i = 0; i < 2; i++) {
+		if (rb->blur[i].texture.is_valid()) {
+			RD::get_singleton()->free(rb->blur[i].texture);
+			rb->blur[i].texture = RID();
+			rb->blur[i].mipmaps.clear();
+		}
+	}
+
+	for (int i = 0; i < rb->luminance.reduce.size(); i++) {
+		RD::get_singleton()->free(rb->luminance.reduce[i]);
+	}
+
+	rb->luminance.reduce.clear();
+
+	if (rb->luminance.current.is_valid()) {
+		RD::get_singleton()->free(rb->luminance.current);
+		rb->luminance.current = RID();
+	}
+}
+
+void RasterizerSceneRD::render_buffers_post_process_and_tonemap(RID p_render_buffers, RID p_environment) {
+
+	RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+	ERR_FAIL_COND(!rb);
+
+	Environent *env = environment_owner.getornull(p_environment);
+	//glow (if enabled)
+
+	int max_glow_level = -1;
+	int glow_mask = 0;
+
+	if (env && env->glow_enabled) {
+
+		/* see that blur textures are allocated */
+
+		if (rb->blur[0].texture.is_null()) {
+			_allocate_blur_textures(rb);
+		}
+
+		for (int i = 0; i < VS::MAX_GLOW_LEVELS; i++) {
+			if (env->glow_levels & (1 << i)) {
+
+				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);
+				}
+			}
+		}
+
+		for (int i = 0; i < (max_glow_level + 1); i++) {
+
+			int vp_w = rb->blur[1].mipmaps[i].width;
+			int vp_h = rb->blur[1].mipmaps[i].height;
+
+			if (i == 0) {
+				storage->get_effects()->gaussian_glow(rb->texture, rb->blur[0].mipmaps[i + 1].framebuffer, rb->blur[0].mipmaps[i + 1].texture, rb->blur[1].mipmaps[i].framebuffer, Vector2(1.0 / vp_w, 1.0 / vp_h), env->glow_strength, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, RID());
+			} else {
+				storage->get_effects()->gaussian_glow(rb->blur[1].mipmaps[i - 1].texture, rb->blur[0].mipmaps[i + 1].framebuffer, rb->blur[0].mipmaps[i + 1].texture, rb->blur[1].mipmaps[i].framebuffer, Vector2(1.0 / vp_w, 1.0 / vp_h), env->glow_strength);
+			}
+		}
+	}
+
+	{
+		//tonemap
+		RasterizerEffectsRD::TonemapSettings tonemap;
+
+		tonemap.color_correction_texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
+		tonemap.exposure_texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE);
+
+		if (env && env->glow_enabled) {
+			tonemap.use_glow = true;
+			tonemap.glow_mode = RasterizerEffectsRD::TonemapSettings::GlowMode(env->glow_blend_mode);
+			tonemap.glow_intensity = env->glow_blend_mode == VS::GLOW_BLEND_MODE_MIX ? env->glow_mix : env->glow_intensity;
+			tonemap.glow_level_flags = glow_mask;
+			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 = env->glow_bicubic_upscale;
+			tonemap.glow_texture = rb->blur[1].texture;
+		} else {
+			tonemap.glow_texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK);
+		}
+
+		if (env) {
+			tonemap.tonemap_mode = env->tone_mapper;
+			tonemap.white = env->white;
+			tonemap.exposure = env->exposure;
+		}
+
+		storage->get_effects()->tonemapper(rb->texture, storage->render_target_get_rd_framebuffer(rb->render_target), tonemap);
+	}
+
+	storage->render_target_disable_clear_request(rb->render_target);
+}
+
+void RasterizerSceneRD::render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas) {
+	RasterizerEffectsRD *effects = storage->get_effects();
+
+	RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+	ERR_FAIL_COND(!rb);
+
+	if (debug_draw == VS::VIEWPORT_DEBUG_DRAW_SHADOW_ATLAS) {
+		if (p_shadow_atlas.is_valid()) {
+			RID shadow_atlas_texture = shadow_atlas_get_texture(p_shadow_atlas);
+			Size2 rtsize = storage->render_target_get_size(rb->render_target);
+
+			effects->copy_to_rect(shadow_atlas_texture, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize / 2));
+		}
+	}
+
+	if (debug_draw == VS::VIEWPORT_DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS) {
+		if (directional_shadow_get_texture().is_valid()) {
+			RID shadow_atlas_texture = directional_shadow_get_texture();
+			Size2 rtsize = storage->render_target_get_size(rb->render_target);
+
+			effects->copy_to_rect(shadow_atlas_texture, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize / 2));
+		}
+	}
+}
+
+RID RasterizerSceneRD::render_buffers_get_back_buffer_texture(RID p_render_buffers) {
+
+	RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+	ERR_FAIL_COND_V(!rb, RID());
+	ERR_FAIL_COND_V(!rb->blur[0].texture.is_valid(), RID()); //should have been created for some reason?
+	return rb->blur[0].texture;
+}
+
 void RasterizerSceneRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, VS::ViewportMSAA p_msaa) {
 void RasterizerSceneRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, VS::ViewportMSAA p_msaa) {
 
 
 	RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
 	RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
@@ -2188,7 +2355,19 @@ void RasterizerSceneRD::render_buffers_configure(RID p_render_buffers, RID p_ren
 	rb->height = p_height;
 	rb->height = p_height;
 	rb->render_target = p_render_target;
 	rb->render_target = p_render_target;
 	rb->msaa = p_msaa;
 	rb->msaa = p_msaa;
-	rb->data->configure(p_render_target, p_width, p_height, p_msaa);
+	_free_render_buffer_data(rb);
+
+	{
+		RD::TextureFormat tf;
+		tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+		tf.width = rb->width;
+		tf.height = rb->height;
+		tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+
+		rb->texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
+	}
+
+	rb->data->configure(rb->texture, p_width, p_height, p_msaa);
 }
 }
 
 
 int RasterizerSceneRD::get_roughness_layers() const {
 int RasterizerSceneRD::get_roughness_layers() const {
@@ -2199,12 +2378,24 @@ bool RasterizerSceneRD::is_using_radiance_cubemap_array() const {
 	return sky_use_cubemap_array;
 	return sky_use_cubemap_array;
 }
 }
 
 
+RasterizerSceneRD::RenderBufferData *RasterizerSceneRD::render_buffers_get_data(RID p_render_buffers) {
+	RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+	ERR_FAIL_COND_V(!rb, NULL);
+	return rb->data;
+}
+
 void RasterizerSceneRD::render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {
 void RasterizerSceneRD::render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {
 
 
-	RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
-	ERR_FAIL_COND(!rb && p_render_buffers.is_valid());
+	Color clear_color;
+	if (p_render_buffers.is_valid()) {
+		RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+		ERR_FAIL_COND(!rb);
+		clear_color = storage->render_target_get_clear_request_color(rb->render_target);
+	} else {
+		clear_color = storage->get_default_clear_color();
+	}
 
 
-	_render_scene(rb ? rb->data : (RenderBufferData *)NULL, p_cam_transform, p_cam_projection, p_cam_ortogonal, p_cull_result, p_cull_count, p_light_cull_result, p_light_cull_count, p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_gi_probe_cull_result, p_gi_probe_cull_count, p_environment, p_shadow_atlas, p_reflection_atlas, p_reflection_probe, p_reflection_probe_pass);
+	_render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_ortogonal, p_cull_result, p_cull_count, p_light_cull_result, p_light_cull_count, p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_gi_probe_cull_result, p_gi_probe_cull_count, p_environment, p_shadow_atlas, p_reflection_atlas, p_reflection_probe, p_reflection_probe_pass, clear_color);
 }
 }
 
 
 void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) {
 void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) {
@@ -2392,6 +2583,7 @@ bool RasterizerSceneRD::free(RID p_rid) {
 
 
 	if (render_buffers_owner.owns(p_rid)) {
 	if (render_buffers_owner.owns(p_rid)) {
 		RenderBuffers *rb = render_buffers_owner.getornull(p_rid);
 		RenderBuffers *rb = render_buffers_owner.getornull(p_rid);
+		_free_render_buffer_data(rb);
 		memdelete(rb->data);
 		memdelete(rb->data);
 		render_buffers_owner.free(p_rid);
 		render_buffers_owner.free(p_rid);
 	} else if (environment_owner.owns(p_rid)) {
 	} else if (environment_owner.owns(p_rid)) {
@@ -2463,6 +2655,10 @@ bool RasterizerSceneRD::free(RID p_rid) {
 	return true;
 	return true;
 }
 }
 
 
+void RasterizerSceneRD::set_debug_draw_mode(VS::ViewportDebugDraw p_debug_draw) {
+	debug_draw = p_debug_draw;
+}
+
 void RasterizerSceneRD::update() {
 void RasterizerSceneRD::update() {
 	_update_dirty_skys();
 	_update_dirty_skys();
 }
 }

+ 55 - 12
servers/visual/rasterizer_rd/rasterizer_scene_rd.h

@@ -49,18 +49,22 @@ public:
 protected:
 protected:
 	struct RenderBufferData {
 	struct RenderBufferData {
 
 
-		virtual void configure(RID p_render_target, int p_width, int p_height, VS::ViewportMSAA p_msaa) = 0;
+		virtual void configure(RID p_color_buffer, int p_width, int p_height, VS::ViewportMSAA p_msaa) = 0;
 		virtual ~RenderBufferData() {}
 		virtual ~RenderBufferData() {}
 	};
 	};
 	virtual RenderBufferData *_create_render_buffer_data() = 0;
 	virtual RenderBufferData *_create_render_buffer_data() = 0;
 
 
-	virtual void _render_scene(RenderBufferData *p_buffer_data, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) = 0;
+	virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_color) = 0;
 	virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool use_dp_flip) = 0;
 	virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool use_dp_flip) = 0;
 	virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) = 0;
 	virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) = 0;
 
 
 	virtual void _debug_giprobe(RID p_gi_probe, RenderingDevice::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha);
 	virtual void _debug_giprobe(RID p_gi_probe, RenderingDevice::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha);
 
 
+	RenderBufferData *render_buffers_get_data(RID p_render_buffers);
+
 private:
 private:
+	VS::ViewportDebugDraw debug_draw = VS::VIEWPORT_DEBUG_DRAW_DISABLED;
+
 	int roughness_layers;
 	int roughness_layers;
 
 
 	RasterizerStorageRD *storage;
 	RasterizerStorageRD *storage;
@@ -461,6 +465,20 @@ private:
 		float max_luminance = 8.0;
 		float max_luminance = 8.0;
 		float auto_exp_speed = 0.2;
 		float auto_exp_speed = 0.2;
 		float auto_exp_scale = 0.5;
 		float auto_exp_scale = 0.5;
+
+		/// Glow
+
+		bool glow_enabled = false;
+		int glow_levels = (1 << 2) | (1 << 4);
+		float glow_intensity = 0.8;
+		float glow_strength = 1.0;
+		float glow_bloom = 0.0;
+		float glow_mix = 0.01;
+		VS::EnvironmentGlowBlendMode glow_blend_mode = VS::GLOW_BLEND_MODE_SOFTLIGHT;
+		float glow_hdr_bleed_threshold = 1.0;
+		float glow_hdr_luminance_cap = 12.0;
+		float glow_hdr_bleed_scale = 2.0;
+		bool glow_bicubic_upscale = false;
 	};
 	};
 
 
 	mutable RID_Owner<Environent> environment_owner;
 	mutable RID_Owner<Environent> environment_owner;
@@ -473,10 +491,37 @@ private:
 		int width = 0, height = 0;
 		int width = 0, height = 0;
 		VS::ViewportMSAA msaa = VS::VIEWPORT_MSAA_DISABLED;
 		VS::ViewportMSAA msaa = VS::VIEWPORT_MSAA_DISABLED;
 		RID render_target;
 		RID render_target;
+
+		RID texture; //main texture for rendering to, must be filled after done rendering
+
+		//built-in textures used for ping pong image processing and blurring
+		struct Blur {
+			RID texture;
+
+			struct Mipmap {
+				RID texture;
+				RID framebuffer;
+				int width;
+				int height;
+			};
+
+			Vector<Mipmap> mipmaps;
+		};
+
+		Blur blur[2]; //the second one starts from the first mipmap
+
+		struct Luminance {
+
+			Vector<RID> reduce;
+			RID current;
+		} luminance;
 	};
 	};
 
 
 	mutable RID_Owner<RenderBuffers> render_buffers_owner;
 	mutable RID_Owner<RenderBuffers> render_buffers_owner;
 
 
+	void _free_render_buffer_data(RenderBuffers *rb);
+	void _allocate_blur_textures(RenderBuffers *rb);
+
 	uint64_t scene_pass = 0;
 	uint64_t scene_pass = 0;
 	uint64_t shadow_atlas_realloc_tolerance_msec = 500;
 	uint64_t shadow_atlas_realloc_tolerance_msec = 500;
 
 
@@ -557,7 +602,7 @@ public:
 
 
 	void environment_set_dof_blur_near(RID p_env, bool p_enable, float p_distance, float p_transition, float p_far_amount, VS::EnvironmentDOFBlurQuality p_quality) {}
 	void environment_set_dof_blur_near(RID p_env, bool p_enable, float p_distance, float p_transition, float p_far_amount, VS::EnvironmentDOFBlurQuality p_quality) {}
 	void environment_set_dof_blur_far(RID p_env, bool p_enable, float p_distance, float p_transition, float p_far_amount, VS::EnvironmentDOFBlurQuality p_quality) {}
 	void environment_set_dof_blur_far(RID p_env, bool p_enable, float p_distance, float p_transition, float p_far_amount, VS::EnvironmentDOFBlurQuality p_quality) {}
-	void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_bloom_threshold, VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale) {}
+	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, VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale);
 
 
 	void environment_set_fog(RID p_env, bool p_enable, float p_begin, float p_end, RID p_gradient_texture) {}
 	void environment_set_fog(RID p_env, bool p_enable, float p_begin, float p_end, RID p_gradient_texture) {}
 
 
@@ -565,15 +610,6 @@ public:
 	void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect, float p_ao_channel_affect, const Color &p_color, VS::EnvironmentSSAOQuality p_quality, VS::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) {}
 	void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect, float p_ao_channel_affect, const Color &p_color, VS::EnvironmentSSAOQuality p_quality, VS::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) {}
 
 
 	void environment_set_tonemap(RID p_env, VS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale);
 	void environment_set_tonemap(RID p_env, VS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale);
-	VS::EnvironmentToneMapper environment_get_tonemapper(RID p_env) const;
-	float environment_get_exposure(RID p_env) const;
-	float environment_get_white(RID p_env) const;
-	bool environment_get_auto_exposure(RID p_env) const;
-	float environment_get_min_luminance(RID p_env) const;
-	float environment_get_max_luminance(RID p_env) const;
-	float environment_get_auto_exposure_scale(RID p_env) const;
-	float environment_get_auto_exposure_speed(RID p_env) const;
-
 	void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp) {}
 	void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp) {}
 
 
 	void environment_set_fog(RID p_env, bool p_enable, const Color &p_color, const Color &p_sun_color, float p_sun_amount) {}
 	void environment_set_fog(RID p_env, bool p_enable, const Color &p_color, const Color &p_sun_color, float p_sun_amount) {}
@@ -802,6 +838,10 @@ public:
 	RID render_buffers_create();
 	RID render_buffers_create();
 	void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, VS::ViewportMSAA p_msaa);
 	void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, VS::ViewportMSAA p_msaa);
 
 
+	RID render_buffers_get_back_buffer_texture(RID p_render_buffers);
+	void render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas);
+	void render_buffers_post_process_and_tonemap(RID p_render_buffers, RID p_environment);
+
 	void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
 	void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
 
 
 	void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count);
 	void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count);
@@ -818,6 +858,9 @@ public:
 
 
 	virtual void update();
 	virtual void update();
 
 
+	virtual void set_debug_draw_mode(VS::ViewportDebugDraw p_debug_draw);
+	_FORCE_INLINE_ VS::ViewportDebugDraw get_debug_draw_mode() const { return debug_draw; }
+
 	RasterizerSceneRD(RasterizerStorageRD *p_storage);
 	RasterizerSceneRD(RasterizerStorageRD *p_storage);
 	~RasterizerSceneRD();
 	~RasterizerSceneRD();
 };
 };

+ 2 - 1
servers/visual/rasterizer_rd/shaders/SCsub

@@ -14,5 +14,6 @@ if 'RD_GLSL' in env['BUILDERS']:
     env.RD_GLSL('giprobe.glsl');
     env.RD_GLSL('giprobe.glsl');
     env.RD_GLSL('giprobe_debug.glsl');
     env.RD_GLSL('giprobe_debug.glsl');
     env.RD_GLSL('giprobe_sdf.glsl');
     env.RD_GLSL('giprobe_sdf.glsl');
-    
+    env.RD_GLSL('luminance_reduce.glsl');
+
 
 

+ 22 - 10
servers/visual/rasterizer_rd/shaders/blur.glsl

@@ -125,31 +125,43 @@ void main() {
 
 
 	//Glow uses larger sigma 1 for a more rounded blur effect
 	//Glow uses larger sigma 1 for a more rounded blur effect
 
 
+#define GLOW_ADD( m_ofs, m_mult )\
+	{\
+		vec2 ofs = uv_interp + m_ofs * pix_size;\
+		vec4 c = texture(source_color, ofs ) * m_mult; \
+		if (any(lessThan(ofs,vec2(0.0))) || any(greaterThan(ofs,vec2(1.0)))) {\
+			c*=0.0;\
+		}\
+		color+=c;\
+	}
+
 	if (bool(blur.flags & FLAG_HORIZONTAL)) {
 	if (bool(blur.flags & FLAG_HORIZONTAL)) {
 
 
 		vec2 pix_size = blur.pixel_size;
 		vec2 pix_size = blur.pixel_size;
 		pix_size *= 0.5; //reading from larger buffer, so use more samples
 		pix_size *= 0.5; //reading from larger buffer, so use more samples
 		vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.174938;
 		vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.174938;
-		color += texture(source_color, uv_interp + vec2(1.0, 0.0) * pix_size) * 0.165569;
-		color += texture(source_color, uv_interp + vec2(2.0, 0.0) * pix_size) * 0.140367;
-		color += texture(source_color, uv_interp + vec2(3.0, 0.0) * pix_size) * 0.106595;
-		color += texture(source_color, uv_interp + vec2(-1.0, 0.0) * pix_size) * 0.165569;
-		color += texture(source_color, uv_interp + vec2(-2.0, 0.0) * pix_size) * 0.140367;
-		color += texture(source_color, uv_interp + vec2(-3.0, 0.0) * pix_size) * 0.106595;
+		GLOW_ADD(vec2(1.0, 0.0),0.165569);
+		GLOW_ADD(vec2(2.0, 0.0),0.140367);
+		GLOW_ADD(vec2(3.0, 0.0), 0.106595);
+		GLOW_ADD(vec2(-1.0, 0.0),0.165569);
+		GLOW_ADD(vec2(-2.0, 0.0),0.140367);
+		GLOW_ADD(vec2(-3.0, 0.0),0.106595);
 		color *= blur.glow_strength;
 		color *= blur.glow_strength;
 		frag_color = color;
 		frag_color = color;
 	} else {
 	} else {
 
 
 		vec2 pix_size = blur.pixel_size;
 		vec2 pix_size = blur.pixel_size;
 		vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.288713;
 		vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.288713;
-		color += texture(source_color, uv_interp + vec2(0.0, 1.0) * pix_size) * 0.233062;
-		color += texture(source_color, uv_interp + vec2(0.0, 2.0) * pix_size) * 0.122581;
-		color += texture(source_color, uv_interp + vec2(0.0, -1.0) * pix_size) * 0.233062;
-		color += texture(source_color, uv_interp + vec2(0.0, -2.0) * pix_size) * 0.122581;
+		GLOW_ADD(vec2(0.0, 1.0),0.233062);
+		GLOW_ADD(vec2(0.0, 2.0),0.122581);
+		GLOW_ADD(vec2(0.0, -1.0),0.233062);
+		GLOW_ADD(vec2(0.0, -2.0),0.122581);
 		color *= blur.glow_strength;
 		color *= blur.glow_strength;
 		frag_color = color;
 		frag_color = color;
 	}
 	}
 
 
+#undef GLOW_ADD
+
 	if (bool(blur.flags & FLAG_GLOW_FIRST_PASS)) {
 	if (bool(blur.flags & FLAG_GLOW_FIRST_PASS)) {
 #ifdef GLOW_USE_AUTO_EXPOSURE
 #ifdef GLOW_USE_AUTO_EXPOSURE
 
 

+ 76 - 0
servers/visual/rasterizer_rd/shaders/luminance_reduce.glsl

@@ -0,0 +1,76 @@
+/* clang-format off */
+[compute]
+/* clang-format on */
+#version 450
+
+VERSION_DEFINES
+
+#define BLOCK_SIZE 8
+
+layout(local_size_x = BLOCK_SIZE, local_size_y = BLOCK_SIZE, local_size_z = 1) in;
+
+shared float tmp_data[BLOCK_SIZE*BLOCK_SIZE];
+
+
+#ifdef READ_TEXTURE
+
+//use for main texture
+layout(set = 0, binding = 1) uniform texture2D source_texture;
+layout(set = 0, binding = 2) uniform sampler source_sampler;
+
+#else
+
+//use for intermediate textures
+layout(r32f, set = 0, binding = 1) uniform restrict readonly image2D source_luminance;
+
+#endif
+
+layout(r32f, set = 0, binding = 3) uniform restrict writeonly image2D dest_luminance;
+
+layout(push_constant, binding = 0, std430) uniform Params {
+	ivec2 source_size;
+} params;
+
+void main() {
+
+
+	uint t = gl_LocalInvocationID.y * BLOCK_SIZE + gl_LocalInvocationID.x;
+	ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
+
+	if (any(lessThan(pos,params.source_size))) {
+
+#ifdef READ_TEXTURE
+		vec3 v = texelFetch(sampler2D(source_texture,source_sampler),pos).rgb;
+		avg += max(v.r,max(v.g,v.b));
+		tmp_data[t] = 0.0;
+#else
+		tmp_data[t] = imageLoad(source_luminance, pos);
+#endif
+	} else {
+		tmp_data[t] = 0.0;
+	}
+
+	groupMemoryBarrier();
+	barrier();
+
+	uint size = (BLOCK_SIZE * BLOCK_SIZE)>>1;
+
+	do {
+		if (t<size) {
+			tmp_data[t]+=tmp_data[t+size];
+		}
+		groupMemoryBarrier();
+		barrier();
+
+		size>>=1;
+
+	} while(size>1);
+
+	if (t==0) {
+		//compute rect size
+		ivec2 rect_size = max(params.source_size - pos,ivec2(BLOCK_SIZE));
+		float avg = tmp_data[0] / float(rect_size.x*rect_size.y);
+		pos/=ivec2(BLOCK_SIZE);
+		imageStore(dest_luminance, pos, vec4(avg));
+	}
+}

+ 16 - 8
servers/visual/rasterizer_rd/shaders/tonemap.glsl

@@ -187,31 +187,31 @@ vec3 gather_glow(sampler2D tex, vec2 uv) { // sample all selected glow levels
 	vec3 glow = vec3(0.0f);
 	vec3 glow = vec3(0.0f);
 
 
 	if (bool(params.glow_level_flags & (1 << 0))) {
 	if (bool(params.glow_level_flags & (1 << 0))) {
-		glow += GLOW_TEXTURE_SAMPLE(tex, uv, 1).rgb;
+		glow += GLOW_TEXTURE_SAMPLE(tex, uv, 0).rgb;
 	}
 	}
 
 
 	if (bool(params.glow_level_flags & (1 << 1))) {
 	if (bool(params.glow_level_flags & (1 << 1))) {
-		glow += GLOW_TEXTURE_SAMPLE(tex, uv, 2).rgb;
+		glow += GLOW_TEXTURE_SAMPLE(tex, uv, 1).rgb;
 	}
 	}
 
 
 	if (bool(params.glow_level_flags & (1 << 2))) {
 	if (bool(params.glow_level_flags & (1 << 2))) {
-		glow += GLOW_TEXTURE_SAMPLE(tex, uv, 3).rgb;
+		glow += GLOW_TEXTURE_SAMPLE(tex, uv, 2).rgb;
 	}
 	}
 
 
 	if (bool(params.glow_level_flags & (1 << 3))) {
 	if (bool(params.glow_level_flags & (1 << 3))) {
-		glow += GLOW_TEXTURE_SAMPLE(tex, uv, 4).rgb;
+		glow += GLOW_TEXTURE_SAMPLE(tex, uv, 3).rgb;
 	}
 	}
 
 
 	if (bool(params.glow_level_flags & (1 << 4))) {
 	if (bool(params.glow_level_flags & (1 << 4))) {
-		glow += GLOW_TEXTURE_SAMPLE(tex, uv, 5).rgb;
+		glow += GLOW_TEXTURE_SAMPLE(tex, uv, 4).rgb;
 	}
 	}
 
 
 	if (bool(params.glow_level_flags & (1 << 5))) {
 	if (bool(params.glow_level_flags & (1 << 5))) {
-		glow += GLOW_TEXTURE_SAMPLE(tex, uv, 6).rgb;
+		glow += GLOW_TEXTURE_SAMPLE(tex, uv, 5).rgb;
 	}
 	}
 
 
 	if (bool(params.glow_level_flags & (1 << 6))) {
 	if (bool(params.glow_level_flags & (1 << 6))) {
-		glow += GLOW_TEXTURE_SAMPLE(tex, uv, 7).rgb;
+		glow += GLOW_TEXTURE_SAMPLE(tex, uv, 6).rgb;
 	}
 	}
 
 
 	return glow;
 	return glow;
@@ -221,6 +221,7 @@ vec3 gather_glow(sampler2D tex, vec2 uv) { // sample all selected glow levels
 #define GLOW_MODE_SCREEN 1
 #define GLOW_MODE_SCREEN 1
 #define GLOW_MODE_SOFTLIGHT 2
 #define GLOW_MODE_SOFTLIGHT 2
 #define GLOW_MODE_REPLACE 3
 #define GLOW_MODE_REPLACE 3
+#define GLOW_MODE_MIX 4
 
 
 vec3 apply_glow(vec3 color, vec3 glow) { // apply glow using the selected blending mode
 vec3 apply_glow(vec3 color, vec3 glow) { // apply glow using the selected blending mode
 	if (params.glow_mode == GLOW_MODE_ADD) {
 	if (params.glow_mode == GLOW_MODE_ADD) {
@@ -266,13 +267,20 @@ void main() {
 
 
 	// Early Tonemap & SRGB Conversion
 	// Early Tonemap & SRGB Conversion
 
 
+	if (params.use_glow && params.glow_mode == GLOW_MODE_MIX) {
+
+		vec3 glow = gather_glow(source_glow, uv_interp);
+		color.rgb = mix(color.rgb,glow,params.glow_intensity);
+
+	}
+
 	color = apply_tonemapping(color, params.white);
 	color = apply_tonemapping(color, params.white);
 
 
 	color = linear_to_srgb(color); // regular linear -> SRGB conversion
 	color = linear_to_srgb(color); // regular linear -> SRGB conversion
 
 
 	// Glow
 	// Glow
 
 
-	if (params.use_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;
 
 

+ 1 - 1
servers/visual/visual_server_raster.h

@@ -528,7 +528,7 @@ public:
 
 
 	BIND6(environment_set_dof_blur_near, RID, bool, float, float, float, EnvironmentDOFBlurQuality)
 	BIND6(environment_set_dof_blur_near, RID, bool, float, float, float, EnvironmentDOFBlurQuality)
 	BIND6(environment_set_dof_blur_far, RID, bool, float, float, float, EnvironmentDOFBlurQuality)
 	BIND6(environment_set_dof_blur_far, RID, bool, float, float, float, EnvironmentDOFBlurQuality)
-	BIND11(environment_set_glow, RID, bool, int, float, float, float, EnvironmentGlowBlendMode, float, float, float, bool)
+	BIND12(environment_set_glow, RID, bool, int, float, float, float, float, EnvironmentGlowBlendMode, float, float, float, bool)
 
 
 	BIND9(environment_set_tonemap, RID, EnvironmentToneMapper, float, float, bool, float, float, float, float)
 	BIND9(environment_set_tonemap, RID, EnvironmentToneMapper, float, float, bool, float, float, float, float)
 
 

+ 1 - 1
servers/visual/visual_server_wrap_mt.h

@@ -442,7 +442,7 @@ public:
 
 
 	FUNC6(environment_set_dof_blur_near, RID, bool, float, float, float, EnvironmentDOFBlurQuality)
 	FUNC6(environment_set_dof_blur_near, RID, bool, float, float, float, EnvironmentDOFBlurQuality)
 	FUNC6(environment_set_dof_blur_far, RID, bool, float, float, float, EnvironmentDOFBlurQuality)
 	FUNC6(environment_set_dof_blur_far, RID, bool, float, float, float, EnvironmentDOFBlurQuality)
-	FUNC11(environment_set_glow, RID, bool, int, float, float, float, EnvironmentGlowBlendMode, float, float, float, bool)
+	FUNC12(environment_set_glow, RID, bool, int, float, float, float, float, EnvironmentGlowBlendMode, float, float, float, bool)
 
 
 	FUNC9(environment_set_tonemap, RID, EnvironmentToneMapper, float, float, bool, float, float, float, float)
 	FUNC9(environment_set_tonemap, RID, EnvironmentToneMapper, float, float, bool, float, float, float, float)
 
 

+ 2 - 1
servers/visual_server.h

@@ -740,8 +740,9 @@ public:
 		GLOW_BLEND_MODE_SCREEN,
 		GLOW_BLEND_MODE_SCREEN,
 		GLOW_BLEND_MODE_SOFTLIGHT,
 		GLOW_BLEND_MODE_SOFTLIGHT,
 		GLOW_BLEND_MODE_REPLACE,
 		GLOW_BLEND_MODE_REPLACE,
+		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_bloom_threshold, EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale) = 0;
+	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, bool p_bicubic_upscale) = 0;
 
 
 	enum EnvironmentToneMapper {
 	enum EnvironmentToneMapper {
 		ENV_TONE_MAPPER_LINEAR,
 		ENV_TONE_MAPPER_LINEAR,