Implement Physical Light Units as an optional setting.

This allows light sources to be specified in physical light units in addition to the regular energy multiplier. In order to avoid loss of precision at high values, brightness values are premultiplied by an exposure normalization value.

In support of Physical Light Units this PR also renames CameraEffects to CameraAttributes.
This commit is contained in:
clayjohn 2022-07-31 16:20:24 -07:00
parent 736632ee7e
commit 385ee5c70b
131 changed files with 2692 additions and 1283 deletions

View file

@ -337,7 +337,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
#### Rendering
- Some Environment settings such as depth of field have been moved to a CameraEffects resource which is assigned to individual Camera nodes.
- Some Environment settings such as depth of field have been moved to a CameraAttributes resource which is assigned to individual Camera nodes.
- [The ACES Fitted tonemapping algorithm is now used in place of the old ACES algorithm.](https://github.com/godotengine/godot/pull/52476)
- The old non-fitted ACES tonemapping algorithm was removed.
- Quality settings have been moved from individual nodes and resources to the Project Settings for better centralization.

View file

@ -194,10 +194,13 @@
The emitted light's color. See [member emission_enabled].
</member>
<member name="emission_enabled" type="bool" setter="set_feature" getter="get_feature" default="false">
If [code]true[/code], the body emits light. Emitting light makes the object appear brighter. The object can also cast light on other objects if a [VoxelGI] is used and this object is used in baked lighting.
If [code]true[/code], the body emits light. Emitting light makes the object appear brighter. The object can also cast light on other objects if a [VoxelGI], SDFGI, or [LightmapGI] is used and this object is used in baked lighting.
</member>
<member name="emission_energy" type="float" setter="set_emission_energy" getter="get_emission_energy" default="1.0">
The emitted light's strength. See [member emission_enabled].
<member name="emission_energy_multiplier" type="float" setter="set_emission_energy_multiplier" getter="get_emission_energy_multiplier" default="1.0">
Multiplier for emitted light. See [member emission_enabled].
</member>
<member name="emission_intensity" type="float" setter="set_emission_intensity" getter="get_emission_intensity">
Luminance of emitted light, measured in nits (candela per square meter). Only available when [member ProjectSettings.rendering/lights_and_shadows/use_physical_light_units] is enabled. The default is roughly equivalent to an indoor lightbulb.
</member>
<member name="emission_on_uv2" type="bool" setter="set_flag" getter="get_flag" default="false">
Use [code]UV2[/code] to read from the [member emission_texture].

View file

@ -150,6 +150,9 @@
</method>
</methods>
<members>
<member name="attributes" type="CameraAttributes" setter="set_attributes" getter="get_attributes">
The [CameraAttributes] to use for this camera.
</member>
<member name="cull_mask" type="int" setter="set_cull_mask" getter="get_cull_mask" default="1048575">
The culling mask that describes which 3D render layers are rendered by this camera.
</member>
@ -160,9 +163,6 @@
<member name="doppler_tracking" type="int" setter="set_doppler_tracking" getter="get_doppler_tracking" enum="Camera3D.DopplerTracking" default="0">
If not [constant DOPPLER_TRACKING_DISABLED], this camera will simulate the [url=https://en.wikipedia.org/wiki/Doppler_effect]Doppler effect[/url] for objects changed in particular [code]_process[/code] methods. See [enum DopplerTracking] for possible values.
</member>
<member name="effects" type="CameraEffects" setter="set_effects" getter="get_effects">
The [CameraEffects] to use for this camera.
</member>
<member name="environment" type="Environment" setter="set_environment" getter="get_environment">
The [Environment] to use for this camera.
</member>

View file

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="CameraAttributes" inherits="Resource" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Parent class for camera settings.
</brief_description>
<description>
Controls camera-specific attributes such as depth of field and exposure override.
When used in a [WorldEnvironment] it provides default settings for exposure, auto-exposure, and depth of field that will be used by all cameras without their own [CameraAttributes], including the editor camera. When used in a [Camera3D] it will override any [CameraAttributes] set in the [WorldEnvironment]. When used in [VoxelGI] or [LightmapGI], only the exposure settings will be used.
See also [Environment] for general 3D environment settings.
This is a pure virtual class that is inherited by [CameraAttributesPhysical] and [CameraAttributesPractical].
</description>
<tutorials>
</tutorials>
<members>
<member name="auto_exposure_enabled" type="bool" setter="set_auto_exposure_enabled" getter="is_auto_exposure_enabled">
If [code]true[/code], enables the tonemapping auto exposure mode of the scene renderer. If [code]true[/code], the renderer will automatically determine the exposure setting to adapt to the scene's illumination and the observed light.
</member>
<member name="auto_exposure_scale" type="float" setter="set_auto_exposure_scale" getter="get_auto_exposure_scale">
The scale of the auto exposure effect. Affects the intensity of auto exposure.
</member>
<member name="auto_exposure_speed" type="float" setter="set_auto_exposure_speed" getter="get_auto_exposure_speed">
The speed of the auto exposure effect. Affects the time needed for the camera to perform auto exposure.
</member>
<member name="exposure_multiplier" type="float" setter="set_exposure_multiplier" getter="get_exposure_multiplier">
Multiplier for the exposure amount. A higher value results in a brighter image.
</member>
<member name="exposure_sensitivity" type="float" setter="set_exposure_sensitivity" getter="get_exposure_sensitivity">
Sensitivity of camera sensors, measured in ISO. A higher sensitivity results in a brighter image. Only available when [member ProjectSettings.rendering/lights_and_shadows/use_physical_light_units] is enabled. When [member auto_exposure_enabled] this can be used as a method of exposure compensation, doubling the value will increase the exposure value (measured in EV100) by 1 stop.
</member>
</members>
</class>

View file

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="CameraAttributesPhysical" inherits="CameraAttributes" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Physically-based camera settings.
</brief_description>
<description>
[CameraAttributesPhysical] is used to set rendering settings based on a physically-based camera's settings. It is responsible for exposure, auto-exposure, and depth of field.
When used in a [WorldEnvironment] it provides default settings for exposure, auto-exposure, and depth of field that will be used by all cameras without their own [CameraAttributes], including the editor camera. When used in a [Camera3D] it will override any [CameraAttributes] set in the [WorldEnvironment] and will override the [Camera3D]s [member Camera3D.far], [member Camera3D.near], [member Camera3D.fov], and [member Camera3D.keep_aspect] properties. When used in [VoxelGI] or [LightmapGI], only the exposure settings will be used.
The default settings are intended for use in an outdoor environment, tips for settings for use in an indoor environment can be found in each setting's documentation.
</description>
<tutorials>
</tutorials>
<methods>
<method name="get_fov" qualifiers="const">
<return type="float" />
<description>
Returns the vertical field of view that corresponds to the [member frustum_focal_length]. This value is calculated internally whenever [member frustum_focal_length] is changed.
</description>
</method>
</methods>
<members>
<member name="auto_exposure_max_exposure_value" type="float" setter="set_auto_exposure_max_exposure_value" getter="get_auto_exposure_max_exposure_value" default="10.0">
The maximum luminance (in EV100) used when calculating auto exposure. When calculating scene average luminance, color values will be clamped to at least this value. This limits the auto-exposure from exposing below a certain brightness, resulting in a cut off point where the scene will remain bright.
</member>
<member name="auto_exposure_min_exposure_value" type="float" setter="set_auto_exposure_min_exposure_value" getter="get_auto_exposure_min_exposure_value" default="-8.0">
The minimum luminance luminance (in EV100) used when calculating auto exposure. When calculating scene average luminance, color values will be clamped to at least this value. This limits the auto-exposure from exposing above a certain brightness, resulting in a cut off point where the scene will remain dark.
</member>
<member name="exposure_aperture" type="float" setter="set_aperture" getter="get_aperture" default="16.0">
Size of the aperture of the camera, measured in f-stops. An f-stop is a unitless ratio between the focal length of the camera and the diameter of the aperture. A high aperture setting will result in a smaller aperture which leads to a dimmer image and sharper focus. A low aperture results in a wide aperture which lets in more light resulting in a brighter, less-focused image. Default is appropriate for outdoors at daytime (i.e. for use with a default [DirectionalLight3D]), for indoor lighting, a value between 2 and 4 is more appropriate.
Only available when [member ProjectSettings.rendering/lights_and_shadows/use_physical_light_units] is enabled.
</member>
<member name="exposure_shutter_speed" type="float" setter="set_shutter_speed" getter="get_shutter_speed" default="100.0">
Time for shutter to open and close, measured in seconds. A higher value will let in more light leading to a brighter image, while a lower amount will let in less light leading to a darker image.
Only available when [member ProjectSettings.rendering/lights_and_shadows/use_physical_light_units] is enabled.
</member>
<member name="frustum_far" type="float" setter="set_far" getter="get_far" default="4000.0">
Override value for [member Camera3D.far]. Used internally when calculating depth of field. When attached to a [Camera3D] as its [member Camera3D.attributes], it will override the [member Camera3D.far] property.
</member>
<member name="frustum_focal_length" type="float" setter="set_focal_length" getter="get_focal_length" default="35.0">
Distance between camera lens and camera aperture, measured in millimeters. Controls field of view and depth of field. A larger focal length will result in a smaller field of view and a narrower depth of field meaning fewer objects will be in focus. A smaller focal length will result in a wider field of view and a larger depth of field meaning more objects will be in focus. When attached to a [Camera3D] as its [member Camera3D.attributes], it will override the [member Camera3D.fov] property and the [member Camera3D.keep_aspect] property.
</member>
<member name="frustum_focus_distance" type="float" setter="set_focus_distance" getter="get_focus_distance" default="10.0">
Distance from camera of object that will be in focus, measured in meters. Internally this will be clamped to be at least 1 millimeter larger than [member frustum_focal_length].
</member>
<member name="frustum_near" type="float" setter="set_near" getter="get_near" default="0.05">
Override value for [member Camera3D.near]. Used internally when calculating depth of field. When attached to a [Camera3D] as its [member Camera3D.attributes], it will override the [member Camera3D.near] property.
</member>
</members>
</class>

View file

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="CameraAttributesPractical" inherits="CameraAttributes" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Camera settings in an easy to use format.
</brief_description>
<description>
Controls camera-specific attributes such as auto-exposure, depth of field, and exposure override.
When used in a [WorldEnvironment] it provides default settings for exposure, auto-exposure, and depth of field that will be used by all cameras without their own [CameraAttributes], including the editor camera. When used in a [Camera3D] it will override any [CameraAttributes] set in the [WorldEnvironment]. When used in [VoxelGI] or [LightmapGI], only the exposure settings will be used.
</description>
<tutorials>
</tutorials>
<members>
<member name="auto_exposure_max_sensitivity" type="float" setter="set_auto_exposure_max_sensitivity" getter="get_auto_exposure_max_sensitivity" default="800.0">
The maximum sensitivity (in ISO) used when calculating auto exposure. When calculating scene average luminance, color values will be clamped to at least this value. This limits the auto-exposure from exposing below a certain brightness, resulting in a cut off point where the scene will remain bright.
</member>
<member name="auto_exposure_min_sensitivity" type="float" setter="set_auto_exposure_min_sensitivity" getter="get_auto_exposure_min_sensitivity" default="0.0">
The minimum sensitivity (in ISO) used when calculating auto exposure. When calculating scene average luminance, color values will be clamped to at least this value. This limits the auto-exposure from exposing above a certain brightness, resulting in a cut off point where the scene will remain dark.
</member>
<member name="dof_blur_amount" type="float" setter="set_dof_blur_amount" getter="get_dof_blur_amount" default="0.1">
Sets the maximum amount of blur. When using physically-based blur amounts, will instead act as a multiplier. High values lead to an increased amount of bluriness, but can be much more expensive to calculate. It is best to keep this as low as possible for a given art style.
</member>
<member name="dof_blur_far_distance" type="float" setter="set_dof_blur_far_distance" getter="get_dof_blur_far_distance" default="10.0">
Objects further from the [Camera3D] by this amount will be blurred by the depth of field effect. Measured in meters.
</member>
<member name="dof_blur_far_enabled" type="bool" setter="set_dof_blur_far_enabled" getter="is_dof_blur_far_enabled" default="false">
Enables depth of field blur for objects further than [member dof_blur_far_distance]. Strength of blur is controlled by [member dof_blur_amount] and modulated by [member dof_blur_far_transition].
</member>
<member name="dof_blur_far_transition" type="float" setter="set_dof_blur_far_transition" getter="get_dof_blur_far_transition" default="5.0">
When positive, distance over which (starting from [member dof_blur_far_distance]) blur effect will scale from 0 to [member dof_blur_amount]. When negative, uses physically-based scaling so depth of field effect will scale from 0 at [member dof_blur_far_distance] and will increase in a physically accurate way as objects get further from the [Camera3D].
</member>
<member name="dof_blur_near_distance" type="float" setter="set_dof_blur_near_distance" getter="get_dof_blur_near_distance" default="2.0">
Objects closer from the [Camera3D] by this amount will be blurred by the depth of field effect. Measured in meters.
</member>
<member name="dof_blur_near_enabled" type="bool" setter="set_dof_blur_near_enabled" getter="is_dof_blur_near_enabled" default="false">
Enables depth of field blur for objects closer than [member dof_blur_near_distance]. Strength of blur is controlled by [member dof_blur_amount] and modulated by [member dof_blur_near_transition].
</member>
<member name="dof_blur_near_transition" type="float" setter="set_dof_blur_near_transition" getter="get_dof_blur_near_transition" default="1.0">
When positive, distance over which blur effect will scale from 0 to [member dof_blur_amount], ending at [member dof_blur_near_distance]. When negative, uses physically-based scaling so depth of field effect will scale from 0 at [member dof_blur_near_distance] and will increase in a physically accurate way as objects get closer to the [Camera3D].
</member>
</members>
</class>

View file

@ -1,41 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="CameraEffects" inherits="Resource" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Contains camera-specific effects such as depth of field and exposure override.
</brief_description>
<description>
Contains camera-specific effects such as depth of field and exposure override.
See also [Environment] for general 3D environment settings.
</description>
<tutorials>
</tutorials>
<members>
<member name="dof_blur_amount" type="float" setter="set_dof_blur_amount" getter="get_dof_blur_amount" default="0.1">
The amount of blur for both near and far depth-of-field effects. The amount of blur increases the radius of the blur effect, making the affected area blurrier. However, If the amount is too high, you might start to see lines appearing, especially when using a low quality blur.
</member>
<member name="dof_blur_far_distance" type="float" setter="set_dof_blur_far_distance" getter="get_dof_blur_far_distance" default="10.0">
The distance from the camera where the far blur effect affects the rendering.
</member>
<member name="dof_blur_far_enabled" type="bool" setter="set_dof_blur_far_enabled" getter="is_dof_blur_far_enabled" default="false">
If [code]true[/code], enables the depth-of-field far blur effect. This has a significant performance cost. Consider disabling it in scenes where there are no far away objects.
</member>
<member name="dof_blur_far_transition" type="float" setter="set_dof_blur_far_transition" getter="get_dof_blur_far_transition" default="5.0">
The length of the transition between the no-blur area and far blur.
</member>
<member name="dof_blur_near_distance" type="float" setter="set_dof_blur_near_distance" getter="get_dof_blur_near_distance" default="2.0">
Distance from the camera where the near blur effect affects the rendering.
</member>
<member name="dof_blur_near_enabled" type="bool" setter="set_dof_blur_near_enabled" getter="is_dof_blur_near_enabled" default="false">
If [code]true[/code], enables the depth-of-field near blur effect. This has a significant performance cost. Consider disabling it in scenes where there are no nearby objects.
</member>
<member name="dof_blur_near_transition" type="float" setter="set_dof_blur_near_transition" getter="get_dof_blur_near_transition" default="1.0">
The length of the transition between the near blur and no-blur area.
</member>
<member name="override_exposure" type="float" setter="set_override_exposure" getter="get_override_exposure" default="1.0">
The exposure override value to use. Higher values will result in a brighter scene. Only effective if [member override_exposure_enabled] is [code]true[/code].
</member>
<member name="override_exposure_enabled" type="bool" setter="set_override_exposure_enabled" getter="is_override_exposure_enabled" default="false">
If [code]true[/code], overrides the manual or automatic exposure defined in the [Environment] with the value in [member override_exposure].
</member>
</members>
</class>

View file

@ -63,21 +63,6 @@
<member name="ambient_light_source" type="int" setter="set_ambient_source" getter="get_ambient_source" enum="Environment.AmbientSource" default="0">
The ambient light source to use for rendering materials and global illumination.
</member>
<member name="auto_exposure_enabled" type="bool" setter="set_tonemap_auto_exposure_enabled" getter="is_tonemap_auto_exposure_enabled" default="false">
If [code]true[/code], enables the tonemapping auto exposure mode of the scene renderer. If [code]true[/code], the renderer will automatically determine the exposure setting to adapt to the scene's illumination and the observed light.
</member>
<member name="auto_exposure_max_luma" type="float" setter="set_tonemap_auto_exposure_max" getter="get_tonemap_auto_exposure_max" default="8.0">
The maximum luminance value for the auto exposure.
</member>
<member name="auto_exposure_min_luma" type="float" setter="set_tonemap_auto_exposure_min" getter="get_tonemap_auto_exposure_min" default="0.05">
The minimum luminance value for the auto exposure.
</member>
<member name="auto_exposure_scale" type="float" setter="set_tonemap_auto_exposure_grey" getter="get_tonemap_auto_exposure_grey" default="0.4">
The scale of the auto exposure effect. Affects the intensity of auto exposure.
</member>
<member name="auto_exposure_speed" type="float" setter="set_tonemap_auto_exposure_speed" getter="get_tonemap_auto_exposure_speed" default="0.5">
The speed of the auto exposure effect. Affects the time needed for the camera to perform auto exposure.
</member>
<member name="background_camera_feed_id" type="int" setter="set_camera_feed_id" getter="get_camera_feed_id" default="1">
The ID of the camera feed to show in the background.
</member>
@ -87,8 +72,11 @@
<member name="background_color" type="Color" setter="set_bg_color" getter="get_bg_color" default="Color(0, 0, 0, 1)">
The [Color] displayed for clear areas of the scene. Only effective when using the [constant BG_COLOR] background mode.
</member>
<member name="background_energy" type="float" setter="set_bg_energy" getter="get_bg_energy" default="1.0">
The power of the light emitted by the background.
<member name="background_energy_multiplier" type="float" setter="set_bg_energy_multiplier" getter="get_bg_energy_multiplier" default="1.0">
Multiplier for background energy. Increase to make background brighter, decrease to make background dimmer.
</member>
<member name="background_intensity" type="float" setter="set_bg_intensity" getter="get_bg_intensity" default="30000.0">
Luminance of background measured in nits (candela per square meter). Only used when [member ProjectSettings.rendering/lights_and_shadows/use_physical_light_units] is enabled. The default value is roughly equivalent to the sky at midday.
</member>
<member name="background_mode" type="int" setter="set_background" getter="get_background" enum="Environment.BGMode" default="0">
The background mode. See [enum BGMode] for possible values.

View file

@ -11,6 +11,12 @@
<link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link>
</tutorials>
<methods>
<method name="get_correlated_color" qualifiers="const">
<return type="Color" />
<description>
Returns the [Color] of an idealized blackbody at the given [member light_temperature]. This value is calculated internally based on the [member light_temperature]. This [Color] is multiplied by [member light_color] before being sent to the [RenderingServer].
</description>
</method>
<method name="get_param" qualifiers="const">
<return type="float" />
<param index="0" name="param" type="int" enum="Light3D.Param" />
@ -67,6 +73,15 @@
Secondary multiplier used with indirect light (light bounces). Used with [VoxelGI] and SDFGI (see [member Environment.sdfgi_enabled]).
[b]Note:[/b] This property is ignored if [member light_energy] is equal to [code]0.0[/code], as the light won't be present at all in the GI shader.
</member>
<member name="light_intensity_lumens" type="float" setter="set_param" getter="get_param">
Used by positional lights ([OmniLight3D] and [SpotLight3D]) when [member ProjectSettings.rendering/lights_and_shadows/use_physical_light_units] is [code]true[/code]. Sets the intensity of the light source measured in Lumens. Lumens are a measure of luminous flux, which is the total amount of visible light emitted by a light source per unit of time.
For [SpotLight3D]s, we assume that the area outside the visible cone is surrounded by a perfect light absorbing material. Accordingly, the apparent brightness of the cone area does not change as the cone increases and decreases in size.
A typical household lightbulb can range from around 600 lumens to 1,200 lumens, a candle is about 13 lumens, while a streetlight can be approximately 60,000 lumens.
</member>
<member name="light_intensity_lux" type="float" setter="set_param" getter="get_param">
Used by [DirectionalLight3D]s when [member ProjectSettings.rendering/lights_and_shadows/use_physical_light_units] is [code]true[/code]. Sets the intensity of the light source measured in Lux. Lux is a measure pf luminous flux per unit area, it is equal to one lumen per square metre. Lux is the measure of how much light hits a surface at a given time.
On a clear sunny day a surface in direct sunlight may be approximately 100,000 lux, a typical room in a home may be approximately 50 lux, while the moonlit ground may be approximately 0.1 lux.
</member>
<member name="light_negative" type="bool" setter="set_negative" getter="is_negative" default="false">
If [code]true[/code], the light's effect is reversed, darkening areas and casting bright shadows.
</member>
@ -80,6 +95,10 @@
<member name="light_specular" type="float" setter="set_param" getter="get_param" default="0.5">
The intensity of the specular blob in objects affected by the light. At [code]0[/code], the light becomes a pure diffuse light. When not baking emission, this can be used to avoid unrealistic reflections when placing lights above an emissive surface.
</member>
<member name="light_temperature" type="float" setter="set_temperature" getter="get_temperature">
Sets the color temperature of the light source, measured in Kelvin. This is used to calculate a correlated color temperature which tints the [member light_color].
The sun on a cloudy day is approximately 6500 Kelvin, on a clear day it is between 5500 to 6000 Kelvin, and on a clear day at sunrise or sunset it ranges to around 1850 Kelvin.
</member>
<member name="light_volumetric_fog_energy" type="float" setter="set_param" getter="get_param" default="1.0">
Secondary multiplier multiplied with [member light_energy] then used with the [Environment]'s volumetric fog (if enabled). If set to [code]0.0[/code], computing volumetric fog will be skipped for this light, which can improve performance for large amounts of lights when volumetric fog is enabled.
[b]Note:[/b] To prevent short-lived dynamic light effects from poorly interacting with volumetric fog, lights used in those effects should have [member light_volumetric_fog_energy] set to [code]0.0[/code] unless [member Environment.volumetric_fog_temporal_reprojection_enabled] is disabled (or unless the reprojection amount is significantly lowered).
@ -166,7 +185,10 @@
<constant name="PARAM_TRANSMITTANCE_BIAS" value="19" enum="Param">
Constant for accessing [member shadow_transmittance_bias].
</constant>
<constant name="PARAM_MAX" value="20" enum="Param">
<constant name="PARAM_INTENSITY" value="20" enum="Param">
Constant for accessing [member light_intensity_lumens] and [member light_intensity_lux]. Only used when [member ProjectSettings.rendering/lights_and_shadows/use_physical_light_units] is [code]true[/code].
</constant>
<constant name="PARAM_MAX" value="21" enum="Param">
Represents the size of the [enum Param] enum.
</constant>
<constant name="BAKE_DISABLED" value="0" enum="BakeMode">

View file

@ -20,6 +20,9 @@
<member name="bounces" type="int" setter="set_bounces" getter="get_bounces" default="1">
Number of light bounces that are taken into account during baking. Higher values result in brighter, more realistic lighting, at the cost of longer bake times. If set to [code]0[/code], only environment lighting, direct light and emissive lighting is baked.
</member>
<member name="camera_attributes" type="CameraAttributes" setter="set_camera_attributes" getter="get_camera_attributes">
The [CameraAttributes] resource that specifies exposure levels to bake at. Auto-exposure and non exposure properties will be ignored. Exposure settings should be used to reduce the dynamic range present when baking. If exposure is too high, the [LightmapGI] will have banding artifacts or may have over-exposure artifacts.
</member>
<member name="directional" type="bool" setter="set_directional" getter="is_directional" default="false">
If [code]true[/code], bakes lightmaps to contain directional information as spherical harmonics. This results in more realistic lighting appearance, especially with normal mapped materials and for lights that have their direct light baked ([member Light3D.light_bake_mode] set to [constant Light3D.BAKE_STATIC]). The directional information is also used to provide rough reflections for static and dynamic objects. This has a small run-time performance cost as the shader has to perform more work to interpret the direction information from the lightmap. Directional lightmaps also take longer to bake and result in larger file sizes.
[b]Note:[/b] The property's name has no relationship with [DirectionalLight3D]. [member directional] works with all light types.

View file

@ -11,8 +11,7 @@
<tutorials>
</tutorials>
<members>
<member name="exposure" type="float" setter="set_exposure" getter="get_exposure" default="0.1">
Sets the exposure of the sky. Higher exposure values make the entire sky brighter.
<member name="energy_multiplier" type="float" setter="set_energy_multiplier" getter="get_energy_multiplier" default="1.0">
</member>
<member name="ground_color" type="Color" setter="set_ground_color" getter="get_ground_color" default="Color(0.1, 0.07, 0.034, 1)">
Modulates the [Color] on the bottom half of the sky to represent the ground.

View file

@ -17,14 +17,14 @@
<member name="ground_curve" type="float" setter="set_ground_curve" getter="get_ground_curve" default="0.02">
How quickly the [member ground_horizon_color] fades into the [member ground_bottom_color].
</member>
<member name="ground_energy" type="float" setter="set_ground_energy" getter="get_ground_energy" default="1.0">
Amount of energy contribution from the ground.
<member name="ground_energy_multiplier" type="float" setter="set_ground_energy_multiplier" getter="get_ground_energy_multiplier" default="1.0">
Multiplier for ground color. A higher value will make the ground brighter.
</member>
<member name="ground_horizon_color" type="Color" setter="set_ground_horizon_color" getter="get_ground_horizon_color" default="Color(0.6463, 0.6558, 0.6708, 1)">
Color of the ground at the horizon. Blends with [member ground_bottom_color].
</member>
<member name="sky_cover" type="Texture2D" setter="set_sky_cover" getter="get_sky_cover">
The sky cover texture to use. This texture must use an equirectangular projection (similar to [PanoramaSkyMaterial]). The texture's colors will be [i]added[/i] to the existing sky color, and will be multiplied by [member sky_energy] and [member sky_cover_modulate]. This is mainly suited to displaying stars at night, but it can also be used to display clouds at day or night (with a non-physically-accurate look).
The sky cover texture to use. This texture must use an equirectangular projection (similar to [PanoramaSkyMaterial]). The texture's colors will be [i]added[/i] to the existing sky color, and will be multiplied by [member sky_energy_multiplier] and [member sky_cover_modulate]. This is mainly suited to displaying stars at night, but it can also be used to display clouds at day or night (with a non-physically-accurate look).
</member>
<member name="sky_cover_modulate" type="Color" setter="set_sky_cover_modulate" getter="get_sky_cover_modulate" default="Color(1, 1, 1, 1)">
The tint to apply to the [member sky_cover] texture. This can be used to change the sky cover's colors or opacity independently of the sky energy, which is useful for day/night or weather transitions. Only effective if a texture is defined in [member sky_cover].
@ -32,8 +32,8 @@
<member name="sky_curve" type="float" setter="set_sky_curve" getter="get_sky_curve" default="0.15">
How quickly the [member sky_horizon_color] fades into the [member sky_top_color].
</member>
<member name="sky_energy" type="float" setter="set_sky_energy" getter="get_sky_energy" default="1.0">
Amount of energy contribution from the sky.
<member name="sky_energy_multiplier" type="float" setter="set_sky_energy_multiplier" getter="get_sky_energy_multiplier" default="1.0">
Multiplier for sky color. A higher value will make the sky brighter.
</member>
<member name="sky_horizon_color" type="Color" setter="set_sky_horizon_color" getter="get_sky_horizon_color" default="Color(0.6463, 0.6558, 0.6708, 1)">
Color of the sky at the horizon. Blends with [member sky_top_color].

View file

@ -1807,6 +1807,55 @@
<member name="rendering/lightmapping/probe_capture/update_speed" type="float" setter="" getter="" default="15">
The framerate-independent update speed when representing dynamic object lighting from [LightmapProbe]s. Higher values make dynamic object lighting update faster. Higher values can prevent fast-moving objects from having "outdated" indirect lighting displayed on them, at the cost of possible flickering when an object moves from a bright area to a shaded area.
</member>
<member name="rendering/lights_and_shadows/directional_shadow/16_bits" type="bool" setter="" getter="" default="true">
Use 16 bits for shadow depth map. Enabling this results in shadows having less precision and may result in shadow acne, but can lead to performance improvements on some devices.
</member>
<member name="rendering/lights_and_shadows/directional_shadow/size" type="int" setter="" getter="" default="4096">
The directional shadow's size in pixels. Higher values will result in sharper shadows, at the cost of performance. The value will be rounded up to the nearest power of 2.
</member>
<member name="rendering/lights_and_shadows/directional_shadow/size.mobile" type="int" setter="" getter="" default="2048">
Lower-end override for [member rendering/lights_and_shadows/directional_shadow/size] on mobile devices, due to performance concerns or driver support.
</member>
<member name="rendering/lights_and_shadows/directional_shadow/soft_shadow_filter_quality" type="int" setter="" getter="" default="2">
Quality setting for shadows cast by [DirectionalLight3D]s. Higher quality settings use more samples when reading from shadow maps and are thus slower. Low quality settings may result in shadows looking grainy.
[b]Note:[/b] The Soft Very Low setting will automatically multiply [i]constant[/i] shadow blur by 0.75x to reduce the amount of noise visible. This automatic blur change only affects the constant blur factor defined in [member Light3D.shadow_blur], not the variable blur performed by [DirectionalLight3D]s' [member Light3D.light_angular_distance].
[b]Note:[/b] The Soft High and Soft Ultra settings will automatically multiply [i]constant[/i] shadow blur by 1.5× and 2× respectively to make better use of the increased sample count. This increased blur also improves stability of dynamic object shadows.
</member>
<member name="rendering/lights_and_shadows/directional_shadow/soft_shadow_filter_quality.mobile" type="int" setter="" getter="" default="0">
Lower-end override for [member rendering/lights_and_shadows/directional_shadow/soft_shadow_filter_quality] on mobile devices, due to performance concerns or driver support.
</member>
<member name="rendering/lights_and_shadows/positional_shadow/atlas_16_bits" type="bool" setter="" getter="" default="true">
Use 16 bits for shadow depth map. Enabling this results in shadows having less precision and may result in shadow acne, but can lead to performance improvements on some devices.
</member>
<member name="rendering/lights_and_shadows/positional_shadow/atlas_quadrant_0_subdiv" type="int" setter="" getter="" default="2">
Subdivision quadrant size for shadow mapping. See shadow mapping documentation.
</member>
<member name="rendering/lights_and_shadows/positional_shadow/atlas_quadrant_1_subdiv" type="int" setter="" getter="" default="2">
Subdivision quadrant size for shadow mapping. See shadow mapping documentation.
</member>
<member name="rendering/lights_and_shadows/positional_shadow/atlas_quadrant_2_subdiv" type="int" setter="" getter="" default="3">
Subdivision quadrant size for shadow mapping. See shadow mapping documentation.
</member>
<member name="rendering/lights_and_shadows/positional_shadow/atlas_quadrant_3_subdiv" type="int" setter="" getter="" default="4">
Subdivision quadrant size for shadow mapping. See shadow mapping documentation.
</member>
<member name="rendering/lights_and_shadows/positional_shadow/atlas_size" type="int" setter="" getter="" default="4096">
Size for shadow atlas (used for OmniLights and SpotLights). See documentation.
</member>
<member name="rendering/lights_and_shadows/positional_shadow/atlas_size.mobile" type="int" setter="" getter="" default="2048">
Lower-end override for [member rendering/lights_and_shadows/positional_shadow/atlas_size] on mobile devices, due to performance concerns or driver support.
</member>
<member name="rendering/lights_and_shadows/positional_shadow/soft_shadow_filter_quality" type="int" setter="" getter="" default="2">
Quality setting for shadows cast by [OmniLight3D]s and [SpotLight3D]s. Higher quality settings use more samples when reading from shadow maps and are thus slower. Low quality settings may result in shadows looking grainy.
[b]Note:[/b] The Soft Very Low setting will automatically multiply [i]constant[/i] shadow blur by 0.75x to reduce the amount of noise visible. This automatic blur change only affects the constant blur factor defined in [member Light3D.shadow_blur], not the variable blur performed by [DirectionalLight3D]s' [member Light3D.light_angular_distance].
[b]Note:[/b] The Soft High and Soft Ultra settings will automatically multiply shadow blur by 1.5× and 2× respectively to make better use of the increased sample count. This increased blur also improves stability of dynamic object shadows.
</member>
<member name="rendering/lights_and_shadows/positional_shadow/soft_shadow_filter_quality.mobile" type="int" setter="" getter="" default="0">
Lower-end override for [member rendering/lights_and_shadows/positional_shadow/soft_shadow_filter_quality] on mobile devices, due to performance concerns or driver support.
</member>
<member name="rendering/lights_and_shadows/use_physical_light_units" type="bool" setter="" getter="" default="false">
Enables the use of physically based units for light sources. Physically based units tend to be much larger than the arbitrary units used by Godot, but they can be used to match lighting within Godot to real-world lighting. Due to the large dynamic range of lighting conditions present in nature, Godot bakes exposure into the various lighting quantities before rendering. Most light sources bake exposure automatically at run time based on the active [CameraAttributes] resource, but [LightmapGI] and [VoxelGI] require a [CameraAttributes] resource to be set at bake time to reduce the dynamic range. At run time, Godot will automatically reconcile the baked exposure with the active exposure to ensure lighting remains consistent.
</member>
<member name="rendering/limits/cluster_builder/max_clustered_elements" type="float" setter="" getter="" default="512">
</member>
<member name="rendering/limits/forward_renderer/threaded_render_minimum_instances" type="int" setter="" getter="" default="500">
@ -1901,50 +1950,6 @@
<member name="rendering/shading/overrides/force_vertex_shading.mobile" type="bool" setter="" getter="" default="true">
Lower-end override for [member rendering/shading/overrides/force_vertex_shading] on mobile devices, due to performance concerns or driver support.
</member>
<member name="rendering/shadows/directional_shadow/16_bits" type="bool" setter="" getter="" default="true">
</member>
<member name="rendering/shadows/directional_shadow/size" type="int" setter="" getter="" default="4096">
The directional shadow's size in pixels. Higher values will result in sharper shadows, at the cost of performance. The value will be rounded up to the nearest power of 2.
</member>
<member name="rendering/shadows/directional_shadow/size.mobile" type="int" setter="" getter="" default="2048">
Lower-end override for [member rendering/shadows/directional_shadow/size] on mobile devices, due to performance concerns or driver support.
</member>
<member name="rendering/shadows/directional_shadow/soft_shadow_filter_quality" type="int" setter="" getter="" default="2">
Quality setting for shadows cast by [DirectionalLight3D]s. Higher quality settings use more samples when reading from shadow maps and are thus slower. Low quality settings may result in shadows looking grainy.
[b]Note:[/b] The Soft Very Low setting will automatically multiply [i]constant[/i] shadow blur by 0.75x to reduce the amount of noise visible. This automatic blur change only affects the constant blur factor defined in [member Light3D.shadow_blur], not the variable blur performed by [DirectionalLight3D]s' [member Light3D.light_angular_distance].
[b]Note:[/b] The Soft High and Soft Ultra settings will automatically multiply [i]constant[/i] shadow blur by 1.5× and 2× respectively to make better use of the increased sample count. This increased blur also improves stability of dynamic object shadows.
</member>
<member name="rendering/shadows/directional_shadow/soft_shadow_filter_quality.mobile" type="int" setter="" getter="" default="0">
Lower-end override for [member rendering/shadows/directional_shadow/soft_shadow_filter_quality] on mobile devices, due to performance concerns or driver support.
</member>
<member name="rendering/shadows/positional_shadow/atlas_16_bits" type="bool" setter="" getter="" default="true">
</member>
<member name="rendering/shadows/positional_shadow/atlas_quadrant_0_subdiv" type="int" setter="" getter="" default="2">
Subdivision quadrant size for shadow mapping. See shadow mapping documentation.
</member>
<member name="rendering/shadows/positional_shadow/atlas_quadrant_1_subdiv" type="int" setter="" getter="" default="2">
Subdivision quadrant size for shadow mapping. See shadow mapping documentation.
</member>
<member name="rendering/shadows/positional_shadow/atlas_quadrant_2_subdiv" type="int" setter="" getter="" default="3">
Subdivision quadrant size for shadow mapping. See shadow mapping documentation.
</member>
<member name="rendering/shadows/positional_shadow/atlas_quadrant_3_subdiv" type="int" setter="" getter="" default="4">
Subdivision quadrant size for shadow mapping. See shadow mapping documentation.
</member>
<member name="rendering/shadows/positional_shadow/atlas_size" type="int" setter="" getter="" default="4096">
Size for shadow atlas (used for OmniLights and SpotLights). See documentation.
</member>
<member name="rendering/shadows/positional_shadow/atlas_size.mobile" type="int" setter="" getter="" default="2048">
Lower-end override for [member rendering/shadows/positional_shadow/atlas_size] on mobile devices, due to performance concerns or driver support.
</member>
<member name="rendering/shadows/positional_shadow/soft_shadow_filter_quality" type="int" setter="" getter="" default="2">
Quality setting for shadows cast by [OmniLight3D]s and [SpotLight3D]s. Higher quality settings use more samples when reading from shadow maps and are thus slower. Low quality settings may result in shadows looking grainy.
[b]Note:[/b] The Soft Very Low setting will automatically multiply [i]constant[/i] shadow blur by 0.75x to reduce the amount of noise visible. This automatic blur change only affects the constant blur factor defined in [member Light3D.shadow_blur], not the variable blur performed by [DirectionalLight3D]s' [member Light3D.light_angular_distance].
[b]Note:[/b] The Soft High and Soft Ultra settings will automatically multiply shadow blur by 1.5× and 2× respectively to make better use of the increased sample count. This increased blur also improves stability of dynamic object shadows.
</member>
<member name="rendering/shadows/positional_shadow/soft_shadow_filter_quality.mobile" type="int" setter="" getter="" default="0">
Lower-end override for [member rendering/shadows/positional_shadow/soft_shadow_filter_quality] on mobile devices, due to performance concerns or driver support.
</member>
<member name="rendering/textures/decals/filter" type="int" setter="" getter="" default="3">
The filtering quality to use for [Decal] nodes. When using one of the anisotropic filtering modes, the anisotropic filtering level is controlled by [member rendering/textures/default_filters/anisotropic_filtering_level].
</member>

View file

@ -26,29 +26,27 @@
<description>
</description>
</method>
<method name="camera_create">
<method name="camera_attributes_create">
<return type="RID" />
<description>
Creates a camera and adds it to the RenderingServer. It can be accessed with the RID that is returned. This RID will be used in all [code]camera_*[/code] RenderingServer functions.
Creates a camera attributes object and adds it to the RenderingServer. It can be accessed with the RID that is returned. This RID will be used in all [code]camera_attributes_[/code] RenderingServer functions.
Once finished with your RID, you will want to free the RID using the RenderingServer's [method free_rid] static method.
</description>
</method>
<method name="camera_effects_create">
<return type="RID" />
<description>
</description>
</method>
<method name="camera_effects_set_custom_exposure">
<method name="camera_attributes_set_auto_exposure">
<return type="void" />
<param index="0" name="camera_effects" type="RID" />
<param index="0" name="camera_attributes" type="RID" />
<param index="1" name="enable" type="bool" />
<param index="2" name="exposure" type="float" />
<param index="2" name="min_sensitivity" type="float" />
<param index="3" name="max_sensitivity" type="float" />
<param index="4" name="speed" type="float" />
<param index="5" name="scale" type="float" />
<description>
</description>
</method>
<method name="camera_effects_set_dof_blur">
<method name="camera_attributes_set_dof_blur">
<return type="void" />
<param index="0" name="camera_effects" type="RID" />
<param index="0" name="camera_attributes" type="RID" />
<param index="1" name="far_enable" type="bool" />
<param index="2" name="far_distance" type="float" />
<param index="3" name="far_transition" type="float" />
@ -59,20 +57,46 @@
<description>
</description>
</method>
<method name="camera_effects_set_dof_blur_bokeh_shape">
<method name="camera_attributes_set_dof_blur_bokeh_shape">
<return type="void" />
<param index="0" name="shape" type="int" enum="RenderingServer.DOFBokehShape" />
<description>
</description>
</method>
<method name="camera_effects_set_dof_blur_quality">
<method name="camera_attributes_set_dof_blur_quality">
<return type="void" />
<param index="0" name="quality" type="int" enum="RenderingServer.DOFBlurQuality" />
<param index="1" name="use_jitter" type="bool" />
<description>
</description>
</method>
<method name="camera_set_camera_effects">
<method name="camera_attributes_set_exposure">
<return type="void" />
<param index="0" name="camera_attributes" type="RID" />
<param index="1" name="multiplier" type="float" />
<param index="2" name="normalization" type="float" />
<description>
Sets the exposure values that will be used by the renderers. The normalization amount is used to bake a given Exposure Value (EV) into rendering calculations to reduce the dynamic range of the scene.
The normalization factor can be calculated from exposure value (EV100) as follows:
[codeblock]
func get_exposure_normalization(float ev100):
return 1.0 / (pow(2.0, ev100) * 1.2)
[/codeblock]
The exposure value can be calculated from aperture (in f-stops), shutter speed (in seconds), and sensitivity (in ISO) as follows:
[codeblock]
func get_exposure(float aperture, float shutter_speed, float sensitivity):
return log2((aperture * aperture) / shutterSpeed * (100.0 / sensitivity))
[/codeblock]
</description>
</method>
<method name="camera_create">
<return type="RID" />
<description>
Creates a camera and adds it to the RenderingServer. It can be accessed with the RID that is returned. This RID will be used in all [code]camera_*[/code] RenderingServer functions.
Once finished with your RID, you will want to free the RID using the RenderingServer's [method free_rid] static method.
</description>
</method>
<method name="camera_set_camera_attributes">
<return type="void" />
<param index="0" name="camera" type="RID" />
<param index="1" name="effects" type="RID" />
@ -976,7 +1000,8 @@
<method name="environment_set_bg_energy">
<return type="void" />
<param index="0" name="env" type="RID" />
<param index="1" name="energy" type="float" />
<param index="1" name="multiplier" type="float" />
<param index="2" name="exposure_value" type="float" />
<description>
Sets the intensity of the background color.
</description>
@ -1143,11 +1168,6 @@
<param index="1" name="tone_mapper" type="int" enum="RenderingServer.EnvironmentToneMapper" />
<param index="2" name="exposure" type="float" />
<param index="3" name="white" type="float" />
<param index="4" name="auto_exposure" type="bool" />
<param index="5" name="min_luminance" type="float" />
<param index="6" name="max_luminance" type="float" />
<param index="7" name="auto_exp_speed" type="float" />
<param index="8" name="auto_exp_grey" type="float" />
<description>
Sets the variables to be used with the "tonemap" post-process effect. See [Environment] for more details.
</description>
@ -1767,6 +1787,14 @@
<description>
</description>
</method>
<method name="lightmap_set_baked_exposure_normalization">
<return type="void" />
<param index="0" name="lightmap" type="RID" />
<param index="1" name="baked_exposure" type="float" />
<description>
Used to inform the renderer what exposure normalization value was used while baking the lightmap. This value will be used and modulated at run time to ensure that the lightmap maintains a consistent level of exposure even if the scene-wide exposure normalization is changed at run time. For more information see [method camera_attributes_set_exposure].
</description>
</method>
<method name="lightmap_set_probe_bounds">
<return type="void" />
<param index="0" name="lightmap" type="RID" />
@ -2665,7 +2693,7 @@
The scenario is the 3D world that all the visual instances exist in.
</description>
</method>
<method name="scenario_set_camera_effects">
<method name="scenario_set_camera_attributes">
<return type="void" />
<param index="0" name="scenario" type="RID" />
<param index="1" name="effects" type="RID" />
@ -3480,6 +3508,14 @@
<description>
</description>
</method>
<method name="voxel_gi_set_baked_exposure_normalization">
<return type="void" />
<param index="0" name="voxel_gi" type="RID" />
<param index="1" name="baked_exposure" type="float" />
<description>
Used to inform the renderer what exposure normalization value was used while baking the voxel gi. This value will be used and modulated at run time to ensure that the voxel gi maintains a consistent level of exposure even if the scene-wide exposure normalization is changed at run time. For more information see [method camera_attributes_set_exposure].
</description>
</method>
<method name="voxel_gi_set_bias">
<return type="void" />
<param index="0" name="voxel_gi" type="RID" />
@ -3850,7 +3886,7 @@
</constant>
<constant name="LIGHT_PARAM_TRANSMITTANCE_BIAS" value="19" enum="LightParam">
</constant>
<constant name="LIGHT_PARAM_MAX" value="20" enum="LightParam">
<constant name="LIGHT_PARAM_MAX" value="21" enum="LightParam">
Represents the size of the [enum LightParam] enum.
</constant>
<constant name="LIGHT_BAKE_DISABLED" value="0" enum="LightBakeMode">

View file

@ -32,6 +32,9 @@
</method>
</methods>
<members>
<member name="camera_attributes" type="CameraAttributes" setter="set_camera_attributes" getter="get_camera_attributes">
The [CameraAttributes] resource that specifies exposure levels to bake at. Auto-exposure and non exposure properties will be ignored. Exposure settings should be used to reduce the dynamic range present when baking. If exposure is too high, the [VoxelGI] will have banding artifacts or may have over-exposure artifacts.
</member>
<member name="data" type="VoxelGIData" setter="set_probe_data" getter="get_probe_data">
The [VoxelGIData] resource that holds the data for this [VoxelGI].
</member>

View file

@ -10,7 +10,8 @@
<link title="Ray-casting">$DOCS_URL/tutorials/physics/ray-casting.html</link>
</tutorials>
<members>
<member name="camera_effects" type="CameraEffects" setter="set_camera_effects" getter="get_camera_effects">
<member name="camera_attributes" type="CameraAttributes" setter="set_camera_attributes" getter="get_camera_attributes">
The default [CameraAttributes] resource to use if none set on the [Camera3D].
</member>
<member name="direct_space_state" type="PhysicsDirectSpaceState3D" setter="" getter="get_direct_space_state">
Direct access to the world's physics 3D space state. Used for querying current and potential collisions.

View file

@ -15,8 +15,8 @@
<link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link>
</tutorials>
<members>
<member name="camera_effects" type="CameraEffects" setter="set_camera_effects" getter="get_camera_effects">
The [CameraEffects] resource used by this [WorldEnvironment], defining the default properties. This [CameraEffects] resource will be used by all [Camera3D]s that do not define their own [CameraEffects].
<member name="camera_attributes" type="CameraAttributes" setter="set_camera_attributes" getter="get_camera_attributes">
The default [CameraAttributes] resource to use if none set on the [Camera3D].
</member>
<member name="environment" type="Environment" setter="set_environment" getter="get_environment">
The [Environment] resource used by this [WorldEnvironment], defining the default properties.

View file

@ -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) {
}

View file

@ -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;

View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -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();
}

View file

@ -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;

View file

@ -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;
}

View file

@ -501,10 +501,10 @@ void EditorNode::_update_from_settings() {
}
RS::DOFBokehShape dof_shape = RS::DOFBokehShape(int(GLOBAL_GET("rendering/camera/depth_of_field/depth_of_field_bokeh_shape")));
RS::get_singleton()->camera_effects_set_dof_blur_bokeh_shape(dof_shape);
RS::get_singleton()->camera_attributes_set_dof_blur_bokeh_shape(dof_shape);
RS::DOFBlurQuality dof_quality = RS::DOFBlurQuality(int(GLOBAL_GET("rendering/camera/depth_of_field/depth_of_field_bokeh_quality")));
bool dof_jitter = GLOBAL_GET("rendering/camera/depth_of_field/depth_of_field_use_jitter");
RS::get_singleton()->camera_effects_set_dof_blur_quality(dof_quality, dof_jitter);
RS::get_singleton()->camera_attributes_set_dof_blur_quality(dof_quality, dof_jitter);
RS::get_singleton()->environment_set_ssao_quality(RS::EnvironmentSSAOQuality(int(GLOBAL_GET("rendering/environment/ssao/quality"))), GLOBAL_GET("rendering/environment/ssao/half_size"), GLOBAL_GET("rendering/environment/ssao/adaptive_target"), GLOBAL_GET("rendering/environment/ssao/blur_passes"), GLOBAL_GET("rendering/environment/ssao/fadeout_from"), GLOBAL_GET("rendering/environment/ssao/fadeout_to"));
RS::get_singleton()->screen_space_roughness_limiter_set_active(GLOBAL_GET("rendering/anti_aliasing/screen_space_roughness_limiter/enabled"), GLOBAL_GET("rendering/anti_aliasing/screen_space_roughness_limiter/amount"), GLOBAL_GET("rendering/anti_aliasing/screen_space_roughness_limiter/limit"));
bool glow_bicubic = int(GLOBAL_GET("rendering/environment/glow/upscale_mode")) > 0;
@ -520,13 +520,13 @@ void EditorNode::_update_from_settings() {
float sss_depth_scale = GLOBAL_GET("rendering/environment/subsurface_scattering/subsurface_scattering_depth_scale");
RS::get_singleton()->sub_surface_scattering_set_scale(sss_scale, sss_depth_scale);
uint32_t directional_shadow_size = GLOBAL_GET("rendering/shadows/directional_shadow/size");
uint32_t directional_shadow_16_bits = GLOBAL_GET("rendering/shadows/directional_shadow/16_bits");
uint32_t directional_shadow_size = GLOBAL_GET("rendering/lights_and_shadows/directional_shadow/size");
uint32_t directional_shadow_16_bits = GLOBAL_GET("rendering/lights_and_shadows/directional_shadow/16_bits");
RS::get_singleton()->directional_shadow_atlas_set_size(directional_shadow_size, directional_shadow_16_bits);
RS::ShadowQuality shadows_quality = RS::ShadowQuality(int(GLOBAL_GET("rendering/shadows/positional_shadow/soft_shadow_filter_quality")));
RS::ShadowQuality shadows_quality = RS::ShadowQuality(int(GLOBAL_GET("rendering/lights_and_shadows/positional_shadow/soft_shadow_filter_quality")));
RS::get_singleton()->positional_soft_shadow_filter_set_quality(shadows_quality);
RS::ShadowQuality directional_shadow_quality = RS::ShadowQuality(int(GLOBAL_GET("rendering/shadows/directional_shadow/soft_shadow_filter_quality")));
RS::ShadowQuality directional_shadow_quality = RS::ShadowQuality(int(GLOBAL_GET("rendering/lights_and_shadows/directional_shadow/soft_shadow_filter_quality")));
RS::get_singleton()->directional_soft_shadow_filter_set_quality(directional_shadow_quality);
float probe_update_speed = GLOBAL_GET("rendering/lightmapping/probe_capture/update_speed");
RS::get_singleton()->lightmap_set_probe_capture_update_speed(probe_update_speed);

View file

@ -155,6 +155,10 @@ void EditorSpinSlider::_grabber_gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> mb = p_event;
if (is_read_only()) {
return;
}
if (grabbing_grabber) {
if (mb.is_valid()) {
if (mb->get_button_index() == MouseButton::WHEEL_UP) {
@ -196,7 +200,7 @@ void EditorSpinSlider::_grabber_gui_input(const Ref<InputEvent> &p_event) {
void EditorSpinSlider::_value_input_gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventKey> k = p_event;
if (k.is_valid() && k->is_pressed()) {
if (k.is_valid() && k->is_pressed() && !is_read_only()) {
double step = get_step();
double real_step = step;
if (step < 1) {

View file

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View file

@ -30,6 +30,7 @@
#include "scene_import_settings.h"
#include "core/config/project_settings.h"
#include "editor/editor_file_dialog.h"
#include "editor/editor_file_system.h"
#include "editor/editor_inspector.h"
@ -1288,6 +1289,11 @@ SceneImportSettings::SceneImportSettings() {
base_viewport->add_child(camera);
camera->make_current();
if (GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units")) {
camera_attributes.instantiate();
camera->set_attributes(camera_attributes);
}
light = memnew(DirectionalLight3D);
light->set_transform(Transform3D().looking_at(Vector3(-1, -2, -0.6), Vector3(0, 1, 0)));
base_viewport->add_child(light);

View file

@ -74,6 +74,7 @@ class SceneImportSettings : public ConfirmationDialog {
SubViewport *base_viewport = nullptr;
Camera3D *camera = nullptr;
Ref<CameraAttributesPractical> camera_attributes;
bool first_aabb = false;
AABB contents_aabb;

View file

@ -342,6 +342,12 @@ EditorMaterialPreviewPlugin::EditorMaterialPreviewPlugin() {
RS::get_singleton()->camera_set_transform(camera, Transform3D(Basis(), Vector3(0, 0, 3)));
RS::get_singleton()->camera_set_perspective(camera, 45, 0.1, 10);
if (GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units")) {
camera_attributes = RS::get_singleton()->camera_attributes_create();
RS::get_singleton()->camera_attributes_set_exposure(camera_attributes, 1.0, 0.000032552); // Matches default CameraAttributesPhysical to work well with default DirectionalLight3Ds.
RS::get_singleton()->camera_set_camera_attributes(camera, camera_attributes);
}
light = RS::get_singleton()->directional_light_create();
light_instance = RS::get_singleton()->instance_create2(light, scenario);
RS::get_singleton()->instance_set_transform(light_instance, Transform3D().looking_at(Vector3(-1, -1, -1), Vector3(0, 1, 0)));
@ -440,6 +446,7 @@ EditorMaterialPreviewPlugin::~EditorMaterialPreviewPlugin() {
RS::get_singleton()->free(light2);
RS::get_singleton()->free(light_instance2);
RS::get_singleton()->free(camera);
RS::get_singleton()->free(camera_attributes);
RS::get_singleton()->free(scenario);
}
@ -743,6 +750,12 @@ EditorMeshPreviewPlugin::EditorMeshPreviewPlugin() {
//RS::get_singleton()->camera_set_perspective(camera,45,0.1,10);
RS::get_singleton()->camera_set_orthogonal(camera, 1.0, 0.01, 1000.0);
if (GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units")) {
camera_attributes = RS::get_singleton()->camera_attributes_create();
RS::get_singleton()->camera_attributes_set_exposure(camera_attributes, 1.0, 0.000032552); // Matches default CameraAttributesPhysical to work well with default DirectionalLight3Ds.
RS::get_singleton()->camera_set_camera_attributes(camera, camera_attributes);
}
light = RS::get_singleton()->directional_light_create();
light_instance = RS::get_singleton()->instance_create2(light, scenario);
RS::get_singleton()->instance_set_transform(light_instance, Transform3D().looking_at(Vector3(-1, -1, -1), Vector3(0, 1, 0)));
@ -768,6 +781,7 @@ EditorMeshPreviewPlugin::~EditorMeshPreviewPlugin() {
RS::get_singleton()->free(light2);
RS::get_singleton()->free(light_instance2);
RS::get_singleton()->free(camera);
RS::get_singleton()->free(camera_attributes);
RS::get_singleton()->free(scenario);
}

View file

@ -91,6 +91,7 @@ class EditorMaterialPreviewPlugin : public EditorResourcePreviewGenerator {
RID light2;
RID light_instance2;
RID camera;
RID camera_attributes;
Semaphore preview_done;
void _generate_frame_started();
@ -133,6 +134,7 @@ class EditorMeshPreviewPlugin : public EditorResourcePreviewGenerator {
RID light2;
RID light_instance2;
RID camera;
RID camera_attributes;
Semaphore preview_done;
void _generate_frame_started();

View file

@ -30,6 +30,7 @@
#include "material_editor_plugin.h"
#include "core/config/project_settings.h"
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
@ -161,6 +162,10 @@ MaterialEditor::MaterialEditor() {
// without much distortion.
camera->set_perspective(20, 0.1, 10);
camera->make_current();
if (GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units")) {
camera_attributes.instantiate();
camera->set_attributes(camera_attributes);
}
viewport->add_child(camera);
light1 = memnew(DirectionalLight3D);

View file

@ -55,6 +55,7 @@ class MaterialEditor : public Control {
DirectionalLight3D *light1 = nullptr;
DirectionalLight3D *light2 = nullptr;
Camera3D *camera = nullptr;
Ref<CameraAttributesPractical> camera_attributes;
Ref<SphereMesh> sphere_mesh;
Ref<BoxMesh> box_mesh;

View file

@ -30,6 +30,7 @@
#include "mesh_editor_plugin.h"
#include "core/config/project_settings.h"
#include "editor/editor_scale.h"
void MeshEditor::gui_input(const Ref<InputEvent> &p_event) {
@ -119,6 +120,11 @@ MeshEditor::MeshEditor() {
camera->set_perspective(45, 0.1, 10);
viewport->add_child(camera);
if (GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units")) {
camera_attributes.instantiate();
camera->set_attributes(camera_attributes);
}
light1 = memnew(DirectionalLight3D);
light1->set_transform(Transform3D().looking_at(Vector3(-1, -1, -1), Vector3(0, 1, 0)));
viewport->add_child(light1);

View file

@ -36,6 +36,7 @@
#include "scene/3d/light_3d.h"
#include "scene/3d/mesh_instance_3d.h"
#include "scene/gui/subviewport_container.h"
#include "scene/resources/camera_attributes.h"
#include "scene/resources/material.h"
class MeshEditor : public SubViewportContainer {
@ -50,6 +51,7 @@ class MeshEditor : public SubViewportContainer {
DirectionalLight3D *light1 = nullptr;
DirectionalLight3D *light2 = nullptr;
Camera3D *camera = nullptr;
Ref<CameraAttributesPractical> camera_attributes;
Ref<Mesh> mesh;

View file

@ -1365,7 +1365,8 @@ void Light3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_i
void Light3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
Light3D *light = Object::cast_to<Light3D>(p_gizmo->get_spatial_node());
Color color = light->get_color();
Color color = light->get_color().srgb_to_linear() * light->get_correlated_color().srgb_to_linear();
color = color.linear_to_srgb();
// Make the gizmo color as bright as possible for better visibility
color.set_hsv(color.get_h(), color.get_s(), 1);

View file

@ -2375,12 +2375,12 @@ void Node3DEditorPlugin::edited_scene_changed() {
void Node3DEditorViewport::_project_settings_changed() {
//update shadow atlas if changed
int shadowmap_size = ProjectSettings::get_singleton()->get("rendering/shadows/positional_shadow/atlas_size");
bool shadowmap_16_bits = ProjectSettings::get_singleton()->get("rendering/shadows/positional_shadow/atlas_16_bits");
int atlas_q0 = ProjectSettings::get_singleton()->get("rendering/shadows/positional_shadow/atlas_quadrant_0_subdiv");
int atlas_q1 = ProjectSettings::get_singleton()->get("rendering/shadows/positional_shadow/atlas_quadrant_1_subdiv");
int atlas_q2 = ProjectSettings::get_singleton()->get("rendering/shadows/positional_shadow/atlas_quadrant_2_subdiv");
int atlas_q3 = ProjectSettings::get_singleton()->get("rendering/shadows/positional_shadow/atlas_quadrant_3_subdiv");
int shadowmap_size = ProjectSettings::get_singleton()->get("rendering/lights_and_shadows/positional_shadow/atlas_size");
bool shadowmap_16_bits = ProjectSettings::get_singleton()->get("rendering/lights_and_shadows/positional_shadow/atlas_16_bits");
int atlas_q0 = ProjectSettings::get_singleton()->get("rendering/lights_and_shadows/positional_shadow/atlas_quadrant_0_subdiv");
int atlas_q1 = ProjectSettings::get_singleton()->get("rendering/lights_and_shadows/positional_shadow/atlas_quadrant_1_subdiv");
int atlas_q2 = ProjectSettings::get_singleton()->get("rendering/lights_and_shadows/positional_shadow/atlas_quadrant_2_subdiv");
int atlas_q3 = ProjectSettings::get_singleton()->get("rendering/lights_and_shadows/positional_shadow/atlas_quadrant_3_subdiv");
viewport->set_positional_shadow_atlas_size(shadowmap_size);
viewport->set_positional_shadow_atlas_16_bits(shadowmap_16_bits);
@ -7122,6 +7122,9 @@ void Node3DEditor::_add_environment_to_scene(bool p_already_added_sun) {
WorldEnvironment *new_env = memnew(WorldEnvironment);
new_env->set_environment(preview_environment->get_environment()->duplicate(true));
if (GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units")) {
new_env->set_camera_attributes(preview_environment->get_camera_attributes()->duplicate(true));
}
undo_redo->create_action(TTR("Add Preview Environment to Scene"));
undo_redo->add_do_method(base, "add_child", new_env, true);
@ -7588,7 +7591,7 @@ void Node3DEditor::_preview_settings_changed() {
}
{ //preview env
sky_material->set_sky_energy(environ_energy->get_value());
sky_material->set_sky_energy_multiplier(environ_energy->get_value());
Color hz_color = environ_sky_color->get_pick_color().lerp(environ_ground_color->get_pick_color(), 0.5).lerp(Color(1, 1, 1), 0.5);
sky_material->set_sky_top_color(environ_sky_color->get_pick_color());
sky_material->set_sky_horizon_color(hz_color);
@ -8308,6 +8311,10 @@ void fragment() {
preview_environment = memnew(WorldEnvironment);
environment.instantiate();
preview_environment->set_environment(environment);
if (GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units")) {
camera_attributes.instantiate();
preview_environment->set_camera_attributes(camera_attributes);
}
Ref<Sky> sky;
sky.instantiate();
sky_material.instantiate();

View file

@ -765,6 +765,7 @@ private:
DirectionalLight3D *preview_sun = nullptr;
WorldEnvironment *preview_environment = nullptr;
Ref<Environment> environment;
Ref<CameraAttributesPhysical> camera_attributes;
Ref<ProceduralSkyMaterial> sky_material;
bool sun_environ_updating = false;

View file

@ -527,7 +527,6 @@ static const char *gdscript_function_renames[][2] = {
{ "set_tangent", "surface_set_tangent" }, // ImmediateGeometry broke SurfaceTool
{ "set_text_align", "set_text_alignment" }, // Button
{ "set_timer_process_mode", "set_timer_process_callback" }, // Timer
{ "set_tonemap_auto_exposure", "set_tonemap_auto_exposure_enabled" }, // Environment
{ "set_translation", "set_position" }, // Node3D - this broke GLTFNode which is used rarely
{ "set_unit_offset", "set_progress_ratio" }, // PathFollow2D, PathFollow3D
{ "set_uv2", "surface_set_uv2" }, // ImmediateMesh broke Surffacetool
@ -1247,12 +1246,12 @@ static const char *project_settings_renames[][2] = {
{ "rendering/quality/shading/force_lambert_over_burley.mobile", "rendering/shading/overrides/force_lambert_over_burley.mobile" },
{ "rendering/quality/shading/force_vertex_shading", "rendering/shading/overrides/force_vertex_shading" },
{ "rendering/quality/shading/force_vertex_shading.mobile", "rendering/shading/overrides/force_vertex_shading.mobile" },
{ "rendering/quality/shadow_atlas/quadrant_0_subdiv", "rendering/shadows/shadow_atlas/quadrant_0_subdiv" },
{ "rendering/quality/shadow_atlas/quadrant_1_subdiv", "rendering/shadows/shadow_atlas/quadrant_1_subdiv" },
{ "rendering/quality/shadow_atlas/quadrant_2_subdiv", "rendering/shadows/shadow_atlas/quadrant_2_subdiv" },
{ "rendering/quality/shadow_atlas/quadrant_3_subdiv", "rendering/shadows/shadow_atlas/quadrant_3_subdiv" },
{ "rendering/quality/shadow_atlas/size", "rendering/shadows/shadow_atlas/size" },
{ "rendering/quality/shadow_atlas/size.mobile", "rendering/shadows/shadow_atlas/size.mobile" },
{ "rendering/quality/shadow_atlas/quadrant_0_subdiv", "rendering/lights_and_shadows/shadow_atlas/quadrant_0_subdiv" },
{ "rendering/quality/shadow_atlas/quadrant_1_subdiv", "rendering/lights_and_shadows/shadow_atlas/quadrant_1_subdiv" },
{ "rendering/quality/shadow_atlas/quadrant_2_subdiv", "rendering/lights_and_shadows/shadow_atlas/quadrant_2_subdiv" },
{ "rendering/quality/shadow_atlas/quadrant_3_subdiv", "rendering/lights_and_shadows/shadow_atlas/quadrant_3_subdiv" },
{ "rendering/quality/shadow_atlas/size", "rendering/lights_and_shadows/shadow_atlas/size" },
{ "rendering/quality/shadow_atlas/size.mobile", "rendering/lights_and_shadows/shadow_atlas/size.mobile" },
{ "rendering/vram_compression/import_bptc", "rendering/textures/vram_compression/import_bptc" },
{ "rendering/vram_compression/import_etc", "rendering/textures/vram_compression/import_etc" },
{ "rendering/vram_compression/import_etc2", "rendering/textures/vram_compression/import_etc2" },

View file

@ -670,7 +670,7 @@ LightmapperRD::BakeError LightmapperRD::_dilate(RenderingDevice *rd, Ref<RDShade
return BAKE_OK;
}
LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_denoiser, int p_bounces, float p_bias, int p_max_texture_size, bool p_bake_sh, GenerateProbes p_generate_probes, const Ref<Image> &p_environment_panorama, const Basis &p_environment_transform, BakeStepFunc p_step_function, void *p_bake_userdata) {
LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_denoiser, int p_bounces, float p_bias, int p_max_texture_size, bool p_bake_sh, GenerateProbes p_generate_probes, const Ref<Image> &p_environment_panorama, const Basis &p_environment_transform, BakeStepFunc p_step_function, void *p_bake_userdata, float p_exposure_normalization) {
if (p_step_function) {
p_step_function(0.0, RTR("Begin Bake"), p_bake_userdata, true);
}
@ -1165,6 +1165,8 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d
rd->compute_list_bind_uniform_set(compute_list, compute_base_uniform_set, 0);
rd->compute_list_bind_uniform_set(compute_list, light_uniform_set, 1);
push_constant.environment_xform[11] = p_exposure_normalization;
for (int i = 0; i < atlas_slices; i++) {
push_constant.atlas_slice = i;
rd->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant));
@ -1172,6 +1174,8 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d
//no barrier, let them run all together
}
rd->compute_list_end(); //done
push_constant.environment_xform[11] = 0.0;
}
#ifdef DEBUG_TEXTURES

View file

@ -241,7 +241,7 @@ public:
virtual void add_omni_light(bool p_static, const Vector3 &p_position, const Color &p_color, float p_energy, float p_range, float p_attenuation, float p_size, float p_shadow_blur) override;
virtual void add_spot_light(bool p_static, const Vector3 &p_position, const Vector3 p_direction, const Color &p_color, float p_energy, float p_range, float p_attenuation, float p_spot_angle, float p_spot_attenuation, float p_size, float p_shadow_blur) override;
virtual void add_probe(const Vector3 &p_position) override;
virtual BakeError bake(BakeQuality p_quality, bool p_use_denoiser, int p_bounces, float p_bias, int p_max_texture_size, bool p_bake_sh, GenerateProbes p_generate_probes, const Ref<Image> &p_environment_panorama, const Basis &p_environment_transform, BakeStepFunc p_step_function = nullptr, void *p_bake_userdata = nullptr) override;
virtual BakeError bake(BakeQuality p_quality, bool p_use_denoiser, int p_bounces, float p_bias, int p_max_texture_size, bool p_bake_sh, GenerateProbes p_generate_probes, const Ref<Image> &p_environment_panorama, const Basis &p_environment_transform, BakeStepFunc p_step_function = nullptr, void *p_bake_userdata = nullptr, float p_exposure_normalization = 1.0) override;
int get_bake_texture_count() const override;
Ref<Image> get_bake_texture(int p_index) const override;

View file

@ -434,6 +434,7 @@ void main() {
imageStore(primary_dynamic, ivec3(atlas_pos, params.atlas_slice), vec4(dynamic_light, 1.0));
dynamic_light += static_light * albedo; //send for bounces
dynamic_light *= params.env_transform[2][3]; // exposure_normalization
imageStore(dest_light, ivec3(atlas_pos, params.atlas_slice), vec4(dynamic_light, 1.0));
#ifdef USE_SH_LIGHTMAPS
@ -444,6 +445,7 @@ void main() {
imageStore(accum_light, ivec3(atlas_pos, params.atlas_slice * 4 + 3), sh_accum[3]);
#else
static_light *= params.env_transform[2][3]; // exposure_normalization
imageStore(accum_light, ivec3(atlas_pos, params.atlas_slice), vec4(static_light, 1.0));
#endif

View file

@ -31,6 +31,7 @@
#include "camera_3d.h"
#include "collision_object_3d.h"
#include "core/core_string_names.h"
#include "core/math/projection.h"
#include "scene/main/viewport.h"
@ -71,6 +72,17 @@ void Camera3D::_validate_property(PropertyInfo &p_property) const {
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
}
}
if (attributes.is_valid()) {
const CameraAttributesPhysical *physical_attributes = Object::cast_to<CameraAttributesPhysical>(attributes.ptr());
if (physical_attributes) {
if (p_property.name == "near" || p_property.name == "far" || p_property.name == "fov" || p_property.name == "keep_aspect") {
p_property.usage = PROPERTY_USAGE_READ_ONLY | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR;
}
}
}
Node3D::_validate_property(p_property);
}
void Camera3D::_update_camera() {
@ -400,18 +412,44 @@ Ref<Environment> Camera3D::get_environment() const {
return environment;
}
void Camera3D::set_effects(const Ref<CameraEffects> &p_effects) {
effects = p_effects;
if (effects.is_valid()) {
RS::get_singleton()->camera_set_camera_effects(camera, effects->get_rid());
} else {
RS::get_singleton()->camera_set_camera_effects(camera, RID());
void Camera3D::set_attributes(const Ref<CameraAttributes> &p_attributes) {
if (attributes.is_valid()) {
CameraAttributesPhysical *physical_attributes = Object::cast_to<CameraAttributesPhysical>(attributes.ptr());
if (physical_attributes) {
attributes->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Camera3D::_attributes_changed));
}
}
_update_camera_mode();
attributes = p_attributes;
if (attributes.is_valid()) {
CameraAttributesPhysical *physical_attributes = Object::cast_to<CameraAttributesPhysical>(attributes.ptr());
if (physical_attributes) {
attributes->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Camera3D::_attributes_changed));
_attributes_changed();
}
RS::get_singleton()->camera_set_camera_attributes(camera, attributes->get_rid());
} else {
RS::get_singleton()->camera_set_camera_attributes(camera, RID());
}
notify_property_list_changed();
}
Ref<CameraEffects> Camera3D::get_effects() const {
return effects;
Ref<CameraAttributes> Camera3D::get_attributes() const {
return attributes;
}
void Camera3D::_attributes_changed() {
CameraAttributesPhysical *physical_attributes = Object::cast_to<CameraAttributesPhysical>(attributes.ptr());
ERR_FAIL_COND(!physical_attributes);
fov = physical_attributes->get_fov();
near = physical_attributes->get_near();
far = physical_attributes->get_far();
keep_aspect = KEEP_HEIGHT;
_update_camera_mode();
}
void Camera3D::set_keep_aspect_mode(KeepAspect p_aspect) {
@ -479,8 +517,8 @@ void Camera3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_cull_mask"), &Camera3D::get_cull_mask);
ClassDB::bind_method(D_METHOD("set_environment", "env"), &Camera3D::set_environment);
ClassDB::bind_method(D_METHOD("get_environment"), &Camera3D::get_environment);
ClassDB::bind_method(D_METHOD("set_effects", "env"), &Camera3D::set_effects);
ClassDB::bind_method(D_METHOD("get_effects"), &Camera3D::get_effects);
ClassDB::bind_method(D_METHOD("set_attributes", "env"), &Camera3D::set_attributes);
ClassDB::bind_method(D_METHOD("get_attributes"), &Camera3D::get_attributes);
ClassDB::bind_method(D_METHOD("set_keep_aspect_mode", "mode"), &Camera3D::set_keep_aspect_mode);
ClassDB::bind_method(D_METHOD("get_keep_aspect_mode"), &Camera3D::get_keep_aspect_mode);
ClassDB::bind_method(D_METHOD("set_doppler_tracking", "mode"), &Camera3D::set_doppler_tracking);
@ -498,7 +536,7 @@ void Camera3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "keep_aspect", PROPERTY_HINT_ENUM, "Keep Width,Keep Height"), "set_keep_aspect_mode", "get_keep_aspect_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "environment", PROPERTY_HINT_RESOURCE_TYPE, "Environment"), "set_environment", "get_environment");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "effects", PROPERTY_HINT_RESOURCE_TYPE, "CameraEffects"), "set_effects", "get_effects");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "attributes", PROPERTY_HINT_RESOURCE_TYPE, "CameraAttributesPractical,CameraAttributesPhysical"), "set_attributes", "get_attributes");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "h_offset", PROPERTY_HINT_NONE, "suffix:m"), "set_h_offset", "get_h_offset");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "v_offset", PROPERTY_HINT_NONE, "suffix:m"), "set_v_offset", "get_v_offset");
ADD_PROPERTY(PropertyInfo(Variant::INT, "doppler_tracking", PROPERTY_HINT_ENUM, "Disabled,Idle,Physics"), "set_doppler_tracking", "get_doppler_tracking");

View file

@ -33,7 +33,7 @@
#include "scene/3d/node_3d.h"
#include "scene/3d/velocity_tracker_3d.h"
#include "scene/resources/camera_effects.h"
#include "scene/resources/camera_attributes.h"
#include "scene/resources/environment.h"
class Camera3D : public Node3D {
@ -64,11 +64,11 @@ private:
ProjectionType mode = PROJECTION_PERSPECTIVE;
real_t fov = 0.0;
real_t fov = 75.0;
real_t size = 1.0;
Vector2 frustum_offset;
real_t near = 0.0;
real_t far = 0.0;
real_t near = 0.05;
real_t far = 4000.0;
real_t v_offset = 0.0;
real_t h_offset = 0.0;
KeepAspect keep_aspect = KEEP_HEIGHT;
@ -81,7 +81,8 @@ private:
uint32_t layers = 0xfffff;
Ref<Environment> environment;
Ref<CameraEffects> effects;
Ref<CameraAttributes> attributes;
void _attributes_changed();
// void _camera_make_current(Node *p_camera);
friend class Viewport;
@ -159,8 +160,8 @@ public:
void set_environment(const Ref<Environment> &p_environment);
Ref<Environment> get_environment() const;
void set_effects(const Ref<CameraEffects> &p_effects);
Ref<CameraEffects> get_effects() const;
void set_attributes(const Ref<CameraAttributes> &p_effects);
Ref<CameraAttributes> get_attributes() const;
void set_keep_aspect_mode(KeepAspect p_aspect);
KeepAspect get_keep_aspect_mode() const;

View file

@ -29,6 +29,7 @@
/*************************************************************************/
#include "fog_volume.h"
#include "scene/resources/environment.h"
///////////////////////////

View file

@ -28,6 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "core/config/project_settings.h"
#include "light_3d.h"
void Light3D::set_param(Param p_param, real_t p_value) {
@ -122,7 +124,14 @@ uint32_t Light3D::get_cull_mask() const {
void Light3D::set_color(const Color &p_color) {
color = p_color;
RS::get_singleton()->light_set_color(light, p_color);
if (GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units")) {
Color combined = color.srgb_to_linear();
combined *= correlated_color.srgb_to_linear();
RS::get_singleton()->light_set_color(light, combined.linear_to_srgb());
} else {
RS::get_singleton()->light_set_color(light, color);
}
// The gizmo color depends on the light color, so update it.
update_gizmos();
}
@ -181,6 +190,56 @@ void Light3D::owner_changed_notify() {
_update_visibility();
}
// Temperature expressed in Kelvins. Valid range 1000 - 15000
// First converts to CIE 1960 then to sRGB
// As explained in the Filament documentation: https://google.github.io/filament/Filament.md.html#lighting/directlighting/lightsparameterization
Color _color_from_temperature(float p_temperature) {
float T2 = p_temperature * p_temperature;
float u = (0.860117757f + 1.54118254e-4f * p_temperature + 1.28641212e-7f * T2) /
(1.0f + 8.42420235e-4f * p_temperature + 7.08145163e-7f * T2);
float v = (0.317398726f + 4.22806245e-5f * p_temperature + 4.20481691e-8f * T2) /
(1.0f - 2.89741816e-5f * p_temperature + 1.61456053e-7f * T2);
// Convert to xyY space.
float d = 1.0f / (2.0f * u - 8.0f * v + 4.0f);
float x = 3.0f * u * d;
float y = 2.0f * v * d;
// Convert to XYZ space
const float a = 1.0 / MAX(y, 1e-5f);
Vector3 xyz = Vector3(x * a, 1.0, (1.0f - x - y) * a);
// Convert from XYZ to sRGB(linear)
Vector3 linear = Vector3(3.2404542f * xyz.x - 1.5371385f * xyz.y - 0.4985314f * xyz.z,
-0.9692660f * xyz.x + 1.8760108f * xyz.y + 0.0415560f * xyz.z,
0.0556434f * xyz.x - 0.2040259f * xyz.y + 1.0572252f * xyz.z);
linear /= MAX(1e-5f, linear[linear.max_axis_index()]);
// Normalize, clamp, and convert to sRGB.
return Color(linear.x, linear.y, linear.z).clamp().linear_to_srgb();
}
void Light3D::set_temperature(const float p_temperature) {
temperature = p_temperature;
if (!GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units")) {
return;
}
correlated_color = _color_from_temperature(temperature);
Color combined = color.srgb_to_linear() * correlated_color.srgb_to_linear();
RS::get_singleton()->light_set_color(light, combined.linear_to_srgb());
// The gizmo color depends on the light color, so update it.
update_gizmos();
}
Color Light3D::get_correlated_color() const {
return correlated_color;
}
float Light3D::get_temperature() const {
return temperature;
}
void Light3D::_update_visibility() {
if (!is_inside_tree()) {
return;
@ -228,8 +287,14 @@ void Light3D::_validate_property(PropertyInfo &p_property) const {
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
}
if (get_light_type() != RS::LIGHT_DIRECTIONAL && p_property.name == "light_angular_distance") {
// Angular distance is only used in DirectionalLight3D.
if (get_light_type() != RS::LIGHT_DIRECTIONAL && (p_property.name == "light_angular_distance" || p_property.name == "light_intensity_lux")) {
// Angular distance and Light Intensity Lux are only used in DirectionalLight3D.
p_property.usage = PROPERTY_USAGE_NONE;
} else if (get_light_type() == RS::LIGHT_DIRECTIONAL && p_property.name == "light_intensity_lumens") {
p_property.usage = PROPERTY_USAGE_NONE;
}
if (!GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units") && (p_property.name == "light_intensity_lumens" || p_property.name == "light_intensity_lux" || p_property.name == "light_temperature")) {
p_property.usage = PROPERTY_USAGE_NONE;
}
@ -278,7 +343,14 @@ void Light3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_projector", "projector"), &Light3D::set_projector);
ClassDB::bind_method(D_METHOD("get_projector"), &Light3D::get_projector);
ClassDB::bind_method(D_METHOD("set_temperature", "temperature"), &Light3D::set_temperature);
ClassDB::bind_method(D_METHOD("get_temperature"), &Light3D::get_temperature);
ClassDB::bind_method(D_METHOD("get_correlated_color"), &Light3D::get_correlated_color);
ADD_GROUP("Light", "light_");
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_intensity_lumens", PROPERTY_HINT_RANGE, "0,100000.0,0.01,or_greater,suffix:lm"), "set_param", "get_param", PARAM_INTENSITY);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_intensity_lux", PROPERTY_HINT_RANGE, "0,150000.0,0.01,or_greater,suffix:lx"), "set_param", "get_param", PARAM_INTENSITY);
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "light_temperature", PROPERTY_HINT_RANGE, "1000,15000.0,1.0,suffix:k"), "set_temperature", "get_temperature");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "light_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_color", "get_color");
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_energy", PROPERTY_HINT_RANGE, "0,16,0.001,or_greater"), "set_param", "get_param", PARAM_ENERGY);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_indirect_energy", PROPERTY_HINT_RANGE, "0,16,0.001,or_greater"), "set_param", "get_param", PARAM_INDIRECT_ENERGY);
@ -331,6 +403,7 @@ void Light3D::_bind_methods() {
BIND_ENUM_CONSTANT(PARAM_SHADOW_OPACITY);
BIND_ENUM_CONSTANT(PARAM_SHADOW_BLUR);
BIND_ENUM_CONSTANT(PARAM_TRANSMITTANCE_BIAS);
BIND_ENUM_CONSTANT(PARAM_INTENSITY);
BIND_ENUM_CONSTANT(PARAM_MAX);
BIND_ENUM_CONSTANT(BAKE_DISABLED);
@ -382,6 +455,9 @@ Light3D::Light3D(RenderingServer::LightType p_type) {
set_param(PARAM_SHADOW_NORMAL_BIAS, 1.0);
set_param(PARAM_TRANSMITTANCE_BIAS, 0.05);
set_param(PARAM_SHADOW_FADE_START, 1);
// For OmniLight3D and SpotLight3D, specified in Lumens.
set_param(PARAM_INTENSITY, 1000.0);
set_temperature(6500.0); // Nearly white.
set_disable_scale(true);
}
@ -487,6 +563,7 @@ DirectionalLight3D::DirectionalLight3D() :
set_param(PARAM_SHADOW_FADE_START, 0.8);
// Increase the default shadow bias to better suit most scenes.
set_param(PARAM_SHADOW_BIAS, 0.1);
set_param(PARAM_INTENSITY, 100000.0); // Specified in Lux, approximate mid-day sun.
set_shadow_mode(SHADOW_PARALLEL_4_SPLITS);
blend_splits = false;
set_sky_mode(SKY_MODE_LIGHT_AND_SKY);

View file

@ -58,6 +58,7 @@ public:
PARAM_SHADOW_OPACITY = RS::LIGHT_PARAM_SHADOW_OPACITY,
PARAM_SHADOW_BLUR = RS::LIGHT_PARAM_SHADOW_BLUR,
PARAM_TRANSMITTANCE_BIAS = RS::LIGHT_PARAM_TRANSMITTANCE_BIAS,
PARAM_INTENSITY = RS::LIGHT_PARAM_INTENSITY,
PARAM_MAX = RS::LIGHT_PARAM_MAX
};
@ -83,6 +84,8 @@ private:
void _update_visibility();
BakeMode bake_mode = BAKE_DYNAMIC;
Ref<Texture2D> projector;
Color correlated_color = Color(1.0, 1.0, 1.0);
float temperature = 6500.0;
// bind helpers
@ -139,6 +142,10 @@ public:
void set_projector(const Ref<Texture2D> &p_texture);
Ref<Texture2D> get_projector() const;
void set_temperature(const float p_temperature);
float get_temperature() const;
Color get_correlated_color() const;
virtual AABB get_aabb() const override;
Light3D();

View file

@ -30,10 +30,14 @@
#include "lightmap_gi.h"
#include "core/config/project_settings.h"
#include "core/io/config_file.h"
#include "core/math/delaunay_3d.h"
#include "lightmap_probe.h"
#include "scene/3d/mesh_instance_3d.h"
#include "scene/resources/camera_attributes.h"
#include "scene/resources/environment.h"
#include "scene/resources/sky.h"
void LightmapGIData::add_user(const NodePath &p_path, const Rect2 &p_uv_scale, int p_slice_index, int32_t p_sub_instance) {
User user;
@ -207,7 +211,7 @@ bool LightmapGIData::is_using_spherical_harmonics() const {
return uses_spherical_harmonics;
}
void LightmapGIData::set_capture_data(const AABB &p_bounds, bool p_interior, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) {
void LightmapGIData::set_capture_data(const AABB &p_bounds, bool p_interior, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree, float p_baked_exposure) {
if (p_points.size()) {
int pc = p_points.size();
ERR_FAIL_COND(pc * 9 != p_point_sh.size());
@ -221,6 +225,8 @@ void LightmapGIData::set_capture_data(const AABB &p_bounds, bool p_interior, con
RS::get_singleton()->lightmap_set_probe_bounds(lightmap, AABB());
RS::get_singleton()->lightmap_set_probe_interior(lightmap, false);
}
RS::get_singleton()->lightmap_set_baked_exposure_normalization(lightmap, p_baked_exposure);
baked_exposure = p_baked_exposure;
interior = p_interior;
bounds = p_bounds;
}
@ -249,6 +255,10 @@ bool LightmapGIData::is_interior() const {
return interior;
}
float LightmapGIData::get_baked_exposure() const {
return baked_exposure;
}
void LightmapGIData::_set_probe_data(const Dictionary &p_data) {
ERR_FAIL_COND(!p_data.has("bounds"));
ERR_FAIL_COND(!p_data.has("points"));
@ -256,7 +266,8 @@ void LightmapGIData::_set_probe_data(const Dictionary &p_data) {
ERR_FAIL_COND(!p_data.has("bsp"));
ERR_FAIL_COND(!p_data.has("sh"));
ERR_FAIL_COND(!p_data.has("interior"));
set_capture_data(p_data["bounds"], p_data["interior"], p_data["points"], p_data["sh"], p_data["tetrahedra"], p_data["bsp"]);
ERR_FAIL_COND(!p_data.has("baked_exposure"));
set_capture_data(p_data["bounds"], p_data["interior"], p_data["points"], p_data["sh"], p_data["tetrahedra"], p_data["bsp"], p_data["baked_exposure"]);
}
Dictionary LightmapGIData::_get_probe_data() const {
@ -267,6 +278,7 @@ Dictionary LightmapGIData::_get_probe_data() const {
d["bsp"] = get_capture_bsp_tree();
d["sh"] = get_capture_sh();
d["interior"] = is_interior();
d["baked_exposure"] = get_baked_exposure();
return d;
}
@ -977,15 +989,21 @@ LightmapGI::BakeError LightmapGI::bake(Node *p_from_node, String p_image_data_pa
Transform3D xf = lights_found[i].xform;
Color linear_color = light->get_color().srgb_to_linear();
float energy = light->get_param(Light3D::PARAM_ENERGY);
if (GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units")) {
energy *= light->get_param(Light3D::PARAM_INTENSITY);
linear_color *= light->get_correlated_color().srgb_to_linear();
}
if (Object::cast_to<DirectionalLight3D>(light)) {
DirectionalLight3D *l = Object::cast_to<DirectionalLight3D>(light);
lightmapper->add_directional_light(light->get_bake_mode() == Light3D::BAKE_STATIC, -xf.basis.get_column(Vector3::AXIS_Z).normalized(), linear_color, l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_SIZE), l->get_param(Light3D::PARAM_SHADOW_BLUR));
lightmapper->add_directional_light(light->get_bake_mode() == Light3D::BAKE_STATIC, -xf.basis.get_column(Vector3::AXIS_Z).normalized(), linear_color, energy, l->get_param(Light3D::PARAM_SIZE), l->get_param(Light3D::PARAM_SHADOW_BLUR));
} else if (Object::cast_to<OmniLight3D>(light)) {
OmniLight3D *l = Object::cast_to<OmniLight3D>(light);
lightmapper->add_omni_light(light->get_bake_mode() == Light3D::BAKE_STATIC, xf.origin, linear_color, l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_RANGE), l->get_param(Light3D::PARAM_ATTENUATION), l->get_param(Light3D::PARAM_SIZE), l->get_param(Light3D::PARAM_SHADOW_BLUR));
lightmapper->add_omni_light(light->get_bake_mode() == Light3D::BAKE_STATIC, xf.origin, linear_color, energy * (1.0 / (Math_PI * 4.0)), l->get_param(Light3D::PARAM_RANGE), l->get_param(Light3D::PARAM_ATTENUATION), l->get_param(Light3D::PARAM_SIZE), l->get_param(Light3D::PARAM_SHADOW_BLUR));
} else if (Object::cast_to<SpotLight3D>(light)) {
SpotLight3D *l = Object::cast_to<SpotLight3D>(light);
lightmapper->add_spot_light(light->get_bake_mode() == Light3D::BAKE_STATIC, xf.origin, -xf.basis.get_column(Vector3::AXIS_Z).normalized(), linear_color, l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_RANGE), l->get_param(Light3D::PARAM_ATTENUATION), l->get_param(Light3D::PARAM_SPOT_ANGLE), l->get_param(Light3D::PARAM_SPOT_ATTENUATION), l->get_param(Light3D::PARAM_SIZE), l->get_param(Light3D::PARAM_SHADOW_BLUR));
lightmapper->add_spot_light(light->get_bake_mode() == Light3D::BAKE_STATIC, xf.origin, -xf.basis.get_column(Vector3::AXIS_Z).normalized(), linear_color, energy * (1.0 / Math_PI), l->get_param(Light3D::PARAM_RANGE), l->get_param(Light3D::PARAM_ATTENUATION), l->get_param(Light3D::PARAM_SPOT_ANGLE), l->get_param(Light3D::PARAM_SPOT_ATTENUATION), l->get_param(Light3D::PARAM_SIZE), l->get_param(Light3D::PARAM_SHADOW_BLUR));
}
}
for (int i = 0; i < probes_found.size(); i++) {
@ -1040,7 +1058,12 @@ LightmapGI::BakeError LightmapGI::bake(Node *p_from_node, String p_image_data_pa
}
}
Lightmapper::BakeError bake_err = lightmapper->bake(Lightmapper::BakeQuality(bake_quality), use_denoiser, bounces, bias, max_texture_size, directional, Lightmapper::GenerateProbes(gen_probes), environment_image, environment_transform, _lightmap_bake_step_function, &bsud);
float exposure_normalization = 1.0;
if (camera_attributes.is_valid()) {
exposure_normalization = camera_attributes->calculate_exposure_normalization() * camera_attributes->get_exposure_multiplier();
}
Lightmapper::BakeError bake_err = lightmapper->bake(Lightmapper::BakeQuality(bake_quality), use_denoiser, bounces, bias, max_texture_size, directional, Lightmapper::GenerateProbes(gen_probes), environment_image, environment_transform, _lightmap_bake_step_function, &bsud, exposure_normalization);
if (bake_err == Lightmapper::BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES) {
return BAKE_ERROR_MESHES_INVALID;
@ -1214,7 +1237,7 @@ LightmapGI::BakeError LightmapGI::bake(Node *p_from_node, String p_image_data_pa
/* Obtain the colors from the images, they will be re-created as cubemaps on the server, depending on the driver */
data->set_capture_data(bounds, interior, points, sh, tetrahedrons, bsp_array);
data->set_capture_data(bounds, interior, points, sh, tetrahedrons, bsp_array, exposure_normalization);
/* Compute a BSP tree of the simplices, so it's easy to find the exact one */
}
@ -1410,6 +1433,14 @@ LightmapGI::GenerateProbes LightmapGI::get_generate_probes() const {
return gen_probes;
}
void LightmapGI::set_camera_attributes(const Ref<CameraAttributes> &p_camera_attributes) {
camera_attributes = p_camera_attributes;
}
Ref<CameraAttributes> LightmapGI::get_camera_attributes() const {
return camera_attributes;
}
void LightmapGI::_validate_property(PropertyInfo &p_property) const {
if (p_property.name == "environment_custom_sky" && environment_mode != ENVIRONMENT_MODE_CUSTOM_SKY) {
p_property.usage = PROPERTY_USAGE_NONE;
@ -1462,6 +1493,9 @@ void LightmapGI::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_directional", "directional"), &LightmapGI::set_directional);
ClassDB::bind_method(D_METHOD("is_directional"), &LightmapGI::is_directional);
ClassDB::bind_method(D_METHOD("set_camera_attributes", "camera_attributes"), &LightmapGI::set_camera_attributes);
ClassDB::bind_method(D_METHOD("get_camera_attributes"), &LightmapGI::get_camera_attributes);
// ClassDB::bind_method(D_METHOD("bake", "from_node"), &LightmapGI::bake, DEFVAL(Variant()));
ADD_GROUP("Tweaks", "");
@ -1477,6 +1511,7 @@ void LightmapGI::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "environment_custom_sky", PROPERTY_HINT_RESOURCE_TYPE, "Sky"), "set_environment_custom_sky", "get_environment_custom_sky");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "environment_custom_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_environment_custom_color", "get_environment_custom_color");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "environment_custom_energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_environment_custom_energy", "get_environment_custom_energy");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "camera_attributes", PROPERTY_HINT_RESOURCE_TYPE, "CameraAttributesPractical,CameraAttributesPhysical"), "set_camera_attributes", "get_camera_attributes");
ADD_GROUP("Gen Probes", "generate_probes_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "generate_probes_subdiv", PROPERTY_HINT_ENUM, "Disabled,4,8,16,32"), "set_generate_probes", "get_generate_probes");
ADD_GROUP("Data", "");

View file

@ -36,6 +36,9 @@
#include "scene/3d/lightmapper.h"
#include "scene/3d/visual_instance_3d.h"
class Sky;
class CameraAttributes;
class LightmapGIData : public Resource {
GDCLASS(LightmapGIData, Resource);
RES_BASE_EXTENSION("lmbake")
@ -47,6 +50,7 @@ class LightmapGIData : public Resource {
RID lightmap;
AABB bounds;
float baked_exposure = 1.0;
struct User {
NodePath path;
@ -83,8 +87,9 @@ public:
bool is_using_spherical_harmonics() const;
bool is_interior() const;
float get_baked_exposure() const;
void set_capture_data(const AABB &p_bounds, bool p_interior, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree);
void set_capture_data(const AABB &p_bounds, bool p_interior, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree, float p_baked_exposure);
PackedVector3Array get_capture_points() const;
PackedColorArray get_capture_sh() const;
PackedInt32Array get_capture_tetrahedra() const;
@ -147,6 +152,7 @@ private:
float environment_custom_energy = 1.0;
bool directional = false;
GenerateProbes gen_probes = GENERATE_PROBES_DISABLED;
Ref<CameraAttributes> camera_attributes;
Ref<LightmapGIData> light_data;
@ -260,6 +266,9 @@ public:
void set_generate_probes(GenerateProbes p_generate_probes);
GenerateProbes get_generate_probes() const;
void set_camera_attributes(const Ref<CameraAttributes> &p_camera_attributes);
Ref<CameraAttributes> get_camera_attributes() const;
AABB get_aabb() const override;
BakeError bake(Node *p_from_node, String p_image_data_path = "", Lightmapper::BakeStepFunc p_bake_step = nullptr, void *p_bake_userdata = nullptr);

View file

@ -180,7 +180,7 @@ public:
virtual void add_omni_light(bool p_static, const Vector3 &p_position, const Color &p_color, float p_energy, float p_range, float p_attenuation, float p_size, float p_shadow_blur) = 0;
virtual void add_spot_light(bool p_static, const Vector3 &p_position, const Vector3 p_direction, const Color &p_color, float p_energy, float p_range, float p_attenuation, float p_spot_angle, float p_spot_attenuation, float p_size, float p_shadow_blur) = 0;
virtual void add_probe(const Vector3 &p_position) = 0;
virtual BakeError bake(BakeQuality p_quality, bool p_use_denoiser, int p_bounces, float p_bias, int p_max_texture_size, bool p_bake_sh, GenerateProbes p_generate_probes, const Ref<Image> &p_environment_panorama, const Basis &p_environment_transform, BakeStepFunc p_step_function = nullptr, void *p_step_userdata = nullptr) = 0;
virtual BakeError bake(BakeQuality p_quality, bool p_use_denoiser, int p_bounces, float p_bias, int p_max_texture_size, bool p_bake_sh, GenerateProbes p_generate_probes, const Ref<Image> &p_environment_panorama, const Basis &p_environment_transform, BakeStepFunc p_step_function = nullptr, void *p_step_userdata = nullptr, float p_exposure_normalization = 1.0) = 0;
virtual int get_bake_texture_count() const = 0;
virtual Ref<Image> get_bake_texture(int p_index) const = 0;

View file

@ -30,8 +30,10 @@
#include "voxel_gi.h"
#include "core/core_string_names.h"
#include "mesh_instance_3d.h"
#include "multimesh_instance_3d.h"
#include "scene/resources/camera_attributes.h"
#include "voxelizer.h"
void VoxelGIData::_set_data(const Dictionary &p_data) {
@ -281,6 +283,14 @@ Vector3 VoxelGI::get_extents() const {
return extents;
}
void VoxelGI::set_camera_attributes(const Ref<CameraAttributes> &p_camera_attributes) {
camera_attributes = p_camera_attributes;
}
Ref<CameraAttributes> VoxelGI::get_camera_attributes() const {
return camera_attributes;
}
void VoxelGI::_find_meshes(Node *p_at_node, List<PlotMesh> &plot_meshes) {
MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_at_node);
if (mi && mi->get_gi_mode() == GeometryInstance3D::GI_MODE_STATIC && mi->is_visible_in_tree()) {
@ -370,9 +380,14 @@ void VoxelGI::bake(Node *p_from_node, bool p_create_visual_debug) {
p_from_node = p_from_node ? p_from_node : get_parent();
ERR_FAIL_NULL(p_from_node);
float exposure_normalization = 1.0;
if (camera_attributes.is_valid()) {
exposure_normalization = camera_attributes->calculate_exposure_normalization() * camera_attributes->get_exposure_multiplier();
}
Voxelizer baker;
baker.begin_bake(subdiv_value[subdiv], AABB(-extents, extents * 2.0));
baker.begin_bake(subdiv_value[subdiv], AABB(-extents, extents * 2.0), exposure_normalization);
List<PlotMesh> mesh_list;
@ -428,6 +443,8 @@ void VoxelGI::bake(Node *p_from_node, bool p_create_visual_debug) {
Vector<uint8_t> df = baker.get_sdf_3d_image();
RS::get_singleton()->voxel_gi_set_baked_exposure_normalization(probe_data->get_rid(), exposure_normalization);
probe_data->allocate(baker.get_to_cell_space_xform(), AABB(-extents, extents * 2.0), baker.get_voxel_gi_octree_size(), baker.get_voxel_gi_octree_cells(), baker.get_voxel_gi_data_cells(), df, baker.get_voxel_gi_level_cell_count());
set_probe_data(probe_data);
@ -472,12 +489,16 @@ void VoxelGI::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_extents", "extents"), &VoxelGI::set_extents);
ClassDB::bind_method(D_METHOD("get_extents"), &VoxelGI::get_extents);
ClassDB::bind_method(D_METHOD("set_camera_attributes", "camera_attributes"), &VoxelGI::set_camera_attributes);
ClassDB::bind_method(D_METHOD("get_camera_attributes"), &VoxelGI::get_camera_attributes);
ClassDB::bind_method(D_METHOD("bake", "from_node", "create_visual_debug"), &VoxelGI::bake, DEFVAL(Variant()), DEFVAL(false));
ClassDB::bind_method(D_METHOD("debug_bake"), &VoxelGI::_debug_bake);
ClassDB::set_method_flags(get_class_static(), _scs_create("debug_bake"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
ADD_PROPERTY(PropertyInfo(Variant::INT, "subdiv", PROPERTY_HINT_ENUM, "64,128,256,512"), "set_subdiv", "get_subdiv");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents", PROPERTY_HINT_NONE, "suffix:m"), "set_extents", "get_extents");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "camera_attributes", PROPERTY_HINT_RESOURCE_TYPE, "CameraAttributesPractical,CameraAttributesPhysical"), "set_camera_attributes", "get_camera_attributes");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "data", PROPERTY_HINT_RESOURCE_TYPE, "VoxelGIData", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE), "set_probe_data", "get_probe_data");
BIND_ENUM_CONSTANT(SUBDIV_64);

View file

@ -33,6 +33,8 @@
#include "scene/3d/visual_instance_3d.h"
class CameraAttributes;
class VoxelGIData : public Resource {
GDCLASS(VoxelGIData, Resource);
@ -117,6 +119,7 @@ private:
Subdiv subdiv = SUBDIV_128;
Vector3 extents = Vector3(10, 10, 10);
Ref<CameraAttributes> camera_attributes;
struct PlotMesh {
Ref<Material> override_material;
@ -144,6 +147,10 @@ public:
void set_extents(const Vector3 &p_extents);
Vector3 get_extents() const;
void set_camera_attributes(const Ref<CameraAttributes> &p_camera_attributes);
Ref<CameraAttributes> get_camera_attributes() const;
Vector3i get_estimated_cell_size() const;
void bake(Node *p_from_node = nullptr, bool p_create_visual_debug = false);

View file

@ -30,6 +30,8 @@
#include "voxelizer.h"
#include "core/config/project_settings.h"
static _FORCE_INLINE_ void get_uv_and_normal(const Vector3 &p_pos, const Vector3 *p_vtx, const Vector2 *p_uv, const Vector3 *p_normal, Vector2 &r_uv, Vector3 &r_normal) {
if (p_pos.is_equal_approx(p_vtx[0])) {
r_uv = p_uv[0];
@ -348,7 +350,10 @@ Voxelizer::MaterialCache Voxelizer::_get_material_cache(Ref<Material> p_material
Ref<Texture2D> emission_tex = mat->get_texture(BaseMaterial3D::TEXTURE_EMISSION);
Color emission_col = mat->get_emission();
float emission_energy = mat->get_emission_energy();
float emission_energy = mat->get_emission_energy_multiplier() * exposure_normalization;
if (GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units")) {
emission_energy *= mat->get_emission_intensity();
}
Ref<Image> img_emission;
@ -608,10 +613,11 @@ void Voxelizer::_fixup_plot(int p_idx, int p_level) {
}
}
void Voxelizer::begin_bake(int p_subdiv, const AABB &p_bounds) {
void Voxelizer::begin_bake(int p_subdiv, const AABB &p_bounds, float p_exposure_normalization) {
sorted = false;
original_bounds = p_bounds;
cell_subdiv = p_subdiv;
exposure_normalization = p_exposure_normalization;
bake_cells.resize(1);
material_cache.clear();

View file

@ -87,6 +87,7 @@ private:
};
HashMap<Ref<Material>, MaterialCache> material_cache;
float exposure_normalization = 1.0;
AABB original_bounds;
AABB po2_bounds;
int axis_cell_size[3] = {};
@ -111,7 +112,7 @@ private:
void _sort();
public:
void begin_bake(int p_subdiv, const AABB &p_bounds);
void begin_bake(int p_subdiv, const AABB &p_bounds, float p_exposure_normalization);
void plot_mesh(const Transform3D &p_xform, Ref<Mesh> &p_mesh, const Vector<Ref<Material>> &p_materials, const Ref<Material> &p_override_material);
void end_bake();

View file

@ -42,9 +42,9 @@ void WorldEnvironment::_notification(int p_what) {
_update_current_environment();
}
if (camera_effects.is_valid()) {
add_to_group("_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
_update_current_camera_effects();
if (camera_attributes.is_valid()) {
add_to_group("_world_camera_attributes_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
_update_current_camera_attributes();
}
} break;
@ -55,9 +55,9 @@ void WorldEnvironment::_notification(int p_what) {
_update_current_environment();
}
if (camera_effects.is_valid()) {
remove_from_group("_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
_update_current_camera_effects();
if (camera_attributes.is_valid()) {
remove_from_group("_world_camera_attributes_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
_update_current_camera_attributes();
}
} break;
}
@ -74,15 +74,15 @@ void WorldEnvironment::_update_current_environment() {
get_tree()->call_group_flags(SceneTree::GROUP_CALL_DEFERRED, "_world_environment_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()), "update_configuration_warnings");
}
void WorldEnvironment::_update_current_camera_effects() {
WorldEnvironment *first = Object::cast_to<WorldEnvironment>(get_tree()->get_first_node_in_group("_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id())));
void WorldEnvironment::_update_current_camera_attributes() {
WorldEnvironment *first = Object::cast_to<WorldEnvironment>(get_tree()->get_first_node_in_group("_world_camera_attributes_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id())));
if (first) {
get_viewport()->find_world_3d()->set_camera_effects(first->camera_effects);
get_viewport()->find_world_3d()->set_camera_attributes(first->camera_attributes);
} else {
get_viewport()->find_world_3d()->set_camera_effects(Ref<CameraEffects>());
get_viewport()->find_world_3d()->set_camera_attributes(Ref<CameraAttributes>());
}
get_tree()->call_group_flags(SceneTree::GROUP_CALL_DEFERRED, "_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()), "update_configuration_warnings");
get_tree()->call_group_flags(SceneTree::GROUP_CALL_DEFERRED, "_world_camera_attributes_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()), "update_configuration_warnings");
}
void WorldEnvironment::set_environment(const Ref<Environment> &p_environment) {
@ -110,36 +110,36 @@ Ref<Environment> WorldEnvironment::get_environment() const {
return environment;
}
void WorldEnvironment::set_camera_effects(const Ref<CameraEffects> &p_camera_effects) {
if (camera_effects == p_camera_effects) {
void WorldEnvironment::set_camera_attributes(const Ref<CameraAttributes> &p_camera_attributes) {
if (camera_attributes == p_camera_attributes) {
return;
}
if (is_inside_tree() && camera_effects.is_valid() && get_viewport()->find_world_3d()->get_camera_effects() == camera_effects) {
remove_from_group("_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
if (is_inside_tree() && camera_attributes.is_valid() && get_viewport()->find_world_3d()->get_camera_attributes() == camera_attributes) {
remove_from_group("_world_camera_attributes_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
}
camera_effects = p_camera_effects;
if (is_inside_tree() && camera_effects.is_valid()) {
add_to_group("_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
camera_attributes = p_camera_attributes;
if (is_inside_tree() && camera_attributes.is_valid()) {
add_to_group("_world_camera_attributes_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
}
if (is_inside_tree()) {
_update_current_camera_effects();
_update_current_camera_attributes();
} else {
update_configuration_warnings();
}
}
Ref<CameraEffects> WorldEnvironment::get_camera_effects() const {
return camera_effects;
Ref<CameraAttributes> WorldEnvironment::get_camera_attributes() const {
return camera_attributes;
}
TypedArray<String> WorldEnvironment::get_configuration_warnings() const {
TypedArray<String> warnings = Node::get_configuration_warnings();
if (!environment.is_valid() && !camera_effects.is_valid()) {
warnings.push_back(RTR("To have any visible effect, WorldEnvironment requires its \"Environment\" property to contain an Environment, its \"Camera Effects\" property to contain a CameraEffects resource, or both."));
if (!environment.is_valid() && !camera_attributes.is_valid()) {
warnings.push_back(RTR("To have any visible effect, WorldEnvironment requires its \"Environment\" property to contain an Environment, its \"Camera Attributes\" property to contain a CameraAttributes resource, or both."));
}
if (!is_inside_tree()) {
@ -150,7 +150,7 @@ TypedArray<String> WorldEnvironment::get_configuration_warnings() const {
warnings.push_back(("Only the first Environment has an effect in a scene (or set of instantiated scenes)."));
}
if (camera_effects.is_valid() && get_viewport()->find_world_3d()->get_camera_effects() != camera_effects) {
if (camera_attributes.is_valid() && get_viewport()->find_world_3d()->get_camera_attributes() != camera_attributes) {
warnings.push_back(RTR("Only one WorldEnvironment is allowed per scene (or set of instantiated scenes)."));
}
@ -162,9 +162,9 @@ void WorldEnvironment::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_environment"), &WorldEnvironment::get_environment);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "environment", PROPERTY_HINT_RESOURCE_TYPE, "Environment"), "set_environment", "get_environment");
ClassDB::bind_method(D_METHOD("set_camera_effects", "env"), &WorldEnvironment::set_camera_effects);
ClassDB::bind_method(D_METHOD("get_camera_effects"), &WorldEnvironment::get_camera_effects);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "camera_effects", PROPERTY_HINT_RESOURCE_TYPE, "CameraEffects"), "set_camera_effects", "get_camera_effects");
ClassDB::bind_method(D_METHOD("set_camera_attributes", "camera_attributes"), &WorldEnvironment::set_camera_attributes);
ClassDB::bind_method(D_METHOD("get_camera_attributes"), &WorldEnvironment::get_camera_attributes);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "camera_attributes", PROPERTY_HINT_RESOURCE_TYPE, "CameraAttributesPractical,CameraAttributesPhysical"), "set_camera_attributes", "get_camera_attributes");
}
WorldEnvironment::WorldEnvironment() {

View file

@ -32,17 +32,17 @@
#define WORLD_ENVIRONMENT_H
#include "scene/main/node.h"
#include "scene/resources/camera_effects.h"
#include "scene/resources/camera_attributes.h"
#include "scene/resources/environment.h"
class WorldEnvironment : public Node {
GDCLASS(WorldEnvironment, Node);
Ref<Environment> environment;
Ref<CameraEffects> camera_effects;
Ref<CameraAttributes> camera_attributes;
void _update_current_environment();
void _update_current_camera_effects();
void _update_current_camera_attributes();
protected:
void _notification(int p_what);
@ -52,8 +52,8 @@ public:
void set_environment(const Ref<Environment> &p_environment);
Ref<Environment> get_environment() const;
void set_camera_effects(const Ref<CameraEffects> &p_camera_effects);
Ref<CameraEffects> get_camera_effects() const;
void set_camera_attributes(const Ref<CameraAttributes> &p_camera_attributes);
Ref<CameraAttributes> get_camera_attributes() const;
TypedArray<String> get_configuration_warnings() const override;

View file

@ -46,6 +46,7 @@
#include "scene/debugger/scene_debugger.h"
#include "scene/main/multiplayer_api.h"
#include "scene/main/viewport.h"
#include "scene/resources/environment.h"
#include "scene/resources/font.h"
#include "scene/resources/material.h"
#include "scene/resources/mesh.h"
@ -1472,18 +1473,18 @@ SceneTree::SceneTree() {
}
}
int shadowmap_size = GLOBAL_DEF("rendering/shadows/positional_shadow/atlas_size", 4096);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/positional_shadow/atlas_size", PropertyInfo(Variant::INT, "rendering/shadows/positional_shadow/atlas_size", PROPERTY_HINT_RANGE, "256,16384"));
GLOBAL_DEF("rendering/shadows/positional_shadow/atlas_size.mobile", 2048);
bool shadowmap_16_bits = GLOBAL_DEF("rendering/shadows/positional_shadow/atlas_16_bits", true);
int atlas_q0 = GLOBAL_DEF("rendering/shadows/positional_shadow/atlas_quadrant_0_subdiv", 2);
int atlas_q1 = GLOBAL_DEF("rendering/shadows/positional_shadow/atlas_quadrant_1_subdiv", 2);
int atlas_q2 = GLOBAL_DEF("rendering/shadows/positional_shadow/atlas_quadrant_2_subdiv", 3);
int atlas_q3 = GLOBAL_DEF("rendering/shadows/positional_shadow/atlas_quadrant_3_subdiv", 4);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/positional_shadow/atlas_quadrant_0_subdiv", PropertyInfo(Variant::INT, "rendering/shadows/positional_shadow/atlas_quadrant_0_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"));
ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/positional_shadow/atlas_quadrant_1_subdiv", PropertyInfo(Variant::INT, "rendering/shadows/positional_shadow/atlas_quadrant_1_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"));
ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/positional_shadow/atlas_quadrant_2_subdiv", PropertyInfo(Variant::INT, "rendering/shadows/positional_shadow/atlas_quadrant_2_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"));
ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/positional_shadow/atlas_quadrant_3_subdiv", PropertyInfo(Variant::INT, "rendering/shadows/positional_shadow/atlas_quadrant_3_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"));
int shadowmap_size = GLOBAL_DEF("rendering/lights_and_shadows/positional_shadow/atlas_size", 4096);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/lights_and_shadows/positional_shadow/atlas_size", PropertyInfo(Variant::INT, "rendering/lights_and_shadows/positional_shadow/atlas_size", PROPERTY_HINT_RANGE, "256,16384"));
GLOBAL_DEF("rendering/lights_and_shadows/positional_shadow/atlas_size.mobile", 2048);
bool shadowmap_16_bits = GLOBAL_DEF("rendering/lights_and_shadows/positional_shadow/atlas_16_bits", true);
int atlas_q0 = GLOBAL_DEF("rendering/lights_and_shadows/positional_shadow/atlas_quadrant_0_subdiv", 2);
int atlas_q1 = GLOBAL_DEF("rendering/lights_and_shadows/positional_shadow/atlas_quadrant_1_subdiv", 2);
int atlas_q2 = GLOBAL_DEF("rendering/lights_and_shadows/positional_shadow/atlas_quadrant_2_subdiv", 3);
int atlas_q3 = GLOBAL_DEF("rendering/lights_and_shadows/positional_shadow/atlas_quadrant_3_subdiv", 4);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/lights_and_shadows/positional_shadow/atlas_quadrant_0_subdiv", PropertyInfo(Variant::INT, "rendering/lights_and_shadows/positional_shadow/atlas_quadrant_0_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"));
ProjectSettings::get_singleton()->set_custom_property_info("rendering/lights_and_shadows/positional_shadow/atlas_quadrant_1_subdiv", PropertyInfo(Variant::INT, "rendering/lights_and_shadows/positional_shadow/atlas_quadrant_1_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"));
ProjectSettings::get_singleton()->set_custom_property_info("rendering/lights_and_shadows/positional_shadow/atlas_quadrant_2_subdiv", PropertyInfo(Variant::INT, "rendering/lights_and_shadows/positional_shadow/atlas_quadrant_2_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"));
ProjectSettings::get_singleton()->set_custom_property_info("rendering/lights_and_shadows/positional_shadow/atlas_quadrant_3_subdiv", PropertyInfo(Variant::INT, "rendering/lights_and_shadows/positional_shadow/atlas_quadrant_3_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"));
root->set_positional_shadow_atlas_size(shadowmap_size);
root->set_positional_shadow_atlas_16_bits(shadowmap_16_bits);

View file

@ -142,7 +142,7 @@
#include "scene/resources/bit_map.h"
#include "scene/resources/bone_map.h"
#include "scene/resources/box_shape_3d.h"
#include "scene/resources/camera_effects.h"
#include "scene/resources/camera_attributes.h"
#include "scene/resources/capsule_shape_2d.h"
#include "scene/resources/capsule_shape_3d.h"
#include "scene/resources/circle_shape_2d.h"
@ -152,6 +152,7 @@
#include "scene/resources/convex_polygon_shape_3d.h"
#include "scene/resources/cylinder_shape_3d.h"
#include "scene/resources/default_theme/default_theme.h"
#include "scene/resources/environment.h"
#include "scene/resources/font.h"
#include "scene/resources/gradient.h"
#include "scene/resources/height_map_shape_3d.h"
@ -836,7 +837,9 @@ void register_scene_types() {
GDREGISTER_CLASS(PhysicsMaterial);
GDREGISTER_CLASS(World3D);
GDREGISTER_CLASS(Environment);
GDREGISTER_CLASS(CameraEffects);
GDREGISTER_VIRTUAL_CLASS(CameraAttributes);
GDREGISTER_CLASS(CameraAttributesPhysical);
GDREGISTER_CLASS(CameraAttributesPractical);
GDREGISTER_CLASS(World2D);
GDREGISTER_VIRTUAL_CLASS(Texture);
GDREGISTER_VIRTUAL_CLASS(Texture2D);

View file

@ -0,0 +1,493 @@
/*************************************************************************/
/* camera_attributes.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "camera_attributes.h"
#include "core/config/project_settings.h"
#include "servers/rendering_server.h"
void CameraAttributes::set_exposure_multiplier(float p_multiplier) {
exposure_multiplier = p_multiplier;
_update_exposure();
emit_changed();
}
float CameraAttributes::get_exposure_multiplier() const {
return exposure_multiplier;
}
void CameraAttributes::set_exposure_sensitivity(float p_sensitivity) {
exposure_sensitivity = p_sensitivity;
_update_exposure();
emit_changed();
}
float CameraAttributes::get_exposure_sensitivity() const {
return exposure_sensitivity;
}
void CameraAttributes::_update_exposure() {
float exposure_normalization = 1.0;
// Ignore physical properties if not using physical light units.
if (GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units")) {
exposure_normalization = calculate_exposure_normalization();
}
RS::get_singleton()->camera_attributes_set_exposure(camera_attributes, exposure_multiplier, exposure_normalization);
}
void CameraAttributes::set_auto_exposure_enabled(bool p_enabled) {
auto_exposure_enabled = p_enabled;
_update_auto_exposure();
notify_property_list_changed();
}
bool CameraAttributes::is_auto_exposure_enabled() const {
return auto_exposure_enabled;
}
void CameraAttributes::set_auto_exposure_speed(float p_auto_exposure_speed) {
auto_exposure_speed = p_auto_exposure_speed;
_update_auto_exposure();
}
float CameraAttributes::get_auto_exposure_speed() const {
return auto_exposure_speed;
}
void CameraAttributes::set_auto_exposure_scale(float p_auto_exposure_scale) {
auto_exposure_scale = p_auto_exposure_scale;
_update_auto_exposure();
}
float CameraAttributes::get_auto_exposure_scale() const {
return auto_exposure_scale;
}
RID CameraAttributes::get_rid() const {
return camera_attributes;
}
void CameraAttributes::_validate_property(PropertyInfo &p_property) const {
if (!GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units") && p_property.name == "exposure_sensitivity") {
p_property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL;
return;
}
if (p_property.name.begins_with("auto_exposure_") && p_property.name != "auto_exposure_enabled" && !auto_exposure_enabled) {
p_property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL;
return;
}
}
void CameraAttributes::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_exposure_multiplier", "multiplier"), &CameraAttributes::set_exposure_multiplier);
ClassDB::bind_method(D_METHOD("get_exposure_multiplier"), &CameraAttributes::get_exposure_multiplier);
ClassDB::bind_method(D_METHOD("set_exposure_sensitivity", "sensitivity"), &CameraAttributes::set_exposure_sensitivity);
ClassDB::bind_method(D_METHOD("get_exposure_sensitivity"), &CameraAttributes::get_exposure_sensitivity);
ClassDB::bind_method(D_METHOD("set_auto_exposure_enabled", "enabled"), &CameraAttributes::set_auto_exposure_enabled);
ClassDB::bind_method(D_METHOD("is_auto_exposure_enabled"), &CameraAttributes::is_auto_exposure_enabled);
ClassDB::bind_method(D_METHOD("set_auto_exposure_speed", "exposure_speed"), &CameraAttributes::set_auto_exposure_speed);
ClassDB::bind_method(D_METHOD("get_auto_exposure_speed"), &CameraAttributes::get_auto_exposure_speed);
ClassDB::bind_method(D_METHOD("set_auto_exposure_scale", "exposure_grey"), &CameraAttributes::set_auto_exposure_scale);
ClassDB::bind_method(D_METHOD("get_auto_exposure_scale"), &CameraAttributes::get_auto_exposure_scale);
ADD_GROUP("Exposure", "exposure");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "exposure_sensitivity", PROPERTY_HINT_RANGE, "0.1,32000.0,0.1,suffix:ISO"), "set_exposure_sensitivity", "get_exposure_sensitivity");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "exposure_multiplier", PROPERTY_HINT_RANGE, "0.0,2048.0,0.001"), "set_exposure_multiplier", "get_exposure_multiplier");
ADD_GROUP("Auto Exposure", "auto_exposure_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_exposure_enabled"), "set_auto_exposure_enabled", "is_auto_exposure_enabled");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "auto_exposure_scale", PROPERTY_HINT_RANGE, "0.01,64,0.01"), "set_auto_exposure_scale", "get_auto_exposure_scale");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "auto_exposure_speed", PROPERTY_HINT_RANGE, "0.01,64,0.01"), "set_auto_exposure_speed", "get_auto_exposure_speed");
}
CameraAttributes::CameraAttributes() {
camera_attributes = RS::get_singleton()->camera_attributes_create();
}
CameraAttributes::~CameraAttributes() {
RS::get_singleton()->free(camera_attributes);
}
//////////////////////////////////////////////////////
/* CameraAttributesPractical */
void CameraAttributesPractical::set_dof_blur_far_enabled(bool p_enabled) {
dof_blur_far_enabled = p_enabled;
_update_dof_blur();
notify_property_list_changed();
}
bool CameraAttributesPractical::is_dof_blur_far_enabled() const {
return dof_blur_far_enabled;
}
void CameraAttributesPractical::set_dof_blur_far_distance(float p_distance) {
dof_blur_far_distance = p_distance;
_update_dof_blur();
}
float CameraAttributesPractical::get_dof_blur_far_distance() const {
return dof_blur_far_distance;
}
void CameraAttributesPractical::set_dof_blur_far_transition(float p_distance) {
dof_blur_far_transition = p_distance;
_update_dof_blur();
}
float CameraAttributesPractical::get_dof_blur_far_transition() const {
return dof_blur_far_transition;
}
void CameraAttributesPractical::set_dof_blur_near_enabled(bool p_enabled) {
dof_blur_near_enabled = p_enabled;
_update_dof_blur();
notify_property_list_changed();
}
bool CameraAttributesPractical::is_dof_blur_near_enabled() const {
return dof_blur_near_enabled;
}
void CameraAttributesPractical::set_dof_blur_near_distance(float p_distance) {
dof_blur_near_distance = p_distance;
_update_dof_blur();
}
float CameraAttributesPractical::get_dof_blur_near_distance() const {
return dof_blur_near_distance;
}
void CameraAttributesPractical::set_dof_blur_near_transition(float p_distance) {
dof_blur_near_transition = p_distance;
_update_dof_blur();
}
float CameraAttributesPractical::get_dof_blur_near_transition() const {
return dof_blur_near_transition;
}
void CameraAttributesPractical::set_dof_blur_amount(float p_amount) {
dof_blur_amount = p_amount;
_update_dof_blur();
}
float CameraAttributesPractical::get_dof_blur_amount() const {
return dof_blur_amount;
}
void CameraAttributesPractical::_update_dof_blur() {
RS::get_singleton()->camera_attributes_set_dof_blur(
get_rid(),
dof_blur_far_enabled,
dof_blur_far_distance,
dof_blur_far_transition,
dof_blur_near_enabled,
dof_blur_near_distance,
dof_blur_near_transition,
dof_blur_amount);
}
float CameraAttributesPractical::calculate_exposure_normalization() const {
return exposure_sensitivity / 3072007.0; // Matches exposure normalization for default CameraAttributesPhysical at ISO 100.
}
void CameraAttributesPractical::set_auto_exposure_min_sensitivity(float p_min) {
auto_exposure_min = p_min;
_update_auto_exposure();
}
float CameraAttributesPractical::get_auto_exposure_min_sensitivity() const {
return auto_exposure_min;
}
void CameraAttributesPractical::set_auto_exposure_max_sensitivity(float p_max) {
auto_exposure_max = p_max;
_update_auto_exposure();
}
float CameraAttributesPractical::get_auto_exposure_max_sensitivity() const {
return auto_exposure_max;
}
void CameraAttributesPractical::_update_auto_exposure() {
RS::get_singleton()->camera_attributes_set_auto_exposure(
get_rid(),
auto_exposure_enabled,
auto_exposure_min * ((12.5 / 100.0) / exposure_sensitivity), // Convert from Sensitivity to Luminance
auto_exposure_max * ((12.5 / 100.0) / exposure_sensitivity), // Convert from Sensitivity to Luminance
auto_exposure_speed,
auto_exposure_scale);
emit_changed();
}
void CameraAttributesPractical::_validate_property(PropertyInfo &p_property) const {
if ((!dof_blur_far_enabled && (p_property.name == "dof_blur_far_distance" || p_property.name == "dof_blur_far_transition")) ||
(!dof_blur_near_enabled && (p_property.name == "dof_blur_near_distance" || p_property.name == "dof_blur_near_transition"))) {
p_property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL;
}
}
void CameraAttributesPractical::_bind_methods() {
// DOF blur
ClassDB::bind_method(D_METHOD("set_dof_blur_far_enabled", "enabled"), &CameraAttributesPractical::set_dof_blur_far_enabled);
ClassDB::bind_method(D_METHOD("is_dof_blur_far_enabled"), &CameraAttributesPractical::is_dof_blur_far_enabled);
ClassDB::bind_method(D_METHOD("set_dof_blur_far_distance", "distance"), &CameraAttributesPractical::set_dof_blur_far_distance);
ClassDB::bind_method(D_METHOD("get_dof_blur_far_distance"), &CameraAttributesPractical::get_dof_blur_far_distance);
ClassDB::bind_method(D_METHOD("set_dof_blur_far_transition", "distance"), &CameraAttributesPractical::set_dof_blur_far_transition);
ClassDB::bind_method(D_METHOD("get_dof_blur_far_transition"), &CameraAttributesPractical::get_dof_blur_far_transition);
ClassDB::bind_method(D_METHOD("set_dof_blur_near_enabled", "enabled"), &CameraAttributesPractical::set_dof_blur_near_enabled);
ClassDB::bind_method(D_METHOD("is_dof_blur_near_enabled"), &CameraAttributesPractical::is_dof_blur_near_enabled);
ClassDB::bind_method(D_METHOD("set_dof_blur_near_distance", "distance"), &CameraAttributesPractical::set_dof_blur_near_distance);
ClassDB::bind_method(D_METHOD("get_dof_blur_near_distance"), &CameraAttributesPractical::get_dof_blur_near_distance);
ClassDB::bind_method(D_METHOD("set_dof_blur_near_transition", "distance"), &CameraAttributesPractical::set_dof_blur_near_transition);
ClassDB::bind_method(D_METHOD("get_dof_blur_near_transition"), &CameraAttributesPractical::get_dof_blur_near_transition);
ClassDB::bind_method(D_METHOD("set_dof_blur_amount", "amount"), &CameraAttributesPractical::set_dof_blur_amount);
ClassDB::bind_method(D_METHOD("get_dof_blur_amount"), &CameraAttributesPractical::get_dof_blur_amount);
ClassDB::bind_method(D_METHOD("set_auto_exposure_max_sensitivity", "max_sensitivity"), &CameraAttributesPractical::set_auto_exposure_max_sensitivity);
ClassDB::bind_method(D_METHOD("get_auto_exposure_max_sensitivity"), &CameraAttributesPractical::get_auto_exposure_max_sensitivity);
ClassDB::bind_method(D_METHOD("set_auto_exposure_min_sensitivity", "min_sensitivity"), &CameraAttributesPractical::set_auto_exposure_min_sensitivity);
ClassDB::bind_method(D_METHOD("get_auto_exposure_min_sensitivity"), &CameraAttributesPractical::get_auto_exposure_min_sensitivity);
ADD_GROUP("DOF Blur", "dof_blur_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "dof_blur_far_enabled"), "set_dof_blur_far_enabled", "is_dof_blur_far_enabled");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_far_distance", PROPERTY_HINT_RANGE, "0.01,8192,0.01,exp,suffix:m"), "set_dof_blur_far_distance", "get_dof_blur_far_distance");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_far_transition", PROPERTY_HINT_RANGE, "0.01,8192,0.01,exp"), "set_dof_blur_far_transition", "get_dof_blur_far_transition");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "dof_blur_near_enabled"), "set_dof_blur_near_enabled", "is_dof_blur_near_enabled");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_near_distance", PROPERTY_HINT_RANGE, "0.01,8192,0.01,exp,suffix:m"), "set_dof_blur_near_distance", "get_dof_blur_near_distance");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_near_transition", PROPERTY_HINT_RANGE, "0.01,8192,0.01,exp"), "set_dof_blur_near_transition", "get_dof_blur_near_transition");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_amount", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_dof_blur_amount", "get_dof_blur_amount");
ADD_GROUP("Auto Exposure", "auto_exposure_");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "auto_exposure_min_sensitivity", PROPERTY_HINT_RANGE, "0,1600,0.01,or_greater,suffic:ISO"), "set_auto_exposure_min_sensitivity", "get_auto_exposure_min_sensitivity");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "auto_exposure_max_sensitivity", PROPERTY_HINT_RANGE, "0,64000,0.1,or_greater,suffic:ISO"), "set_auto_exposure_max_sensitivity", "get_auto_exposure_max_sensitivity");
}
CameraAttributesPractical::CameraAttributesPractical() {
_update_dof_blur();
_update_exposure();
set_auto_exposure_min_sensitivity(0.0);
set_auto_exposure_max_sensitivity(800.0);
notify_property_list_changed();
}
CameraAttributesPractical::~CameraAttributesPractical() {
}
//////////////////////////////////////////////////////
/* CameraAttributesPhysical */
void CameraAttributesPhysical::set_aperture(float p_aperture) {
exposure_aperture = p_aperture;
_update_exposure();
_update_frustum();
}
float CameraAttributesPhysical::get_aperture() const {
return exposure_aperture;
}
void CameraAttributesPhysical::set_shutter_speed(float p_shutter_speed) {
exposure_shutter_speed = p_shutter_speed;
_update_exposure();
}
float CameraAttributesPhysical::get_shutter_speed() const {
return exposure_shutter_speed;
}
void CameraAttributesPhysical::set_focal_length(float p_focal_length) {
frustum_focal_length = p_focal_length;
_update_frustum();
emit_changed();
}
float CameraAttributesPhysical::get_focal_length() const {
return frustum_focal_length;
}
void CameraAttributesPhysical::set_focus_distance(float p_focus_distance) {
frustum_focus_distance = p_focus_distance;
_update_frustum();
}
float CameraAttributesPhysical::get_focus_distance() const {
return frustum_focus_distance;
}
void CameraAttributesPhysical::set_near(real_t p_near) {
frustum_near = p_near;
_update_frustum();
emit_changed();
}
real_t CameraAttributesPhysical::get_near() const {
return frustum_near;
}
void CameraAttributesPhysical::set_far(real_t p_far) {
frustum_far = p_far;
_update_frustum();
emit_changed();
}
real_t CameraAttributesPhysical::get_far() const {
return frustum_far;
}
real_t CameraAttributesPhysical::get_fov() const {
return frustum_fov;
}
void CameraAttributesPhysical::_update_frustum() {
//https://en.wikipedia.org/wiki/Circle_of_confusion#Circle_of_confusion_diameter_limit_based_on_d/1500
Vector2i sensor_size = Vector2i(36, 24); // Matches high-end DSLR, could be made variable if there is demand.
float CoC = sensor_size.length() / 1500.0;
frustum_fov = Math::rad_to_deg(2 * atan(sensor_size.height / (2 * frustum_focal_length)));
// Based on https://en.wikipedia.org/wiki/Depth_of_field.
float u = MAX(frustum_focus_distance * 1000.0, frustum_focal_length + 1.0); // Focus distance expressed in mm and clamped to at least 1 mm away from lens.
float hyperfocal_length = frustum_focal_length + ((frustum_focal_length * frustum_focal_length) / (exposure_aperture * CoC));
// This computes the start and end of the depth of field. Anything between these two points has a Circle of Confusino so small
// that it is not picked up by the camera sensors.
// To be properly physically-based, we would run the DoF shader at all depths. To be efficient, we are only running it where the CoC
// will be visible, this introduces some value shifts in the near field that we have to compensate for below.
float near = ((hyperfocal_length * u) / (hyperfocal_length + (u - frustum_focal_length))) / 1000.0; // In meters.
float far = ((hyperfocal_length * u) / (hyperfocal_length - (u - frustum_focal_length))) / 1000.0; // In meters.
float scale = (frustum_focal_length / (u - frustum_focal_length)) * (frustum_focal_length / exposure_aperture);
bool use_far = (far < frustum_far) && (far > 0.0);
bool use_near = near > frustum_near;
RS::get_singleton()->camera_attributes_set_dof_blur(
get_rid(),
use_far,
u / 1000.0, // Focus distance clampd to focal length expressed in meters.
-1.0, // Negative to tell Bokeh effect to use physically-based scaling.
use_near,
u / 1000.0,
-1.0,
scale / 5.0); // Arbitrary scaling to get close to how much blur there should be.
}
float CameraAttributesPhysical::calculate_exposure_normalization() const {
const float e = (exposure_aperture * exposure_aperture) * exposure_shutter_speed * (100.0 / exposure_sensitivity);
return 1.0 / (e * 1.2);
}
void CameraAttributesPhysical::set_auto_exposure_min_exposure_value(float p_min) {
auto_exposure_min = p_min;
_update_auto_exposure();
}
float CameraAttributesPhysical::get_auto_exposure_min_exposure_value() const {
return auto_exposure_min;
}
void CameraAttributesPhysical::set_auto_exposure_max_exposure_value(float p_max) {
auto_exposure_max = p_max;
_update_auto_exposure();
}
float CameraAttributesPhysical::get_auto_exposure_max_exposure_value() const {
return auto_exposure_max;
}
void CameraAttributesPhysical::_update_auto_exposure() {
RS::get_singleton()->camera_attributes_set_auto_exposure(
get_rid(),
auto_exposure_enabled,
pow(2.0, auto_exposure_min) * (12.5 / exposure_sensitivity), // Convert from EV100 to Luminance
pow(2.0, auto_exposure_max) * (12.5 / exposure_sensitivity), // Convert from EV100 to Luminance
auto_exposure_speed,
auto_exposure_scale);
emit_changed();
}
void CameraAttributesPhysical::_validate_property(PropertyInfo &property) const {
if (!GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units") && (property.name == "exposure_aperture" || property.name == "exposure_shutter_speed")) {
property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL;
return;
}
}
void CameraAttributesPhysical::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_aperture", "aperture"), &CameraAttributesPhysical::set_aperture);
ClassDB::bind_method(D_METHOD("get_aperture"), &CameraAttributesPhysical::get_aperture);
ClassDB::bind_method(D_METHOD("set_shutter_speed", "shutter_speed"), &CameraAttributesPhysical::set_shutter_speed);
ClassDB::bind_method(D_METHOD("get_shutter_speed"), &CameraAttributesPhysical::get_shutter_speed);
ClassDB::bind_method(D_METHOD("set_focal_length", "focal_length"), &CameraAttributesPhysical::set_focal_length);
ClassDB::bind_method(D_METHOD("get_focal_length"), &CameraAttributesPhysical::get_focal_length);
ClassDB::bind_method(D_METHOD("set_focus_distance", "focus_distance"), &CameraAttributesPhysical::set_focus_distance);
ClassDB::bind_method(D_METHOD("get_focus_distance"), &CameraAttributesPhysical::get_focus_distance);
ClassDB::bind_method(D_METHOD("set_near", "near"), &CameraAttributesPhysical::set_near);
ClassDB::bind_method(D_METHOD("get_near"), &CameraAttributesPhysical::get_near);
ClassDB::bind_method(D_METHOD("set_far", "far"), &CameraAttributesPhysical::set_far);
ClassDB::bind_method(D_METHOD("get_far"), &CameraAttributesPhysical::get_far);
ClassDB::bind_method(D_METHOD("get_fov"), &CameraAttributesPhysical::get_fov);
ClassDB::bind_method(D_METHOD("set_auto_exposure_max_exposure_value", "exposure_value_max"), &CameraAttributesPhysical::set_auto_exposure_max_exposure_value);
ClassDB::bind_method(D_METHOD("get_auto_exposure_max_exposure_value"), &CameraAttributesPhysical::get_auto_exposure_max_exposure_value);
ClassDB::bind_method(D_METHOD("set_auto_exposure_min_exposure_value", "exposure_value_min"), &CameraAttributesPhysical::set_auto_exposure_min_exposure_value);
ClassDB::bind_method(D_METHOD("get_auto_exposure_min_exposure_value"), &CameraAttributesPhysical::get_auto_exposure_min_exposure_value);
ADD_GROUP("Frustum", "frustum_");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "frustum_focus_distance", PROPERTY_HINT_RANGE, "0.01,4000.0,0.01,suffix:m"), "set_focus_distance", "get_focus_distance");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "frustum_focal_length", PROPERTY_HINT_RANGE, "1.0,800.0,0.01,exp,suffix:mm"), "set_focal_length", "get_focal_length");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "frustum_near", PROPERTY_HINT_RANGE, "0.001,10,0.001,or_greater,exp,suffix:m"), "set_near", "get_near");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "frustum_far", PROPERTY_HINT_RANGE, "0.01,4000,0.01,or_greater,exp,suffix:m"), "set_far", "get_far");
ADD_GROUP("Exposure", "exposure");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "exposure_aperture", PROPERTY_HINT_RANGE, "0.5,64.0,0.01,exp,suffix:f-stop"), "set_aperture", "get_aperture");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "exposure_shutter_speed", PROPERTY_HINT_RANGE, "0.1,8000.0,0.001,suffix:1/s"), "set_shutter_speed", "get_shutter_speed");
ADD_GROUP("Auto Exposure", "auto_exposure_");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "auto_exposure_min_exposure_value", PROPERTY_HINT_RANGE, "-16.0,16.0,0.01,or_greater,suffix:EV100"), "set_auto_exposure_min_exposure_value", "get_auto_exposure_min_exposure_value");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "auto_exposure_max_exposure_value", PROPERTY_HINT_RANGE, "-16.0,16.0,0.01,or_greater,suffix:EV100"), "set_auto_exposure_max_exposure_value", "get_auto_exposure_max_exposure_value");
};
CameraAttributesPhysical::CameraAttributesPhysical() {
_update_exposure();
_update_frustum();
set_auto_exposure_min_exposure_value(-8);
set_auto_exposure_max_exposure_value(10); // Use a wide range by default to feel more like a real camera.
notify_property_list_changed();
}
CameraAttributesPhysical::~CameraAttributesPhysical() {
}

View file

@ -1,5 +1,5 @@
/*************************************************************************/
/* camera_effects.h */
/* camera_attributes.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@ -28,18 +28,57 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef CAMERA_EFFECTS_H
#define CAMERA_EFFECTS_H
#ifndef CAMERA_ATTRIBUTES_H
#define CAMERA_ATTRIBUTES_H
#include "core/io/resource.h"
#include "core/templates/rid.h"
class CameraEffects : public Resource {
GDCLASS(CameraEffects, Resource);
class CameraAttributes : public Resource {
GDCLASS(CameraAttributes, Resource);
private:
RID camera_effects;
RID camera_attributes;
protected:
static void _bind_methods();
void _validate_property(PropertyInfo &p_property) const;
float exposure_multiplier = 1.0;
float exposure_sensitivity = 100.0; // In ISO.
void _update_exposure();
bool auto_exposure_enabled = false;
float auto_exposure_min = 0.01;
float auto_exposure_max = 64.0;
float auto_exposure_speed = 0.5;
float auto_exposure_scale = 0.4;
virtual void _update_auto_exposure(){};
public:
virtual RID get_rid() const override;
virtual float calculate_exposure_normalization() const { return 1.0; }
void set_exposure_multiplier(float p_multiplier);
float get_exposure_multiplier() const;
void set_exposure_sensitivity(float p_sensitivity);
float get_exposure_sensitivity() const;
void set_auto_exposure_enabled(bool p_enabled);
bool is_auto_exposure_enabled() const;
void set_auto_exposure_speed(float p_auto_exposure_speed);
float get_auto_exposure_speed() const;
void set_auto_exposure_scale(float p_auto_exposure_scale);
float get_auto_exposure_scale() const;
CameraAttributes();
~CameraAttributes();
};
class CameraAttributesPractical : public CameraAttributes {
GDCLASS(CameraAttributesPractical, CameraAttributes);
private:
// DOF blur
bool dof_blur_far_enabled = false;
float dof_blur_far_distance = 10.0;
@ -52,18 +91,13 @@ private:
float dof_blur_amount = 0.1;
void _update_dof_blur();
// Override exposure
bool override_exposure_enabled = false;
float override_exposure = 1.0;
void _update_override_exposure();
virtual void _update_auto_exposure() override;
protected:
static void _bind_methods();
void _validate_property(PropertyInfo &p_property) const;
public:
virtual RID get_rid() const override;
// DOF blur
void set_dof_blur_far_enabled(bool p_enabled);
bool is_dof_blur_far_enabled() const;
@ -78,18 +112,72 @@ public:
float get_dof_blur_near_distance() const;
void set_dof_blur_near_transition(float p_distance);
float get_dof_blur_near_transition() const;
void set_dof_blur_amount(float p_amount);
float get_dof_blur_amount() const;
// Override exposure
void set_override_exposure_enabled(bool p_enabled);
bool is_override_exposure_enabled() const;
void set_override_exposure(float p_exposure);
float get_override_exposure() const;
void set_auto_exposure_min_sensitivity(float p_min);
float get_auto_exposure_min_sensitivity() const;
void set_auto_exposure_max_sensitivity(float p_max);
float get_auto_exposure_max_sensitivity() const;
CameraEffects();
~CameraEffects();
virtual float calculate_exposure_normalization() const override;
CameraAttributesPractical();
~CameraAttributesPractical();
};
#endif // CAMERA_EFFECTS_H
class CameraAttributesPhysical : public CameraAttributes {
GDCLASS(CameraAttributesPhysical, CameraAttributes);
private:
// Exposure
float exposure_aperture = 16.0; // In f-stops;
float exposure_shutter_speed = 100.0; // In 1 / seconds;
// Camera properties.
float frustum_focal_length = 35.0; // In millimeters.
float frustum_focus_distance = 10.0; // In Meters.
real_t frustum_near = 0.05;
real_t frustum_far = 4000.0;
real_t frustum_fov = 75.0;
void _update_frustum();
virtual void _update_auto_exposure() override;
protected:
static void _bind_methods();
void _validate_property(PropertyInfo &property) const;
public:
void set_aperture(float p_aperture);
float get_aperture() const;
void set_shutter_speed(float p_shutter_speed);
float get_shutter_speed() const;
void set_focal_length(float p_focal_length);
float get_focal_length() const;
void set_focus_distance(float p_focus_distance);
float get_focus_distance() const;
void set_near(real_t p_near);
real_t get_near() const;
void set_far(real_t p_far);
real_t get_far() const;
real_t get_fov() const;
void set_auto_exposure_min_exposure_value(float p_min);
float get_auto_exposure_min_exposure_value() const;
void set_auto_exposure_max_exposure_value(float p_max);
float get_auto_exposure_max_exposure_value() const;
virtual float calculate_exposure_normalization() const override;
CameraAttributesPhysical();
~CameraAttributesPhysical();
};
#endif // CAMERA_ATTRIBUTES_H

View file

@ -1,206 +0,0 @@
/*************************************************************************/
/* camera_effects.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "camera_effects.h"
#include "servers/rendering_server.h"
RID CameraEffects::get_rid() const {
return camera_effects;
}
// DOF blur
void CameraEffects::set_dof_blur_far_enabled(bool p_enabled) {
dof_blur_far_enabled = p_enabled;
_update_dof_blur();
notify_property_list_changed();
}
bool CameraEffects::is_dof_blur_far_enabled() const {
return dof_blur_far_enabled;
}
void CameraEffects::set_dof_blur_far_distance(float p_distance) {
dof_blur_far_distance = p_distance;
_update_dof_blur();
}
float CameraEffects::get_dof_blur_far_distance() const {
return dof_blur_far_distance;
}
void CameraEffects::set_dof_blur_far_transition(float p_distance) {
dof_blur_far_transition = p_distance;
_update_dof_blur();
}
float CameraEffects::get_dof_blur_far_transition() const {
return dof_blur_far_transition;
}
void CameraEffects::set_dof_blur_near_enabled(bool p_enabled) {
dof_blur_near_enabled = p_enabled;
_update_dof_blur();
notify_property_list_changed();
}
bool CameraEffects::is_dof_blur_near_enabled() const {
return dof_blur_near_enabled;
}
void CameraEffects::set_dof_blur_near_distance(float p_distance) {
dof_blur_near_distance = p_distance;
_update_dof_blur();
}
float CameraEffects::get_dof_blur_near_distance() const {
return dof_blur_near_distance;
}
void CameraEffects::set_dof_blur_near_transition(float p_distance) {
dof_blur_near_transition = p_distance;
_update_dof_blur();
}
float CameraEffects::get_dof_blur_near_transition() const {
return dof_blur_near_transition;
}
void CameraEffects::set_dof_blur_amount(float p_amount) {
dof_blur_amount = p_amount;
_update_dof_blur();
}
float CameraEffects::get_dof_blur_amount() const {
return dof_blur_amount;
}
void CameraEffects::_update_dof_blur() {
RS::get_singleton()->camera_effects_set_dof_blur(
camera_effects,
dof_blur_far_enabled,
dof_blur_far_distance,
dof_blur_far_transition,
dof_blur_near_enabled,
dof_blur_near_distance,
dof_blur_near_transition,
dof_blur_amount);
}
// Custom exposure
void CameraEffects::set_override_exposure_enabled(bool p_enabled) {
override_exposure_enabled = p_enabled;
_update_override_exposure();
notify_property_list_changed();
}
bool CameraEffects::is_override_exposure_enabled() const {
return override_exposure_enabled;
}
void CameraEffects::set_override_exposure(float p_exposure) {
override_exposure = p_exposure;
_update_override_exposure();
}
float CameraEffects::get_override_exposure() const {
return override_exposure;
}
void CameraEffects::_update_override_exposure() {
RS::get_singleton()->camera_effects_set_custom_exposure(
camera_effects,
override_exposure_enabled,
override_exposure);
}
// Private methods, constructor and destructor
void CameraEffects::_validate_property(PropertyInfo &p_property) const {
if ((!dof_blur_far_enabled && (p_property.name == "dof_blur_far_distance" || p_property.name == "dof_blur_far_transition")) ||
(!dof_blur_near_enabled && (p_property.name == "dof_blur_near_distance" || p_property.name == "dof_blur_near_transition")) ||
(!override_exposure_enabled && p_property.name == "override_exposure")) {
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
}
}
void CameraEffects::_bind_methods() {
// DOF blur
ClassDB::bind_method(D_METHOD("set_dof_blur_far_enabled", "enabled"), &CameraEffects::set_dof_blur_far_enabled);
ClassDB::bind_method(D_METHOD("is_dof_blur_far_enabled"), &CameraEffects::is_dof_blur_far_enabled);
ClassDB::bind_method(D_METHOD("set_dof_blur_far_distance", "distance"), &CameraEffects::set_dof_blur_far_distance);
ClassDB::bind_method(D_METHOD("get_dof_blur_far_distance"), &CameraEffects::get_dof_blur_far_distance);
ClassDB::bind_method(D_METHOD("set_dof_blur_far_transition", "distance"), &CameraEffects::set_dof_blur_far_transition);
ClassDB::bind_method(D_METHOD("get_dof_blur_far_transition"), &CameraEffects::get_dof_blur_far_transition);
ClassDB::bind_method(D_METHOD("set_dof_blur_near_enabled", "enabled"), &CameraEffects::set_dof_blur_near_enabled);
ClassDB::bind_method(D_METHOD("is_dof_blur_near_enabled"), &CameraEffects::is_dof_blur_near_enabled);
ClassDB::bind_method(D_METHOD("set_dof_blur_near_distance", "distance"), &CameraEffects::set_dof_blur_near_distance);
ClassDB::bind_method(D_METHOD("get_dof_blur_near_distance"), &CameraEffects::get_dof_blur_near_distance);
ClassDB::bind_method(D_METHOD("set_dof_blur_near_transition", "distance"), &CameraEffects::set_dof_blur_near_transition);
ClassDB::bind_method(D_METHOD("get_dof_blur_near_transition"), &CameraEffects::get_dof_blur_near_transition);
ClassDB::bind_method(D_METHOD("set_dof_blur_amount", "amount"), &CameraEffects::set_dof_blur_amount);
ClassDB::bind_method(D_METHOD("get_dof_blur_amount"), &CameraEffects::get_dof_blur_amount);
ADD_GROUP("DOF Blur", "dof_blur_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "dof_blur_far_enabled"), "set_dof_blur_far_enabled", "is_dof_blur_far_enabled");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_far_distance", PROPERTY_HINT_RANGE, "0.01,8192,0.01,exp,suffix:m"), "set_dof_blur_far_distance", "get_dof_blur_far_distance");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_far_transition", PROPERTY_HINT_RANGE, "0.01,8192,0.01,exp"), "set_dof_blur_far_transition", "get_dof_blur_far_transition");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "dof_blur_near_enabled"), "set_dof_blur_near_enabled", "is_dof_blur_near_enabled");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_near_distance", PROPERTY_HINT_RANGE, "0.01,8192,0.01,exp,suffix:m"), "set_dof_blur_near_distance", "get_dof_blur_near_distance");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_near_transition", PROPERTY_HINT_RANGE, "0.01,8192,0.01,exp"), "set_dof_blur_near_transition", "get_dof_blur_near_transition");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_amount", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_dof_blur_amount", "get_dof_blur_amount");
// Override exposure
ClassDB::bind_method(D_METHOD("set_override_exposure_enabled", "enabled"), &CameraEffects::set_override_exposure_enabled);
ClassDB::bind_method(D_METHOD("is_override_exposure_enabled"), &CameraEffects::is_override_exposure_enabled);
ClassDB::bind_method(D_METHOD("set_override_exposure", "exposure"), &CameraEffects::set_override_exposure);
ClassDB::bind_method(D_METHOD("get_override_exposure"), &CameraEffects::get_override_exposure);
ADD_GROUP("Override Exposure", "override_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "override_exposure_enabled"), "set_override_exposure_enabled", "is_override_exposure_enabled");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "override_exposure", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_override_exposure", "get_override_exposure");
}
CameraEffects::CameraEffects() {
camera_effects = RS::get_singleton()->camera_effects_create();
_update_dof_blur();
_update_override_exposure();
}
CameraEffects::~CameraEffects() {
RS::get_singleton()->free(camera_effects);
}

View file

@ -94,13 +94,30 @@ Color Environment::get_bg_color() const {
return bg_color;
}
void Environment::set_bg_energy(float p_energy) {
bg_energy = p_energy;
RS::get_singleton()->environment_set_bg_energy(environment, p_energy);
void Environment::set_bg_energy_multiplier(float p_multiplier) {
bg_energy_multiplier = p_multiplier;
_update_bg_energy();
}
float Environment::get_bg_energy() const {
return bg_energy;
float Environment::get_bg_energy_multiplier() const {
return bg_energy_multiplier;
}
void Environment::set_bg_intensity(float p_exposure_value) {
bg_intensity = p_exposure_value;
_update_bg_energy();
}
float Environment::get_bg_intensity() const {
return bg_intensity;
}
void Environment::_update_bg_energy() {
if (GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units")) {
RS::get_singleton()->environment_set_bg_energy(environment, bg_energy_multiplier, bg_intensity);
} else {
RS::get_singleton()->environment_set_bg_energy(environment, bg_energy_multiplier, 1.0);
}
}
void Environment::set_canvas_max_layer(int p_max_layer) {
@ -214,63 +231,12 @@ float Environment::get_tonemap_white() const {
return tonemap_white;
}
void Environment::set_tonemap_auto_exposure_enabled(bool p_enabled) {
tonemap_auto_exposure_enabled = p_enabled;
_update_tonemap();
notify_property_list_changed();
}
bool Environment::is_tonemap_auto_exposure_enabled() const {
return tonemap_auto_exposure_enabled;
}
void Environment::set_tonemap_auto_exposure_min(float p_auto_exposure_min) {
tonemap_auto_exposure_min = p_auto_exposure_min;
_update_tonemap();
}
float Environment::get_tonemap_auto_exposure_min() const {
return tonemap_auto_exposure_min;
}
void Environment::set_tonemap_auto_exposure_max(float p_auto_exposure_max) {
tonemap_auto_exposure_max = p_auto_exposure_max;
_update_tonemap();
}
float Environment::get_tonemap_auto_exposure_max() const {
return tonemap_auto_exposure_max;
}
void Environment::set_tonemap_auto_exposure_speed(float p_auto_exposure_speed) {
tonemap_auto_exposure_speed = p_auto_exposure_speed;
_update_tonemap();
}
float Environment::get_tonemap_auto_exposure_speed() const {
return tonemap_auto_exposure_speed;
}
void Environment::set_tonemap_auto_exposure_grey(float p_auto_exposure_grey) {
tonemap_auto_exposure_grey = p_auto_exposure_grey;
_update_tonemap();
}
float Environment::get_tonemap_auto_exposure_grey() const {
return tonemap_auto_exposure_grey;
}
void Environment::_update_tonemap() {
RS::get_singleton()->environment_set_tonemap(
environment,
RS::EnvironmentToneMapper(tone_mapper),
tonemap_exposure,
tonemap_white,
tonemap_auto_exposure_enabled,
tonemap_auto_exposure_min,
tonemap_auto_exposure_max,
tonemap_auto_exposure_speed,
tonemap_auto_exposure_grey);
tonemap_white);
}
// SSR
@ -1080,10 +1046,13 @@ void Environment::_validate_property(PropertyInfo &p_property) const {
}
}
if (p_property.name == "background_intensity" && !GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units")) {
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
}
static const char *hide_prefixes[] = {
"fog_",
"volumetric_fog_",
"auto_exposure_",
"ssr_",
"ssao_",
"ssil_",
@ -1095,7 +1064,6 @@ void Environment::_validate_property(PropertyInfo &p_property) const {
};
static const char *high_end_prefixes[] = {
"auto_exposure_",
"ssr_",
"ssao_",
nullptr
@ -1162,8 +1130,10 @@ void Environment::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_sky_rotation"), &Environment::get_sky_rotation);
ClassDB::bind_method(D_METHOD("set_bg_color", "color"), &Environment::set_bg_color);
ClassDB::bind_method(D_METHOD("get_bg_color"), &Environment::get_bg_color);
ClassDB::bind_method(D_METHOD("set_bg_energy", "energy"), &Environment::set_bg_energy);
ClassDB::bind_method(D_METHOD("get_bg_energy"), &Environment::get_bg_energy);
ClassDB::bind_method(D_METHOD("set_bg_energy_multiplier", "energy"), &Environment::set_bg_energy_multiplier);
ClassDB::bind_method(D_METHOD("get_bg_energy_multiplier"), &Environment::get_bg_energy_multiplier);
ClassDB::bind_method(D_METHOD("set_bg_intensity", "energy"), &Environment::set_bg_intensity);
ClassDB::bind_method(D_METHOD("get_bg_intensity"), &Environment::get_bg_intensity);
ClassDB::bind_method(D_METHOD("set_canvas_max_layer", "layer"), &Environment::set_canvas_max_layer);
ClassDB::bind_method(D_METHOD("get_canvas_max_layer"), &Environment::get_canvas_max_layer);
ClassDB::bind_method(D_METHOD("set_camera_feed_id", "id"), &Environment::set_camera_feed_id);
@ -1172,7 +1142,9 @@ void Environment::_bind_methods() {
ADD_GROUP("Background", "background_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "background_mode", PROPERTY_HINT_ENUM, "Clear Color,Custom Color,Sky,Canvas,Keep,Camera Feed"), "set_background", "get_background");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "background_color"), "set_bg_color", "get_bg_color");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "background_energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_bg_energy", "get_bg_energy");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "background_energy_multiplier", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_bg_energy_multiplier", "get_bg_energy_multiplier");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "background_intensity", PROPERTY_HINT_RANGE, "0,100000,0.01,suffix:nt"), "set_bg_intensity", "get_bg_intensity");
ADD_PROPERTY(PropertyInfo(Variant::INT, "background_canvas_max_layer", PROPERTY_HINT_RANGE, "-1000,1000,1"), "set_canvas_max_layer", "get_canvas_max_layer");
ADD_PROPERTY(PropertyInfo(Variant::INT, "background_camera_feed_id", PROPERTY_HINT_RANGE, "1,10,1"), "set_camera_feed_id", "get_camera_feed_id");
@ -1211,27 +1183,11 @@ void Environment::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_tonemap_exposure"), &Environment::get_tonemap_exposure);
ClassDB::bind_method(D_METHOD("set_tonemap_white", "white"), &Environment::set_tonemap_white);
ClassDB::bind_method(D_METHOD("get_tonemap_white"), &Environment::get_tonemap_white);
ClassDB::bind_method(D_METHOD("set_tonemap_auto_exposure_enabled", "enabled"), &Environment::set_tonemap_auto_exposure_enabled);
ClassDB::bind_method(D_METHOD("is_tonemap_auto_exposure_enabled"), &Environment::is_tonemap_auto_exposure_enabled);
ClassDB::bind_method(D_METHOD("set_tonemap_auto_exposure_max", "exposure_max"), &Environment::set_tonemap_auto_exposure_max);
ClassDB::bind_method(D_METHOD("get_tonemap_auto_exposure_max"), &Environment::get_tonemap_auto_exposure_max);
ClassDB::bind_method(D_METHOD("set_tonemap_auto_exposure_min", "exposure_min"), &Environment::set_tonemap_auto_exposure_min);
ClassDB::bind_method(D_METHOD("get_tonemap_auto_exposure_min"), &Environment::get_tonemap_auto_exposure_min);
ClassDB::bind_method(D_METHOD("set_tonemap_auto_exposure_speed", "exposure_speed"), &Environment::set_tonemap_auto_exposure_speed);
ClassDB::bind_method(D_METHOD("get_tonemap_auto_exposure_speed"), &Environment::get_tonemap_auto_exposure_speed);
ClassDB::bind_method(D_METHOD("set_tonemap_auto_exposure_grey", "exposure_grey"), &Environment::set_tonemap_auto_exposure_grey);
ClassDB::bind_method(D_METHOD("get_tonemap_auto_exposure_grey"), &Environment::get_tonemap_auto_exposure_grey);
ADD_GROUP("Tonemap", "tonemap_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "tonemap_mode", PROPERTY_HINT_ENUM, "Linear,Reinhard,Filmic,ACES"), "set_tonemapper", "get_tonemapper");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tonemap_exposure", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_tonemap_exposure", "get_tonemap_exposure");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tonemap_white", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_tonemap_white", "get_tonemap_white");
ADD_GROUP("Auto Exposure", "auto_exposure_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_exposure_enabled"), "set_tonemap_auto_exposure_enabled", "is_tonemap_auto_exposure_enabled");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "auto_exposure_scale", PROPERTY_HINT_RANGE, "0.01,64,0.01"), "set_tonemap_auto_exposure_grey", "get_tonemap_auto_exposure_grey");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "auto_exposure_min_luma", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_tonemap_auto_exposure_min", "get_tonemap_auto_exposure_min");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "auto_exposure_max_luma", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_tonemap_auto_exposure_max", "get_tonemap_auto_exposure_max");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "auto_exposure_speed", PROPERTY_HINT_RANGE, "0.01,64,0.01"), "set_tonemap_auto_exposure_speed", "get_tonemap_auto_exposure_speed");
// SSR
@ -1549,6 +1505,7 @@ Environment::Environment() {
_update_fog();
_update_adjustment();
_update_volumetric_fog();
_update_bg_energy();
notify_property_list_changed();
}

View file

@ -92,9 +92,11 @@ private:
float bg_sky_custom_fov = 0.0;
Vector3 bg_sky_rotation;
Color bg_color;
float bg_energy = 1.0;
int bg_canvas_max_layer = 0;
int bg_camera_feed_id = 1;
float bg_energy_multiplier = 1.0;
float bg_intensity = 30000.0; // Measured in nits or candela/m^2
void _update_bg_energy();
// Ambient light
Color ambient_color;
@ -108,11 +110,6 @@ private:
ToneMapper tone_mapper = TONE_MAPPER_LINEAR;
float tonemap_exposure = 1.0;
float tonemap_white = 1.0;
bool tonemap_auto_exposure_enabled = false;
float tonemap_auto_exposure_min = 0.05;
float tonemap_auto_exposure_max = 8.0;
float tonemap_auto_exposure_speed = 0.5;
float tonemap_auto_exposure_grey = 0.4;
void _update_tonemap();
// SSR
@ -231,8 +228,10 @@ public:
Vector3 get_sky_rotation() const;
void set_bg_color(const Color &p_color);
Color get_bg_color() const;
void set_bg_energy(float p_energy);
float get_bg_energy() const;
void set_bg_energy_multiplier(float p_energy);
float get_bg_energy_multiplier() const;
void set_bg_intensity(float p_energy);
float get_bg_intensity() const;
void set_canvas_max_layer(int p_max_layer);
int get_canvas_max_layer() const;
void set_camera_feed_id(int p_id);
@ -257,16 +256,6 @@ public:
float get_tonemap_exposure() const;
void set_tonemap_white(float p_white);
float get_tonemap_white() const;
void set_tonemap_auto_exposure_enabled(bool p_enabled);
bool is_tonemap_auto_exposure_enabled() const;
void set_tonemap_auto_exposure_min(float p_auto_exposure_min);
float get_tonemap_auto_exposure_min() const;
void set_tonemap_auto_exposure_max(float p_auto_exposure_max);
float get_tonemap_auto_exposure_max() const;
void set_tonemap_auto_exposure_speed(float p_auto_exposure_speed);
float get_tonemap_auto_exposure_speed() const;
void set_tonemap_auto_exposure_grey(float p_auto_exposure_grey);
float get_tonemap_auto_exposure_grey() const;
// SSR
void set_ssr_enabled(bool p_enabled);

View file

@ -31,6 +31,8 @@
#include "material.h"
#include "core/config/engine.h"
#include "core/config/project_settings.h"
#include "core/error/error_macros.h"
#include "core/version.h"
#include "scene/main/scene_tree.h"
#include "scene/scene_string_names.h"
@ -1504,13 +1506,27 @@ Color BaseMaterial3D::get_emission() const {
return emission;
}
void BaseMaterial3D::set_emission_energy(float p_emission_energy) {
emission_energy = p_emission_energy;
RS::get_singleton()->material_set_param(_get_material(), shader_names->emission_energy, p_emission_energy);
void BaseMaterial3D::set_emission_energy_multiplier(float p_emission_energy_multiplier) {
emission_energy_multiplier = p_emission_energy_multiplier;
if (GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units")) {
RS::get_singleton()->material_set_param(_get_material(), shader_names->emission_energy, p_emission_energy_multiplier * emission_intensity);
} else {
RS::get_singleton()->material_set_param(_get_material(), shader_names->emission_energy, p_emission_energy_multiplier);
}
}
float BaseMaterial3D::get_emission_energy() const {
return emission_energy;
float BaseMaterial3D::get_emission_energy_multiplier() const {
return emission_energy_multiplier;
}
void BaseMaterial3D::set_emission_intensity(float p_emission_intensity) {
ERR_FAIL_COND_EDMSG(!GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units"), "Cannot set material emission intensity when Physical Light Units disabled.");
emission_intensity = p_emission_intensity;
RS::get_singleton()->material_set_param(_get_material(), shader_names->emission_energy, emission_energy_multiplier * emission_intensity);
}
float BaseMaterial3D::get_emission_intensity() const {
return emission_intensity;
}
void BaseMaterial3D::set_normal_scale(float p_normal_scale) {
@ -1884,6 +1900,10 @@ void BaseMaterial3D::_validate_property(PropertyInfo &p_property) const {
_validate_high_end("subsurf_scatter", p_property);
_validate_high_end("heightmap", p_property);
if (p_property.name == "emission_intensity" && !GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units")) {
p_property.usage = PROPERTY_USAGE_NONE;
}
if (p_property.name.begins_with("particles_anim_") && billboard_mode != BILLBOARD_PARTICLES) {
p_property.usage = PROPERTY_USAGE_NONE;
}
@ -2463,8 +2483,11 @@ void BaseMaterial3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_emission", "emission"), &BaseMaterial3D::set_emission);
ClassDB::bind_method(D_METHOD("get_emission"), &BaseMaterial3D::get_emission);
ClassDB::bind_method(D_METHOD("set_emission_energy", "emission_energy"), &BaseMaterial3D::set_emission_energy);
ClassDB::bind_method(D_METHOD("get_emission_energy"), &BaseMaterial3D::get_emission_energy);
ClassDB::bind_method(D_METHOD("set_emission_energy_multiplier", "emission_energy_multiplier"), &BaseMaterial3D::set_emission_energy_multiplier);
ClassDB::bind_method(D_METHOD("get_emission_energy_multiplier"), &BaseMaterial3D::get_emission_energy_multiplier);
ClassDB::bind_method(D_METHOD("set_emission_intensity", "emission_energy_multiplier"), &BaseMaterial3D::set_emission_intensity);
ClassDB::bind_method(D_METHOD("get_emission_intensity"), &BaseMaterial3D::get_emission_intensity);
ClassDB::bind_method(D_METHOD("set_normal_scale", "normal_scale"), &BaseMaterial3D::set_normal_scale);
ClassDB::bind_method(D_METHOD("get_normal_scale"), &BaseMaterial3D::get_normal_scale);
@ -2681,7 +2704,9 @@ void BaseMaterial3D::_bind_methods() {
ADD_GROUP("Emission", "emission_");
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "emission_enabled"), "set_feature", "get_feature", FEATURE_EMISSION);
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "emission", PROPERTY_HINT_COLOR_NO_ALPHA), "set_emission", "get_emission");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_emission_energy", "get_emission_energy");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_energy_multiplier", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_emission_energy_multiplier", "get_emission_energy_multiplier");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_intensity", PROPERTY_HINT_RANGE, "0,100000.0,0.01,or_greater,suffix:nt"), "set_emission_intensity", "get_emission_intensity");
ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_operator", PROPERTY_HINT_ENUM, "Add,Multiply"), "set_emission_operator", "get_emission_operator");
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "emission_on_uv2"), "set_flag", "get_flag", FLAG_EMISSION_ON_UV2);
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "emission_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_EMISSION);
@ -2943,7 +2968,7 @@ BaseMaterial3D::BaseMaterial3D(bool p_orm) :
set_roughness(1.0);
set_metallic(0.0);
set_emission(Color(0, 0, 0));
set_emission_energy(1.0);
set_emission_energy_multiplier(1.0);
set_normal_scale(1);
set_rim(1.0);
set_rim_tint(0.5);
@ -3096,6 +3121,8 @@ bool StandardMaterial3D::_set(const StringName &p_name, const Variant &p_value)
{ "depth_flip_binormal", "heightmap_flip_binormal" },
{ "depth_texture", "heightmap_texture" },
{ "emission_energy", "emission_energy_multiplier" },
{ nullptr, nullptr },
};

View file

@ -467,7 +467,8 @@ private:
float metallic = 0.0f;
float roughness = 0.0f;
Color emission;
float emission_energy = 0.0f;
float emission_energy_multiplier = 1.0f;
float emission_intensity = 1000.0f; // In nits, equivalent to indoor lighting.
float normal_scale = 0.0f;
float rim = 0.0f;
float rim_tint = 0.0f;
@ -573,8 +574,11 @@ public:
void set_emission(const Color &p_emission);
Color get_emission() const;
void set_emission_energy(float p_emission_energy);
float get_emission_energy() const;
void set_emission_energy_multiplier(float p_emission_energy_multiplier);
float get_emission_energy_multiplier() const;
void set_emission_intensity(float p_emission_intensity);
float get_emission_intensity() const;
void set_normal_scale(float p_normal_scale);
float get_normal_scale() const;

View file

@ -30,6 +30,7 @@
#include "sky_material.h"
#include "core/config/project_settings.h"
#include "core/version.h"
Mutex ProceduralSkyMaterial::shader_mutex;
@ -62,13 +63,13 @@ float ProceduralSkyMaterial::get_sky_curve() const {
return sky_curve;
}
void ProceduralSkyMaterial::set_sky_energy(float p_energy) {
sky_energy = p_energy;
RS::get_singleton()->material_set_param(_get_material(), "sky_energy", sky_energy);
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);
}
float ProceduralSkyMaterial::get_sky_energy() const {
return sky_energy;
float ProceduralSkyMaterial::get_sky_energy_multiplier() const {
return sky_energy_multiplier;
}
void ProceduralSkyMaterial::set_sky_cover(const Ref<Texture2D> &p_sky_cover) {
@ -117,13 +118,13 @@ float ProceduralSkyMaterial::get_ground_curve() const {
return ground_curve;
}
void ProceduralSkyMaterial::set_ground_energy(float p_energy) {
ground_energy = p_energy;
RS::get_singleton()->material_set_param(_get_material(), "ground_energy", ground_energy);
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);
}
float ProceduralSkyMaterial::get_ground_energy() const {
return ground_energy;
float ProceduralSkyMaterial::get_ground_energy_multiplier() const {
return ground_energy_multiplier;
}
void ProceduralSkyMaterial::set_sun_angle_max(float p_angle) {
@ -171,6 +172,12 @@ RID ProceduralSkyMaterial::get_shader_rid() const {
return shader;
}
void ProceduralSkyMaterial::_validate_property(PropertyInfo &p_property) const {
if ((p_property.name == "sky_luminance" || p_property.name == "ground_luminance") && !GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units")) {
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
}
}
void ProceduralSkyMaterial::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_sky_top_color", "color"), &ProceduralSkyMaterial::set_sky_top_color);
ClassDB::bind_method(D_METHOD("get_sky_top_color"), &ProceduralSkyMaterial::get_sky_top_color);
@ -181,8 +188,8 @@ void ProceduralSkyMaterial::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_sky_curve", "curve"), &ProceduralSkyMaterial::set_sky_curve);
ClassDB::bind_method(D_METHOD("get_sky_curve"), &ProceduralSkyMaterial::get_sky_curve);
ClassDB::bind_method(D_METHOD("set_sky_energy", "energy"), &ProceduralSkyMaterial::set_sky_energy);
ClassDB::bind_method(D_METHOD("get_sky_energy"), &ProceduralSkyMaterial::get_sky_energy);
ClassDB::bind_method(D_METHOD("set_sky_energy_multiplier", "multiplier"), &ProceduralSkyMaterial::set_sky_energy_multiplier);
ClassDB::bind_method(D_METHOD("get_sky_energy_multiplier"), &ProceduralSkyMaterial::get_sky_energy_multiplier);
ClassDB::bind_method(D_METHOD("set_sky_cover", "sky_cover"), &ProceduralSkyMaterial::set_sky_cover);
ClassDB::bind_method(D_METHOD("get_sky_cover"), &ProceduralSkyMaterial::get_sky_cover);
@ -199,8 +206,8 @@ void ProceduralSkyMaterial::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_ground_curve", "curve"), &ProceduralSkyMaterial::set_ground_curve);
ClassDB::bind_method(D_METHOD("get_ground_curve"), &ProceduralSkyMaterial::get_ground_curve);
ClassDB::bind_method(D_METHOD("set_ground_energy", "energy"), &ProceduralSkyMaterial::set_ground_energy);
ClassDB::bind_method(D_METHOD("get_ground_energy"), &ProceduralSkyMaterial::get_ground_energy);
ClassDB::bind_method(D_METHOD("set_ground_energy_multiplier", "energy"), &ProceduralSkyMaterial::set_ground_energy_multiplier);
ClassDB::bind_method(D_METHOD("get_ground_energy_multiplier"), &ProceduralSkyMaterial::get_ground_energy_multiplier);
ClassDB::bind_method(D_METHOD("set_sun_angle_max", "degrees"), &ProceduralSkyMaterial::set_sun_angle_max);
ClassDB::bind_method(D_METHOD("get_sun_angle_max"), &ProceduralSkyMaterial::get_sun_angle_max);
@ -215,7 +222,7 @@ void ProceduralSkyMaterial::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "sky_top_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_sky_top_color", "get_sky_top_color");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "sky_horizon_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_sky_horizon_color", "get_sky_horizon_color");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sky_curve", PROPERTY_HINT_EXP_EASING), "set_sky_curve", "get_sky_curve");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sky_energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_sky_energy", "get_sky_energy");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sky_energy_multiplier", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_sky_energy_multiplier", "get_sky_energy_multiplier");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "sky_cover", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_sky_cover", "get_sky_cover");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "sky_cover_modulate"), "set_sky_cover_modulate", "get_sky_cover_modulate");
@ -223,7 +230,7 @@ void ProceduralSkyMaterial::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ground_bottom_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_ground_bottom_color", "get_ground_bottom_color");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ground_horizon_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_ground_horizon_color", "get_ground_horizon_color");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ground_curve", PROPERTY_HINT_EXP_EASING), "set_ground_curve", "get_ground_curve");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ground_energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_ground_energy", "get_ground_energy");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ground_energy_multiplier", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_ground_energy_multiplier", "get_ground_energy_multiplier");
ADD_GROUP("Sun", "sun_");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sun_angle_max", PROPERTY_HINT_RANGE, "0,360,0.01,degrees"), "set_sun_angle_max", "get_sun_angle_max");
@ -253,7 +260,7 @@ 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;
uniform float sky_energy = 1.0; // In Lux.
uniform sampler2D sky_cover : source_color, hint_default_black;
uniform vec4 sky_cover_modulate : source_color = vec4(1.0, 1.0, 1.0, 1.0);
uniform vec4 ground_bottom_color : source_color = vec4(0.2, 0.169, 0.133, 1.0);
@ -338,13 +345,13 @@ ProceduralSkyMaterial::ProceduralSkyMaterial() {
set_sky_top_color(Color(0.385, 0.454, 0.55));
set_sky_horizon_color(Color(0.6463, 0.6558, 0.6708));
set_sky_curve(0.15);
set_sky_energy(1.0);
set_sky_energy_multiplier(1.0);
set_sky_cover_modulate(Color(1, 1, 1));
set_ground_bottom_color(Color(0.2, 0.169, 0.133));
set_ground_horizon_color(Color(0.6463, 0.6558, 0.6708));
set_ground_curve(0.02);
set_ground_energy(1.0);
set_ground_energy_multiplier(1.0);
set_sun_angle_max(30.0);
set_sun_curve(0.15);
@ -528,13 +535,13 @@ Color PhysicalSkyMaterial::get_ground_color() const {
return ground_color;
}
void PhysicalSkyMaterial::set_exposure(float p_exposure) {
exposure = p_exposure;
RS::get_singleton()->material_set_param(_get_material(), "exposure", exposure);
void PhysicalSkyMaterial::set_energy_multiplier(float p_multiplier) {
energy_multiplier = p_multiplier;
RS::get_singleton()->material_set_param(_get_material(), "exposure", energy_multiplier);
}
float PhysicalSkyMaterial::get_exposure() const {
return exposure;
float PhysicalSkyMaterial::get_energy_multiplier() const {
return energy_multiplier;
}
void PhysicalSkyMaterial::set_use_debanding(bool p_use_debanding) {
@ -574,6 +581,12 @@ RID PhysicalSkyMaterial::get_shader_rid() const {
return shader;
}
void PhysicalSkyMaterial::_validate_property(PropertyInfo &p_property) const {
if (p_property.name == "exposure_value" && !GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units")) {
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
}
}
Mutex PhysicalSkyMaterial::shader_mutex;
RID PhysicalSkyMaterial::shader;
@ -602,8 +615,8 @@ void PhysicalSkyMaterial::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_ground_color", "color"), &PhysicalSkyMaterial::set_ground_color);
ClassDB::bind_method(D_METHOD("get_ground_color"), &PhysicalSkyMaterial::get_ground_color);
ClassDB::bind_method(D_METHOD("set_exposure", "exposure"), &PhysicalSkyMaterial::set_exposure);
ClassDB::bind_method(D_METHOD("get_exposure"), &PhysicalSkyMaterial::get_exposure);
ClassDB::bind_method(D_METHOD("set_energy_multiplier", "multiplier"), &PhysicalSkyMaterial::set_energy_multiplier);
ClassDB::bind_method(D_METHOD("get_energy_multiplier"), &PhysicalSkyMaterial::get_energy_multiplier);
ClassDB::bind_method(D_METHOD("set_use_debanding", "use_debanding"), &PhysicalSkyMaterial::set_use_debanding);
ClassDB::bind_method(D_METHOD("get_use_debanding"), &PhysicalSkyMaterial::get_use_debanding);
@ -623,7 +636,7 @@ void PhysicalSkyMaterial::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "turbidity", PROPERTY_HINT_RANGE, "0,1000,0.01"), "set_turbidity", "get_turbidity");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sun_disk_scale", PROPERTY_HINT_RANGE, "0,360,0.01"), "set_sun_disk_scale", "get_sun_disk_scale");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ground_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_ground_color", "get_ground_color");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "exposure", PROPERTY_HINT_RANGE, "0,128,0.01"), "set_exposure", "get_exposure");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "energy_multiplier", PROPERTY_HINT_RANGE, "0,128,0.01"), "set_energy_multiplier", "get_energy_multiplier");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_debanding"), "set_use_debanding", "get_use_debanding");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "night_sky", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_night_sky", "get_night_sky");
}
@ -654,16 +667,13 @@ uniform vec4 mie_color : source_color = vec4(0.69, 0.729, 0.812, 1.0);
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) = 0.1;
uniform float exposure : hint_range(0, 128) = 1.0;
uniform bool use_debanding = true;
uniform sampler2D night_sky : source_color, hint_default_black;
const vec3 UP = vec3( 0.0, 1.0, 0.0 );
// Sun constants
const float SUN_ENERGY = 1000.0;
// Optical length at zenith for molecules.
const float rayleigh_zenith_size = 8.4e3;
const float mie_zenith_size = 1.25e3;
@ -683,7 +693,7 @@ vec3 interleaved_gradient_noise(vec2 pos) {
void sky() {
if (LIGHT0_ENABLED) {
float zenith_angle = clamp( dot(UP, normalize(LIGHT0_DIRECTION)), -1.0, 1.0 );
float sun_energy = max(0.0, 1.0 - exp(-((PI * 0.5) - acos(zenith_angle)))) * SUN_ENERGY * LIGHT0_ENERGY;
float sun_energy = max(0.0, 1.0 - exp(-((PI * 0.5) - acos(zenith_angle)))) * LIGHT0_ENERGY;
float sun_fade = 1.0 - clamp(1.0 - exp(LIGHT0_DIRECTION.y), 0.0, 1.0);
// Rayleigh coefficients.
@ -721,10 +731,10 @@ void sky() {
float sunAngularDiameterCos = cos(LIGHT0_SIZE * sun_disk_scale);
float sunAngularDiameterCos2 = cos(LIGHT0_SIZE * sun_disk_scale*0.5);
float sundisk = smoothstep(sunAngularDiameterCos, sunAngularDiameterCos2, cos_theta);
vec3 L0 = (sun_energy * 1900.0 * extinction) * sundisk * LIGHT0_COLOR;
vec3 L0 = (sun_energy * extinction) * sundisk * LIGHT0_COLOR;
L0 += texture(night_sky, SKY_COORDS).xyz * extinction;
vec3 color = (Lin + L0) * 0.04;
vec3 color = Lin + L0;
COLOR = pow(color, vec3(1.0 / (1.2 + (1.2 * sun_fade))));
COLOR *= exposure;
if (use_debanding) {
@ -732,7 +742,7 @@ void sky() {
}
} else {
// There is no sun, so display night_sky and nothing else.
COLOR = texture(night_sky, SKY_COORDS).xyz * 0.04;
COLOR = texture(night_sky, SKY_COORDS).xyz;
COLOR *= exposure;
}
}
@ -751,7 +761,7 @@ PhysicalSkyMaterial::PhysicalSkyMaterial() {
set_turbidity(10.0);
set_sun_disk_scale(1.0);
set_ground_color(Color(0.1, 0.07, 0.034));
set_exposure(0.1);
set_energy_multiplier(1.0);
set_use_debanding(true);
}

View file

@ -41,14 +41,14 @@ private:
Color sky_top_color;
Color sky_horizon_color;
float sky_curve = 0.0f;
float sky_energy = 0.0f;
float sky_energy_multiplier = 0.0f;
Ref<Texture2D> sky_cover;
Color sky_cover_modulate;
Color ground_bottom_color;
Color ground_horizon_color;
float ground_curve = 0.0f;
float ground_energy = 0.0f;
float ground_energy_multiplier = 0.0f;
float sun_angle_max = 0.0f;
float sun_curve = 0.0f;
@ -61,6 +61,7 @@ private:
protected:
static void _bind_methods();
void _validate_property(PropertyInfo &property) const;
public:
void set_sky_top_color(const Color &p_sky_top);
@ -72,8 +73,8 @@ public:
void set_sky_curve(float p_curve);
float get_sky_curve() const;
void set_sky_energy(float p_energy);
float get_sky_energy() const;
void set_sky_energy_multiplier(float p_multiplier);
float get_sky_energy_multiplier() const;
void set_sky_cover(const Ref<Texture2D> &p_sky_cover);
Ref<Texture2D> get_sky_cover() const;
@ -90,8 +91,8 @@ public:
void set_ground_curve(float p_curve);
float get_ground_curve() const;
void set_ground_energy(float p_energy);
float get_ground_energy() const;
void set_ground_energy_multiplier(float p_energy);
float get_ground_energy_multiplier() const;
void set_sun_angle_max(float p_angle);
float get_sun_angle_max() const;
@ -138,6 +139,9 @@ public:
void set_filtering_enabled(bool p_enabled);
bool is_filtering_enabled() const;
void set_energy_multiplier(float p_multiplier);
float get_energy_multiplier() const;
virtual Shader::Mode get_shader_mode() const override;
virtual RID get_shader_rid() const override;
virtual RID get_rid() const override;
@ -166,7 +170,7 @@ private:
float turbidity = 0.0f;
float sun_disk_scale = 0.0f;
Color ground_color;
float exposure = 0.0f;
float energy_multiplier = 1.0f;
bool use_debanding = true;
Ref<Texture2D> night_sky;
static void _update_shader();
@ -174,6 +178,7 @@ private:
protected:
static void _bind_methods();
void _validate_property(PropertyInfo &property) const;
public:
void set_rayleigh_coefficient(float p_rayleigh);
@ -200,8 +205,11 @@ public:
void set_ground_color(Color p_ground_color);
Color get_ground_color() const;
void set_exposure(float p_exposure);
float get_exposure() const;
void set_energy_multiplier(float p_multiplier);
float get_energy_multiplier() const;
void set_exposure_value(float p_exposure);
float get_exposure_value() const;
void set_use_debanding(bool p_use_debanding);
bool get_use_debanding() const;

View file

@ -33,6 +33,8 @@
#include "core/config/project_settings.h"
#include "scene/3d/camera_3d.h"
#include "scene/3d/visible_on_screen_notifier_3d.h"
#include "scene/resources/camera_attributes.h"
#include "scene/resources/environment.h"
#include "scene/scene_string_names.h"
#include "servers/navigation_server_3d.h"
@ -98,17 +100,17 @@ Ref<Environment> World3D::get_fallback_environment() const {
return fallback_environment;
}
void World3D::set_camera_effects(const Ref<CameraEffects> &p_camera_effects) {
camera_effects = p_camera_effects;
if (camera_effects.is_valid()) {
RS::get_singleton()->scenario_set_camera_effects(scenario, camera_effects->get_rid());
void World3D::set_camera_attributes(const Ref<CameraAttributes> &p_camera_attributes) {
camera_attributes = p_camera_attributes;
if (camera_attributes.is_valid()) {
RS::get_singleton()->scenario_set_camera_attributes(scenario, camera_attributes->get_rid());
} else {
RS::get_singleton()->scenario_set_camera_effects(scenario, RID());
RS::get_singleton()->scenario_set_camera_attributes(scenario, RID());
}
}
Ref<CameraEffects> World3D::get_camera_effects() const {
return camera_effects;
Ref<CameraAttributes> World3D::get_camera_attributes() const {
return camera_attributes;
}
PhysicsDirectSpaceState3D *World3D::get_direct_space_state() {
@ -123,12 +125,12 @@ void World3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_environment"), &World3D::get_environment);
ClassDB::bind_method(D_METHOD("set_fallback_environment", "env"), &World3D::set_fallback_environment);
ClassDB::bind_method(D_METHOD("get_fallback_environment"), &World3D::get_fallback_environment);
ClassDB::bind_method(D_METHOD("set_camera_effects", "effects"), &World3D::set_camera_effects);
ClassDB::bind_method(D_METHOD("get_camera_effects"), &World3D::get_camera_effects);
ClassDB::bind_method(D_METHOD("set_camera_attributes", "attributes"), &World3D::set_camera_attributes);
ClassDB::bind_method(D_METHOD("get_camera_attributes"), &World3D::get_camera_attributes);
ClassDB::bind_method(D_METHOD("get_direct_space_state"), &World3D::get_direct_space_state);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "environment", PROPERTY_HINT_RESOURCE_TYPE, "Environment"), "set_environment", "get_environment");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "fallback_environment", PROPERTY_HINT_RESOURCE_TYPE, "Environment"), "set_fallback_environment", "get_fallback_environment");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "camera_effects", PROPERTY_HINT_RESOURCE_TYPE, "CameraEffects"), "set_camera_effects", "get_camera_effects");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "camera_attributes", PROPERTY_HINT_RESOURCE_TYPE, "CameraAttributesPractical,CameraAttributesPhysical"), "set_camera_attributes", "get_camera_attributes");
ADD_PROPERTY(PropertyInfo(Variant::RID, "space", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "", "get_space");
ADD_PROPERTY(PropertyInfo(Variant::RID, "navigation_map", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "", "get_navigation_map");
ADD_PROPERTY(PropertyInfo(Variant::RID, "scenario", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "", "get_scenario");

View file

@ -32,11 +32,11 @@
#define WORLD_3D_H
#include "core/io/resource.h"
#include "scene/resources/camera_effects.h"
#include "scene/resources/environment.h"
#include "servers/physics_server_3d.h"
#include "servers/rendering_server.h"
class CameraAttributes;
class Camera3D;
class VisibleOnScreenNotifier3D;
struct SpatialIndexer;
@ -51,7 +51,7 @@ private:
Ref<Environment> environment;
Ref<Environment> fallback_environment;
Ref<CameraEffects> camera_effects;
Ref<CameraAttributes> camera_attributes;
HashSet<Camera3D *> cameras;
@ -74,8 +74,8 @@ public:
void set_fallback_environment(const Ref<Environment> &p_environment);
Ref<Environment> get_fallback_environment() const;
void set_camera_effects(const Ref<CameraEffects> &p_camera_effects);
Ref<CameraEffects> get_camera_effects() const;
void set_camera_attributes(const Ref<CameraAttributes> &p_camera_attributes);
Ref<CameraAttributes> get_camera_attributes() const;
_FORCE_INLINE_ const HashSet<Camera3D *> &get_cameras() const { return cameras; }

View file

@ -62,6 +62,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 { return 0.0; }
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 { return 1.0; }
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 { return 0.0; }

View file

@ -140,14 +140,6 @@ public:
Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) override { return Ref<Image>(); }
RID camera_effects_allocate() override { return RID(); }
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 {}
void positional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) override {}
void directional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) override {}
@ -188,7 +180,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_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_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 {}
@ -212,6 +204,9 @@ public:
if (is_environment(p_rid)) {
environment_free(p_rid);
return true;
} else if (RSG::camera_attributes->owns_camera_attributes(p_rid)) {
RSG::camera_attributes->camera_attributes_free(p_rid);
return true;
} else {
return false;
}

View file

@ -119,6 +119,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 { return PackedVector3Array(); }
virtual PackedColorArray lightmap_get_probe_capture_sh(RID p_lightmap) const override { return PackedColorArray(); }
virtual PackedInt32Array lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const override { return PackedInt32Array(); }

View file

@ -63,6 +63,9 @@ public:
virtual void voxel_gi_set_energy(RID p_voxel_gi, float p_energy) = 0;
virtual float voxel_gi_get_energy(RID p_voxel_gi) const = 0;
virtual void voxel_gi_set_baked_exposure_normalization(RID p_voxel_gi, float p_baked_exposure) = 0;
virtual float voxel_gi_get_baked_exposure_normalization(RID p_voxel_gi) const = 0;
virtual void voxel_gi_set_bias(RID p_voxel_gi, float p_bias) = 0;
virtual float voxel_gi_get_bias(RID p_voxel_gi) const = 0;

View file

@ -35,6 +35,7 @@
#include "servers/rendering/environment/renderer_gi.h"
#include "servers/rendering/renderer_canvas_render.h"
#include "servers/rendering/renderer_scene.h"
#include "servers/rendering/storage/camera_attributes_storage.h"
#include "servers/rendering/storage/light_storage.h"
#include "servers/rendering/storage/material_storage.h"
#include "servers/rendering/storage/mesh_storage.h"

View file

@ -33,6 +33,8 @@
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
#include "servers/rendering/rendering_server_default.h"
#include "servers/rendering/storage/camera_attributes_storage.h"
using namespace RendererRD;
@ -84,7 +86,7 @@ BokehDOF::~BokehDOF() {
}
}
void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) {
void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, RID p_camera_attributes, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) {
ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute version of bokeh depth of field with the mobile renderer.");
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
@ -92,22 +94,39 @@ void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far,
MaterialStorage *material_storage = MaterialStorage::get_singleton();
ERR_FAIL_NULL(material_storage);
bool dof_far = RSG::camera_attributes->camera_attributes_get_dof_far_enabled(p_camera_attributes);
float dof_far_begin = RSG::camera_attributes->camera_attributes_get_dof_far_distance(p_camera_attributes);
float dof_far_size = RSG::camera_attributes->camera_attributes_get_dof_far_transition(p_camera_attributes);
bool dof_near = RSG::camera_attributes->camera_attributes_get_dof_near_enabled(p_camera_attributes);
float dof_near_begin = RSG::camera_attributes->camera_attributes_get_dof_near_distance(p_camera_attributes);
float dof_near_size = RSG::camera_attributes->camera_attributes_get_dof_near_transition(p_camera_attributes);
float bokeh_size = RSG::camera_attributes->camera_attributes_get_dof_blur_amount(p_camera_attributes) * 64; // Base 64 pixel radius.
bool use_jitter = RSG::camera_attributes->camera_attributes_get_dof_blur_use_jitter();
RS::DOFBokehShape bokeh_shape = RSG::camera_attributes->camera_attributes_get_dof_blur_bokeh_shape();
RS::DOFBlurQuality blur_quality = RSG::camera_attributes->camera_attributes_get_dof_blur_quality();
// setup our push constant
memset(&bokeh.push_constant, 0, sizeof(BokehPushConstant));
bokeh.push_constant.blur_far_active = p_dof_far;
bokeh.push_constant.blur_far_begin = p_dof_far_begin;
bokeh.push_constant.blur_far_end = p_dof_far_begin + p_dof_far_size;
bokeh.push_constant.blur_far_active = dof_far;
bokeh.push_constant.blur_far_begin = dof_far_begin;
bokeh.push_constant.blur_far_end = dof_far_begin + dof_far_size; // Only used with non-physically-based.
bokeh.push_constant.use_physical_far = dof_far_size < 0.0;
bokeh.push_constant.blur_size_far = bokeh_size; // Only used with physically-based.
bokeh.push_constant.blur_near_active = p_dof_near;
bokeh.push_constant.blur_near_begin = p_dof_near_begin;
bokeh.push_constant.blur_near_end = MAX(0, p_dof_near_begin - p_dof_near_size);
bokeh.push_constant.use_jitter = p_use_jitter;
bokeh.push_constant.blur_near_active = dof_near;
bokeh.push_constant.blur_near_begin = dof_near_begin;
bokeh.push_constant.blur_near_end = dof_near_begin - dof_near_size; // Only used with non-physically-based.
bokeh.push_constant.use_physical_near = dof_near_size < 0.0;
bokeh.push_constant.blur_size_near = bokeh_size; // Only used with physically-based.
bokeh.push_constant.use_jitter = use_jitter;
bokeh.push_constant.jitter_seed = Math::randf() * 1000.0;
bokeh.push_constant.z_near = p_cam_znear;
bokeh.push_constant.z_far = p_cam_zfar;
bokeh.push_constant.orthogonal = p_cam_orthogonal;
bokeh.push_constant.blur_size = p_bokeh_size;
bokeh.push_constant.blur_size = (dof_near_size < 0.0 && dof_far_size < 0.0) ? 32 : bokeh_size; // Cap with physically-based to keep performance reasonable.
bokeh.push_constant.second_pass = false;
bokeh.push_constant.half_size = false;
@ -150,9 +169,9 @@ void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far,
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_buffers.base_texture_size.x, p_buffers.base_texture_size.y, 1);
RD::get_singleton()->compute_list_add_barrier(compute_list);
if (p_bokeh_shape == RS::DOF_BOKEH_BOX || p_bokeh_shape == RS::DOF_BOKEH_HEXAGON) {
if (bokeh_shape == RS::DOF_BOKEH_BOX || bokeh_shape == RS::DOF_BOKEH_HEXAGON) {
//second pass
BokehMode mode = p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL;
BokehMode mode = bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL;
shader = bokeh.compute_shader.version_get_shader(bokeh.shader_version, mode);
ERR_FAIL_COND(shader.is_null());
@ -160,9 +179,9 @@ void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far,
static const int quality_samples[4] = { 6, 12, 12, 24 };
bokeh.push_constant.steps = quality_samples[p_quality];
bokeh.push_constant.steps = quality_samples[blur_quality];
if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
if (blur_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || blur_quality == RS::DOF_BLUR_QUALITY_LOW) {
//box and hexagon are more or less the same, and they can work in either half (very low and low quality) or full (medium and high quality_ sizes)
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_half_image0), 0);
@ -187,7 +206,7 @@ void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far,
//third pass
bokeh.push_constant.second_pass = true;
if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
if (blur_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || blur_quality == RS::DOF_BLUR_QUALITY_LOW) {
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_half_image1), 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_half_texture0), 1);
} else {
@ -200,7 +219,7 @@ void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far,
RD::get_singleton()->compute_list_dispatch_threads(compute_list, bokeh.push_constant.size[0], bokeh.push_constant.size[1], 1);
RD::get_singleton()->compute_list_add_barrier(compute_list);
if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
if (blur_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || blur_quality == RS::DOF_BLUR_QUALITY_LOW) {
//forth pass, upscale for low quality
shader = bokeh.compute_shader.version_get_shader(bokeh.shader_version, BOKEH_COMPOSITE);
@ -232,7 +251,7 @@ void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far,
static const float quality_scale[4] = { 8.0, 4.0, 1.0, 0.5 };
bokeh.push_constant.steps = 0;
bokeh.push_constant.blur_scale = quality_scale[p_quality];
bokeh.push_constant.blur_scale = quality_scale[blur_quality];
//circle always runs in half size, otherwise too expensive
@ -273,7 +292,7 @@ void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far,
RD::get_singleton()->compute_list_end();
}
void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_dof_blur_amount, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) {
void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, RID p_camera_attributes, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) {
ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't blur-based depth of field with the clustered renderer.");
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
@ -281,6 +300,17 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, f
MaterialStorage *material_storage = MaterialStorage::get_singleton();
ERR_FAIL_NULL(material_storage);
bool dof_far = RSG::camera_attributes->camera_attributes_get_dof_far_enabled(p_camera_attributes);
float dof_far_begin = RSG::camera_attributes->camera_attributes_get_dof_far_distance(p_camera_attributes);
float dof_far_size = RSG::camera_attributes->camera_attributes_get_dof_far_transition(p_camera_attributes);
bool dof_near = RSG::camera_attributes->camera_attributes_get_dof_near_enabled(p_camera_attributes);
float dof_near_begin = RSG::camera_attributes->camera_attributes_get_dof_near_distance(p_camera_attributes);
float dof_near_size = RSG::camera_attributes->camera_attributes_get_dof_near_transition(p_camera_attributes);
float bokeh_size = RSG::camera_attributes->camera_attributes_get_dof_blur_amount(p_camera_attributes) * 64; // Base 64 pixel radius.
RS::DOFBokehShape bokeh_shape = RSG::camera_attributes->camera_attributes_get_dof_blur_bokeh_shape();
RS::DOFBlurQuality blur_quality = RSG::camera_attributes->camera_attributes_get_dof_blur_quality();
// setup our base push constant
memset(&bokeh.push_constant, 0, sizeof(BokehPushConstant));
@ -292,7 +322,7 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, f
bokeh.push_constant.second_pass = false;
bokeh.push_constant.half_size = false;
bokeh.push_constant.blur_size = p_dof_blur_amount;
bokeh.push_constant.blur_size = bokeh_size;
// setup our uniforms
RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
@ -307,17 +337,17 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, f
RD::Uniform u_weight_texture2(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.weight_texture[2] }));
RD::Uniform u_weight_texture3(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.weight_texture[3] }));
if (p_dof_far || p_dof_near) {
if (p_dof_far) {
if (dof_far || dof_near) {
if (dof_far) {
bokeh.push_constant.blur_far_active = true;
bokeh.push_constant.blur_far_begin = p_dof_far_begin;
bokeh.push_constant.blur_far_end = p_dof_far_begin + p_dof_far_size;
bokeh.push_constant.blur_far_begin = dof_far_begin;
bokeh.push_constant.blur_far_end = dof_far_begin + dof_far_size;
}
if (p_dof_near) {
if (dof_near) {
bokeh.push_constant.blur_near_active = true;
bokeh.push_constant.blur_near_begin = p_dof_near_begin;
bokeh.push_constant.blur_near_end = p_dof_near_begin - p_dof_near_size;
bokeh.push_constant.blur_near_begin = dof_near_begin;
bokeh.push_constant.blur_near_end = dof_near_begin - dof_near_size;
}
{
@ -337,14 +367,14 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, f
RD::get_singleton()->draw_list_end();
}
if (p_bokeh_shape == RS::DOF_BOKEH_BOX || p_bokeh_shape == RS::DOF_BOKEH_HEXAGON) {
if (bokeh_shape == RS::DOF_BOKEH_BOX || bokeh_shape == RS::DOF_BOKEH_HEXAGON) {
// double pass approach
BokehMode mode = p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL;
BokehMode mode = bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL;
RID shader = bokeh.raster_shader.version_get_shader(bokeh.shader_version, mode);
ERR_FAIL_COND(shader.is_null());
if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
if (blur_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || blur_quality == RS::DOF_BLUR_QUALITY_LOW) {
//box and hexagon are more or less the same, and they can work in either half (very low and low quality) or full (medium and high quality_ sizes)
bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1;
bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1;
@ -354,7 +384,7 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, f
static const int quality_samples[4] = { 6, 12, 12, 24 };
bokeh.push_constant.blur_scale = 0.5;
bokeh.push_constant.steps = quality_samples[p_quality];
bokeh.push_constant.steps = quality_samples[blur_quality];
RID framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[0] : p_buffers.secondary_fb;
@ -373,7 +403,7 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, f
// Pass 2
if (!bokeh.push_constant.half_size) {
// do not output weight, we're writing back into our base buffer
mode = p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX_NOWEIGHT : BOKEH_GEN_BOKEH_HEXAGONAL_NOWEIGHT;
mode = bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX_NOWEIGHT : BOKEH_GEN_BOKEH_HEXAGONAL_NOWEIGHT;
shader = bokeh.raster_shader.version_get_shader(bokeh.shader_version, mode);
ERR_FAIL_COND(shader.is_null());
@ -432,7 +462,7 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, f
}
static const float quality_scale[4] = { 8.0, 4.0, 1.0, 0.5 };
bokeh.push_constant.blur_scale = quality_scale[p_quality];
bokeh.push_constant.blur_scale = quality_scale[blur_quality];
bokeh.push_constant.steps = 0.0;
RID framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[0] : p_buffers.secondary_fb;

View file

@ -66,6 +66,11 @@ private:
uint32_t use_jitter;
float jitter_seed;
uint32_t use_physical_near;
uint32_t use_physical_far;
float blur_size_near;
float blur_size_far;
uint32_t pad[2];
};
@ -111,8 +116,8 @@ public:
BokehDOF(bool p_prefer_raster_effects);
~BokehDOF();
void bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, RS::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal);
void bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_dof_blur_amount, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal);
void bokeh_dof_compute(const BokehBuffers &p_buffers, RID p_camera_attributes, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal);
void bokeh_dof_raster(const BokehBuffers &p_buffers, RID p_camera_attributes, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal);
};
} // namespace RendererRD

View file

@ -654,7 +654,7 @@ void CopyEffects::gaussian_blur(RID p_source_rd_texture, RID p_texture, const Re
RD::get_singleton()->compute_list_end();
}
void CopyEffects::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) {
void CopyEffects::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_scale) {
ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the gaussian glow with the mobile renderer.");
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
@ -678,7 +678,7 @@ void CopyEffects::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, con
copy.push_constant.glow_white = 0; //actually unused
copy.push_constant.glow_luminance_cap = p_luminance_cap;
copy.push_constant.glow_auto_exposure_grey = p_auto_exposure_grey; //unused also
copy.push_constant.glow_auto_exposure_scale = p_auto_exposure_scale; //unused also
// setup our uniforms
RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
@ -705,7 +705,7 @@ void CopyEffects::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, con
RD::get_singleton()->compute_list_end();
}
void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, float p_luminance_multiplier, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) {
void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, float p_luminance_multiplier, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_scale) {
ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of the gaussian glow with the clustered renderer.");
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
@ -729,7 +729,7 @@ void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, float p_luminanc
blur_raster.push_constant.glow_white = 0; //actually unused
blur_raster.push_constant.glow_luminance_cap = p_luminance_cap;
blur_raster.push_constant.glow_auto_exposure_grey = p_auto_exposure_grey; //unused also
blur_raster.push_constant.glow_auto_exposure_scale = p_auto_exposure_scale; //unused also
blur_raster.push_constant.luminance_multiplier = p_luminance_multiplier;

View file

@ -86,7 +86,7 @@ private:
float glow_exposure;
float glow_white;
float glow_luminance_cap;
float glow_auto_exposure_grey;
float glow_auto_exposure_scale;
float luminance_multiplier;
float res1;
@ -148,7 +148,7 @@ private:
float glow_exposure;
float glow_white;
float glow_luminance_cap;
float glow_auto_exposure_grey;
float glow_auto_exposure_scale;
// DOF.
float camera_z_far;
float camera_z_near;
@ -321,8 +321,8 @@ public:
void copy_raster(RID p_source_texture, RID p_dest_framebuffer);
void gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, bool p_8bit_dst = false);
void gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, 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_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
void gaussian_glow_raster(RID p_source_rd_texture, float p_luminance_multiplier, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, 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_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
void gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, 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_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_scale = 1.0);
void gaussian_glow_raster(RID p_source_rd_texture, float p_luminance_multiplier, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, 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_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_scale = 1.0);
void make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size);
void make_mipmap_raster(RID p_source_rd_texture, RID p_dest_framebuffer, const Size2i &p_size);

View file

@ -117,7 +117,7 @@ void ToneMapper::tonemapper(RID p_source_color, RID p_dst_framebuffer, const Ton
tonemap.push_constant.use_auto_exposure = p_settings.use_auto_exposure;
tonemap.push_constant.exposure = p_settings.exposure;
tonemap.push_constant.white = p_settings.white;
tonemap.push_constant.auto_exposure_grey = p_settings.auto_exposure_grey;
tonemap.push_constant.auto_exposure_scale = p_settings.auto_exposure_scale;
tonemap.push_constant.luminance_multiplier = p_settings.luminance_multiplier;
tonemap.push_constant.use_color_correction = p_settings.use_color_correction;
@ -203,7 +203,7 @@ void ToneMapper::tonemapper(RD::DrawListID p_subpass_draw_list, RID p_source_col
tonemap.push_constant.use_auto_exposure = p_settings.use_auto_exposure;
tonemap.push_constant.exposure = p_settings.exposure;
tonemap.push_constant.white = p_settings.white;
tonemap.push_constant.auto_exposure_grey = p_settings.auto_exposure_grey;
tonemap.push_constant.auto_exposure_scale = p_settings.auto_exposure_scale;
tonemap.push_constant.use_color_correction = p_settings.use_color_correction;

View file

@ -77,7 +77,7 @@ private:
float exposure; // 4 - 84
float white; // 4 - 88
float auto_exposure_grey; // 4 - 92
float auto_exposure_scale; // 4 - 92
float luminance_multiplier; // 4 - 96
float pixel_size[2]; // 8 - 104
@ -124,7 +124,7 @@ public:
float white = 1.0;
bool use_auto_exposure = false;
float auto_exposure_grey = 0.5;
float auto_exposure_scale = 0.5;
RID exposure_texture;
float luminance_multiplier = 1.0;

View file

@ -287,6 +287,19 @@ float GI::voxel_gi_get_energy(RID p_voxel_gi) const {
return voxel_gi->energy;
}
void GI::voxel_gi_set_baked_exposure_normalization(RID p_voxel_gi, float p_baked_exposure) {
VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
ERR_FAIL_COND(!voxel_gi);
voxel_gi->baked_exposure = p_baked_exposure;
}
float GI::voxel_gi_get_baked_exposure_normalization(RID p_voxel_gi) const {
VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
ERR_FAIL_COND_V(!voxel_gi, 0);
return voxel_gi->baked_exposure;
}
void GI::voxel_gi_set_bias(RID p_voxel_gi, float p_bias) {
VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
ERR_FAIL_COND(!voxel_gi);
@ -1292,7 +1305,7 @@ void GI::SDFGI::update_probes(RID p_env, SkyRD::Sky *p_sky) {
push_constant.y_mult = y_mult;
if (reads_sky && p_env.is_valid()) {
push_constant.sky_energy = RendererSceneRenderRD::get_singleton()->environment_get_bg_energy(p_env);
push_constant.sky_energy = RendererSceneRenderRD::get_singleton()->environment_get_bg_energy_multiplier(p_env);
if (RendererSceneRenderRD::get_singleton()->environment_get_background(p_env) == RS::ENV_BG_CLEAR_COLOR) {
push_constant.sky_mode = SDFGIShader::IntegratePushConstant::SKY_MODE_COLOR;
@ -1840,6 +1853,11 @@ void GI::SDFGI::pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_r
c.probe_world_offset[2] = probe_ofs.z;
c.to_cell = 1.0 / cascades[i].cell_size;
c.exposure_normalization = 1.0;
if (p_render_data->camera_attributes.is_valid()) {
float exposure_normalization = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
c.exposure_normalization = exposure_normalization / cascades[i].baked_exposure_normalization;
}
}
RD::get_singleton()->buffer_update(gi->sdfgi_ubo, 0, sizeof(SDFGIData), &sdfgi_data, RD::BARRIER_MASK_COMPUTE);
@ -1876,6 +1894,14 @@ void GI::SDFGI::pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_r
lights[idx].color[2] = color.b;
lights[idx].type = RS::LIGHT_DIRECTIONAL;
lights[idx].energy = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_INDIRECT_ENERGY);
if (p_scene_render->is_using_physical_light_units()) {
lights[idx].energy *= RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_INTENSITY);
}
if (p_render_data->camera_attributes.is_valid()) {
lights[idx].energy *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
}
lights[idx].has_shadow = RSG::light_storage->light_has_shadow(li->light);
idx++;
@ -1920,7 +1946,25 @@ void GI::SDFGI::pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_r
lights[idx].color[1] = color.g;
lights[idx].color[2] = color.b;
lights[idx].type = RSG::light_storage->light_get_type(li->light);
lights[idx].energy = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_INDIRECT_ENERGY);
if (p_scene_render->is_using_physical_light_units()) {
lights[idx].energy *= RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_INTENSITY);
// Convert from Luminous Power to Luminous Intensity
if (lights[idx].type == RS::LIGHT_OMNI) {
lights[idx].energy *= 1.0 / (Math_PI * 4.0);
} else if (lights[idx].type == RS::LIGHT_SPOT) {
// 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.
lights[idx].energy *= 1.0 / Math_PI;
}
}
if (p_render_data->camera_attributes.is_valid()) {
lights[idx].energy *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
}
lights[idx].has_shadow = RSG::light_storage->light_has_shadow(li->light);
lights[idx].attenuation = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ATTENUATION);
lights[idx].radius = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_RANGE);
@ -1938,7 +1982,7 @@ void GI::SDFGI::pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_r
}
}
void GI::SDFGI::render_region(RID p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render) {
void GI::SDFGI::render_region(RID p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render, float p_exposure_normalization) {
//print_line("rendering region " + itos(p_region));
RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb); // we wouldn't be here if this failed but...
@ -1960,7 +2004,7 @@ void GI::SDFGI::render_region(RID p_render_buffers, int p_region, const PagedArr
}
//print_line("rendering cascade " + itos(p_region) + " objects: " + itos(p_cull_count) + " bounds: " + bounds + " from: " + from + " size: " + size + " cell size: " + rtos(cascades[cascade].cell_size));
p_scene_render->_render_sdfgi(p_render_buffers, from, size, bounds, p_instances, render_albedo, render_emission, render_emission_aniso, render_geom_facing);
p_scene_render->_render_sdfgi(p_render_buffers, from, size, bounds, p_instances, render_albedo, render_emission, render_emission_aniso, render_geom_facing, p_exposure_normalization);
if (cascade_next != cascade) {
RD::get_singleton()->draw_command_begin_label("SDFGI Pre-Process Cascade");
@ -1989,6 +2033,7 @@ void GI::SDFGI::render_region(RID p_render_buffers, int p_region, const PagedArr
}
cascades[cascade].all_dynamic_lights_dirty = true;
cascades[cascade].baked_exposure_normalization = p_exposure_normalization;
push_constant.grid_size = cascade_size;
push_constant.cascade = cascade;
@ -2297,7 +2342,7 @@ void GI::SDFGI::render_region(RID p_render_buffers, int p_region, const PagedArr
}
}
void GI::SDFGI::render_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result, RendererSceneRenderRD *p_scene_render) {
void GI::SDFGI::render_static_lights(RenderDataRD *p_render_data, RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result, RendererSceneRenderRD *p_scene_render) {
RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers);
ERR_FAIL_COND(!rb); // we wouldn't be here if this failed but...
@ -2358,7 +2403,25 @@ void GI::SDFGI::render_static_lights(RID p_render_buffers, uint32_t p_cascade_co
lights[idx].color[0] = color.r;
lights[idx].color[1] = color.g;
lights[idx].color[2] = color.b;
lights[idx].energy = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_INDIRECT_ENERGY);
if (p_scene_render->is_using_physical_light_units()) {
lights[idx].energy *= RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_INTENSITY);
// Convert from Luminous Power to Luminous Intensity
if (lights[idx].type == RS::LIGHT_OMNI) {
lights[idx].energy *= 1.0 / (Math_PI * 4.0);
} else if (lights[idx].type == RS::LIGHT_SPOT) {
// 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.
lights[idx].energy *= 1.0 / Math_PI;
}
}
if (p_render_data->camera_attributes.is_valid()) {
lights[idx].energy *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
}
lights[idx].has_shadow = RSG::light_storage->light_has_shadow(li->light);
lights[idx].attenuation = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ATTENUATION);
lights[idx].radius = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_RANGE);
@ -2794,6 +2857,22 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID
l.attenuation = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_ATTENUATION);
l.energy = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_INDIRECT_ENERGY);
if (p_scene_render->is_using_physical_light_units()) {
l.energy *= RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_INTENSITY);
l.energy *= gi->voxel_gi_get_baked_exposure_normalization(probe);
// Convert from Luminous Power to Luminous Intensity
if (l.type == RS::LIGHT_OMNI) {
l.energy *= 1.0 / (Math_PI * 4.0);
} else if (l.type == RS::LIGHT_SPOT) {
// 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.
l.energy *= 1.0 / Math_PI;
}
}
l.radius = to_cell.basis.xform(Vector3(RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_RANGE), 0, 0)).length();
Color color = RSG::light_storage->light_get_color(light).srgb_to_linear();
l.color[0] = color.r;
@ -3003,7 +3082,12 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID
}
p_scene_render->cull_argument[0] = instance;
p_scene_render->_render_material(to_world_xform * xform, cm, true, p_scene_render->cull_argument, dynamic_maps[0].fb, Rect2i(Vector2i(), rect.size));
float exposure_normalization = 1.0;
if (p_scene_render->is_using_physical_light_units()) {
exposure_normalization = gi->voxel_gi_get_baked_exposure_normalization(probe);
}
p_scene_render->_render_material(to_world_xform * xform, cm, true, p_scene_render->cull_argument, dynamic_maps[0].fb, Rect2i(Vector2i(), rect.size), exposure_normalization);
VoxelGIDynamicPushConstant push_constant;
memset(&push_constant, 0, sizeof(VoxelGIDynamicPushConstant));
@ -3496,7 +3580,7 @@ GI::SDFGI *GI::create_sdfgi(RID p_env, const Vector3 &p_world_position, uint32_t
return sdfgi;
}
void GI::setup_voxel_gi_instances(RID p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render) {
void GI::setup_voxel_gi_instances(RenderDataRD *p_render_data, RID p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
r_voxel_gi_instances_used = 0;
@ -3555,6 +3639,11 @@ void GI::setup_voxel_gi_instances(RID p_render_buffers, const Transform3D &p_tra
gipd.normal_bias = voxel_gi_get_normal_bias(base_probe);
gipd.blend_ambient = !voxel_gi_is_interior(base_probe);
gipd.mipmaps = gipi->mipmaps.size();
gipd.exposure_normalization = 1.0;
if (p_render_data->camera_attributes.is_valid()) {
float exposure_normalization = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
gipd.exposure_normalization = exposure_normalization / voxel_gi_get_baked_exposure_normalization(base_probe);
}
}
r_voxel_gi_instances_used++;

View file

@ -76,6 +76,7 @@ public:
float dynamic_range = 2.0;
float energy = 1.0;
float baked_exposure = 1.0;
float bias = 1.4;
float normal_bias = 0.0;
float propagation = 0.5;
@ -398,6 +399,9 @@ public:
virtual void voxel_gi_set_energy(RID p_voxel_gi, float p_energy) 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_bias) override;
virtual float voxel_gi_get_bias(RID p_voxel_gi) const override;
@ -512,6 +516,7 @@ public:
float to_cell;
int32_t probe_offset[3];
uint32_t pad;
float pad2[4];
};
//cascade blocks are full-size for volume (128^3), half size for albedo/emission
@ -551,6 +556,8 @@ public:
RID integrate_uniform_set;
RID lights_buffer;
float baked_exposure_normalization = 1.0;
bool all_dynamic_lights_dirty = true;
};
@ -630,8 +637,8 @@ public:
void debug_probes(RID p_framebuffer, const uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth);
void pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_render_data, RendererSceneRenderRD *p_scene_render);
void render_region(RID p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render);
void render_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result, RendererSceneRenderRD *p_scene_render);
void render_region(RID p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render, float p_exposure_normalization);
void render_static_lights(RenderDataRD *p_render_data, RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result, RendererSceneRenderRD *p_scene_render);
};
RS::EnvironmentSDFGIRayCount sdfgi_ray_count = RS::ENV_SDFGI_RAY_COUNT_16;
@ -705,6 +712,8 @@ public:
float to_probe; // 1/bounds * grid_size
int32_t probe_world_offset[3];
float to_cell; // 1/bounds * grid_size
float pad[3];
float exposure_normalization;
};
ProbeCascadeData cascades[SDFGI::MAX_CASCADES];
@ -720,6 +729,9 @@ public:
float normal_bias; // 4 - 88
uint32_t blend_ambient; // 4 - 92
uint32_t mipmaps; // 4 - 96
float pad[3]; // 12 - 108
float exposure_normalization; // 4 - 112
};
struct SceneData {
@ -777,7 +789,7 @@ public:
SDFGI *create_sdfgi(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size);
void setup_voxel_gi_instances(RID p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render);
void setup_voxel_gi_instances(RenderDataRD *p_render_data, RID p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render);
void process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, const RID *p_vrs_slices, RID p_environment, uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render);
RID voxel_gi_instance_create(RID p_base);

View file

@ -292,7 +292,7 @@ static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_basis, float *p_ar
p_array[11] = 0;
}
void SkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const Projection *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position, float p_luminance_multiplier) {
void SkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const Projection *p_projections, const Basis &p_orientation, const Vector3 &p_position, float p_luminance_multiplier) {
SkyPushConstant sky_push_constant;
memset(&sky_push_constant, 0, sizeof(SkyPushConstant));
@ -307,7 +307,6 @@ void SkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineC
sky_push_constant.position[0] = p_position.x;
sky_push_constant.position[1] = p_position.y;
sky_push_constant.position[2] = p_position.z;
sky_push_constant.multiplier = p_multiplier;
sky_push_constant.time = p_time;
sky_push_constant.luminance_multiplier = p_luminance_multiplier;
store_transform_3x3(p_orientation, sky_push_constant.orientation);
@ -762,7 +761,7 @@ Ref<Image> SkyRD::Sky::bake_panorama(float p_energy, int p_roughness_layers, con
RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton();
RD::TextureFormat tf;
tf.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
tf.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; // Could be RGBA16
tf.width = p_size.width;
tf.height = p_size.height;
tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
@ -868,7 +867,7 @@ void SkyRD::init() {
actions.renames["COLOR"] = "color";
actions.renames["ALPHA"] = "alpha";
actions.renames["EYEDIR"] = "cube_normal";
actions.renames["POSITION"] = "params.position_multiplier.xyz";
actions.renames["POSITION"] = "params.position";
actions.renames["SKY_COORDS"] = "panorama_coords";
actions.renames["SCREEN_UV"] = "uv";
actions.renames["FRAGCOORD"] = "gl_FragCoord";
@ -1110,7 +1109,7 @@ SkyRD::~SkyRD() {
RD::get_singleton()->free(index_buffer); //array gets freed as dependency
}
void SkyRD::setup(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, RendererSceneRenderRD *p_scene_render) {
void SkyRD::setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) {
RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
ERR_FAIL_COND(p_env.is_null());
@ -1220,6 +1219,14 @@ void SkyRD::setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_ligh
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 (p_scene_render->is_using_physical_light_units()) {
sky_light_data.energy *= light_storage->light_get_param(base, RS::LIGHT_PARAM_INTENSITY);
}
if (p_camera_attributes.is_valid()) {
sky_light_data.energy *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_camera_attributes);
}
Color linear_col = light_storage->light_get_color(base).srgb_to_linear();
sky_light_data.color[0] = linear_col.r;
sky_light_data.color[1] = linear_col.g;
@ -1351,8 +1358,6 @@ void SkyRD::update(RID p_env, const Projection &p_projection, const Transform3D
ERR_FAIL_COND(!shader_data);
float multiplier = RendererSceneRenderRD::get_singleton()->environment_get_bg_energy(p_env);
bool update_single_frame = sky->mode == RS::SKY_MODE_REALTIME || sky->mode == RS::SKY_MODE_QUALITY;
RS::SkyMode sky_mode = sky->mode;
@ -1415,7 +1420,7 @@ void SkyRD::update(RID p_env, const Projection &p_projection, const Transform3D
RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES, sky_shader.default_shader_rd);
cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[2].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
_render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[2].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, multiplier, p_transform.origin, p_luminance_multiplier);
_render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[2].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, p_transform.origin, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
RD::get_singleton()->draw_command_end_label();
@ -1434,7 +1439,7 @@ void SkyRD::update(RID p_env, const Projection &p_projection, const Transform3D
RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_CUBEMAP_HALF_RES, sky_shader.default_shader_rd);
cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[1].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
_render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[1].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, multiplier, p_transform.origin, p_luminance_multiplier);
_render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[1].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, p_transform.origin, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
RD::get_singleton()->draw_command_end_label();
@ -1449,7 +1454,7 @@ void SkyRD::update(RID p_env, const Projection &p_projection, const Transform3D
RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_CUBEMAP, sky_shader.default_shader_rd);
cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[0].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
_render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[0].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, multiplier, p_transform.origin, p_luminance_multiplier);
_render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[0].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, p_transform.origin, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
RD::get_singleton()->draw_command_end_label();
@ -1475,7 +1480,7 @@ void SkyRD::update(RID p_env, const Projection &p_projection, const Transform3D
}
sky->processing_layer = 1;
}
sky->baked_exposure = p_luminance_multiplier;
sky->reflection.dirty = false;
} else {
@ -1491,7 +1496,7 @@ void SkyRD::update(RID p_env, const Projection &p_projection, const Transform3D
}
}
void SkyRD::draw(RID p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time) {
void SkyRD::draw(RID p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
ERR_FAIL_COND(p_env.is_null());
@ -1536,7 +1541,6 @@ void SkyRD::draw(RID p_env, bool p_can_continue_color, bool p_can_continue_depth
Basis sky_transform = RendererSceneRenderRD::get_singleton()->environment_get_sky_orientation(p_env);
sky_transform.invert();
float multiplier = RendererSceneRenderRD::get_singleton()->environment_get_bg_energy(p_env);
float custom_fov = RendererSceneRenderRD::get_singleton()->environment_get_sky_custom_fov(p_env);
// Camera
@ -1567,7 +1571,7 @@ void SkyRD::draw(RID p_env, bool p_can_continue_color, bool p_can_continue_depth
clear_colors.push_back(Color(0.0, 0.0, 0.0));
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->quarter_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors);
_render_sky(draw_list, p_time, sky->quarter_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, 1.0);
_render_sky(draw_list, p_time, sky->quarter_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, p_transform.origin, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
@ -1580,7 +1584,7 @@ void SkyRD::draw(RID p_env, bool p_can_continue_color, bool p_can_continue_depth
clear_colors.push_back(Color(0.0, 0.0, 0.0));
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->half_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors);
_render_sky(draw_list, p_time, sky->half_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, 1.0);
_render_sky(draw_list, p_time, sky->half_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, p_transform.origin, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
@ -1594,7 +1598,7 @@ void SkyRD::draw(RID p_env, bool p_can_continue_color, bool p_can_continue_depth
}
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_fb, RD::INITIAL_ACTION_CONTINUE, p_can_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, p_can_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ);
_render_sky(draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, 1.0);
_render_sky(draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, p_transform.origin, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
@ -1634,7 +1638,6 @@ void SkyRD::update_res_buffers(RID p_env, uint32_t p_view_count, const Projectio
Basis sky_transform = RendererSceneRenderRD::get_singleton()->environment_get_sky_orientation(p_env);
sky_transform.invert();
float multiplier = RendererSceneRenderRD::get_singleton()->environment_get_bg_energy(p_env);
float custom_fov = RendererSceneRenderRD::get_singleton()->environment_get_sky_custom_fov(p_env);
// Camera
@ -1665,7 +1668,7 @@ void SkyRD::update_res_buffers(RID p_env, uint32_t p_view_count, const Projectio
clear_colors.push_back(Color(0.0, 0.0, 0.0));
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->quarter_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors);
_render_sky(draw_list, p_time, sky->quarter_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, p_luminance_multiplier);
_render_sky(draw_list, p_time, sky->quarter_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, p_transform.origin, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
@ -1678,7 +1681,7 @@ void SkyRD::update_res_buffers(RID p_env, uint32_t p_view_count, const Projectio
clear_colors.push_back(Color(0.0, 0.0, 0.0));
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->half_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors);
_render_sky(draw_list, p_time, sky->half_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, p_luminance_multiplier);
_render_sky(draw_list, p_time, sky->half_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, p_transform.origin, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
}
@ -1728,7 +1731,6 @@ void SkyRD::draw(RD::DrawListID p_draw_list, RID p_env, RID p_fb, uint32_t p_vie
Basis sky_transform = RendererSceneRenderRD::get_singleton()->environment_get_sky_orientation(p_env);
sky_transform.invert();
float multiplier = RendererSceneRenderRD::get_singleton()->environment_get_bg_energy(p_env);
float custom_fov = RendererSceneRenderRD::get_singleton()->environment_get_sky_custom_fov(p_env);
// Camera
@ -1759,7 +1761,7 @@ void SkyRD::draw(RD::DrawListID p_draw_list, RID p_env, RID p_fb, uint32_t p_vie
texture_uniform_set = sky_scene_state.fog_only_texture_uniform_set;
}
_render_sky(p_draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, p_luminance_multiplier);
_render_sky(p_draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, p_transform.origin, p_luminance_multiplier);
}
void SkyRD::invalidate_sky(Sky *p_sky) {
@ -1881,6 +1883,13 @@ RID SkyRD::sky_get_material(RID p_sky) const {
return sky->material;
}
float SkyRD::sky_get_baked_exposure(RID p_sky) const {
Sky *sky = get_sky(p_sky);
ERR_FAIL_COND_V(!sky, 1.0);
return sky->baked_exposure;
}
RID SkyRD::allocate_sky_rid() {
return sky_owner.allocate_rid();
}

View file

@ -100,10 +100,9 @@ private:
float orientation[12]; // 48 - 48
float projections[RendererSceneRender::MAX_RENDER_VIEWS][4]; // 2 x 16 - 80
float position[3]; // 12 - 92
float multiplier; // 4 - 96
float time; // 4 - 100
float luminance_multiplier; // 4 - 104
float pad[2]; // 8 - 112 // Using pad to align on 16 bytes
float time; // 4 - 96
float pad[3]; // 12 - 108
float luminance_multiplier; // 4 - 112
// 128 is the max size of a push constant. We can replace "pad" but we can't add any more.
};
@ -143,7 +142,7 @@ private:
virtual ~SkyShaderData();
};
void _render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const Projection *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position, float p_luminance_multiplier);
void _render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const Projection *p_projections, const Basis &p_orientation, const Vector3 &p_position, float p_luminance_multiplier);
public:
struct SkySceneState {
@ -264,6 +263,7 @@ public:
bool dirty = false;
int processing_layer = 0;
Sky *dirty_list = nullptr;
float baked_exposure = 1.0;
//State to track when radiance cubemap needs updating
SkyMaterialData *prev_material = nullptr;
@ -296,9 +296,9 @@ public:
void set_texture_format(RD::DataFormat p_texture_format);
~SkyRD();
void setup(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, RendererSceneRenderRD *p_scene_render);
void setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render);
void update(RID p_env, const Projection &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0);
void draw(RID p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time); // only called by clustered renderer
void draw(RID p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0); // only called by clustered renderer
void update_res_buffers(RID p_env, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0);
void draw(RD::DrawListID p_draw_list, RID p_env, RID p_fb, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0);
@ -306,6 +306,8 @@ public:
void update_dirty_skys();
RID sky_get_material(RID p_sky) const;
RID sky_get_radiance_texture_rd(RID p_sky) const;
float sky_get_baked_exposure(RID p_sky) const;
RID allocate_sky_rid();
void initialize_sky_rid(RID p_rid);
@ -315,8 +317,6 @@ public:
void sky_set_mode(RID p_sky, RS::SkyMode p_mode);
void sky_set_material(RID p_sky, RID p_material);
Ref<Image> sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size);
RID sky_get_radiance_texture_rd(RID p_sky) const;
};
} // namespace RendererRD

View file

@ -906,8 +906,9 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
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);
@ -916,9 +917,9 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
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 {
@ -987,6 +988,25 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
scene_state.ubo.ss_effects_flags = 0;
}
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) / _render_buffers_get_luminance_multiplier();
scene_state.ubo.IBL_exposure_normalization = current_exposure / MAX(0.001, sky.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;
}
scene_state.ubo.roughness_limiter_enabled = p_opaque_render_buffers && screen_space_roughness_limiter_is_active();
scene_state.ubo.roughness_limiter_amount = screen_space_roughness_limiter_get_amount();
scene_state.ubo.roughness_limiter_limit = screen_space_roughness_limiter_get_limit();
@ -1383,7 +1403,7 @@ void RenderForwardClustered::_setup_voxelgis(const PagedArray<RID> &p_voxelgis)
}
}
void RenderForwardClustered::_setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform3D &p_cam_transform) {
void RenderForwardClustered::_setup_lightmaps(const RenderDataRD *p_render_data, const PagedArray<RID> &p_lightmaps, const Transform3D &p_cam_transform) {
scene_state.lightmaps_used = 0;
for (int i = 0; i < (int)p_lightmaps.size(); i++) {
if (i >= (int)scene_state.max_lightmaps) {
@ -1395,6 +1415,13 @@ void RenderForwardClustered::_setup_lightmaps(const PagedArray<RID> &p_lightmaps
Basis to_lm = lightmap_instance_get_transform(p_lightmaps[i]).basis.inverse() * p_cam_transform.basis;
to_lm = to_lm.inverse().transposed(); //will transform normals
RendererRD::MaterialStorage::store_transform_3x3(to_lm, scene_state.lightmaps[i].normal_xform);
scene_state.lightmaps[i].exposure_normalization = 1.0;
if (p_render_data->camera_attributes.is_valid()) {
float baked_exposure = RendererRD::LightStorage::get_singleton()->lightmap_get_baked_exposure_normalization(lightmap);
float enf = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
scene_state.lightmaps[i].exposure_normalization = enf / baked_exposure;
}
scene_state.lightmap_ids[i] = p_lightmaps[i];
scene_state.lightmap_has_sh[i] = RendererRD::LightStorage::get_singleton()->lightmap_uses_spherical_harmonics(lightmap);
@ -1513,9 +1540,11 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
scene_state.ubo.viewport_size[0] = screen_size.x;
scene_state.ubo.viewport_size[1] = screen_size.y;
scene_state.ubo.emissive_exposure_normalization = -1.0;
RD::get_singleton()->draw_command_begin_label("Render Setup");
_setup_lightmaps(*p_render_data->lightmaps, p_render_data->cam_transform);
_setup_lightmaps(p_render_data, *p_render_data->lightmaps, p_render_data->cam_transform);
_setup_voxelgis(*p_render_data->voxel_gi_instances);
_setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false);
@ -1539,6 +1568,8 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
RID radiance_texture;
bool draw_sky = false;
bool draw_sky_fog_only = false;
// We invert luminance_multiplier for sky so that we can combine it with exposure value.
float sky_energy_multiplier = 1.0 / _render_buffers_get_luminance_multiplier();
Color clear_color;
bool keep_color = false;
@ -1547,13 +1578,19 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
clear_color = Color(0, 0, 0, 1); //in overdraw mode, BG should always be black
} else if (is_environment(p_render_data->environment)) {
RS::EnvironmentBG bg_mode = environment_get_background(p_render_data->environment);
float bg_energy = environment_get_bg_energy(p_render_data->environment);
float bg_energy_multiplier = environment_get_bg_energy_multiplier(p_render_data->environment);
bg_energy_multiplier *= environment_get_bg_intensity(p_render_data->environment);
if (p_render_data->camera_attributes.is_valid()) {
bg_energy_multiplier *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
}
switch (bg_mode) {
case RS::ENV_BG_CLEAR_COLOR: {
clear_color = p_default_bg_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 ((p_render_data->render_buffers.is_valid() && render_buffers_has_volumetric_fog(p_render_data->render_buffers)) || environment_get_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear()));
@ -1561,9 +1598,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
} break;
case RS::ENV_BG_COLOR: {
clear_color = environment_get_bg_color(p_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 ((p_render_data->render_buffers.is_valid() && render_buffers_has_volumetric_fog(p_render_data->render_buffers)) || environment_get_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear()));
@ -1594,11 +1631,13 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
projection = correction * p_render_data->cam_projection;
}
sky.setup(p_render_data->environment, p_render_data->render_buffers, *p_render_data->lights, projection, p_render_data->cam_transform, screen_size, this);
sky.setup(p_render_data->environment, p_render_data->render_buffers, *p_render_data->lights, p_render_data->camera_attributes, projection, p_render_data->cam_transform, screen_size, this);
sky_energy_multiplier *= bg_energy_multiplier;
RID sky_rid = environment_get_sky(p_render_data->environment);
if (sky_rid.is_valid()) {
sky.update(p_render_data->environment, projection, p_render_data->cam_transform, time);
sky.update(p_render_data->environment, projection, p_render_data->cam_transform, time, sky_energy_multiplier);
radiance_texture = sky.sky_get_radiance_texture_rd(sky_rid);
} else {
// do not try to draw sky if invalid
@ -1753,9 +1792,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
Projection correction;
correction.set_depth_correction(true);
Projection projection = correction * p_render_data->cam_projection;
sky.draw(p_render_data->environment, can_continue_color, can_continue_depth, color_only_framebuffer, 1, &projection, p_render_data->cam_transform, time);
sky.draw(p_render_data->environment, can_continue_color, can_continue_depth, color_only_framebuffer, 1, &projection, p_render_data->cam_transform, time, sky_energy_multiplier);
} else {
sky.draw(p_render_data->environment, can_continue_color, can_continue_depth, color_only_framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time);
sky.draw(p_render_data->environment, can_continue_color, can_continue_depth, color_only_framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time, sky_energy_multiplier);
}
RD::get_singleton()->draw_command_end_label();
}
@ -2000,7 +2039,7 @@ void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, con
RD::get_singleton()->draw_command_end_label();
}
void RenderForwardClustered::_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) {
void RenderForwardClustered::_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, float p_exposure_normalization) {
RENDER_TIMESTAMP("Setup Rendering 3D Material");
RD::get_singleton()->draw_command_begin_label("Render 3D Material");
@ -2018,6 +2057,7 @@ void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform
scene_state.ubo.dual_paraboloid_side = 0;
scene_state.ubo.material_uv2_mode = false;
scene_state.ubo.opaque_prepass_threshold = 0.0f;
scene_state.ubo.emissive_exposure_normalization = p_exposure_normalization;
_setup_environment(&render_data, true, Vector2(1, 1), false, Color());
@ -2064,6 +2104,7 @@ void RenderForwardClustered::_render_uv2(const PagedArray<RenderGeometryInstance
scene_state.ubo.dual_paraboloid_side = 0;
scene_state.ubo.material_uv2_mode = true;
scene_state.ubo.opaque_prepass_threshold = 0.0;
scene_state.ubo.emissive_exposure_normalization = -1.0;
_setup_environment(&render_data, true, Vector2(1, 1), false, Color());
@ -2119,7 +2160,7 @@ void RenderForwardClustered::_render_uv2(const PagedArray<RenderGeometryInstance
RD::get_singleton()->draw_command_end_label();
}
void RenderForwardClustered::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) {
void RenderForwardClustered::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) {
RENDER_TIMESTAMP("Render SDFGI");
RD::get_singleton()->draw_command_begin_label("Render SDFGI Voxel");
@ -2187,6 +2228,7 @@ void RenderForwardClustered::_render_sdfgi(RID p_render_buffers, const Vector3i
RendererRD::MaterialStorage::store_transform(to_bounds.affine_inverse() * render_data.cam_transform, scene_state.ubo.sdf_to_bounds);
scene_state.ubo.emissive_exposure_normalization = p_exposure_normalization;
_setup_environment(&render_data, true, Vector2(1, 1), false, Color());
RID rp_uniform_set = _setup_sdfgi_render_pass_uniform_set(p_albedo_texture, p_emission_texture, p_emission_aniso_texture, p_geom_facing_texture);

View file

@ -218,6 +218,8 @@ class RenderForwardClustered : public RendererSceneRenderRD {
struct LightmapData {
float normal_xform[12];
float pad[3];
float exposure_normalization;
};
struct LightmapCaptureData {
@ -324,7 +326,8 @@ class RenderForwardClustered : public RendererSceneRenderRD {
uint32_t pancake_shadows;
float taa_jitter[2];
uint32_t pad[2];
float emissive_exposure_normalization; // Needed to normalize emissive when using physical units.
float IBL_exposure_normalization;
};
struct PushConstant {
@ -397,7 +400,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
void _setup_environment(const RenderDataRD *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false, int p_index = 0);
void _setup_voxelgis(const PagedArray<RID> &p_voxelgis);
void _setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform3D &p_cam_transform);
void _setup_lightmaps(const RenderDataRD *p_render_data, const PagedArray<RID> &p_lightmaps, const Transform3D &p_cam_transform);
struct RenderElementInfo {
enum { MAX_REPEATS = (1 << 20) - 1 };
@ -618,9 +621,9 @@ protected:
virtual void _render_shadow_process() override;
virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL) override;
virtual 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;
virtual 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, float p_exposure_normalization) override;
virtual void _render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) override;
virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) override;
virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) override;
public:

View file

@ -469,7 +469,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
return render_pass_uniform_sets[p_index];
}
void RenderForwardMobile::_setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform3D &p_cam_transform) {
void RenderForwardMobile::_setup_lightmaps(const RenderDataRD *p_render_data, const PagedArray<RID> &p_lightmaps, const Transform3D &p_cam_transform) {
// This probably needs to change...
scene_state.lightmaps_used = 0;
for (int i = 0; i < (int)p_lightmaps.size(); i++) {
@ -482,6 +482,13 @@ void RenderForwardMobile::_setup_lightmaps(const PagedArray<RID> &p_lightmaps, c
Basis to_lm = lightmap_instance_get_transform(p_lightmaps[i]).basis.inverse() * p_cam_transform.basis;
to_lm = to_lm.inverse().transposed(); //will transform normals
RendererRD::MaterialStorage::store_transform_3x3(to_lm, scene_state.lightmaps[i].normal_xform);
scene_state.lightmaps[i].exposure_normalization = 1.0;
if (p_render_data->camera_attributes.is_valid()) {
float baked_exposure = RendererRD::LightStorage::get_singleton()->lightmap_get_baked_exposure_normalization(lightmap);
float enf = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
scene_state.lightmaps[i].exposure_normalization = enf / baked_exposure;
}
scene_state.lightmap_ids[i] = p_lightmaps[i];
scene_state.lightmap_has_sh[i] = RendererRD::LightStorage::get_singleton()->lightmap_uses_spherical_harmonics(lightmap);
@ -539,7 +546,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
if (render_buffer->color_fbs[FB_CONFIG_FOUR_SUBPASSES].is_null()) {
// can't do blit subpass
using_subpass_post_process = false;
} else if (p_render_data->environment.is_valid() && (environment_get_glow_enabled(p_render_data->environment) || environment_get_auto_exposure(p_render_data->environment) || camera_effects_uses_dof(p_render_data->camera_effects))) {
} else if (p_render_data->environment.is_valid() && (environment_get_glow_enabled(p_render_data->environment) || RSG::camera_attributes->camera_attributes_uses_auto_exposure(p_render_data->camera_attributes) || RSG::camera_attributes->camera_attributes_uses_dof(p_render_data->camera_attributes))) {
// can't do blit subpass
using_subpass_post_process = false;
}
@ -580,10 +587,11 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
scene_state.ubo.viewport_size[0] = screen_size.x;
scene_state.ubo.viewport_size[1] = screen_size.y;
scene_state.ubo.emissive_exposure_normalization = -1.0;
RD::get_singleton()->draw_command_begin_label("Render Setup");
_setup_lightmaps(*p_render_data->lightmaps, p_render_data->cam_transform);
_setup_lightmaps(p_render_data, *p_render_data->lightmaps, p_render_data->cam_transform);
_setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false);
_update_render_base_uniform_set(); //may have changed due to the above (light buffer enlarged, as an example)
@ -594,6 +602,8 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
RID radiance_texture;
bool draw_sky = false;
bool draw_sky_fog_only = false;
// We invert luminance_multiplier for sky so that we can combine it with exposure value.
float sky_energy_multiplier = 1.0 / _render_buffers_get_luminance_multiplier();
Color clear_color = p_default_bg_color;
bool keep_color = false;
@ -602,13 +612,19 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
clear_color = Color(0, 0, 0, 1); //in overdraw mode, BG should always be black
} else if (is_environment(p_render_data->environment)) {
RS::EnvironmentBG bg_mode = environment_get_background(p_render_data->environment);
float bg_energy = environment_get_bg_energy(p_render_data->environment);
float bg_energy_multiplier = environment_get_bg_energy_multiplier(p_render_data->environment);
bg_energy_multiplier *= environment_get_bg_intensity(p_render_data->environment);
if (p_render_data->camera_attributes.is_valid()) {
bg_energy_multiplier *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
}
switch (bg_mode) {
case RS::ENV_BG_CLEAR_COLOR: {
clear_color = p_default_bg_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 (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_get_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
@ -618,9 +634,9 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
} break;
case RS::ENV_BG_COLOR: {
clear_color = environment_get_bg_color(p_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 (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_get_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
@ -653,11 +669,13 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
projection = correction * p_render_data->cam_projection;
}
sky.setup(p_render_data->environment, p_render_data->render_buffers, *p_render_data->lights, projection, p_render_data->cam_transform, screen_size, this);
sky.setup(p_render_data->environment, p_render_data->render_buffers, *p_render_data->lights, p_render_data->camera_attributes, projection, p_render_data->cam_transform, screen_size, this);
sky_energy_multiplier *= bg_energy_multiplier;
RID sky_rid = environment_get_sky(p_render_data->environment);
if (sky_rid.is_valid()) {
sky.update(p_render_data->environment, projection, p_render_data->cam_transform, time, _render_buffers_get_luminance_multiplier());
sky.update(p_render_data->environment, projection, p_render_data->cam_transform, time, sky_energy_multiplier);
radiance_texture = sky.sky_get_radiance_texture_rd(sky_rid);
} else {
// do not try to draw sky if invalid
@ -681,9 +699,9 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
Projection correction;
correction.set_depth_correction(true);
Projection projection = correction * p_render_data->cam_projection;
sky.update_res_buffers(p_render_data->environment, 1, &projection, p_render_data->cam_transform, time);
sky.update_res_buffers(p_render_data->environment, 1, &projection, p_render_data->cam_transform, time, sky_energy_multiplier);
} else {
sky.update_res_buffers(p_render_data->environment, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time);
sky.update_res_buffers(p_render_data->environment, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time, sky_energy_multiplier);
}
RD::get_singleton()->draw_command_end_label(); // Setup Sky resolution buffers
@ -780,9 +798,9 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
Projection correction;
correction.set_depth_correction(true);
Projection projection = correction * p_render_data->cam_projection;
sky.draw(draw_list, p_render_data->environment, framebuffer, 1, &projection, p_render_data->cam_transform, time, _render_buffers_get_luminance_multiplier());
sky.draw(draw_list, p_render_data->environment, framebuffer, 1, &projection, p_render_data->cam_transform, time, sky_energy_multiplier);
} else {
sky.draw(draw_list, p_render_data->environment, framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time, _render_buffers_get_luminance_multiplier());
sky.draw(draw_list, p_render_data->environment, framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time, sky_energy_multiplier);
}
RD::get_singleton()->draw_command_end_label(); // Draw Sky Subpass
@ -999,7 +1017,7 @@ void RenderForwardMobile::_render_shadow_end(uint32_t p_barrier) {
/* */
void RenderForwardMobile::_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) {
void RenderForwardMobile::_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, float p_exposure_normalization) {
RENDER_TIMESTAMP("Setup Rendering 3D Material");
RD::get_singleton()->draw_command_begin_label("Render 3D Material");
@ -1009,6 +1027,7 @@ void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, c
scene_state.ubo.dual_paraboloid_side = 0;
scene_state.ubo.material_uv2_mode = false;
scene_state.ubo.opaque_prepass_threshold = 0.0f;
scene_state.ubo.emissive_exposure_normalization = p_exposure_normalization;
RenderDataRD render_data;
render_data.cam_projection = p_cam_projection;
@ -1054,6 +1073,7 @@ void RenderForwardMobile::_render_uv2(const PagedArray<RenderGeometryInstance *>
scene_state.ubo.dual_paraboloid_side = 0;
scene_state.ubo.material_uv2_mode = true;
scene_state.ubo.emissive_exposure_normalization = -1.0;
RenderDataRD render_data;
render_data.instances = &p_instances;
@ -1112,7 +1132,7 @@ void RenderForwardMobile::_render_uv2(const PagedArray<RenderGeometryInstance *>
RD::get_singleton()->draw_command_end_label();
}
void RenderForwardMobile::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) {
void RenderForwardMobile::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) {
// we don't do GI in low end..
}
@ -1650,8 +1670,9 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data,
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);
@ -1660,9 +1681,9 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data,
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 {
@ -1726,6 +1747,25 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data,
scene_state.ubo.ssao_enabled = false;
}
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) / _render_buffers_get_luminance_multiplier();
scene_state.ubo.IBL_exposure_normalization = current_exposure / MAX(0.001, sky.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;
}
scene_state.ubo.roughness_limiter_enabled = p_opaque_render_buffers && screen_space_roughness_limiter_is_active();
scene_state.ubo.roughness_limiter_amount = screen_space_roughness_limiter_get_amount();
scene_state.ubo.roughness_limiter_limit = screen_space_roughness_limiter_get_limit();

View file

@ -216,9 +216,9 @@ protected:
virtual void _render_shadow_process() override;
virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL) override;
virtual 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;
virtual 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, float p_exposure_normalization) override;
virtual void _render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) override;
virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) override;
virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) override;
uint64_t lightmap_texture_array_version = 0xFFFFFFFF;
@ -235,7 +235,7 @@ protected:
static RenderForwardMobile *singleton;
void _setup_environment(const RenderDataRD *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false, int p_index = 0);
void _setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform3D &p_cam_transform);
void _setup_lightmaps(const RenderDataRD *p_render_data, const PagedArray<RID> &p_lightmaps, const Transform3D &p_cam_transform);
RID render_base_uniform_set;
LocalVector<RID> render_pass_uniform_sets;
@ -244,6 +244,8 @@ protected:
struct LightmapData {
float normal_xform[12];
float pad[3];
float exposure_normalization;
};
struct LightmapCaptureData {
@ -315,8 +317,8 @@ protected:
float reflection_multiplier;
uint32_t pancake_shadows;
uint32_t pad1;
uint32_t pad2;
float emissive_exposure_normalization; // Needed to normalize emissive when using physical units.
float IBL_exposure_normalization; // Adjusts for baked exposure.
uint32_t pad3;
};

View file

@ -37,6 +37,7 @@
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/rendering_server_default.h"
#include "servers/rendering/storage/camera_attributes_storage.h"
void get_vogel_disk(float *r_kernel, int p_sample_count) {
const float golden_angle = 2.4;
@ -246,7 +247,7 @@ Ref<Image> RendererSceneRenderRD::environment_bake_panorama(RID p_env, bool p_ba
}
if (use_cube_map) {
Ref<Image> panorama = sky_bake_panorama(environment_get_sky(p_env), environment_get_bg_energy(p_env), p_bake_irradiance, p_size);
Ref<Image> panorama = sky_bake_panorama(environment_get_sky(p_env), environment_get_bg_energy_multiplier(p_env), p_bake_irradiance, p_size);
if (use_ambient_light) {
for (int x = 0; x < p_size.width; x++) {
for (int y = 0; y < p_size.height; y++) {
@ -256,12 +257,12 @@ Ref<Image> RendererSceneRenderRD::environment_bake_panorama(RID p_env, bool p_ba
}
return panorama;
} else {
const float bg_energy = environment_get_bg_energy(p_env);
const float bg_energy_multiplier = environment_get_bg_energy_multiplier(p_env);
Color panorama_color = ((environment_background == RS::ENV_BG_CLEAR_COLOR) ? RSG::texture_storage->get_default_clear_color() : environment_get_bg_color(p_env));
panorama_color = panorama_color.srgb_to_linear();
panorama_color.r *= bg_energy;
panorama_color.g *= bg_energy;
panorama_color.b *= bg_energy;
panorama_color.r *= bg_energy_multiplier;
panorama_color.g *= bg_energy_multiplier;
panorama_color.b *= bg_energy_multiplier;
if (use_ambient_light) {
panorama_color = ambient_color.lerp(panorama_color, ambient_color_sky_mix);
@ -1083,45 +1084,6 @@ int RendererSceneRenderRD::get_directional_light_shadow_size(RID p_light_intance
//////////////////////////////////////////////////
RID RendererSceneRenderRD::camera_effects_allocate() {
return camera_effects_owner.allocate_rid();
}
void RendererSceneRenderRD::camera_effects_initialize(RID p_rid) {
camera_effects_owner.initialize_rid(p_rid, CameraEffects());
}
void RendererSceneRenderRD::camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) {
dof_blur_quality = p_quality;
dof_blur_use_jitter = p_use_jitter;
}
void RendererSceneRenderRD::camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape) {
dof_blur_bokeh_shape = p_shape;
}
void RendererSceneRenderRD::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) {
CameraEffects *camfx = camera_effects_owner.get_or_null(p_camera_effects);
ERR_FAIL_COND(!camfx);
camfx->dof_blur_far_enabled = p_far_enable;
camfx->dof_blur_far_distance = p_far_distance;
camfx->dof_blur_far_transition = p_far_transition;
camfx->dof_blur_near_enabled = p_near_enable;
camfx->dof_blur_near_distance = p_near_distance;
camfx->dof_blur_near_transition = p_near_transition;
camfx->dof_blur_amount = p_amount;
}
void RendererSceneRenderRD::camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) {
CameraEffects *camfx = camera_effects_owner.get_or_null(p_camera_effects);
ERR_FAIL_COND(!camfx);
camfx->override_exposure_enabled = p_enable;
camfx->override_exposure = p_exposure;
}
RID RendererSceneRenderRD::light_instance_create(RID p_light) {
RID li = light_instance_owner.make_rid(LightInstance());
@ -1860,13 +1822,11 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers);
ERR_FAIL_COND(!rb);
// Glow and override exposure (if enabled).
CameraEffects *camfx = camera_effects_owner.get_or_null(p_render_data->camera_effects);
// Glow, auto exposure and DoF (if enabled).
bool can_use_effects = rb->width >= 8 && rb->height >= 8;
bool can_use_storage = _render_buffers_can_be_storage();
if (can_use_effects && camfx && (camfx->dof_blur_near_enabled || camfx->dof_blur_far_enabled) && camfx->dof_blur_amount > 0.0) {
if (can_use_effects && RSG::camera_attributes->camera_attributes_uses_dof(p_render_data->camera_attributes)) {
RENDER_TIMESTAMP("Depth of Field");
RD::get_singleton()->draw_command_begin_label("DOF");
if (rb->blur[0].texture.is_null()) {
@ -1881,7 +1841,6 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
buffers.half_texture[0] = rb->blur[1].layers[0].mipmaps[0].texture;
buffers.half_texture[1] = rb->blur[0].layers[0].mipmaps[1].texture;
float bokeh_size = camfx->dof_blur_amount * 64.0;
if (can_use_storage) {
for (uint32_t i = 0; i < rb->view_count; i++) {
buffers.base_texture = rb->views[i].view_texture;
@ -1890,7 +1849,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
// In stereo p_render_data->z_near and p_render_data->z_far can be offset for our combined frustrum
float z_near = p_render_data->view_projection[i].get_z_near();
float z_far = p_render_data->view_projection[i].get_z_far();
bokeh_dof->bokeh_dof_compute(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, dof_blur_use_jitter, z_near, z_far, p_render_data->cam_orthogonal);
bokeh_dof->bokeh_dof_compute(buffers, p_render_data->camera_attributes, z_near, z_far, p_render_data->cam_orthogonal);
};
} else {
// Set framebuffers.
@ -1913,27 +1872,32 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
// In stereo p_render_data->z_near and p_render_data->z_far can be offset for our combined frustrum
float z_near = p_render_data->view_projection[i].get_z_near();
float z_far = p_render_data->view_projection[i].get_z_far();
bokeh_dof->bokeh_dof_raster(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, z_near, z_far, p_render_data->cam_orthogonal);
bokeh_dof->bokeh_dof_raster(buffers, p_render_data->camera_attributes, z_near, z_far, p_render_data->cam_orthogonal);
}
}
RD::get_singleton()->draw_command_end_label();
}
if (can_use_effects && p_render_data->environment.is_valid() && environment_get_auto_exposure(p_render_data->environment)) {
float auto_exposure_scale = 1.0;
if (can_use_effects && RSG::camera_attributes->camera_attributes_uses_auto_exposure(p_render_data->camera_attributes)) {
RENDER_TIMESTAMP("Auto exposure");
RD::get_singleton()->draw_command_begin_label("Auto exposure");
if (rb->luminance.current.is_null()) {
_allocate_luminance_textures(rb);
}
uint64_t auto_exposure_version = RSG::camera_attributes->camera_attributes_get_auto_exposure_version(p_render_data->camera_attributes);
bool set_immediate = auto_exposure_version != rb->auto_exposure_version;
rb->auto_exposure_version = auto_exposure_version;
bool set_immediate = environment_get_auto_exposure_version(p_render_data->environment) != rb->auto_exposure_version;
rb->auto_exposure_version = environment_get_auto_exposure_version(p_render_data->environment);
double step = environment_get_auto_exp_speed(p_render_data->environment) * time_step;
double step = RSG::camera_attributes->camera_attributes_get_auto_exposure_adjust_speed(p_render_data->camera_attributes) * time_step;
float auto_exposure_min_sensitivity = RSG::camera_attributes->camera_attributes_get_auto_exposure_min_sensitivity(p_render_data->camera_attributes);
float auto_exposure_max_sensitivity = RSG::camera_attributes->camera_attributes_get_auto_exposure_max_sensitivity(p_render_data->camera_attributes);
if (can_use_storage) {
RendererCompositorRD::singleton->get_effects()->luminance_reduction(rb->internal_texture, Size2i(rb->internal_width, rb->internal_height), rb->luminance.reduce, rb->luminance.current, environment_get_min_luminance(p_render_data->environment), environment_get_max_luminance(p_render_data->environment), step, set_immediate);
RendererCompositorRD::singleton->get_effects()->luminance_reduction(rb->internal_texture, Size2i(rb->internal_width, rb->internal_height), rb->luminance.reduce, rb->luminance.current, auto_exposure_min_sensitivity, auto_exposure_max_sensitivity, step, set_immediate);
} else {
RendererCompositorRD::singleton->get_effects()->luminance_reduction_raster(rb->internal_texture, Size2i(rb->internal_width, rb->internal_height), rb->luminance.reduce, rb->luminance.fb, rb->luminance.current, environment_get_min_luminance(p_render_data->environment), environment_get_max_luminance(p_render_data->environment), step, set_immediate);
RendererCompositorRD::singleton->get_effects()->luminance_reduction_raster(rb->internal_texture, Size2i(rb->internal_width, rb->internal_height), rb->luminance.reduce, rb->luminance.fb, rb->luminance.current, auto_exposure_min_sensitivity, auto_exposure_max_sensitivity, step, set_immediate);
}
// Swap final reduce with prev luminance.
SWAP(rb->luminance.current, rb->luminance.reduce.write[rb->luminance.reduce.size() - 1]);
@ -1941,6 +1905,8 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
SWAP(rb->luminance.current_fb, rb->luminance.fb.write[rb->luminance.fb.size() - 1]);
}
auto_exposure_scale = RSG::camera_attributes->camera_attributes_get_auto_exposure_scale(p_render_data->camera_attributes);
RenderingServerDefault::redraw_request(); // Redraw all the time if auto exposure rendering is on.
RD::get_singleton()->draw_command_end_label();
}
@ -1975,13 +1941,13 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
if (i == 0) {
RID luminance_texture;
if (environment_get_auto_exposure(p_render_data->environment) && rb->luminance.current.is_valid()) {
if (RSG::camera_attributes->camera_attributes_uses_auto_exposure(p_render_data->camera_attributes) && rb->luminance.current.is_valid()) {
luminance_texture = rb->luminance.current;
}
if (can_use_storage) {
copy_effects->gaussian_glow(rb->views[l].view_texture, rb->blur[1].layers[l].mipmaps[i].texture, Size2i(vp_w, vp_h), environment_get_glow_strength(p_render_data->environment), glow_high_quality, true, environment_get_glow_hdr_luminance_cap(p_render_data->environment), environment_get_exposure(p_render_data->environment), environment_get_glow_bloom(p_render_data->environment), environment_get_glow_hdr_bleed_threshold(p_render_data->environment), environment_get_glow_hdr_bleed_scale(p_render_data->environment), luminance_texture, environment_get_auto_exp_scale(p_render_data->environment));
copy_effects->gaussian_glow(rb->views[l].view_texture, rb->blur[1].layers[l].mipmaps[i].texture, Size2i(vp_w, vp_h), environment_get_glow_strength(p_render_data->environment), glow_high_quality, true, environment_get_glow_hdr_luminance_cap(p_render_data->environment), environment_get_exposure(p_render_data->environment), environment_get_glow_bloom(p_render_data->environment), environment_get_glow_hdr_bleed_threshold(p_render_data->environment), environment_get_glow_hdr_bleed_scale(p_render_data->environment), luminance_texture, auto_exposure_scale);
} else {
copy_effects->gaussian_glow_raster(rb->views[l].view_texture, luminance_multiplier, rb->blur[1].layers[l].mipmaps[i].half_fb, rb->blur[1].layers[l].mipmaps[i].half_texture, rb->blur[1].layers[l].mipmaps[i].fb, Size2i(vp_w, vp_h), environment_get_glow_strength(p_render_data->environment), glow_high_quality, true, environment_get_glow_hdr_luminance_cap(p_render_data->environment), environment_get_exposure(p_render_data->environment), environment_get_glow_bloom(p_render_data->environment), environment_get_glow_hdr_bleed_threshold(p_render_data->environment), environment_get_glow_hdr_bleed_scale(p_render_data->environment), luminance_texture, environment_get_auto_exp_scale(p_render_data->environment));
copy_effects->gaussian_glow_raster(rb->views[l].view_texture, luminance_multiplier, rb->blur[1].layers[l].mipmaps[i].half_fb, rb->blur[1].layers[l].mipmaps[i].half_texture, rb->blur[1].layers[l].mipmaps[i].fb, Size2i(vp_w, vp_h), environment_get_glow_strength(p_render_data->environment), glow_high_quality, true, environment_get_glow_hdr_luminance_cap(p_render_data->environment), environment_get_exposure(p_render_data->environment), environment_get_glow_bloom(p_render_data->environment), environment_get_glow_hdr_bleed_threshold(p_render_data->environment), environment_get_glow_hdr_bleed_scale(p_render_data->environment), luminance_texture, auto_exposure_scale);
}
} else {
if (can_use_storage) {
@ -2002,10 +1968,10 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
RendererRD::ToneMapper::TonemapSettings tonemap;
if (can_use_effects && p_render_data->environment.is_valid() && environment_get_auto_exposure(p_render_data->environment) && rb->luminance.current.is_valid()) {
if (can_use_effects && RSG::camera_attributes->camera_attributes_uses_auto_exposure(p_render_data->camera_attributes) && rb->luminance.current.is_valid()) {
tonemap.use_auto_exposure = true;
tonemap.exposure_texture = rb->luminance.current;
tonemap.auto_exposure_grey = environment_get_auto_exp_scale(p_render_data->environment);
tonemap.auto_exposure_scale = auto_exposure_scale;
} else {
tonemap.exposure_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE);
}
@ -2047,10 +2013,6 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
tonemap.exposure = environment_get_exposure(p_render_data->environment);
}
if (camfx && camfx->override_exposure_enabled) {
tonemap.exposure = camfx->override_exposure;
}
tonemap.use_color_correction = false;
tonemap.use_1d_color_correction = false;
tonemap.color_correction_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE);
@ -2093,9 +2055,6 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers);
ERR_FAIL_COND(!rb);
// Override exposure (if enabled).
CameraEffects *camfx = camera_effects_owner.get_or_null(p_render_data->camera_effects);
bool can_use_effects = rb->width >= 8 && rb->height >= 8;
RD::DrawListID draw_list = RD::get_singleton()->draw_list_switch_to_next_pass();
@ -2108,18 +2067,15 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr
tonemap.white = environment_get_white(p_render_data->environment);
}
if (camfx && camfx->override_exposure_enabled) {
tonemap.exposure = camfx->override_exposure;
}
// We don't support glow or auto exposure here, if they are needed, don't use subpasses!
// The problem is that we need to use the result so far and process them before we can
// apply this to our results.
if (can_use_effects && p_render_data->environment.is_valid() && environment_get_glow_enabled(p_render_data->environment)) {
ERR_FAIL_MSG("Glow is not supported when using subpasses.");
}
if (can_use_effects && p_render_data->environment.is_valid() && environment_get_auto_exposure(p_render_data->environment)) {
ERR_FAIL_MSG("Glow is not supported when using subpasses.");
if (can_use_effects && RSG::camera_attributes->camera_attributes_uses_auto_exposure(p_render_data->camera_attributes)) {
ERR_FAIL_MSG("Auto Exposure is not supported when using subpasses.");
}
tonemap.use_glow = false;
@ -2739,7 +2695,7 @@ RendererSceneRenderRD::RenderBufferData *RendererSceneRenderRD::render_buffers_g
return rb->data;
}
void RendererSceneRenderRD::_setup_reflections(const PagedArray<RID> &p_reflections, const Transform3D &p_camera_inverse_transform, RID p_environment) {
void RendererSceneRenderRD::_setup_reflections(RenderDataRD *p_render_data, const PagedArray<RID> &p_reflections, const Transform3D &p_camera_inverse_transform, RID p_environment) {
RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
cluster.reflection_count = 0;
@ -2796,6 +2752,12 @@ void RendererSceneRenderRD::_setup_reflections(const PagedArray<RID> &p_reflecti
reflection_ubo.exterior = !light_storage->reflection_probe_is_interior(base_probe);
reflection_ubo.box_project = light_storage->reflection_probe_is_box_projection(base_probe);
reflection_ubo.exposure_normalization = 1.0;
if (p_render_data->camera_attributes.is_valid()) {
float exposure = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
reflection_ubo.exposure_normalization = exposure / light_storage->reflection_probe_get_baked_exposure(base_probe);
}
Color ambient_linear = light_storage->reflection_probe_get_ambient_color(base_probe).srgb_to_linear();
float interior_ambient_energy = light_storage->reflection_probe_get_ambient_color_energy(base_probe);
@ -2819,7 +2781,7 @@ void RendererSceneRenderRD::_setup_reflections(const PagedArray<RID> &p_reflecti
}
}
void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const Transform3D &p_camera_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count, bool &r_directional_light_soft_shadows) {
void RendererSceneRenderRD::_setup_lights(RenderDataRD *p_render_data, const PagedArray<RID> &p_lights, const Transform3D &p_camera_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count, bool &r_directional_light_soft_shadows) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
@ -2863,7 +2825,17 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
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;
@ -3076,7 +3048,26 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
}
}
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;
@ -3645,12 +3636,12 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
}
} else {
//do not render reflections when rendering a reflection probe
_setup_reflections(*p_render_data->reflection_probes, p_render_data->cam_transform.affine_inverse(), p_render_data->environment);
_setup_reflections(p_render_data, *p_render_data->reflection_probes, p_render_data->cam_transform.affine_inverse(), p_render_data->environment);
}
uint32_t directional_light_count = 0;
uint32_t positional_light_count = 0;
_setup_lights(*p_render_data->lights, p_render_data->cam_transform, p_render_data->shadow_atlas, using_shadows, directional_light_count, positional_light_count, p_render_data->directional_light_soft_shadows);
_setup_lights(p_render_data, *p_render_data->lights, p_render_data->cam_transform, p_render_data->shadow_atlas, using_shadows, directional_light_count, positional_light_count, p_render_data->directional_light_soft_shadows);
_setup_decals(*p_render_data->decals, p_render_data->cam_transform.affine_inverse());
p_render_data->directional_light_count = directional_light_count;
@ -3673,7 +3664,7 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
}
}
void RendererSceneRenderRD::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 RendererSceneRenderRD::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) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
// getting this here now so we can direct call a bunch of things more easily
@ -3719,7 +3710,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData
render_data.lightmaps = &p_lightmaps;
render_data.fog_volumes = &p_fog_volumes;
render_data.environment = p_environment;
render_data.camera_effects = p_camera_effects;
render_data.camera_attributes = p_camera_attributes;
render_data.shadow_atlas = p_shadow_atlas;
render_data.reflection_atlas = p_reflection_atlas;
render_data.reflection_probe = p_reflection_probe;
@ -3753,11 +3744,15 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData
//sdfgi first
if (rb != nullptr && rb->sdfgi != nullptr) {
float exposure_normalization = 1.0;
if (p_camera_attributes.is_valid()) {
exposure_normalization = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_camera_attributes);
}
for (int i = 0; i < render_state.render_sdfgi_region_count; i++) {
rb->sdfgi->render_region(p_render_buffers, render_state.render_sdfgi_regions[i].region, render_state.render_sdfgi_regions[i].instances, this);
rb->sdfgi->render_region(p_render_buffers, render_state.render_sdfgi_regions[i].region, render_state.render_sdfgi_regions[i].instances, this, exposure_normalization);
}
if (render_state.sdfgi_update_data->update_static) {
rb->sdfgi->render_static_lights(p_render_buffers, render_state.sdfgi_update_data->static_cascade_count, p_sdfgi_update_data->static_cascade_indices, render_state.sdfgi_update_data->static_positional_lights, this);
rb->sdfgi->render_static_lights(&render_data, p_render_buffers, render_state.sdfgi_update_data->static_cascade_count, p_sdfgi_update_data->static_cascade_indices, render_state.sdfgi_update_data->static_positional_lights, this);
}
}
@ -3790,6 +3785,9 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData
} else {
current_cluster_builder = ra->cluster_builder;
}
if (p_camera_attributes.is_valid()) {
RendererRD::LightStorage::get_singleton()->reflection_probe_set_baked_exposure(rpi->probe, RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_camera_attributes));
}
} else {
ERR_PRINT("No render buffer nor reflection atlas, bug"); //should never happen, will crash
current_cluster_builder = nullptr;
@ -3804,7 +3802,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData
rb->sdfgi->update_light();
}
gi.setup_voxel_gi_instances(render_data.render_buffers, render_data.cam_transform, *render_data.voxel_gi_instances, render_state.voxel_gi_count, this);
gi.setup_voxel_gi_instances(&render_data, render_data.render_buffers, render_data.cam_transform, *render_data.voxel_gi_instances, render_state.voxel_gi_count, this);
}
render_state.depth_prepass_used = false;
@ -4041,7 +4039,7 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
}
void RendererSceneRenderRD::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) {
_render_material(p_cam_transform, p_cam_projection, p_cam_orthogonal, p_instances, p_framebuffer, p_region);
_render_material(p_cam_transform, p_cam_projection, p_cam_orthogonal, p_instances, p_framebuffer, p_region, 1.0);
}
void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<RenderGeometryInstance *> &p_instances) {
@ -4083,9 +4081,8 @@ bool RendererSceneRenderRD::free(RID p_rid) {
render_buffers_owner.free(p_rid);
} else if (is_environment(p_rid)) {
environment_free(p_rid);
} else if (camera_effects_owner.owns(p_rid)) {
//not much to delete, just free it
camera_effects_owner.free(p_rid);
} else if (RSG::camera_attributes->owns_camera_attributes(p_rid)) {
RSG::camera_attributes->camera_attributes_free(p_rid);
} else if (reflection_atlas_owner.owns(p_rid)) {
reflection_atlas_set_size(p_rid, 0, 0);
ReflectionAtlas *ra = reflection_atlas_owner.get_or_null(p_rid);
@ -4335,8 +4332,8 @@ RendererSceneRenderRD::RendererSceneRenderRD() {
void RendererSceneRenderRD::init() {
max_cluster_elements = get_max_elements();
directional_shadow.size = GLOBAL_GET("rendering/shadows/directional_shadow/size");
directional_shadow.use_16_bits = GLOBAL_GET("rendering/shadows/directional_shadow/16_bits");
directional_shadow.size = GLOBAL_GET("rendering/lights_and_shadows/directional_shadow/size");
directional_shadow.use_16_bits = GLOBAL_GET("rendering/lights_and_shadows/directional_shadow/16_bits");
/* SKY SHADER */
@ -4395,8 +4392,10 @@ void RendererSceneRenderRD::init() {
shadow_sampler = RD::get_singleton()->sampler_create(sampler);
}
camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape(int(GLOBAL_GET("rendering/camera/depth_of_field/depth_of_field_bokeh_shape"))));
camera_effects_set_dof_blur_quality(RS::DOFBlurQuality(int(GLOBAL_GET("rendering/camera/depth_of_field/depth_of_field_bokeh_quality"))), GLOBAL_GET("rendering/camera/depth_of_field/depth_of_field_use_jitter"));
RSG::camera_attributes->camera_attributes_set_dof_blur_bokeh_shape(RS::DOFBokehShape(int(GLOBAL_GET("rendering/camera/depth_of_field/depth_of_field_bokeh_shape"))));
RSG::camera_attributes->camera_attributes_set_dof_blur_quality(RS::DOFBlurQuality(int(GLOBAL_GET("rendering/camera/depth_of_field/depth_of_field_bokeh_quality"))), GLOBAL_GET("rendering/camera/depth_of_field/depth_of_field_use_jitter"));
use_physical_light_units = GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units");
environment_set_ssao_quality(RS::EnvironmentSSAOQuality(int(GLOBAL_GET("rendering/environment/ssao/quality"))), GLOBAL_GET("rendering/environment/ssao/half_size"), GLOBAL_GET("rendering/environment/ssao/adaptive_target"), GLOBAL_GET("rendering/environment/ssao/blur_passes"), GLOBAL_GET("rendering/environment/ssao/fadeout_from"), GLOBAL_GET("rendering/environment/ssao/fadeout_to"));
screen_space_roughness_limiter = GLOBAL_GET("rendering/anti_aliasing/screen_space_roughness_limiter/enabled");
screen_space_roughness_limiter_amount = GLOBAL_GET("rendering/anti_aliasing/screen_space_roughness_limiter/amount");
@ -4414,8 +4413,8 @@ void RendererSceneRenderRD::init() {
directional_soft_shadow_kernel = memnew_arr(float, 128);
penumbra_shadow_kernel = memnew_arr(float, 128);
soft_shadow_kernel = memnew_arr(float, 128);
positional_soft_shadow_filter_set_quality(RS::ShadowQuality(int(GLOBAL_GET("rendering/shadows/positional_shadow/soft_shadow_filter_quality"))));
directional_soft_shadow_filter_set_quality(RS::ShadowQuality(int(GLOBAL_GET("rendering/shadows/directional_shadow/soft_shadow_filter_quality"))));
positional_soft_shadow_filter_set_quality(RS::ShadowQuality(int(GLOBAL_GET("rendering/lights_and_shadows/positional_shadow/soft_shadow_filter_quality"))));
directional_soft_shadow_filter_set_quality(RS::ShadowQuality(int(GLOBAL_GET("rendering/lights_and_shadows/directional_shadow/soft_shadow_filter_quality"))));
environment_set_volumetric_fog_volume_size(GLOBAL_GET("rendering/environment/volumetric_fog/volume_size"), GLOBAL_GET("rendering/environment/volumetric_fog/volume_depth"));
environment_set_volumetric_fog_filter_active(GLOBAL_GET("rendering/environment/volumetric_fog/use_filter"));

View file

@ -76,7 +76,7 @@ struct RenderDataRD {
const PagedArray<RID> *lightmaps = nullptr;
const PagedArray<RID> *fog_volumes = nullptr;
RID environment;
RID camera_effects;
RID camera_attributes;
RID shadow_atlas;
RID reflection_atlas;
RID reflection_probe;
@ -114,9 +114,9 @@ protected:
};
virtual RenderBufferData *_create_render_buffer_data() = 0;
void _setup_lights(const PagedArray<RID> &p_lights, const Transform3D &p_camera_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count, bool &r_directional_light_soft_shadows);
void _setup_lights(RenderDataRD *p_render_data, const PagedArray<RID> &p_lights, const Transform3D &p_camera_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count, bool &r_directional_light_soft_shadows);
void _setup_decals(const PagedArray<RID> &p_decals, const Transform3D &p_camera_inverse_xform);
void _setup_reflections(const PagedArray<RID> &p_reflections, const Transform3D &p_camera_inverse_transform, RID p_environment);
void _setup_reflections(RenderDataRD *p_render_data, const PagedArray<RID> &p_reflections, const Transform3D &p_camera_inverse_transform, RID p_environment);
virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_color) = 0;
@ -125,9 +125,9 @@ protected:
virtual void _render_shadow_process() = 0;
virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL) = 0;
virtual 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) = 0;
virtual 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, float p_exposure_normalization) = 0;
virtual void _render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) = 0;
virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) = 0;
virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) = 0;
void _debug_sdfgi_probes(RID p_render_buffers, RID p_framebuffer, uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth);
@ -418,31 +418,11 @@ private:
bool glow_high_quality = false;
RS::EnvironmentSSRRoughnessQuality ssr_roughness_quality = RS::ENV_SSR_ROUGHNESS_QUALITY_LOW;
/* CAMERA EFFECTS */
struct CameraEffects {
bool dof_blur_far_enabled = false;
float dof_blur_far_distance = 10;
float dof_blur_far_transition = 5;
bool dof_blur_near_enabled = false;
float dof_blur_near_distance = 2;
float dof_blur_near_transition = 1;
float dof_blur_amount = 0.1;
bool override_exposure_enabled = false;
float override_exposure = 1;
};
RS::DOFBlurQuality dof_blur_quality = RS::DOF_BLUR_QUALITY_MEDIUM;
RS::DOFBokehShape dof_blur_bokeh_shape = RS::DOF_BOKEH_HEXAGON;
bool dof_blur_use_jitter = false;
RS::SubSurfaceScatteringQuality sss_quality = RS::SUB_SURFACE_SCATTERING_QUALITY_MEDIUM;
float sss_scale = 0.05;
float sss_depth_scale = 0.01;
mutable RID_Owner<CameraEffects, true> camera_effects_owner;
bool use_physical_light_units = false;
/* RENDER BUFFERS */
@ -592,7 +572,7 @@ private:
uint32_t exterior;
uint32_t box_project;
uint32_t ambient_mode;
uint32_t pad;
float exposure_normalization;
float local_matrix[16]; // up to here for spot and omni, rest is for directional
};
@ -831,21 +811,8 @@ public:
virtual Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) override;
/* CAMERA EFFECTS */
virtual RID camera_effects_allocate() override;
virtual void camera_effects_initialize(RID p_rid) override;
virtual void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) override;
virtual void camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape) override;
virtual 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;
virtual void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) override;
bool camera_effects_uses_dof(RID p_camera_effects) {
CameraEffects *camfx = camera_effects_owner.get_or_null(p_camera_effects);
return camfx && (camfx->dof_blur_near_enabled || camfx->dof_blur_far_enabled) && camfx->dof_blur_amount > 0.0;
_FORCE_INLINE_ bool is_using_physical_light_units() {
return use_physical_light_units;
}
/* LIGHT INSTANCE API */
@ -1139,7 +1106,7 @@ public:
virtual void update_uniform_sets(){};
virtual 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;
virtual 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;
virtual 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;

View file

@ -129,7 +129,7 @@ void main() {
#ifdef GLOW_USE_AUTO_EXPOSURE
frag_color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / blur.glow_auto_exposure_grey;
frag_color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / blur.glow_auto_exposure_scale;
#endif
frag_color *= blur.glow_exposure;

View file

@ -16,7 +16,7 @@ layout(push_constant, std430) uniform Blur {
float glow_exposure; // 04 - 36
float glow_white; // 04 - 40
float glow_luminance_cap; // 04 - 44
float glow_auto_exposure_grey; // 04 - 48
float glow_auto_exposure_scale; // 04 - 48
float luminance_multiplier; // 04 - 52
float res1; // 04 - 56

View file

@ -41,11 +41,25 @@ float get_depth_at_pos(vec2 uv) {
float get_blur_size(float depth) {
if (params.blur_near_active && depth < params.blur_near_begin) {
return -(1.0 - smoothstep(params.blur_near_end, params.blur_near_begin, depth)) * params.blur_size - DEPTH_GAP; //near blur is negative
if (params.use_physical_near) {
// Physically-based.
float d = abs(params.blur_near_begin - depth);
return -(d / (params.blur_near_begin - d)) * params.blur_size_near - DEPTH_GAP; // Near blur is negative.
} else {
// Non-physically-based.
return -(1.0 - smoothstep(params.blur_near_end, params.blur_near_begin, depth)) * params.blur_size - DEPTH_GAP; // Near blur is negative.
}
}
if (params.blur_far_active && depth > params.blur_far_begin) {
return smoothstep(params.blur_far_begin, params.blur_far_end, depth) * params.blur_size + DEPTH_GAP;
if (params.use_physical_far) {
// Physically-based.
float d = abs(params.blur_far_begin - depth);
return (d / (params.blur_far_begin + d)) * params.blur_size_far + DEPTH_GAP;
} else {
// Non-physically-based.
return smoothstep(params.blur_far_begin, params.blur_far_end, depth) * params.blur_size + DEPTH_GAP;
}
}
return 0.0;

View file

@ -20,6 +20,11 @@ layout(push_constant, std430) uniform Params {
bool use_jitter;
float jitter_seed;
bool use_physical_near;
bool use_physical_far;
float blur_size_near;
float blur_size_far;
uint pad[2];
}
params;

View file

@ -63,11 +63,25 @@ float get_depth_at_pos(vec2 uv) {
float get_blur_size(float depth) {
if (params.blur_near_active && depth < params.blur_near_begin) {
return -(1.0 - smoothstep(params.blur_near_end, params.blur_near_begin, depth)) * params.blur_size - DEPTH_GAP; //near blur is negative
if (params.use_physical_near) {
// Physically-based.
float d = abs(params.blur_near_begin - depth);
return -(d / (params.blur_near_begin - d)) * params.blur_size_near - DEPTH_GAP; // Near blur is negative.
} else {
// Non-physically-based.
return -(1.0 - smoothstep(params.blur_near_end, params.blur_near_begin, depth)) * params.blur_size - DEPTH_GAP; // Near blur is negative.
}
}
if (params.blur_far_active && depth > params.blur_far_begin) {
return smoothstep(params.blur_far_begin, params.blur_far_end, depth) * params.blur_size + DEPTH_GAP;
if (params.use_physical_far) {
// Physically-based.
float d = abs(params.blur_far_begin - depth);
return (d / (params.blur_far_begin + d)) * params.blur_size_far + DEPTH_GAP;
} else {
// Non-physically-based.
return smoothstep(params.blur_far_begin, params.blur_far_end, depth) * params.blur_size + DEPTH_GAP;
}
}
return 0.0;

View file

@ -31,7 +31,7 @@ layout(push_constant, std430) uniform Params {
float glow_exposure;
float glow_white;
float glow_luminance_cap;
float glow_auto_exposure_grey;
float glow_auto_exposure_scale;
// DOF.
float camera_z_far;
float camera_z_near;
@ -185,7 +185,7 @@ void main() {
if (bool(params.flags & FLAG_GLOW_FIRST_PASS)) {
#ifdef GLOW_USE_AUTO_EXPOSURE
color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / params.glow_auto_exposure_grey;
color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / params.glow_auto_exposure_scale;
#endif
color *= params.glow_exposure;

View file

@ -75,7 +75,7 @@ layout(push_constant, std430) uniform Params {
float exposure;
float white;
float auto_exposure_grey;
float auto_exposure_scale;
float luminance_multiplier;
vec2 pixel_size;
@ -440,7 +440,7 @@ void main() {
#ifndef SUBPASS
if (params.use_auto_exposure) {
exposure *= 1.0 / (texelFetch(source_auto_exposure, ivec2(0, 0), 0).r * params.luminance_multiplier / params.auto_exposure_grey);
exposure *= 1.0 / (texelFetch(source_auto_exposure, ivec2(0, 0), 0).r * params.luminance_multiplier / params.auto_exposure_scale);
}
#endif

View file

@ -32,6 +32,8 @@ struct ProbeCascadeData {
float to_probe;
ivec3 probe_world_offset;
float to_cell; // 1/bounds * grid_size
vec3 pad;
float exposure_normalization;
};
layout(rgba16f, set = 0, binding = 9) uniform restrict writeonly image2D ambient_buffer;
@ -83,6 +85,9 @@ struct VoxelGIData {
float normal_bias; // 4 - 88
bool blend_ambient; // 4 - 92
uint mipmaps; // 4 - 96
vec3 pad; // 12 - 108
float exposure_normalization; // 4 - 112
};
layout(set = 0, binding = 16, std140) uniform VoxelGIs {
@ -241,7 +246,7 @@ void sdfvoxel_gi_process(uint cascade, vec3 cascade_pos, vec3 cam_pos, vec3 cam_
pos_uvw.x += float(offset.z) * sdfgi.lightprobe_uv_offset.z;
diffuse = textureLod(sampler2DArray(lightprobe_texture, linear_sampler), pos_uvw, 0.0).rgb;
diffuse_accum += vec4(diffuse * weight, weight);
diffuse_accum += vec4(diffuse * weight * sdfgi.cascades[cascade].exposure_normalization, weight);
{
vec3 specular = vec3(0.0);
@ -255,7 +260,7 @@ void sdfvoxel_gi_process(uint cascade, vec3 cascade_pos, vec3 cam_pos, vec3 cam_
specular = mix(specular, textureLod(sampler2DArray(lightprobe_texture, linear_sampler), pos_uvw, 0.0).rgb, (roughness - 0.2) * 1.25);
}
specular_accum += specular * weight;
specular_accum += specular * weight * sdfgi.cascades[cascade].exposure_normalization;
}
}
@ -574,7 +579,7 @@ void voxel_gi_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3
}
}
light.rgb *= voxel_gi_instances.data[index].dynamic_range;
light.rgb *= voxel_gi_instances.data[index].dynamic_range * voxel_gi_instances.data[index].exposure_normalization;
if (!voxel_gi_instances.data[index].blend_ambient) {
light.a = 1.0;
}
@ -583,7 +588,7 @@ void voxel_gi_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3
//radiance
vec4 irr_light = voxel_cone_trace(voxel_gi_textures[index], cell_size, position, ref_vec, tan(roughness * 0.5 * M_PI * 0.99), max_distance, voxel_gi_instances.data[index].bias);
irr_light.rgb *= voxel_gi_instances.data[index].dynamic_range;
irr_light.rgb *= voxel_gi_instances.data[index].dynamic_range * voxel_gi_instances.data[index].exposure_normalization;
if (!voxel_gi_instances.data[index].blend_ambient) {
irr_light.a = 1.0;
}

View file

@ -21,6 +21,7 @@ struct CascadeData {
float to_cell; // 1/bounds * grid_size
ivec3 probe_world_offset;
uint pad;
vec4 pad2;
};
layout(set = 0, binding = 9, std140) uniform Cascades {

Some files were not shown because too many files have changed in this diff Show more