summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gles3/environment/gi.cpp7
-rw-r--r--drivers/gles3/environment/gi.h3
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp154
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.h36
-rw-r--r--drivers/gles3/shaders/sky.glsl3
-rw-r--r--drivers/gles3/storage/light_storage.cpp9
-rw-r--r--drivers/gles3/storage/light_storage.h6
-rw-r--r--drivers/gles3/storage/utilities.cpp5
8 files changed, 163 insertions, 60 deletions
diff --git a/drivers/gles3/environment/gi.cpp b/drivers/gles3/environment/gi.cpp
index 84cdb81d35..5b16d3539f 100644
--- a/drivers/gles3/environment/gi.cpp
+++ b/drivers/gles3/environment/gi.cpp
@@ -98,6 +98,13 @@ float GI::voxel_gi_get_energy(RID p_voxel_gi) const {
return 0.0;
}
+void GI::voxel_gi_set_baked_exposure_normalization(RID p_voxel_gi, float p_baked_exposure) {
+}
+
+float GI::voxel_gi_get_baked_exposure_normalization(RID p_voxel_gi) const {
+ return 1.0;
+}
+
void GI::voxel_gi_set_bias(RID p_voxel_gi, float p_range) {
}
diff --git a/drivers/gles3/environment/gi.h b/drivers/gles3/environment/gi.h
index 7a0634f22b..5b0aad380e 100644
--- a/drivers/gles3/environment/gi.h
+++ b/drivers/gles3/environment/gi.h
@@ -74,6 +74,9 @@ public:
virtual void voxel_gi_set_energy(RID p_voxel_gi, float p_range) override;
virtual float voxel_gi_get_energy(RID p_voxel_gi) const override;
+ virtual void voxel_gi_set_baked_exposure_normalization(RID p_voxel_gi, float p_baked_exposure) override;
+ virtual float voxel_gi_get_baked_exposure_normalization(RID p_voxel_gi) const override;
+
virtual void voxel_gi_set_bias(RID p_voxel_gi, float p_range) override;
virtual float voxel_gi_get_bias(RID p_voxel_gi) const override;
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index cb479dda39..504a7e218d 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -483,6 +483,13 @@ void RasterizerSceneGLES3::sky_set_material(RID p_sky, RID p_material) {
_invalidate_sky(sky);
}
+float RasterizerSceneGLES3::sky_get_baked_exposure(RID p_sky) const {
+ Sky *sky = sky_owner.get_or_null(p_sky);
+ ERR_FAIL_COND_V(!sky, 1.0);
+
+ return sky->baked_exposure;
+}
+
void RasterizerSceneGLES3::_invalidate_sky(Sky *p_sky) {
if (!p_sky->dirty) {
p_sky->dirty = true;
@@ -561,13 +568,13 @@ void RasterizerSceneGLES3::_update_dirty_skys() {
dirty_sky_list = nullptr;
}
-void RasterizerSceneGLES3::_setup_sky(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size) {
+void RasterizerSceneGLES3::_setup_sky(const RenderDataGLES3 *p_render_data, RID p_render_buffers, const PagedArray<RID> &p_lights, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size) {
GLES3::LightStorage *light_storage = GLES3::LightStorage::get_singleton();
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
- ERR_FAIL_COND(p_env.is_null());
+ ERR_FAIL_COND(p_render_data->environment.is_null());
GLES3::SkyMaterialData *material = nullptr;
- Sky *sky = sky_owner.get_or_null(environment_get_sky(p_env));
+ Sky *sky = sky_owner.get_or_null(environment_get_sky(p_render_data->environment));
RID sky_material;
@@ -639,6 +646,14 @@ void RasterizerSceneGLES3::_setup_sky(RID p_env, RID p_render_buffers, const Pag
float sign = light_storage->light_is_negative(base) ? -1 : 1;
sky_light_data.energy = sign * light_storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY);
+ if (is_using_physical_light_units()) {
+ sky_light_data.energy *= light_storage->light_get_param(base, RS::LIGHT_PARAM_INTENSITY);
+ }
+
+ if (p_render_data->camera_attributes.is_valid()) {
+ sky_light_data.energy *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
+ }
+
Color linear_col = light_storage->light_get_color(base);
sky_light_data.color[0] = linear_col.r;
sky_light_data.color[1] = linear_col.g;
@@ -708,7 +723,7 @@ void RasterizerSceneGLES3::_setup_sky(RID p_env, RID p_render_buffers, const Pag
}
}
-void RasterizerSceneGLES3::_draw_sky(RID p_env, const Projection &p_projection, const Transform3D &p_transform) {
+void RasterizerSceneGLES3::_draw_sky(RID p_env, const Projection &p_projection, const Transform3D &p_transform, float p_luminance_multiplier) {
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
ERR_FAIL_COND(p_env.is_null());
@@ -768,12 +783,13 @@ void RasterizerSceneGLES3::_draw_sky(RID p_env, const Projection &p_projection,
GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::PROJECTION, camera.matrix[2][0], camera.matrix[0][0], camera.matrix[2][1], camera.matrix[1][1], shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::POSITION, p_transform.origin, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::TIME, time, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
+ GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::LUMINANCE_MULTIPLIER, p_luminance_multiplier, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
glBindVertexArray(sky_globals.screen_triangle_array);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
-void RasterizerSceneGLES3::_update_sky_radiance(RID p_env, const Projection &p_projection, const Transform3D &p_transform) {
+void RasterizerSceneGLES3::_update_sky_radiance(RID p_env, const Projection &p_projection, const Transform3D &p_transform, float p_luminance_multiplier) {
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
ERR_FAIL_COND(p_env.is_null());
@@ -866,6 +882,7 @@ void RasterizerSceneGLES3::_update_sky_radiance(RID p_env, const Projection &p_p
GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::POSITION, p_transform.origin, shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::TIME, time, shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::PROJECTION, cm.matrix[2][0], cm.matrix[0][0], cm.matrix[2][1], cm.matrix[1][1], shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
+ GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::LUMINANCE_MULTIPLIER, p_luminance_multiplier, shader_data->version, SkyShaderGLES3::MODE_CUBEMAP);
glBindVertexArray(sky_globals.screen_triangle_array);
@@ -887,7 +904,7 @@ void RasterizerSceneGLES3::_update_sky_radiance(RID p_env, const Projection &p_p
_filter_sky_radiance(sky, 0); //Just copy over the first mipmap
}
sky->processing_layer = 1;
-
+ sky->baked_exposure = p_luminance_multiplier;
sky->reflection_dirty = false;
} else {
if (sky_mode == RS::SKY_MODE_INCREMENTAL && sky->processing_layer < max_processing_layer) {
@@ -1061,25 +1078,6 @@ Ref<Image> RasterizerSceneGLES3::environment_bake_panorama(RID p_env, bool p_bak
return Ref<Image>();
}
-RID RasterizerSceneGLES3::camera_effects_allocate() {
- return RID();
-}
-
-void RasterizerSceneGLES3::camera_effects_initialize(RID p_rid) {
-}
-
-void RasterizerSceneGLES3::camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) {
-}
-
-void RasterizerSceneGLES3::camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape) {
-}
-
-void RasterizerSceneGLES3::camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) {
-}
-
-void RasterizerSceneGLES3::camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) {
-}
-
void RasterizerSceneGLES3::positional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) {
}
@@ -1403,8 +1401,9 @@ void RasterizerSceneGLES3::_setup_environment(const RenderDataGLES3 *p_render_da
RS::EnvironmentBG env_bg = environment_get_background(p_render_data->environment);
RS::EnvironmentAmbientSource ambient_src = environment_get_ambient_source(p_render_data->environment);
- float bg_energy = environment_get_bg_energy(p_render_data->environment);
- scene_state.ubo.ambient_light_color_energy[3] = bg_energy;
+ float bg_energy_multiplier = environment_get_bg_energy_multiplier(p_render_data->environment);
+
+ scene_state.ubo.ambient_light_color_energy[3] = bg_energy_multiplier;
scene_state.ubo.ambient_color_sky_mix = environment_get_ambient_sky_contribution(p_render_data->environment);
@@ -1413,9 +1412,9 @@ void RasterizerSceneGLES3::_setup_environment(const RenderDataGLES3 *p_render_da
Color color = env_bg == RS::ENV_BG_CLEAR_COLOR ? p_default_bg_color : environment_get_bg_color(p_render_data->environment);
color = color.srgb_to_linear();
- scene_state.ubo.ambient_light_color_energy[0] = color.r * bg_energy;
- scene_state.ubo.ambient_light_color_energy[1] = color.g * bg_energy;
- scene_state.ubo.ambient_light_color_energy[2] = color.b * bg_energy;
+ scene_state.ubo.ambient_light_color_energy[0] = color.r * bg_energy_multiplier;
+ scene_state.ubo.ambient_light_color_energy[1] = color.g * bg_energy_multiplier;
+ scene_state.ubo.ambient_light_color_energy[2] = color.b * bg_energy_multiplier;
scene_state.ubo.use_ambient_light = true;
scene_state.ubo.use_ambient_cubemap = false;
} else {
@@ -1459,6 +1458,25 @@ void RasterizerSceneGLES3::_setup_environment(const RenderDataGLES3 *p_render_da
} else {
}
+ if (p_render_data->camera_attributes.is_valid()) {
+ scene_state.ubo.emissive_exposure_normalization = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
+ scene_state.ubo.IBL_exposure_normalization = 1.0;
+ if (is_environment(p_render_data->environment)) {
+ RID sky_rid = environment_get_sky(p_render_data->environment);
+ if (sky_rid.is_valid()) {
+ float current_exposure = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes) * environment_get_bg_intensity(p_render_data->environment);
+ scene_state.ubo.IBL_exposure_normalization = current_exposure / MAX(0.001, sky_get_baked_exposure(sky_rid));
+ }
+ }
+ } else if (scene_state.ubo.emissive_exposure_normalization > 0.0) {
+ // This branch is triggered when using render_material().
+ // Emissive is set outside the function, so don't set it.
+ // IBL isn't used don't set it.
+ } else {
+ scene_state.ubo.emissive_exposure_normalization = 1.0;
+ scene_state.ubo.IBL_exposure_normalization = 1.0;
+ }
+
if (scene_state.ubo_buffer == 0) {
glGenBuffers(1, &scene_state.ubo_buffer);
}
@@ -1510,7 +1528,17 @@ void RasterizerSceneGLES3::_setup_lights(const RenderDataGLES3 *p_render_data, b
float sign = light_storage->light_is_negative(base) ? -1 : 1;
- light_data.energy = sign * light_storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY) * Math_PI;
+ light_data.energy = sign * light_storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY);
+
+ if (is_using_physical_light_units()) {
+ light_data.energy *= light_storage->light_get_param(base, RS::LIGHT_PARAM_INTENSITY);
+ } else {
+ light_data.energy *= Math_PI;
+ }
+
+ if (p_render_data->camera_attributes.is_valid()) {
+ light_data.energy *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
+ }
Color linear_col = light_storage->light_get_color(base).srgb_to_linear();
light_data.color[0] = linear_col.r;
@@ -1590,7 +1618,7 @@ void RasterizerSceneGLES3::_setup_lights(const RenderDataGLES3 *p_render_data, b
for (uint32_t i = 0; i < (r_omni_light_count + r_spot_light_count); i++) {
uint32_t index = (i < r_omni_light_count) ? i : i - (r_omni_light_count);
LightData &light_data = (i < r_omni_light_count) ? scene_state.omni_lights[index] : scene_state.spot_lights[index];
- //RS::LightType type = (i < omni_light_count) ? RS::LIGHT_OMNI : RS::LIGHT_SPOT;
+ RS::LightType type = (i < r_omni_light_count) ? RS::LIGHT_OMNI : RS::LIGHT_SPOT;
LightInstance *li = (i < r_omni_light_count) ? scene_state.omni_light_sort[index].instance : scene_state.spot_light_sort[index].instance;
RID base = li->light;
@@ -1634,7 +1662,26 @@ void RasterizerSceneGLES3::_setup_lights(const RenderDataGLES3 *p_render_data, b
}
}
- float energy = sign * light_storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY) * Math_PI * fade;
+ float energy = sign * light_storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY) * fade;
+
+ if (is_using_physical_light_units()) {
+ energy *= light_storage->light_get_param(base, RS::LIGHT_PARAM_INTENSITY);
+
+ // Convert from Luminous Power to Luminous Intensity
+ if (type == RS::LIGHT_OMNI) {
+ energy *= 1.0 / (Math_PI * 4.0);
+ } else {
+ // Spot Lights are not physically accurate, Luminous Intensity should change in relation to the cone angle.
+ // We make this assumption to keep them easy to control.
+ energy *= 1.0 / Math_PI;
+ }
+ } else {
+ energy *= Math_PI;
+ }
+
+ if (p_render_data->camera_attributes.is_valid()) {
+ energy *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
+ }
light_data.color[0] = linear_col.r * energy;
light_data.color[1] = linear_col.g * energy;
@@ -1671,7 +1718,7 @@ void RasterizerSceneGLES3::_setup_lights(const RenderDataGLES3 *p_render_data, b
glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
-void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data, RendererScene::RenderInfo *r_render_info) {
+void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data, RendererScene::RenderInfo *r_render_info) {
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
GLES3::Config *config = GLES3::Config::get_singleton();
RENDER_TIMESTAMP("Setup 3D Scene");
@@ -1707,7 +1754,7 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData *
render_data.lights = &p_lights;
render_data.reflection_probes = &p_reflection_probes;
render_data.environment = p_environment;
- render_data.camera_effects = p_camera_effects;
+ render_data.camera_attributes = p_camera_attributes;
render_data.reflection_probe = p_reflection_probe;
render_data.reflection_probe_pass = p_reflection_probe_pass;
@@ -1768,6 +1815,8 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData *
glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_TONEMAP_UNIFORM_LOCATION, scene_state.tonemap_buffer);
glBufferData(GL_UNIFORM_BUFFER, sizeof(SceneState::TonemapUBO), &tonemap_ubo, GL_STREAM_DRAW);
+ scene_state.ubo.emissive_exposure_normalization = -1.0; // Use default exposure normalization.
+
_setup_lights(&render_data, false, render_data.directional_light_count, render_data.omni_light_count, render_data.spot_light_count);
_setup_environment(&render_data, render_data.reflection_probe.is_valid(), screen_size, !render_data.reflection_probe.is_valid(), clear_color, false);
@@ -1778,17 +1827,24 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData *
bool draw_sky = false;
bool draw_sky_fog_only = false;
bool keep_color = false;
+ float sky_energy_multiplier = 1.0;
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_OVERDRAW) {
clear_color = Color(0, 0, 0, 1); //in overdraw mode, BG should always be black
} else if (render_data.environment.is_valid()) {
RS::EnvironmentBG bg_mode = environment_get_background(render_data.environment);
- float bg_energy = environment_get_bg_energy(render_data.environment);
+ float bg_energy_multiplier = environment_get_bg_energy_multiplier(render_data.environment);
+ bg_energy_multiplier *= environment_get_bg_intensity(render_data.environment);
+
+ if (render_data.camera_attributes.is_valid()) {
+ bg_energy_multiplier *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(render_data.camera_attributes);
+ }
+
switch (bg_mode) {
case RS::ENV_BG_CLEAR_COLOR: {
- clear_color.r *= bg_energy;
- clear_color.g *= bg_energy;
- clear_color.b *= bg_energy;
+ clear_color.r *= bg_energy_multiplier;
+ clear_color.g *= bg_energy_multiplier;
+ clear_color.b *= bg_energy_multiplier;
if (environment_get_fog_enabled(render_data.environment)) {
draw_sky_fog_only = true;
GLES3::MaterialStorage::get_singleton()->material_set_param(sky_globals.fog_material, "clear_color", Variant(clear_color));
@@ -1796,9 +1852,9 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData *
} break;
case RS::ENV_BG_COLOR: {
clear_color = environment_get_bg_color(render_data.environment);
- clear_color.r *= bg_energy;
- clear_color.g *= bg_energy;
- clear_color.b *= bg_energy;
+ clear_color.r *= bg_energy_multiplier;
+ clear_color.g *= bg_energy_multiplier;
+ clear_color.b *= bg_energy_multiplier;
if (environment_get_fog_enabled(render_data.environment)) {
draw_sky_fog_only = true;
GLES3::MaterialStorage::get_singleton()->material_set_param(sky_globals.fog_material, "clear_color", Variant(clear_color));
@@ -1828,11 +1884,13 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData *
projection = correction * render_data.cam_projection;
}
- _setup_sky(render_data.environment, p_render_buffers, *render_data.lights, projection, render_data.cam_transform, screen_size);
+ sky_energy_multiplier *= bg_energy_multiplier;
+
+ _setup_sky(&render_data, p_render_buffers, *render_data.lights, projection, render_data.cam_transform, screen_size);
if (environment_get_sky(render_data.environment).is_valid()) {
if (environment_get_reflection_source(render_data.environment) == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(render_data.environment) == RS::ENV_AMBIENT_SOURCE_SKY || (environment_get_reflection_source(render_data.environment) == RS::ENV_REFLECTION_SOURCE_BG && environment_get_background(render_data.environment) == RS::ENV_BG_SKY)) {
- _update_sky_radiance(render_data.environment, projection, render_data.cam_transform);
+ _update_sky_radiance(render_data.environment, projection, render_data.cam_transform, sky_energy_multiplier);
}
} else {
// do not try to draw sky if invalid
@@ -1936,7 +1994,7 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData *
scene_state.current_depth_draw = GLES3::SceneShaderData::DEPTH_DRAW_DISABLED;
scene_state.cull_mode = GLES3::SceneShaderData::CULL_BACK;
- _draw_sky(render_data.environment, render_data.cam_projection, render_data.cam_transform);
+ _draw_sky(render_data.environment, render_data.cam_projection, render_data.cam_transform, sky_energy_multiplier);
}
RENDER_TIMESTAMP("Render 3D Transparent Pass");
@@ -2406,6 +2464,9 @@ bool RasterizerSceneGLES3::free(RID p_rid) {
LightInstance *light_instance = light_instance_owner.get_or_null(p_rid);
ERR_FAIL_COND_V(!light_instance, false);
light_instance_owner.free(p_rid);
+ } else if (RSG::camera_attributes->owns_camera_attributes(p_rid)) {
+ //not much to delete, just free it
+ RSG::camera_attributes->camera_attributes_free(p_rid);
} else {
return false;
}
@@ -2431,6 +2492,9 @@ RasterizerSceneGLES3::RasterizerSceneGLES3() {
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
GLES3::Config *config = GLES3::Config::get_singleton();
+ // Quality settings.
+ use_physical_light_units = GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units");
+
{
// Setup Lights
diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h
index a54d87a3a3..526da88ef6 100644
--- a/drivers/gles3/rasterizer_scene_gles3.h
+++ b/drivers/gles3/rasterizer_scene_gles3.h
@@ -111,7 +111,7 @@ struct RenderDataGLES3 {
const PagedArray<RID> *lights = nullptr;
const PagedArray<RID> *reflection_probes = nullptr;
RID environment = RID();
- RID camera_effects = RID();
+ RID camera_attributes = RID();
RID reflection_probe = RID();
int reflection_probe_pass = 0;
@@ -344,7 +344,7 @@ private:
float ambient_color_sky_mix;
uint32_t material_uv2_mode;
- float pad2;
+ float emissive_exposure_normalization;
uint32_t use_ambient_light = 0;
uint32_t use_ambient_cubemap = 0;
@@ -357,7 +357,7 @@ private:
uint32_t directional_light_count;
float z_far;
float z_near;
- float pad1;
+ float IBL_exposure_normalization;
uint32_t fog_enabled;
float fog_density;
@@ -537,6 +537,16 @@ protected:
void _render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer);
+ /* Camera Attributes */
+
+ struct CameraAttributes {
+ float exposure_multiplier = 1.0;
+ float exposure_normalization = 1.0;
+ };
+
+ bool use_physical_light_units = false;
+ mutable RID_Owner<CameraAttributes, true> camera_attributes_owner;
+
/* Environment */
RS::EnvironmentSSAOQuality ssao_quality = RS::ENV_SSAO_QUALITY_MEDIUM;
@@ -605,6 +615,7 @@ protected:
bool dirty = false;
int processing_layer = 0;
Sky *dirty_list = nullptr;
+ float baked_exposure = 1.0;
//State to track when radiance cubemap needs updating
GLES3::SkyMaterialData *prev_material;
@@ -615,12 +626,12 @@ protected:
Sky *dirty_sky_list = nullptr;
mutable RID_Owner<Sky, true> sky_owner;
- void _setup_sky(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size);
+ void _setup_sky(const RenderDataGLES3 *p_render_data, RID p_render_buffers, const PagedArray<RID> &p_lights, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size);
void _invalidate_sky(Sky *p_sky);
void _update_dirty_skys();
- void _update_sky_radiance(RID p_env, const Projection &p_projection, const Transform3D &p_transform);
+ void _update_sky_radiance(RID p_env, const Projection &p_projection, const Transform3D &p_transform, float p_luminance_multiplier);
void _filter_sky_radiance(Sky *p_sky, int p_base_layer);
- void _draw_sky(RID p_env, const Projection &p_projection, const Transform3D &p_transform);
+ void _draw_sky(RID p_env, const Projection &p_projection, const Transform3D &p_transform, float p_luminance_multiplier);
void _free_sky_data(Sky *p_sky);
public:
@@ -665,6 +676,7 @@ public:
void sky_set_mode(RID p_sky, RS::SkyMode p_mode) override;
void sky_set_material(RID p_sky, RID p_material) override;
Ref<Image> sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) override;
+ float sky_get_baked_exposure(RID p_sky) const;
/* ENVIRONMENT API */
@@ -686,13 +698,9 @@ public:
Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) override;
- RID camera_effects_allocate() override;
- void camera_effects_initialize(RID p_rid) override;
- void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) override;
- void camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape) override;
-
- void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) override;
- void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) override;
+ _FORCE_INLINE_ bool is_using_physical_light_units() {
+ return use_physical_light_units;
+ }
void positional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) override;
void directional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) override;
@@ -743,7 +751,7 @@ public:
void voxel_gi_set_quality(RS::VoxelGIQuality) override;
- void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override;
+ void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override;
void render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<RenderGeometryInstance *> &p_instances) override;
diff --git a/drivers/gles3/shaders/sky.glsl b/drivers/gles3/shaders/sky.glsl
index eb1befe38e..21f01d2a8f 100644
--- a/drivers/gles3/shaders/sky.glsl
+++ b/drivers/gles3/shaders/sky.glsl
@@ -92,6 +92,7 @@ uniform mat4 orientation;
uniform vec4 projection;
uniform vec3 position;
uniform float time;
+uniform float luminance_multiplier;
uniform float fog_aerial_perspective;
uniform vec3 fog_light_color;
@@ -149,6 +150,8 @@ void main() {
}
+ color *= luminance_multiplier;
+
// Convert to Linear for tonemapping so color matches scene shader better
color = srgb_to_linear(color);
color *= exposure;
diff --git a/drivers/gles3/storage/light_storage.cpp b/drivers/gles3/storage/light_storage.cpp
index 683716ca99..6411590aee 100644
--- a/drivers/gles3/storage/light_storage.cpp
+++ b/drivers/gles3/storage/light_storage.cpp
@@ -422,13 +422,17 @@ float LightStorage::reflection_probe_get_mesh_lod_threshold(RID p_probe) const {
/* LIGHTMAP CAPTURE */
RID LightStorage::lightmap_allocate() {
- return RID();
+ return lightmap_owner.allocate_rid();
}
void LightStorage::lightmap_initialize(RID p_rid) {
+ lightmap_owner.initialize_rid(p_rid, Lightmap());
}
void LightStorage::lightmap_free(RID p_rid) {
+ Lightmap *lightmap = lightmap_owner.get_or_null(p_rid);
+ lightmap->dependency.deleted_notify(p_rid);
+ lightmap_owner.free(p_rid);
}
void LightStorage::lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) {
@@ -443,6 +447,9 @@ void LightStorage::lightmap_set_probe_interior(RID p_lightmap, bool p_interior)
void LightStorage::lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) {
}
+void LightStorage::lightmap_set_baked_exposure_normalization(RID p_lightmap, float p_exposure) {
+}
+
PackedVector3Array LightStorage::lightmap_get_probe_capture_points(RID p_lightmap) const {
return PackedVector3Array();
}
diff --git a/drivers/gles3/storage/light_storage.h b/drivers/gles3/storage/light_storage.h
index fa012a7b58..f054f0fdc6 100644
--- a/drivers/gles3/storage/light_storage.h
+++ b/drivers/gles3/storage/light_storage.h
@@ -92,6 +92,7 @@ struct ReflectionProbe {
bool enable_shadows = false;
uint32_t cull_mask = (1 << 20) - 1;
float mesh_lod_threshold = 0.01;
+ float baked_exposure = 1.0;
Dependency dependency;
};
@@ -103,6 +104,7 @@ struct Lightmap {
bool uses_spherical_harmonics = false;
bool interior = false;
AABB bounds = AABB(Vector3(), Vector3(1, 1, 1));
+ float baked_exposure = 1.0;
int32_t array_index = -1; //unassigned
PackedVector3Array points;
PackedColorArray point_sh;
@@ -297,6 +299,9 @@ public:
/* LIGHTMAP CAPTURE */
+ Lightmap *get_lightmap(RID p_rid) { return lightmap_owner.get_or_null(p_rid); };
+ bool owns_lightmap(RID p_rid) { return lightmap_owner.owns(p_rid); };
+
virtual RID lightmap_allocate() override;
virtual void lightmap_initialize(RID p_rid) override;
virtual void lightmap_free(RID p_rid) override;
@@ -305,6 +310,7 @@ public:
virtual void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) override;
virtual void lightmap_set_probe_interior(RID p_lightmap, bool p_interior) override;
virtual void lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) override;
+ virtual void lightmap_set_baked_exposure_normalization(RID p_lightmap, float p_exposure) override;
virtual PackedVector3Array lightmap_get_probe_capture_points(RID p_lightmap) const override;
virtual PackedColorArray lightmap_get_probe_capture_sh(RID p_lightmap) const override;
virtual PackedInt32Array lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const override;
diff --git a/drivers/gles3/storage/utilities.cpp b/drivers/gles3/storage/utilities.cpp
index 654104722b..16bacf1829 100644
--- a/drivers/gles3/storage/utilities.cpp
+++ b/drivers/gles3/storage/utilities.cpp
@@ -82,6 +82,8 @@ RS::InstanceType Utilities::get_base_type(RID p_rid) const {
return RS::INSTANCE_MULTIMESH;
} else if (GLES3::LightStorage::get_singleton()->owns_light(p_rid)) {
return RS::INSTANCE_LIGHT;
+ } else if (GLES3::LightStorage::get_singleton()->owns_lightmap(p_rid)) {
+ return RS::INSTANCE_LIGHTMAP;
}
return RS::INSTANCE_NONE;
}
@@ -114,6 +116,9 @@ bool Utilities::free(RID p_rid) {
} else if (GLES3::LightStorage::get_singleton()->owns_light(p_rid)) {
GLES3::LightStorage::get_singleton()->light_free(p_rid);
return true;
+ } else if (GLES3::LightStorage::get_singleton()->owns_lightmap(p_rid)) {
+ GLES3::LightStorage::get_singleton()->lightmap_free(p_rid);
+ return true;
} else {
return false;
}