Merge pull request #52918 from Calinou/add-new-light-attenuation-3.x
This commit is contained in:
commit
302ad4e600
12 changed files with 120 additions and 4 deletions
|
@ -1377,6 +1377,10 @@
|
|||
<member name="rendering/quality/shading/force_vertex_shading.mobile" type="bool" setter="" getter="" default="true">
|
||||
Lower-end override for [member rendering/quality/shading/force_vertex_shading] on mobile devices, due to performance concerns or driver support.
|
||||
</member>
|
||||
<member name="rendering/quality/shading/use_physical_light_attenuation" type="bool" setter="" getter="" default="false">
|
||||
If [code]true[/code], enables new physical light attenuation for [OmniLight]s and [SpotLight]s. This results in more realistic lighting appearance with a very small performance cost. When physical light attenuation is enabled, lights will appear to be darker as a result of the new attenuation formula. This can be compensated by adjusting the lights' energy or attenuation values.
|
||||
Changes to this setting will only be applied upon restarting the application.
|
||||
</member>
|
||||
<member name="rendering/quality/shadow_atlas/cubemap_size" type="int" setter="" getter="" default="512">
|
||||
Size for cubemap into which the shadow is rendered before being copied into the shadow atlas. A higher number can result in higher resolution shadows when used with a higher [member rendering/quality/shadow_atlas/size]. Setting higher than a quarter of the [member rendering/quality/shadow_atlas/size] will not result in a perceptible increase in visual quality.
|
||||
</member>
|
||||
|
|
|
@ -2427,6 +2427,8 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
|
|||
storage->info.render.surface_switch_count++;
|
||||
}
|
||||
|
||||
state.scene_shader.set_conditional(SceneShaderGLES2::USE_PHYSICAL_LIGHT_ATTENUATION, storage->config.use_physical_light_attenuation);
|
||||
|
||||
bool octahedral_compression = ((RasterizerStorageGLES2::Surface *)e->geometry)->format & VisualServer::ArrayFormat::ARRAY_FLAG_USE_OCTAHEDRAL_COMPRESSION;
|
||||
if (octahedral_compression != prev_octahedral_compression) {
|
||||
state.scene_shader.set_conditional(SceneShaderGLES2::ENABLE_OCTAHEDRAL_COMPRESSION, octahedral_compression);
|
||||
|
|
|
@ -6508,6 +6508,8 @@ void RasterizerStorageGLES2::initialize() {
|
|||
GLOBAL_DEF_RST("rendering/quality/lightmapping/use_bicubic_sampling.mobile", false);
|
||||
config.use_lightmap_filter_bicubic = GLOBAL_GET("rendering/quality/lightmapping/use_bicubic_sampling");
|
||||
|
||||
config.use_physical_light_attenuation = GLOBAL_GET("rendering/quality/shading/use_physical_light_attenuation");
|
||||
|
||||
int orphan_mode = GLOBAL_GET("rendering/2d/opengl/legacy_orphan_buffers");
|
||||
switch (orphan_mode) {
|
||||
default: {
|
||||
|
|
|
@ -58,6 +58,7 @@ public:
|
|||
bool use_anisotropic_filter;
|
||||
bool use_skeleton_software;
|
||||
bool use_lightmap_filter_bicubic;
|
||||
bool use_physical_light_attenuation;
|
||||
|
||||
int max_vertex_texture_image_units;
|
||||
int max_texture_image_units;
|
||||
|
|
|
@ -206,6 +206,15 @@ uniform highp float light_spot_attenuation;
|
|||
uniform highp float light_spot_range;
|
||||
uniform highp float light_spot_angle;
|
||||
|
||||
float get_omni_attenuation(float distance, float inv_range, float decay) {
|
||||
float nd = distance * inv_range;
|
||||
nd *= nd;
|
||||
nd *= nd; // nd^4
|
||||
nd = max(1.0 - nd, 0.0);
|
||||
nd *= nd; // nd^2
|
||||
return nd * pow(max(distance, 0.0001), -decay);
|
||||
}
|
||||
|
||||
void light_compute(
|
||||
vec3 N,
|
||||
vec3 L,
|
||||
|
@ -546,9 +555,12 @@ VERTEX_SHADER_CODE
|
|||
float normalized_distance = light_length / light_range;
|
||||
|
||||
if (normalized_distance < 1.0) {
|
||||
#ifdef USE_PHYSICAL_LIGHT_ATTENUATION
|
||||
float omni_attenuation = get_omni_attenuation(light_length, 1.0 / light_range, light_attenuation);
|
||||
#else
|
||||
float omni_attenuation = pow(1.0 - normalized_distance, light_attenuation);
|
||||
#endif
|
||||
|
||||
vec3 attenuation = vec3(omni_attenuation);
|
||||
light_att = vec3(omni_attenuation);
|
||||
} else {
|
||||
light_att = vec3(0.0);
|
||||
|
@ -565,7 +577,12 @@ VERTEX_SHADER_CODE
|
|||
float normalized_distance = light_length / light_range;
|
||||
|
||||
if (normalized_distance < 1.0) {
|
||||
#ifdef USE_PHYSICAL_LIGHT_ATTENUATION
|
||||
float spot_attenuation = get_omni_attenuation(light_length, 1.0 / light_range, light_attenuation);
|
||||
#else
|
||||
float spot_attenuation = pow(1.0 - normalized_distance, light_attenuation);
|
||||
#endif
|
||||
|
||||
vec3 spot_dir = light_direction;
|
||||
|
||||
float spot_cutoff = light_spot_angle;
|
||||
|
@ -1222,6 +1239,17 @@ float GTR1(float NdotH, float a) {
|
|||
return (a2 - 1.0) / (M_PI * log(a2) * t);
|
||||
}
|
||||
|
||||
#ifdef USE_PHYSICAL_LIGHT_ATTENUATION
|
||||
float get_omni_attenuation(float distance, float inv_range, float decay) {
|
||||
float nd = distance * inv_range;
|
||||
nd *= nd;
|
||||
nd *= nd; // nd^4
|
||||
nd = max(1.0 - nd, 0.0);
|
||||
nd *= nd; // nd^2
|
||||
return nd * pow(max(distance, 0.0001), -decay);
|
||||
}
|
||||
#endif
|
||||
|
||||
void light_compute(
|
||||
vec3 N,
|
||||
vec3 L,
|
||||
|
@ -1852,7 +1880,11 @@ FRAGMENT_SHADER_CODE
|
|||
|
||||
float normalized_distance = light_length / light_range;
|
||||
if (normalized_distance < 1.0) {
|
||||
#ifdef USE_PHYSICAL_LIGHT_ATTENUATION
|
||||
float omni_attenuation = get_omni_attenuation(light_length, 1.0 / light_range, light_attenuation);
|
||||
#else
|
||||
float omni_attenuation = pow(1.0 - normalized_distance, light_attenuation);
|
||||
#endif
|
||||
|
||||
light_att = vec3(omni_attenuation);
|
||||
} else {
|
||||
|
@ -2134,7 +2166,12 @@ FRAGMENT_SHADER_CODE
|
|||
float normalized_distance = light_length / light_range;
|
||||
|
||||
if (normalized_distance < 1.0) {
|
||||
#ifdef USE_PHYSICAL_LIGHT_ATTENUATION
|
||||
float spot_attenuation = get_omni_attenuation(light_length, 1.0 / light_range, light_attenuation);
|
||||
#else
|
||||
float spot_attenuation = pow(1.0 - normalized_distance, light_attenuation);
|
||||
#endif
|
||||
|
||||
vec3 spot_dir = light_direction;
|
||||
|
||||
float spot_cutoff = light_spot_angle;
|
||||
|
|
|
@ -2112,6 +2112,8 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_
|
|||
}
|
||||
}
|
||||
|
||||
state.scene_shader.set_conditional(SceneShaderGLES3::USE_PHYSICAL_LIGHT_ATTENUATION, storage->config.use_physical_light_attenuation);
|
||||
|
||||
bool octahedral_compression = ((RasterizerStorageGLES3::Surface *)e->geometry)->format & VisualServer::ArrayFormat::ARRAY_FLAG_USE_OCTAHEDRAL_COMPRESSION;
|
||||
if (octahedral_compression != prev_octahedral_compression) {
|
||||
state.scene_shader.set_conditional(SceneShaderGLES3::ENABLE_OCTAHEDRAL_COMPRESSION, octahedral_compression);
|
||||
|
|
|
@ -8252,6 +8252,8 @@ void RasterizerStorageGLES3::initialize() {
|
|||
GLOBAL_DEF("rendering/quality/lightmapping/use_bicubic_sampling.mobile", false);
|
||||
config.use_lightmap_filter_bicubic = GLOBAL_GET("rendering/quality/lightmapping/use_bicubic_sampling");
|
||||
|
||||
config.use_physical_light_attenuation = GLOBAL_GET("rendering/quality/shading/use_physical_light_attenuation");
|
||||
|
||||
config.use_depth_prepass = bool(GLOBAL_GET("rendering/quality/depth_prepass/enable"));
|
||||
if (config.use_depth_prepass) {
|
||||
String vendors = GLOBAL_GET("rendering/quality/depth_prepass/disable_for_vendors");
|
||||
|
|
|
@ -74,6 +74,7 @@ public:
|
|||
bool use_fast_texture_filter;
|
||||
bool use_anisotropic_filter;
|
||||
bool use_lightmap_filter_bicubic;
|
||||
bool use_physical_light_attenuation;
|
||||
|
||||
bool s3tc_supported;
|
||||
bool latc_supported;
|
||||
|
|
|
@ -234,11 +234,27 @@ void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, float roughness, in
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef USE_PHYSICAL_LIGHT_ATTENUATION
|
||||
float get_omni_attenuation(float distance, float inv_range, float decay) {
|
||||
float nd = distance * inv_range;
|
||||
nd *= nd;
|
||||
nd *= nd; // nd^4
|
||||
nd = max(1.0 - nd, 0.0);
|
||||
nd *= nd; // nd^2
|
||||
return nd * pow(max(distance, 0.0001), -decay);
|
||||
}
|
||||
#endif
|
||||
|
||||
void light_process_omni(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, float roughness, inout vec3 diffuse, inout vec3 specular) {
|
||||
vec3 light_rel_vec = omni_lights[idx].light_pos_inv_radius.xyz - vertex;
|
||||
float light_length = length(light_rel_vec);
|
||||
|
||||
#ifdef USE_PHYSICAL_LIGHT_ATTENUATION
|
||||
vec3 light_attenuation = vec3(get_omni_attenuation(light_length, omni_lights[idx].light_pos_inv_radius.w, omni_lights[idx].light_direction_attenuation.w));
|
||||
#else
|
||||
float normalized_distance = light_length * omni_lights[idx].light_pos_inv_radius.w;
|
||||
vec3 light_attenuation = vec3(pow(max(1.0 - normalized_distance, 0.0), omni_lights[idx].light_direction_attenuation.w));
|
||||
#endif
|
||||
|
||||
light_compute(normal, normalize(light_rel_vec), eye_vec, omni_lights[idx].light_color_energy.rgb * light_attenuation, roughness, diffuse, specular);
|
||||
}
|
||||
|
@ -246,8 +262,14 @@ void light_process_omni(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, float r
|
|||
void light_process_spot(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, float roughness, inout vec3 diffuse, inout vec3 specular) {
|
||||
vec3 light_rel_vec = spot_lights[idx].light_pos_inv_radius.xyz - vertex;
|
||||
float light_length = length(light_rel_vec);
|
||||
|
||||
#ifdef USE_PHYSICAL_LIGHT_ATTENUATION
|
||||
vec3 light_attenuation = vec3(get_omni_attenuation(light_length, spot_lights[idx].light_pos_inv_radius.w, spot_lights[idx].light_direction_attenuation.w));
|
||||
#else
|
||||
float normalized_distance = light_length * spot_lights[idx].light_pos_inv_radius.w;
|
||||
vec3 light_attenuation = vec3(pow(max(1.0 - normalized_distance, 0.001), spot_lights[idx].light_direction_attenuation.w));
|
||||
#endif
|
||||
|
||||
vec3 spot_dir = spot_lights[idx].light_direction_attenuation.xyz;
|
||||
float spot_cutoff = spot_lights[idx].light_params.y;
|
||||
float scos = max(dot(-normalize(light_rel_vec), spot_dir), spot_cutoff);
|
||||
|
@ -1250,13 +1272,28 @@ in highp float dp_clip;
|
|||
|
||||
#endif
|
||||
|
||||
#ifdef USE_PHYSICAL_LIGHT_ATTENUATION
|
||||
float get_omni_attenuation(float distance, float inv_range, float decay) {
|
||||
float nd = distance * inv_range;
|
||||
nd *= nd;
|
||||
nd *= nd; // nd^4
|
||||
nd = max(1.0 - nd, 0.0);
|
||||
nd *= nd; // nd^2
|
||||
return nd * pow(max(distance, 0.0001), -decay);
|
||||
}
|
||||
#endif
|
||||
|
||||
void light_process_omni(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 binormal, vec3 tangent, vec3 albedo, vec3 transmission, float roughness, float metallic, float specular, float rim, float rim_tint, float clearcoat, float clearcoat_gloss, float anisotropy, float p_blob_intensity, inout vec3 diffuse_light, inout vec3 specular_light, inout float alpha) {
|
||||
vec3 light_rel_vec = omni_lights[idx].light_pos_inv_radius.xyz - vertex;
|
||||
float light_length = length(light_rel_vec);
|
||||
float normalized_distance = light_length * omni_lights[idx].light_pos_inv_radius.w;
|
||||
float omni_attenuation;
|
||||
if (normalized_distance < 1.0) {
|
||||
#ifdef USE_PHYSICAL_LIGHT_ATTENUATION
|
||||
omni_attenuation = get_omni_attenuation(light_length, omni_lights[idx].light_pos_inv_radius.w, omni_lights[idx].light_direction_attenuation.w);
|
||||
#else
|
||||
omni_attenuation = pow(1.0 - normalized_distance, omni_lights[idx].light_direction_attenuation.w);
|
||||
#endif
|
||||
} else {
|
||||
omni_attenuation = 0.0;
|
||||
}
|
||||
|
@ -1316,7 +1353,11 @@ void light_process_spot(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 bi
|
|||
float normalized_distance = light_length * spot_lights[idx].light_pos_inv_radius.w;
|
||||
float spot_attenuation;
|
||||
if (normalized_distance < 1.0) {
|
||||
spot_attenuation = pow(1.0 - normalized_distance, spot_lights[idx].light_direction_attenuation.w);
|
||||
#ifdef USE_PHYSICAL_LIGHT_ATTENUATION
|
||||
spot_attenuation = get_omni_attenuation(light_length, spot_lights[idx].light_pos_inv_radius.w, spot_lights[idx].light_direction_attenuation.w);
|
||||
#else
|
||||
spot_attenuation = pow(1.0 - normalized_distance, omni_lights[idx].light_direction_attenuation.w);
|
||||
#endif
|
||||
} else {
|
||||
spot_attenuation = 0.0;
|
||||
}
|
||||
|
|
|
@ -704,6 +704,15 @@ _ALWAYS_INLINE_ float uniform_rand() {
|
|||
return float(state) / float(UINT32_MAX);
|
||||
}
|
||||
|
||||
float LightmapperCPU::_get_omni_attenuation(float distance, float inv_range, float decay) const {
|
||||
float nd = distance * inv_range;
|
||||
nd *= nd;
|
||||
nd *= nd; // nd^4
|
||||
nd = MAX(1.0 - nd, 0.0);
|
||||
nd *= nd; // nd^2
|
||||
return nd * powf(MAX(distance, 0.0001f), -decay);
|
||||
}
|
||||
|
||||
void LightmapperCPU::_compute_direct_light(uint32_t p_idx, void *r_lightmap) {
|
||||
LightmapTexel *lightmap = (LightmapTexel *)r_lightmap;
|
||||
for (unsigned int i = 0; i < lights.size(); ++i) {
|
||||
|
@ -734,7 +743,11 @@ void LightmapperCPU::_compute_direct_light(uint32_t p_idx, void *r_lightmap) {
|
|||
soft_shadowing_disk_size = light.size / dist;
|
||||
|
||||
if (light.type == LIGHT_TYPE_OMNI) {
|
||||
attenuation = powf(1.0 - dist / light.range, light.attenuation);
|
||||
if (parameters.use_physical_light_attenuation) {
|
||||
attenuation = _get_omni_attenuation(dist, 1.0f / light.range, light.attenuation);
|
||||
} else {
|
||||
attenuation = powf(1.0 - dist / light.range, light.attenuation);
|
||||
}
|
||||
} else /* (light.type == LIGHT_TYPE_SPOT) */ {
|
||||
float angle = Math::acos(light.direction.dot(light_to_point));
|
||||
|
||||
|
@ -743,7 +756,12 @@ void LightmapperCPU::_compute_direct_light(uint32_t p_idx, void *r_lightmap) {
|
|||
}
|
||||
|
||||
float normalized_dist = dist * (1.0f / MAX(0.001f, light.range));
|
||||
float norm_light_attenuation = Math::pow(MAX(1.0f - normalized_dist, 0.001f), light.attenuation);
|
||||
float norm_light_attenuation;
|
||||
if (parameters.use_physical_light_attenuation) {
|
||||
norm_light_attenuation = _get_omni_attenuation(dist, 1.0f / light.range, light.attenuation);
|
||||
} else {
|
||||
norm_light_attenuation = Math::pow(MAX(1.0f - normalized_dist, 0.001f), light.attenuation);
|
||||
}
|
||||
|
||||
float spot_cutoff = Math::cos(light.spot_angle);
|
||||
float scos = MAX(light_to_point.dot(light.direction), spot_cutoff);
|
||||
|
@ -1279,6 +1297,7 @@ LightmapperCPU::BakeError LightmapperCPU::bake(BakeQuality p_quality, bool p_use
|
|||
|
||||
// Collect parameters
|
||||
parameters.use_denoiser = p_use_denoiser;
|
||||
parameters.use_physical_light_attenuation = bool(GLOBAL_GET("rendering/quality/shading/use_physical_light_attenuation"));
|
||||
parameters.bias = p_bias;
|
||||
parameters.bounces = p_bounces;
|
||||
parameters.bounce_indirect_energy = p_bounce_indirect_energy;
|
||||
|
|
|
@ -85,6 +85,7 @@ class LightmapperCPU : public Lightmapper {
|
|||
float bounce_indirect_energy;
|
||||
int samples;
|
||||
bool use_denoiser = true;
|
||||
bool use_physical_light_attenuation = false;
|
||||
Ref<Image> environment_panorama;
|
||||
Basis environment_transform;
|
||||
};
|
||||
|
@ -151,6 +152,8 @@ class LightmapperCPU : public Lightmapper {
|
|||
Vector3 _fix_sample_position(const Vector3 &p_position, const Vector3 &p_texel_center, const Vector3 &p_normal, const Vector3 &p_tangent, const Vector3 &p_bitangent, const Vector2 &p_texel_size);
|
||||
void _plot_triangle(const Vector2 *p_vertices, const Vector3 *p_positions, const Vector3 *p_normals, const Vector2 *p_uvs, const Ref<Image> &p_albedo_texture, const Ref<Image> &p_emission_texture, Vector2i p_size, LocalVector<LightmapTexel> &r_texels, LocalVector<int> &r_lightmap_indices);
|
||||
|
||||
float _get_omni_attenuation(float distance, float inv_range, float decay) const;
|
||||
|
||||
void _compute_direct_light(uint32_t p_idx, void *r_lightmap);
|
||||
|
||||
void _compute_indirect_light(uint32_t p_idx, void *r_lightmap);
|
||||
|
|
|
@ -2636,6 +2636,8 @@ VisualServer::VisualServer() {
|
|||
|
||||
GLOBAL_DEF_RST("rendering/misc/mesh_storage/split_stream", false);
|
||||
|
||||
GLOBAL_DEF_RST("rendering/quality/shading/use_physical_light_attenuation", false);
|
||||
|
||||
GLOBAL_DEF("rendering/quality/depth_prepass/enable", true);
|
||||
GLOBAL_DEF("rendering/quality/depth_prepass/disable_for_vendors", "PowerVR,Mali,Adreno,Apple");
|
||||
|
||||
|
|
Loading…
Reference in a new issue