diff options
| -rw-r--r-- | drivers/gles3/shaders/sky.glsl | 13 | ||||
| -rw-r--r-- | drivers/gles3/storage/material_storage.cpp | 1 | ||||
| -rw-r--r-- | scene/resources/sky_material.cpp | 86 | ||||
| -rw-r--r-- | scene/resources/sky_material.h | 4 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/environment/sky.cpp | 1 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/environment/sky.glsl | 13 | ||||
| -rw-r--r-- | servers/rendering/shader_types.cpp | 1 | 
7 files changed, 73 insertions, 46 deletions
diff --git a/drivers/gles3/shaders/sky.glsl b/drivers/gles3/shaders/sky.glsl index 21f01d2a8f..4c0fe47f6b 100644 --- a/drivers/gles3/shaders/sky.glsl +++ b/drivers/gles3/shaders/sky.glsl @@ -104,6 +104,15 @@ uniform uint directional_light_count;  layout(location = 0) out vec4 frag_color; +#ifdef USE_DEBANDING +// https://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare +vec3 interleaved_gradient_noise(vec2 pos) { +	const vec3 magic = vec3(0.06711056f, 0.00583715f, 52.9829189f); +	float res = fract(magic.z * fract(dot(pos, magic.xy))) * 2.0 - 1.0; +	return vec3(res, -res, res) / 255.0; +} +#endif +  void main() {  	vec3 cube_normal;  	cube_normal.z = -1.0; @@ -168,4 +177,8 @@ void main() {  	frag_color.rgb = color;  	frag_color.a = alpha; + +#ifdef USE_DEBANDING +	frag_color.rgb += interleaved_gradient_noise(gl_FragCoord.xy); +#endif  } diff --git a/drivers/gles3/storage/material_storage.cpp b/drivers/gles3/storage/material_storage.cpp index 3dbc75392c..523c9dd8e6 100644 --- a/drivers/gles3/storage/material_storage.cpp +++ b/drivers/gles3/storage/material_storage.cpp @@ -1715,6 +1715,7 @@ ShaderCompiler::DefaultIdentifierActions actions;  		actions.usage_defines["HALF_RES_COLOR"] = "\n#define USES_HALF_RES_COLOR\n";  		actions.usage_defines["QUARTER_RES_COLOR"] = "\n#define USES_QUARTER_RES_COLOR\n";  		actions.render_mode_defines["disable_fog"] = "#define DISABLE_FOG\n"; +		actions.render_mode_defines["use_debanding"] = "#define USE_DEBANDING\n";  		actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;  		actions.default_repeat = ShaderLanguage::REPEAT_ENABLE; diff --git a/scene/resources/sky_material.cpp b/scene/resources/sky_material.cpp index fc999d5fcb..d21f04fab8 100644 --- a/scene/resources/sky_material.cpp +++ b/scene/resources/sky_material.cpp @@ -34,7 +34,7 @@  #include "core/version.h"  Mutex ProceduralSkyMaterial::shader_mutex; -RID ProceduralSkyMaterial::shader; +RID ProceduralSkyMaterial::shader_cache[2];  void ProceduralSkyMaterial::set_sky_top_color(const Color &p_sky_top) {  	sky_top_color = p_sky_top; @@ -147,7 +147,11 @@ float ProceduralSkyMaterial::get_sun_curve() const {  void ProceduralSkyMaterial::set_use_debanding(bool p_use_debanding) {  	use_debanding = p_use_debanding; -	RS::get_singleton()->material_set_param(_get_material(), "use_debanding", use_debanding); +	_update_shader(); +	// Only set if shader already compiled +	if (shader_set) { +		RS::get_singleton()->material_set_shader(_get_material(), shader_cache[int(use_debanding)]); +	}  }  bool ProceduralSkyMaterial::get_use_debanding() const { @@ -161,7 +165,8 @@ Shader::Mode ProceduralSkyMaterial::get_shader_mode() const {  RID ProceduralSkyMaterial::get_rid() const {  	_update_shader();  	if (!shader_set) { -		RS::get_singleton()->material_set_shader(_get_material(), shader); +		RS::get_singleton()->material_set_shader(_get_material(), shader_cache[1 - int(use_debanding)]); +		RS::get_singleton()->material_set_shader(_get_material(), shader_cache[int(use_debanding)]);  		shader_set = true;  	}  	return _get_material(); @@ -169,7 +174,7 @@ RID ProceduralSkyMaterial::get_rid() const {  RID ProceduralSkyMaterial::get_shader_rid() const {  	_update_shader(); -	return shader; +	return shader_cache[int(use_debanding)];  }  void ProceduralSkyMaterial::_validate_property(PropertyInfo &p_property) const { @@ -241,21 +246,24 @@ void ProceduralSkyMaterial::_bind_methods() {  }  void ProceduralSkyMaterial::cleanup_shader() { -	if (shader.is_valid()) { -		RS::get_singleton()->free(shader); +	if (shader_cache[0].is_valid()) { +		RS::get_singleton()->free(shader_cache[0]); +		RS::get_singleton()->free(shader_cache[1]);  	}  }  void ProceduralSkyMaterial::_update_shader() {  	shader_mutex.lock(); -	if (shader.is_null()) { -		shader = RS::get_singleton()->shader_create(); +	if (shader_cache[0].is_null()) { +		for (int i = 0; i < 2; i++) { +			shader_cache[i] = RS::get_singleton()->shader_create(); -		// Add a comment to describe the shader origin (useful when converting to ShaderMaterial). -		RS::get_singleton()->shader_set_code(shader, R"( +			// Add a comment to describe the shader origin (useful when converting to ShaderMaterial). +			RS::get_singleton()->shader_set_code(shader_cache[i], vformat(R"(  // NOTE: Shader automatically converted from )" VERSION_NAME " " VERSION_FULL_CONFIG R"('s ProceduralSkyMaterial.  shader_type sky; +%s  uniform vec4 sky_top_color : source_color = vec4(0.385, 0.454, 0.55, 1.0);  uniform vec4 sky_horizon_color : source_color = vec4(0.646, 0.656, 0.67, 1.0); @@ -269,14 +277,6 @@ uniform float ground_curve : hint_range(0, 1) = 0.02;  uniform float ground_energy = 1.0;  uniform float sun_angle_max = 30.0;  uniform float sun_curve : hint_range(0, 1) = 0.15; -uniform bool use_debanding = true; - -// https://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare -vec3 interleaved_gradient_noise(vec2 pos) { -	const vec3 magic = vec3(0.06711056f, 0.00583715f, 52.9829189f); -	float res = fract(magic.z * fract(dot(pos, magic.xy))) * 2.0 - 1.0; -	return vec3(res, -res, res) / 255.0; -}  void sky() {  	float v_angle = acos(clamp(EYEDIR.y, -1.0, 1.0)); @@ -332,11 +332,10 @@ void sky() {  	ground *= ground_energy;  	COLOR = mix(ground, sky, step(0.0, EYEDIR.y)); -	if (use_debanding) { -		COLOR += interleaved_gradient_noise(FRAGCOORD.xy); -	}  } -)"); +)", +																		  i ? "render_mode use_debanding;" : "")); +		}  	}  	shader_mutex.unlock();  } @@ -546,7 +545,11 @@ float PhysicalSkyMaterial::get_energy_multiplier() const {  void PhysicalSkyMaterial::set_use_debanding(bool p_use_debanding) {  	use_debanding = p_use_debanding; -	RS::get_singleton()->material_set_param(_get_material(), "use_debanding", use_debanding); +	_update_shader(); +	// Only set if shader already compiled +	if (shader_set) { +		RS::get_singleton()->material_set_shader(_get_material(), shader_cache[int(use_debanding)]); +	}  }  bool PhysicalSkyMaterial::get_use_debanding() const { @@ -570,7 +573,8 @@ Shader::Mode PhysicalSkyMaterial::get_shader_mode() const {  RID PhysicalSkyMaterial::get_rid() const {  	_update_shader();  	if (!shader_set) { -		RS::get_singleton()->material_set_shader(_get_material(), shader); +		RS::get_singleton()->material_set_shader(_get_material(), shader_cache[1 - int(use_debanding)]); +		RS::get_singleton()->material_set_shader(_get_material(), shader_cache[int(use_debanding)]);  		shader_set = true;  	}  	return _get_material(); @@ -578,7 +582,7 @@ RID PhysicalSkyMaterial::get_rid() const {  RID PhysicalSkyMaterial::get_shader_rid() const {  	_update_shader(); -	return shader; +	return shader_cache[int(use_debanding)];  }  void PhysicalSkyMaterial::_validate_property(PropertyInfo &p_property) const { @@ -588,7 +592,7 @@ void PhysicalSkyMaterial::_validate_property(PropertyInfo &p_property) const {  }  Mutex PhysicalSkyMaterial::shader_mutex; -RID PhysicalSkyMaterial::shader; +RID PhysicalSkyMaterial::shader_cache[2];  void PhysicalSkyMaterial::_bind_methods() {  	ClassDB::bind_method(D_METHOD("set_rayleigh_coefficient", "rayleigh"), &PhysicalSkyMaterial::set_rayleigh_coefficient); @@ -642,21 +646,24 @@ void PhysicalSkyMaterial::_bind_methods() {  }  void PhysicalSkyMaterial::cleanup_shader() { -	if (shader.is_valid()) { -		RS::get_singleton()->free(shader); +	if (shader_cache[0].is_valid()) { +		RS::get_singleton()->free(shader_cache[0]); +		RS::get_singleton()->free(shader_cache[1]);  	}  }  void PhysicalSkyMaterial::_update_shader() {  	shader_mutex.lock(); -	if (shader.is_null()) { -		shader = RS::get_singleton()->shader_create(); +	if (shader_cache[0].is_null()) { +		for (int i = 0; i < 2; i++) { +			shader_cache[i] = RS::get_singleton()->shader_create(); -		// Add a comment to describe the shader origin (useful when converting to ShaderMaterial). -		RS::get_singleton()->shader_set_code(shader, R"( +			// Add a comment to describe the shader origin (useful when converting to ShaderMaterial). +			RS::get_singleton()->shader_set_code(shader_cache[i], vformat(R"(  // NOTE: Shader automatically converted from )" VERSION_NAME " " VERSION_FULL_CONFIG R"('s PhysicalSkyMaterial.  shader_type sky; +%s  uniform float rayleigh : hint_range(0, 64) = 2.0;  uniform vec4 rayleigh_color : source_color = vec4(0.3, 0.405, 0.6, 1.0); @@ -668,7 +675,6 @@ uniform float turbidity : hint_range(0, 1000) = 10.0;  uniform float sun_disk_scale : hint_range(0, 360) = 1.0;  uniform vec4 ground_color : source_color = vec4(0.1, 0.07, 0.034, 1.0);  uniform float exposure : hint_range(0, 128) = 1.0; -uniform bool use_debanding = true;  uniform sampler2D night_sky : source_color, hint_default_black; @@ -683,13 +689,6 @@ float henyey_greenstein(float cos_theta, float g) {  	return k * (1.0 - g * g) / (pow(1.0 + g * g - 2.0 * g * cos_theta, 1.5));  } -// https://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare -vec3 interleaved_gradient_noise(vec2 pos) { -	const vec3 magic = vec3(0.06711056f, 0.00583715f, 52.9829189f); -	float res = fract(magic.z * fract(dot(pos, magic.xy))) * 2.0 - 1.0; -	return vec3(res, -res, res) / 255.0; -} -  void sky() {  	if (LIGHT0_ENABLED) {  		float zenith_angle = clamp( dot(UP, normalize(LIGHT0_DIRECTION)), -1.0, 1.0 ); @@ -737,16 +736,15 @@ void sky() {  		vec3 color = Lin + L0;  		COLOR = pow(color, vec3(1.0 / (1.2 + (1.2 * sun_fade))));  		COLOR *= exposure; -		if (use_debanding) { -			COLOR += interleaved_gradient_noise(FRAGCOORD.xy); -		}  	} else {  		// There is no sun, so display night_sky and nothing else.  		COLOR = texture(night_sky, SKY_COORDS).xyz;  		COLOR *= exposure;  	}  } -)"); +)", +																		  i ? "render_mode use_debanding;" : "")); +		}  	}  	shader_mutex.unlock(); diff --git a/scene/resources/sky_material.h b/scene/resources/sky_material.h index b517fd806b..fbb202d8d8 100644 --- a/scene/resources/sky_material.h +++ b/scene/resources/sky_material.h @@ -55,7 +55,7 @@ private:  	bool use_debanding = true;  	static Mutex shader_mutex; -	static RID shader; +	static RID shader_cache[2];  	static void _update_shader();  	mutable bool shader_set = false; @@ -160,7 +160,7 @@ class PhysicalSkyMaterial : public Material {  private:  	static Mutex shader_mutex; -	static RID shader; +	static RID shader_cache[2];  	float rayleigh = 0.0f;  	Color rayleigh_color; diff --git a/servers/rendering/renderer_rd/environment/sky.cpp b/servers/rendering/renderer_rd/environment/sky.cpp index 65d1d9e705..ceba43ae8f 100644 --- a/servers/rendering/renderer_rd/environment/sky.cpp +++ b/servers/rendering/renderer_rd/environment/sky.cpp @@ -907,6 +907,7 @@ void SkyRD::init() {  		actions.usage_defines["HALF_RES_COLOR"] = "\n#define USES_HALF_RES_COLOR\n";  		actions.usage_defines["QUARTER_RES_COLOR"] = "\n#define USES_QUARTER_RES_COLOR\n";  		actions.render_mode_defines["disable_fog"] = "#define DISABLE_FOG\n"; +		actions.render_mode_defines["use_debanding"] = "#define USE_DEBANDING\n";  		actions.sampler_array_name = "material_samplers";  		actions.base_texture_binding_index = 1; diff --git a/servers/rendering/renderer_rd/shaders/environment/sky.glsl b/servers/rendering/renderer_rd/shaders/environment/sky.glsl index 0eb0f5f8fd..d523461600 100644 --- a/servers/rendering/renderer_rd/shaders/environment/sky.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/sky.glsl @@ -153,6 +153,15 @@ layout(set = 3, binding = 0) uniform texture3D volumetric_fog_texture;  layout(location = 0) out vec4 frag_color; +#ifdef USE_DEBANDING +// https://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare +vec3 interleaved_gradient_noise(vec2 pos) { +	const vec3 magic = vec3(0.06711056f, 0.00583715f, 52.9829189f); +	float res = fract(magic.z * fract(dot(pos, magic.xy))) * 2.0 - 1.0; +	return vec3(res, -res, res) / 255.0; +} +#endif +  vec4 volumetric_fog_process(vec2 screen_uv) {  	vec3 fog_pos = vec3(screen_uv, 1.0); @@ -252,4 +261,8 @@ void main() {  	// For mobile renderer we're multiplying by 0.5 as we're using a UNORM buffer.  	// For both mobile and clustered, we also bake in the exposure value for the environment and camera.  	frag_color.rgb = frag_color.rgb * params.luminance_multiplier; + +#ifdef USE_DEBANDING +	frag_color.rgb += interleaved_gradient_noise(gl_FragCoord.xy); +#endif  } diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp index 43c483a00d..47cb38f268 100644 --- a/servers/rendering/shader_types.cpp +++ b/servers/rendering/shader_types.cpp @@ -444,6 +444,7 @@ ShaderTypes::ShaderTypes() {  		shader_modes[RS::SHADER_SKY].modes.push_back({ PNAME("use_half_res_pass") });  		shader_modes[RS::SHADER_SKY].modes.push_back({ PNAME("use_quarter_res_pass") });  		shader_modes[RS::SHADER_SKY].modes.push_back({ PNAME("disable_fog") }); +		shader_modes[RS::SHADER_SKY].modes.push_back({ PNAME("use_debanding") });  	}  	/************ FOG **************************/  |