-
-
Notifications
You must be signed in to change notification settings - Fork 21.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Optimize ProceduralSkyMaterial by removing uses of acos and simplifying logic #101973
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,11 +34,11 @@ | |
#include "core/version.h" | ||
|
||
Mutex ProceduralSkyMaterial::shader_mutex; | ||
RID ProceduralSkyMaterial::shader_cache[2]; | ||
RID ProceduralSkyMaterial::shader_cache[4]; | ||
|
||
void ProceduralSkyMaterial::set_sky_top_color(const Color &p_sky_top) { | ||
sky_top_color = p_sky_top; | ||
RS::get_singleton()->material_set_param(_get_material(), "sky_top_color", sky_top_color); | ||
RS::get_singleton()->material_set_param(_get_material(), "sky_top_color", sky_top_color * sky_energy_multiplier); | ||
} | ||
|
||
Color ProceduralSkyMaterial::get_sky_top_color() const { | ||
|
@@ -47,7 +47,7 @@ Color ProceduralSkyMaterial::get_sky_top_color() const { | |
|
||
void ProceduralSkyMaterial::set_sky_horizon_color(const Color &p_sky_horizon) { | ||
sky_horizon_color = p_sky_horizon; | ||
RS::get_singleton()->material_set_param(_get_material(), "sky_horizon_color", sky_horizon_color); | ||
RS::get_singleton()->material_set_param(_get_material(), "sky_horizon_color", sky_horizon_color * sky_energy_multiplier); | ||
} | ||
|
||
Color ProceduralSkyMaterial::get_sky_horizon_color() const { | ||
|
@@ -56,7 +56,9 @@ Color ProceduralSkyMaterial::get_sky_horizon_color() const { | |
|
||
void ProceduralSkyMaterial::set_sky_curve(float p_curve) { | ||
sky_curve = p_curve; | ||
RS::get_singleton()->material_set_param(_get_material(), "sky_curve", sky_curve); | ||
// Actual curve passed to shader includes an ad hoc adjustment because the curve used to be | ||
// in calculated in angles and now uses cosines. | ||
RS::get_singleton()->material_set_param(_get_material(), "inv_sky_curve", 0.6 / sky_curve); | ||
} | ||
|
||
float ProceduralSkyMaterial::get_sky_curve() const { | ||
|
@@ -65,7 +67,8 @@ float ProceduralSkyMaterial::get_sky_curve() const { | |
|
||
void ProceduralSkyMaterial::set_sky_energy_multiplier(float p_multiplier) { | ||
sky_energy_multiplier = p_multiplier; | ||
RS::get_singleton()->material_set_param(_get_material(), "sky_energy", sky_energy_multiplier); | ||
RS::get_singleton()->material_set_param(_get_material(), "sky_top_color", sky_top_color * sky_energy_multiplier); | ||
RS::get_singleton()->material_set_param(_get_material(), "sky_horizon_color", sky_horizon_color * sky_energy_multiplier); | ||
} | ||
|
||
float ProceduralSkyMaterial::get_sky_energy_multiplier() const { | ||
|
@@ -74,11 +77,16 @@ float ProceduralSkyMaterial::get_sky_energy_multiplier() const { | |
|
||
void ProceduralSkyMaterial::set_sky_cover(const Ref<Texture2D> &p_sky_cover) { | ||
sky_cover = p_sky_cover; | ||
|
||
if (p_sky_cover.is_valid()) { | ||
RS::get_singleton()->material_set_param(_get_material(), "sky_cover", p_sky_cover->get_rid()); | ||
} else { | ||
RS::get_singleton()->material_set_param(_get_material(), "sky_cover", Variant()); | ||
} | ||
|
||
if (shader_set) { | ||
RS::get_singleton()->material_set_shader(_get_material(), get_shader_cache()); | ||
} | ||
} | ||
|
||
Ref<Texture2D> ProceduralSkyMaterial::get_sky_cover() const { | ||
|
@@ -87,7 +95,7 @@ Ref<Texture2D> ProceduralSkyMaterial::get_sky_cover() const { | |
|
||
void ProceduralSkyMaterial::set_sky_cover_modulate(const Color &p_sky_cover_modulate) { | ||
sky_cover_modulate = p_sky_cover_modulate; | ||
RS::get_singleton()->material_set_param(_get_material(), "sky_cover_modulate", sky_cover_modulate); | ||
RS::get_singleton()->material_set_param(_get_material(), "sky_cover_modulate", Color(sky_cover_modulate.r, sky_cover_modulate.g, sky_cover_modulate.b, sky_cover_modulate.a * sky_energy_multiplier)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sky energy multiplier is multiplying alpha, not the entire thing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's no issue, see how There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if you say so, just stood out to me at a glance There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess we could remove one more multiply by pre multiplying sky color modulate by its own alpha and the energy multiplier |
||
} | ||
|
||
Color ProceduralSkyMaterial::get_sky_cover_modulate() const { | ||
|
@@ -96,7 +104,7 @@ Color ProceduralSkyMaterial::get_sky_cover_modulate() const { | |
|
||
void ProceduralSkyMaterial::set_ground_bottom_color(const Color &p_ground_bottom) { | ||
ground_bottom_color = p_ground_bottom; | ||
RS::get_singleton()->material_set_param(_get_material(), "ground_bottom_color", ground_bottom_color); | ||
RS::get_singleton()->material_set_param(_get_material(), "ground_bottom_color", ground_bottom_color * ground_energy_multiplier); | ||
} | ||
|
||
Color ProceduralSkyMaterial::get_ground_bottom_color() const { | ||
|
@@ -105,7 +113,7 @@ Color ProceduralSkyMaterial::get_ground_bottom_color() const { | |
|
||
void ProceduralSkyMaterial::set_ground_horizon_color(const Color &p_ground_horizon) { | ||
ground_horizon_color = p_ground_horizon; | ||
RS::get_singleton()->material_set_param(_get_material(), "ground_horizon_color", ground_horizon_color); | ||
RS::get_singleton()->material_set_param(_get_material(), "ground_horizon_color", ground_horizon_color * ground_energy_multiplier); | ||
} | ||
|
||
Color ProceduralSkyMaterial::get_ground_horizon_color() const { | ||
|
@@ -114,7 +122,9 @@ Color ProceduralSkyMaterial::get_ground_horizon_color() const { | |
|
||
void ProceduralSkyMaterial::set_ground_curve(float p_curve) { | ||
ground_curve = p_curve; | ||
RS::get_singleton()->material_set_param(_get_material(), "ground_curve", ground_curve); | ||
// Actual curve passed to shader includes an ad hoc adjustment because the curve used to be | ||
// in calculated in angles and now uses cosines. | ||
RS::get_singleton()->material_set_param(_get_material(), "inv_ground_curve", 0.6 / ground_curve); | ||
} | ||
|
||
float ProceduralSkyMaterial::get_ground_curve() const { | ||
|
@@ -123,7 +133,8 @@ float ProceduralSkyMaterial::get_ground_curve() const { | |
|
||
void ProceduralSkyMaterial::set_ground_energy_multiplier(float p_multiplier) { | ||
ground_energy_multiplier = p_multiplier; | ||
RS::get_singleton()->material_set_param(_get_material(), "ground_energy", ground_energy_multiplier); | ||
RS::get_singleton()->material_set_param(_get_material(), "ground_bottom_color", ground_bottom_color * ground_energy_multiplier); | ||
RS::get_singleton()->material_set_param(_get_material(), "ground_horizon_color", ground_horizon_color * ground_energy_multiplier); | ||
} | ||
|
||
float ProceduralSkyMaterial::get_ground_energy_multiplier() const { | ||
|
@@ -132,7 +143,7 @@ float ProceduralSkyMaterial::get_ground_energy_multiplier() const { | |
|
||
void ProceduralSkyMaterial::set_sun_angle_max(float p_angle) { | ||
sun_angle_max = p_angle; | ||
RS::get_singleton()->material_set_param(_get_material(), "sun_angle_max", Math::deg_to_rad(sun_angle_max)); | ||
RS::get_singleton()->material_set_param(_get_material(), "sun_angle_max", Math::cos(Math::deg_to_rad(sun_angle_max))); | ||
} | ||
|
||
float ProceduralSkyMaterial::get_sun_angle_max() const { | ||
|
@@ -141,7 +152,9 @@ float ProceduralSkyMaterial::get_sun_angle_max() const { | |
|
||
void ProceduralSkyMaterial::set_sun_curve(float p_curve) { | ||
sun_curve = p_curve; | ||
RS::get_singleton()->material_set_param(_get_material(), "sun_curve", sun_curve); | ||
// Actual curve passed to shader includes an ad hoc adjustment because the curve used to be | ||
// in calculated in angles and now uses cosines. | ||
RS::get_singleton()->material_set_param(_get_material(), "inv_sun_curve", 1.6f / Math::pow(sun_curve, 1.4f)); | ||
} | ||
|
||
float ProceduralSkyMaterial::get_sun_curve() const { | ||
|
@@ -153,7 +166,7 @@ void ProceduralSkyMaterial::set_use_debanding(bool p_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)]); | ||
RS::get_singleton()->material_set_shader(_get_material(), get_shader_cache()); | ||
} | ||
} | ||
|
||
|
@@ -174,19 +187,24 @@ Shader::Mode ProceduralSkyMaterial::get_shader_mode() const { | |
return Shader::MODE_SKY; | ||
} | ||
|
||
// Internal function to grab the current shader RID. | ||
// Must only be called if the shader is initialized. | ||
RID ProceduralSkyMaterial::get_shader_cache() const { | ||
return shader_cache[int(use_debanding) + (sky_cover.is_valid() ? 2 : 0)]; | ||
} | ||
|
||
RID ProceduralSkyMaterial::get_rid() const { | ||
_update_shader(); | ||
if (!shader_set) { | ||
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)]); | ||
RS::get_singleton()->material_set_shader(_get_material(), get_shader_cache()); | ||
shader_set = true; | ||
} | ||
return _get_material(); | ||
} | ||
|
||
RID ProceduralSkyMaterial::get_shader_rid() const { | ||
_update_shader(); | ||
return shader_cache[int(use_debanding)]; | ||
return get_shader_cache(); | ||
} | ||
|
||
void ProceduralSkyMaterial::_validate_property(PropertyInfo &p_property) const { | ||
|
@@ -265,13 +283,15 @@ void ProceduralSkyMaterial::cleanup_shader() { | |
if (shader_cache[0].is_valid()) { | ||
RS::get_singleton()->free(shader_cache[0]); | ||
RS::get_singleton()->free(shader_cache[1]); | ||
RS::get_singleton()->free(shader_cache[2]); | ||
RS::get_singleton()->free(shader_cache[3]); | ||
} | ||
} | ||
|
||
void ProceduralSkyMaterial::_update_shader() { | ||
MutexLock shader_lock(shader_mutex); | ||
if (shader_cache[0].is_null()) { | ||
for (int i = 0; i < 2; i++) { | ||
for (int i = 0; i < 4; i++) { | ||
shader_cache[i] = RS::get_singleton()->shader_create(); | ||
|
||
// Add a comment to describe the shader origin (useful when converting to ShaderMaterial). | ||
|
@@ -283,75 +303,73 @@ shader_type sky; | |
|
||
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); | ||
uniform float sky_curve : hint_range(0, 1) = 0.15; | ||
uniform float sky_energy = 1.0; // In Lux. | ||
uniform sampler2D sky_cover : filter_linear, source_color, hint_default_black; | ||
uniform vec4 sky_cover_modulate : source_color = vec4(1.0, 1.0, 1.0, 1.0); | ||
uniform float inv_sky_curve : hint_range(1, 100) = 4.0; | ||
uniform vec4 ground_bottom_color : source_color = vec4(0.2, 0.169, 0.133, 1.0); | ||
uniform vec4 ground_horizon_color : source_color = vec4(0.646, 0.656, 0.67, 1.0); | ||
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 float inv_ground_curve : hint_range(1, 100) = 30.0; | ||
uniform float sun_angle_max = 0.877; | ||
uniform float inv_sun_curve : hint_range(1, 100) = 22.78; | ||
uniform float exposure : hint_range(0, 128) = 1.0; | ||
|
||
uniform sampler2D sky_cover : filter_linear, source_color, hint_default_black; | ||
uniform vec4 sky_cover_modulate : source_color = vec4(1.0, 1.0, 1.0, 1.0); | ||
|
||
void sky() { | ||
float v_angle = acos(clamp(EYEDIR.y, -1.0, 1.0)); | ||
float c = (1.0 - v_angle / (PI * 0.5)); | ||
vec3 sky = mix(sky_horizon_color.rgb, sky_top_color.rgb, clamp(1.0 - pow(1.0 - c, 1.0 / sky_curve), 0.0, 1.0)); | ||
sky *= sky_energy; | ||
float v_angle = clamp(EYEDIR.y, -1.0, 1.0); | ||
vec3 sky = mix(sky_top_color.rgb, sky_horizon_color.rgb, clamp(pow(1.0 - v_angle, inv_sky_curve), 0.0, 1.0)); | ||
|
||
if (LIGHT0_ENABLED) { | ||
float sun_angle = acos(dot(LIGHT0_DIRECTION, EYEDIR)); | ||
if (sun_angle < LIGHT0_SIZE) { | ||
float sun_angle = dot(LIGHT0_DIRECTION, EYEDIR); | ||
float sun_size = cos(LIGHT0_SIZE); | ||
if (sun_angle > sun_size) { | ||
sky = LIGHT0_COLOR * LIGHT0_ENERGY; | ||
} else if (sun_angle < sun_angle_max) { | ||
float c2 = (sun_angle - LIGHT0_SIZE) / (sun_angle_max - LIGHT0_SIZE); | ||
sky = mix(LIGHT0_COLOR * LIGHT0_ENERGY, sky, clamp(1.0 - pow(1.0 - c2, 1.0 / sun_curve), 0.0, 1.0)); | ||
} else if (sun_angle > sun_angle_max) { | ||
float c2 = (sun_size - sun_angle) / (sun_size - sun_angle_max); | ||
sky = mix(sky, LIGHT0_COLOR * LIGHT0_ENERGY, clamp(pow(1.0 - c2, inv_sun_curve), 0.0, 1.0)); | ||
} | ||
} | ||
|
||
if (LIGHT1_ENABLED) { | ||
float sun_angle = acos(dot(LIGHT1_DIRECTION, EYEDIR)); | ||
if (sun_angle < LIGHT1_SIZE) { | ||
float sun_angle = dot(LIGHT1_DIRECTION, EYEDIR); | ||
float sun_size = cos(LIGHT1_SIZE); | ||
if (sun_angle > sun_size) { | ||
sky = LIGHT1_COLOR * LIGHT1_ENERGY; | ||
} else if (sun_angle < sun_angle_max) { | ||
float c2 = (sun_angle - LIGHT1_SIZE) / (sun_angle_max - LIGHT1_SIZE); | ||
sky = mix(LIGHT1_COLOR * LIGHT1_ENERGY, sky, clamp(1.0 - pow(1.0 - c2, 1.0 / sun_curve), 0.0, 1.0)); | ||
} else if (sun_angle > sun_angle_max) { | ||
float c2 = (sun_size - sun_angle) / (sun_size - sun_angle_max); | ||
sky = mix(sky, LIGHT1_COLOR * LIGHT1_ENERGY, clamp(pow(1.0 - c2, inv_sun_curve), 0.0, 1.0)); | ||
} | ||
} | ||
|
||
if (LIGHT2_ENABLED) { | ||
float sun_angle = acos(dot(LIGHT2_DIRECTION, EYEDIR)); | ||
if (sun_angle < LIGHT2_SIZE) { | ||
float sun_angle = dot(LIGHT2_DIRECTION, EYEDIR); | ||
float sun_size = cos(LIGHT2_SIZE); | ||
if (sun_angle > sun_size) { | ||
sky = LIGHT2_COLOR * LIGHT2_ENERGY; | ||
} else if (sun_angle < sun_angle_max) { | ||
float c2 = (sun_angle - LIGHT2_SIZE) / (sun_angle_max - LIGHT2_SIZE); | ||
sky = mix(LIGHT2_COLOR * LIGHT2_ENERGY, sky, clamp(1.0 - pow(1.0 - c2, 1.0 / sun_curve), 0.0, 1.0)); | ||
} else if (sun_angle > sun_angle_max) { | ||
float c2 = (sun_size - sun_angle) / (sun_size - sun_angle_max); | ||
sky = mix(sky, LIGHT2_COLOR * LIGHT2_ENERGY, clamp(pow(1.0 - c2, inv_sun_curve), 0.0, 1.0)); | ||
} | ||
} | ||
|
||
if (LIGHT3_ENABLED) { | ||
float sun_angle = acos(dot(LIGHT3_DIRECTION, EYEDIR)); | ||
if (sun_angle < LIGHT3_SIZE) { | ||
float sun_angle = dot(LIGHT3_DIRECTION, EYEDIR); | ||
float sun_size = cos(LIGHT3_SIZE); | ||
if (sun_angle > sun_size) { | ||
sky = LIGHT3_COLOR * LIGHT3_ENERGY; | ||
} else if (sun_angle < sun_angle_max) { | ||
float c2 = (sun_angle - LIGHT3_SIZE) / (sun_angle_max - LIGHT3_SIZE); | ||
sky = mix(LIGHT3_COLOR * LIGHT3_ENERGY, sky, clamp(1.0 - pow(1.0 - c2, 1.0 / sun_curve), 0.0, 1.0)); | ||
} else if (sun_angle > sun_angle_max) { | ||
float c2 = (sun_size - sun_angle) / (sun_size - sun_angle_max); | ||
sky = mix(sky, LIGHT3_COLOR * LIGHT3_ENERGY, clamp(pow(1.0 - c2, inv_sun_curve), 0.0, 1.0)); | ||
} | ||
} | ||
|
||
vec4 sky_cover_texture = texture(sky_cover, SKY_COORDS); | ||
sky += (sky_cover_texture.rgb * sky_cover_modulate.rgb) * sky_cover_texture.a * sky_cover_modulate.a * sky_energy; | ||
|
||
c = (v_angle - (PI * 0.5)) / (PI * 0.5); | ||
vec3 ground = mix(ground_horizon_color.rgb, ground_bottom_color.rgb, clamp(1.0 - pow(1.0 - c, 1.0 / ground_curve), 0.0, 1.0)); | ||
ground *= ground_energy; | ||
%s | ||
%s | ||
vec3 ground = mix(ground_bottom_color.rgb, ground_horizon_color.rgb, clamp(pow(1.0 + v_angle, inv_ground_curve), 0.0, 1.0)); | ||
|
||
COLOR = mix(ground, sky, step(0.0, EYEDIR.y)) * exposure; | ||
} | ||
)", | ||
i ? "render_mode use_debanding;" : "")); | ||
(i % 2) ? "render_mode use_debanding;" : "", i > 1 ? "vec4 sky_cover_texture = texture(sky_cover, SKY_COORDS);" : "", i > 1 ? "sky += (sky_cover_texture.rgb * sky_cover_modulate.rgb) * sky_cover_texture.a * sky_cover_modulate.a;" : "")); | ||
} | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This setter must also update "sky_cover_modulate" material param