Add option to enable HDR rendering in 2D
This is needed to allow 2D to fully make use of 3D effects (e.g. glow), and can be used to substantially improve quality of 2D rendering at the cost of performance Additionally, the 2D rendering pipeline is done in linear space (we skip linear_to_srgb conversion in 3D tonemapping) so the entire Viewport can be kept linear. This is necessary for proper HDR screen support in the future.
This commit is contained in:
parent
237bd0a615
commit
57eb762bae
|
@ -2650,6 +2650,9 @@
|
|||
<member name="rendering/textures/webp_compression/lossless_compression_factor" type="float" setter="" getter="" default="25">
|
||||
The default compression factor for lossless WebP. Decompression speed is mostly unaffected by the compression factor. Supported values are 0 to 100.
|
||||
</member>
|
||||
<member name="rendering/viewport/hdr_2d" type="bool" setter="" getter="" default="false">
|
||||
If [code]true[/code], enables [member Viewport.use_hdr_2d] on the root viewport. This allows 2D rendering to take advantage of effects requiring high dynamic range (e.g. 2D glow).
|
||||
</member>
|
||||
<member name="rendering/viewport/transparent_background" type="bool" setter="" getter="" default="false">
|
||||
If [code]true[/code], enables [member Viewport.transparent_bg] on the root viewport. This allows per-pixel transparency to be effective after also enabling [member display/window/size/transparent] and [member display/window/per_pixel_transparency/allowed].
|
||||
</member>
|
||||
|
|
|
@ -3756,6 +3756,15 @@
|
|||
If [code]true[/code], enables debanding on the specified viewport. Equivalent to [member ProjectSettings.rendering/anti_aliasing/quality/use_debanding].
|
||||
</description>
|
||||
</method>
|
||||
<method name="viewport_set_use_hdr_2d">
|
||||
<return type="void" />
|
||||
<param index="0" name="viewport" type="RID" />
|
||||
<param index="1" name="enabled" type="bool" />
|
||||
<description>
|
||||
If [code]true[/code], 2D rendering will use a high dynamic range (HDR) format framebuffer matching the bit depth of the 3D framebuffer. When using the Forward+ renderer this will be a [code]RGBA16[/code] framebuffer, while when using the Mobile renderer it will be a [code]RGB10_A2[/code] framebuffer. Additionally, 2D rendering will take place in linear color space and will be converted to sRGB space immediately before blitting to the screen (if the Viewport is attached to the screen). Practically speaking, this means that the end result of the Viewport will not be clamped into the [code]0-1[/code] range and can be used in 3D rendering without color space adjustments. This allows 2D rendering to take advantage of effects requiring high dynamic range (e.g. 2D glow) as well as substantially improves the appearance of effects requiring highly detailed gradients. This setting has the same effect as [member Viewport.use_hdr_2d].
|
||||
[b]Note:[/b] This setting will have no effect when using the GL Compatibility renderer as the GL Compatibility renderer always renders in low dynamic range for performance reasons.
|
||||
</description>
|
||||
</method>
|
||||
<method name="viewport_set_use_occlusion_culling">
|
||||
<return type="void" />
|
||||
<param index="0" name="viewport" type="RID" />
|
||||
|
|
|
@ -348,6 +348,10 @@
|
|||
If [code]true[/code], uses a fast post-processing filter to make banding significantly less visible in 3D. 2D rendering is [i]not[/i] affected by debanding unless the [member Environment.background_mode] is [constant Environment.BG_CANVAS]. See also [member ProjectSettings.rendering/anti_aliasing/quality/use_debanding].
|
||||
In some cases, debanding may introduce a slightly noticeable dithering pattern. It's recommended to enable debanding only when actually needed since the dithering pattern will make lossless-compressed screenshots larger.
|
||||
</member>
|
||||
<member name="use_hdr_2d" type="bool" setter="set_use_hdr_2d" getter="is_using_hdr_2d" default="false">
|
||||
If [code]true[/code], 2D rendering will use an high dynamic range (HDR) format framebuffer matching the bit depth of the 3D framebuffer. When using the Forward+ renderer this will be a [code]RGBA16[/code] framebuffer, while when using the Mobile renderer it will be a [code]RGB10_A2[/code] framebuffer. Additionally, 2D rendering will take place in linear color space and will be converted to sRGB space immediately before blitting to the screen (if the Viewport is attached to the screen). Practically speaking, this means that the end result of the Viewport will not be clamped into the [code]0-1[/code] range and can be used in 3D rendering without color space adjustments. This allows 2D rendering to take advantage of effects requiring high dynamic range (e.g. 2D glow) as well as substantially improves the appearance of effects requiring highly detailed gradients.
|
||||
[b]Note:[/b] This setting will have no effect when using the GL Compatibility renderer as the GL Compatibility renderer always renders in low dynamic range for performance reasons.
|
||||
</member>
|
||||
<member name="use_occlusion_culling" type="bool" setter="set_use_occlusion_culling" getter="is_using_occlusion_culling" default="false">
|
||||
If [code]true[/code], [OccluderInstance3D] nodes will be usable for occlusion culling in 3D for this viewport. For the root viewport, [member ProjectSettings.rendering/occlusion_culling/use_occlusion_culling] must be set to [code]true[/code] instead.
|
||||
[b]Note:[/b] Enabling occlusion culling has a cost on the CPU. Only enable occlusion culling if you actually plan to use it, and think whether your scene can actually benefit from occlusion culling. Large, open scenes with few or no objects blocking the view will generally not benefit much from occlusion culling. Large open scenes generally benefit more from mesh LOD and visibility ranges ([member GeometryInstance3D.visibility_range_begin] and [member GeometryInstance3D.visibility_range_end]) compared to occlusion culling.
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
#define FLAGS_CLIP_RECT_UV uint(1 << 9)
|
||||
#define FLAGS_TRANSPOSE_RECT uint(1 << 10)
|
||||
#define FLAGS_USING_LIGHT_MASK uint(1 << 11)
|
||||
// (1 << 11) is for FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR in RD backends, unused here.
|
||||
#define FLAGS_NINEPACH_DRAW_CENTER uint(1 << 12)
|
||||
#define FLAGS_USING_PARTICLES uint(1 << 13)
|
||||
|
||||
|
|
|
@ -629,6 +629,8 @@ public:
|
|||
void render_target_clear_used(RID p_render_target);
|
||||
virtual void render_target_set_msaa(RID p_render_target, RS::ViewportMSAA p_msaa) override;
|
||||
virtual RS::ViewportMSAA render_target_get_msaa(RID p_render_target) const override;
|
||||
virtual void render_target_set_use_hdr(RID p_render_target, bool p_use_hdr_2d) override {}
|
||||
virtual bool render_target_is_using_hdr(RID p_render_target) const override { return false; }
|
||||
|
||||
// new
|
||||
void render_target_set_as_unused(RID p_render_target) override {
|
||||
|
|
|
@ -496,6 +496,9 @@ void EditorNode::_update_from_settings() {
|
|||
Viewport::MSAA msaa = Viewport::MSAA(int(GLOBAL_GET("rendering/anti_aliasing/quality/msaa_2d")));
|
||||
scene_root->set_msaa_2d(msaa);
|
||||
|
||||
bool use_hdr_2d = GLOBAL_GET("rendering/viewport/hdr_2d");
|
||||
scene_root->set_use_hdr_2d(use_hdr_2d);
|
||||
|
||||
float mesh_lod_threshold = GLOBAL_GET("rendering/mesh_lod/lod_change/threshold_pixels");
|
||||
scene_root->set_mesh_lod_threshold(mesh_lod_threshold);
|
||||
|
||||
|
|
|
@ -2658,6 +2658,9 @@ void Node3DEditorViewport::_project_settings_changed() {
|
|||
const bool transparent_background = GLOBAL_GET("rendering/viewport/transparent_background");
|
||||
viewport->set_transparent_background(transparent_background);
|
||||
|
||||
const bool use_hdr_2d = GLOBAL_GET("rendering/viewport/hdr_2d");
|
||||
viewport->set_use_hdr_2d(use_hdr_2d);
|
||||
|
||||
const bool use_debanding = GLOBAL_GET("rendering/anti_aliasing/quality/use_debanding");
|
||||
viewport->set_use_debanding(use_debanding);
|
||||
|
||||
|
|
|
@ -1733,6 +1733,9 @@ SceneTree::SceneTree() {
|
|||
const bool transparent_background = GLOBAL_DEF("rendering/viewport/transparent_background", false);
|
||||
root->set_transparent_background(transparent_background);
|
||||
|
||||
const bool use_hdr_2d = GLOBAL_DEF_RST_BASIC("rendering/viewport/hdr_2d", false);
|
||||
root->set_use_hdr_2d(use_hdr_2d);
|
||||
|
||||
const int ssaa_mode = GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "rendering/anti_aliasing/quality/screen_space_aa", PROPERTY_HINT_ENUM, "Disabled (Fastest),FXAA (Fast)"), 0);
|
||||
root->set_screen_space_aa(Viewport::ScreenSpaceAA(ssaa_mode));
|
||||
|
||||
|
|
|
@ -1177,6 +1177,17 @@ bool Viewport::has_transparent_background() const {
|
|||
return transparent_bg;
|
||||
}
|
||||
|
||||
void Viewport::set_use_hdr_2d(bool p_enable) {
|
||||
ERR_MAIN_THREAD_GUARD;
|
||||
use_hdr_2d = p_enable;
|
||||
RS::get_singleton()->viewport_set_use_hdr_2d(viewport, p_enable);
|
||||
}
|
||||
|
||||
bool Viewport::is_using_hdr_2d() const {
|
||||
ERR_READ_THREAD_GUARD_V(false);
|
||||
return use_hdr_2d;
|
||||
}
|
||||
|
||||
void Viewport::set_world_2d(const Ref<World2D> &p_world_2d) {
|
||||
ERR_MAIN_THREAD_GUARD;
|
||||
if (world_2d == p_world_2d) {
|
||||
|
@ -4271,6 +4282,8 @@ void Viewport::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("get_visible_rect"), &Viewport::get_visible_rect);
|
||||
ClassDB::bind_method(D_METHOD("set_transparent_background", "enable"), &Viewport::set_transparent_background);
|
||||
ClassDB::bind_method(D_METHOD("has_transparent_background"), &Viewport::has_transparent_background);
|
||||
ClassDB::bind_method(D_METHOD("set_use_hdr_2d", "enable"), &Viewport::set_use_hdr_2d);
|
||||
ClassDB::bind_method(D_METHOD("is_using_hdr_2d"), &Viewport::is_using_hdr_2d);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_msaa_2d", "msaa"), &Viewport::set_msaa_2d);
|
||||
ClassDB::bind_method(D_METHOD("get_msaa_2d"), &Viewport::get_msaa_2d);
|
||||
|
@ -4435,6 +4448,8 @@ void Viewport::_bind_methods() {
|
|||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_occlusion_culling"), "set_use_occlusion_culling", "is_using_occlusion_culling");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mesh_lod_threshold", PROPERTY_HINT_RANGE, "0,1024,0.1"), "set_mesh_lod_threshold", "get_mesh_lod_threshold");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "debug_draw", PROPERTY_HINT_ENUM, "Disabled,Unshaded,Lighting,Overdraw,Wireframe"), "set_debug_draw", "get_debug_draw");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_hdr_2d"), "set_use_hdr_2d", "is_using_hdr_2d");
|
||||
|
||||
#ifndef _3D_DISABLED
|
||||
ADD_GROUP("Scaling 3D", "");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "scaling_3d_mode", PROPERTY_HINT_ENUM, "Bilinear (Fastest),FSR 1.0 (Fast)"), "set_scaling_3d_mode", "get_scaling_3d_mode");
|
||||
|
|
|
@ -243,6 +243,7 @@ private:
|
|||
Rect2 last_vp_rect;
|
||||
|
||||
bool transparent_bg = false;
|
||||
bool use_hdr_2d = false;
|
||||
bool gen_mipmaps = false;
|
||||
|
||||
bool snap_controls_to_pixels = true;
|
||||
|
@ -526,6 +527,9 @@ public:
|
|||
void set_transparent_background(bool p_enable);
|
||||
bool has_transparent_background() const;
|
||||
|
||||
void set_use_hdr_2d(bool p_enable);
|
||||
bool is_using_hdr_2d() const;
|
||||
|
||||
Ref<ViewportTexture> get_texture() const;
|
||||
|
||||
void set_positional_shadow_atlas_size(int p_size);
|
||||
|
|
|
@ -177,6 +177,8 @@ public:
|
|||
virtual void render_target_set_as_unused(RID p_render_target) override {}
|
||||
virtual void render_target_set_msaa(RID p_render_target, RS::ViewportMSAA p_msaa) override {}
|
||||
virtual RS::ViewportMSAA render_target_get_msaa(RID p_render_target) const override { return RS::VIEWPORT_MSAA_DISABLED; }
|
||||
virtual void render_target_set_use_hdr(RID p_render_target, bool p_use_hdr_2d) override {}
|
||||
virtual bool render_target_is_using_hdr(RID p_render_target) const override { return false; }
|
||||
|
||||
virtual void render_target_request_clear(RID p_render_target, const Color &p_clear_color) override {}
|
||||
virtual bool render_target_is_clear_requested(RID p_render_target) override { return false; }
|
||||
|
|
|
@ -89,12 +89,12 @@ void ToneMapper::tonemapper(RID p_source_color, RID p_dst_framebuffer, const Ton
|
|||
|
||||
memset(&tonemap.push_constant, 0, sizeof(TonemapPushConstant));
|
||||
|
||||
tonemap.push_constant.use_bcs = p_settings.use_bcs;
|
||||
tonemap.push_constant.flags |= p_settings.use_bcs ? TONEMAP_FLAG_USE_BCS : 0;
|
||||
tonemap.push_constant.bcs[0] = p_settings.brightness;
|
||||
tonemap.push_constant.bcs[1] = p_settings.contrast;
|
||||
tonemap.push_constant.bcs[2] = p_settings.saturation;
|
||||
|
||||
tonemap.push_constant.use_glow = p_settings.use_glow;
|
||||
tonemap.push_constant.flags |= p_settings.use_glow ? TONEMAP_FLAG_USE_GLOW : 0;
|
||||
tonemap.push_constant.glow_intensity = p_settings.glow_intensity;
|
||||
tonemap.push_constant.glow_map_strength = p_settings.glow_map_strength;
|
||||
tonemap.push_constant.glow_levels[0] = p_settings.glow_levels[0]; // clean this up to just pass by pointer or something
|
||||
|
@ -114,19 +114,21 @@ void ToneMapper::tonemapper(RID p_source_color, RID p_dst_framebuffer, const Ton
|
|||
}
|
||||
|
||||
tonemap.push_constant.tonemapper = p_settings.tonemap_mode;
|
||||
tonemap.push_constant.use_auto_exposure = p_settings.use_auto_exposure;
|
||||
tonemap.push_constant.flags |= p_settings.use_auto_exposure ? TONEMAP_FLAG_USE_AUTO_EXPOSURE : 0;
|
||||
tonemap.push_constant.exposure = p_settings.exposure;
|
||||
tonemap.push_constant.white = p_settings.white;
|
||||
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;
|
||||
tonemap.push_constant.flags |= p_settings.use_color_correction ? TONEMAP_FLAG_USE_COLOR_CORRECTION : 0;
|
||||
|
||||
tonemap.push_constant.use_fxaa = p_settings.use_fxaa;
|
||||
tonemap.push_constant.use_debanding = p_settings.use_debanding;
|
||||
tonemap.push_constant.flags |= p_settings.use_fxaa ? TONEMAP_FLAG_USE_FXAA : 0;
|
||||
tonemap.push_constant.flags |= p_settings.use_debanding ? TONEMAP_FLAG_USE_DEBANDING : 0;
|
||||
tonemap.push_constant.pixel_size[0] = 1.0 / p_settings.texture_size.x;
|
||||
tonemap.push_constant.pixel_size[1] = 1.0 / p_settings.texture_size.y;
|
||||
|
||||
tonemap.push_constant.flags |= p_settings.convert_to_srgb ? TONEMAP_FLAG_CONVERT_TO_SRGB : 0;
|
||||
|
||||
if (p_settings.view_count > 1) {
|
||||
// Use MULTIVIEW versions
|
||||
mode += 6;
|
||||
|
@ -185,13 +187,13 @@ void ToneMapper::tonemapper(RD::DrawListID p_subpass_draw_list, RID p_source_col
|
|||
|
||||
memset(&tonemap.push_constant, 0, sizeof(TonemapPushConstant));
|
||||
|
||||
tonemap.push_constant.use_bcs = p_settings.use_bcs;
|
||||
tonemap.push_constant.flags |= p_settings.use_bcs ? TONEMAP_FLAG_USE_BCS : 0;
|
||||
tonemap.push_constant.bcs[0] = p_settings.brightness;
|
||||
tonemap.push_constant.bcs[1] = p_settings.contrast;
|
||||
tonemap.push_constant.bcs[2] = p_settings.saturation;
|
||||
|
||||
ERR_FAIL_COND_MSG(p_settings.use_glow, "Glow is not supported when using subpasses.");
|
||||
tonemap.push_constant.use_glow = p_settings.use_glow;
|
||||
tonemap.push_constant.flags |= p_settings.use_glow ? TONEMAP_FLAG_USE_GLOW : 0;
|
||||
|
||||
int mode = p_settings.use_1d_color_correction ? TONEMAP_MODE_SUBPASS_1D_LUT : TONEMAP_MODE_SUBPASS;
|
||||
if (p_settings.view_count > 1) {
|
||||
|
@ -200,16 +202,18 @@ void ToneMapper::tonemapper(RD::DrawListID p_subpass_draw_list, RID p_source_col
|
|||
}
|
||||
|
||||
tonemap.push_constant.tonemapper = p_settings.tonemap_mode;
|
||||
tonemap.push_constant.use_auto_exposure = p_settings.use_auto_exposure;
|
||||
tonemap.push_constant.flags |= p_settings.use_auto_exposure ? TONEMAP_FLAG_USE_AUTO_EXPOSURE : 0;
|
||||
tonemap.push_constant.exposure = p_settings.exposure;
|
||||
tonemap.push_constant.white = p_settings.white;
|
||||
tonemap.push_constant.auto_exposure_scale = p_settings.auto_exposure_scale;
|
||||
|
||||
tonemap.push_constant.use_color_correction = p_settings.use_color_correction;
|
||||
tonemap.push_constant.flags |= p_settings.use_color_correction ? TONEMAP_FLAG_USE_COLOR_CORRECTION : 0;
|
||||
|
||||
tonemap.push_constant.use_debanding = p_settings.use_debanding;
|
||||
tonemap.push_constant.flags |= p_settings.use_debanding ? TONEMAP_FLAG_USE_DEBANDING : 0;
|
||||
tonemap.push_constant.luminance_multiplier = p_settings.luminance_multiplier;
|
||||
|
||||
tonemap.push_constant.flags |= p_settings.convert_to_srgb ? TONEMAP_FLAG_CONVERT_TO_SRGB : 0;
|
||||
|
||||
RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
RID default_mipmap_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
|
||||
|
|
|
@ -59,14 +59,23 @@ private:
|
|||
TONEMAP_MODE_MAX
|
||||
};
|
||||
|
||||
enum {
|
||||
TONEMAP_FLAG_USE_BCS = (1 << 0),
|
||||
TONEMAP_FLAG_USE_GLOW = (1 << 1),
|
||||
TONEMAP_FLAG_USE_AUTO_EXPOSURE = (1 << 2),
|
||||
TONEMAP_FLAG_USE_COLOR_CORRECTION = (1 << 3),
|
||||
TONEMAP_FLAG_USE_FXAA = (1 << 4),
|
||||
TONEMAP_FLAG_USE_DEBANDING = (1 << 5),
|
||||
TONEMAP_FLAG_CONVERT_TO_SRGB = (1 << 6),
|
||||
};
|
||||
|
||||
struct TonemapPushConstant {
|
||||
float bcs[3]; // 12 - 12
|
||||
uint32_t use_bcs; // 4 - 16
|
||||
uint32_t flags; // 4 - 16
|
||||
|
||||
uint32_t use_glow; // 4 - 20
|
||||
uint32_t use_auto_exposure; // 4 - 24
|
||||
uint32_t use_color_correction; // 4 - 28
|
||||
uint32_t tonemapper; // 4 - 32
|
||||
float pixel_size[2]; // 8 - 24
|
||||
uint32_t tonemapper; // 4 - 28
|
||||
uint32_t pad; // 4 - 32
|
||||
|
||||
uint32_t glow_texture_size[2]; // 8 - 40
|
||||
float glow_intensity; // 4 - 44
|
||||
|
@ -79,10 +88,6 @@ private:
|
|||
float white; // 4 - 88
|
||||
float auto_exposure_scale; // 4 - 92
|
||||
float luminance_multiplier; // 4 - 96
|
||||
|
||||
float pixel_size[2]; // 8 - 104
|
||||
uint32_t use_fxaa; // 4 - 108
|
||||
uint32_t use_debanding; // 4 - 112
|
||||
};
|
||||
|
||||
/* tonemap actually writes to a framebuffer, which is
|
||||
|
@ -141,6 +146,8 @@ public:
|
|||
bool use_debanding = false;
|
||||
Vector2i texture_size;
|
||||
uint32_t view_count = 1;
|
||||
|
||||
bool convert_to_srgb = false;
|
||||
};
|
||||
|
||||
void tonemapper(RID p_source_color, RID p_dst_framebuffer, const TonemapSettings &p_settings);
|
||||
|
|
|
@ -143,7 +143,7 @@ Vector3 Fog::fog_volume_get_size(RID p_fog_volume) const {
|
|||
bool Fog::FogMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
|
||||
uniform_set_updated = true;
|
||||
|
||||
return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, Fog::get_singleton()->volumetric_fog.shader.version_get_shader(shader_data->version, 0), VolumetricFogShader::FogSet::FOG_SET_MATERIAL, true);
|
||||
return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, Fog::get_singleton()->volumetric_fog.shader.version_get_shader(shader_data->version, 0), VolumetricFogShader::FogSet::FOG_SET_MATERIAL, true, true);
|
||||
}
|
||||
|
||||
Fog::FogMaterialData::~FogMaterialData() {
|
||||
|
|
|
@ -185,7 +185,7 @@ bool SkyRD::SkyMaterialData::update_parameters(const HashMap<StringName, Variant
|
|||
|
||||
uniform_set_updated = true;
|
||||
|
||||
return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, scene_singleton->sky.sky_shader.shader.version_get_shader(shader_data->version, 0), SKY_SET_MATERIAL, true);
|
||||
return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, scene_singleton->sky.sky_shader.shader.version_get_shader(shader_data->version, 0), SKY_SET_MATERIAL, true, true);
|
||||
}
|
||||
|
||||
SkyRD::SkyMaterialData::~SkyMaterialData() {
|
||||
|
|
|
@ -1769,7 +1769,8 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
|
|||
case RS::ENV_BG_CANVAS: {
|
||||
if (!is_reflection_probe) {
|
||||
RID texture = RendererRD::TextureStorage::get_singleton()->render_target_get_rd_texture(rb->get_render_target());
|
||||
copy_effects->copy_to_fb_rect(texture, color_only_framebuffer, Rect2i(), false, false, false, false, RID(), false, false, true);
|
||||
bool convert_to_linear = !RendererRD::TextureStorage::get_singleton()->render_target_is_using_hdr(rb->get_render_target());
|
||||
copy_effects->copy_to_fb_rect(texture, color_only_framebuffer, Rect2i(), false, false, false, false, RID(), false, false, convert_to_linear);
|
||||
}
|
||||
keep_color = true;
|
||||
} break;
|
||||
|
|
|
@ -436,7 +436,7 @@ void SceneShaderForwardClustered::MaterialData::set_next_pass(RID p_pass) {
|
|||
bool SceneShaderForwardClustered::MaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
|
||||
SceneShaderForwardClustered *shader_singleton = (SceneShaderForwardClustered *)SceneShaderForwardClustered::singleton;
|
||||
|
||||
return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, shader_singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardClustered::MATERIAL_UNIFORM_SET, true, RD::BARRIER_MASK_RASTER);
|
||||
return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, shader_singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardClustered::MATERIAL_UNIFORM_SET, true, true, RD::BARRIER_MASK_RASTER);
|
||||
}
|
||||
|
||||
SceneShaderForwardClustered::MaterialData::~MaterialData() {
|
||||
|
|
|
@ -803,7 +803,8 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
|
|||
if (rb_data.is_valid()) {
|
||||
RID dest_framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_ONE_PASS);
|
||||
RID texture = RendererRD::TextureStorage::get_singleton()->render_target_get_rd_texture(rb->get_render_target());
|
||||
copy_effects->copy_to_fb_rect(texture, dest_framebuffer, Rect2i(), false, false, false, false, RID(), false, false, true);
|
||||
bool convert_to_linear = !RendererRD::TextureStorage::get_singleton()->render_target_is_using_hdr(rb->get_render_target());
|
||||
copy_effects->copy_to_fb_rect(texture, dest_framebuffer, Rect2i(), false, false, false, false, RID(), false, false, convert_to_linear);
|
||||
}
|
||||
keep_color = true;
|
||||
} break;
|
||||
|
|
|
@ -388,7 +388,7 @@ void SceneShaderForwardMobile::MaterialData::set_next_pass(RID p_pass) {
|
|||
bool SceneShaderForwardMobile::MaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
|
||||
SceneShaderForwardMobile *shader_singleton = (SceneShaderForwardMobile *)SceneShaderForwardMobile::singleton;
|
||||
|
||||
return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, shader_singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardMobile::MATERIAL_UNIFORM_SET, true, RD::BARRIER_MASK_RASTER);
|
||||
return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, shader_singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardMobile::MATERIAL_UNIFORM_SET, true, true, RD::BARRIER_MASK_RASTER);
|
||||
}
|
||||
|
||||
SceneShaderForwardMobile::MaterialData::~MaterialData() {
|
||||
|
|
|
@ -363,7 +363,7 @@ void RendererCanvasRenderRD::_bind_canvas_texture(RD::DrawListID p_draw_list, RI
|
|||
bool use_normal;
|
||||
bool use_specular;
|
||||
|
||||
bool success = RendererRD::TextureStorage::get_singleton()->canvas_texture_get_uniform_set(p_texture, p_base_filter, p_base_repeat, shader.default_version_rd_shader, CANVAS_TEXTURE_UNIFORM_SET, uniform_set, size, specular_shininess, use_normal, use_specular);
|
||||
bool success = RendererRD::TextureStorage::get_singleton()->canvas_texture_get_uniform_set(p_texture, p_base_filter, p_base_repeat, shader.default_version_rd_shader, CANVAS_TEXTURE_UNIFORM_SET, bool(push_constant.flags & FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR), uniform_set, size, specular_shininess, use_normal, use_specular);
|
||||
//something odd happened
|
||||
if (!success) {
|
||||
_bind_canvas_texture(p_draw_list, default_canvas_texture, p_base_filter, p_base_repeat, r_last_texture, push_constant, r_texpixel_size);
|
||||
|
@ -421,6 +421,7 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
|
|||
_update_transform_2d_to_mat2x3(base_transform, push_constant.world);
|
||||
|
||||
Color base_color = p_item->final_modulate;
|
||||
bool use_linear_colors = texture_storage->render_target_is_using_hdr(p_render_target);
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
push_constant.modulation[i] = 0;
|
||||
|
@ -441,6 +442,7 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
|
|||
push_constant.lights[3] = 0;
|
||||
|
||||
uint32_t base_flags = 0;
|
||||
base_flags |= use_linear_colors ? FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR : 0;
|
||||
|
||||
uint16_t light_count = 0;
|
||||
PipelineLightMode light_mode;
|
||||
|
@ -566,10 +568,15 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
|
|||
push_constant.flags |= FLAGS_USE_LCD;
|
||||
}
|
||||
|
||||
push_constant.modulation[0] = rect->modulate.r * base_color.r;
|
||||
push_constant.modulation[1] = rect->modulate.g * base_color.g;
|
||||
push_constant.modulation[2] = rect->modulate.b * base_color.b;
|
||||
push_constant.modulation[3] = rect->modulate.a * base_color.a;
|
||||
Color modulated = rect->modulate * base_color;
|
||||
if (use_linear_colors) {
|
||||
modulated = modulated.srgb_to_linear();
|
||||
}
|
||||
|
||||
push_constant.modulation[0] = modulated.r;
|
||||
push_constant.modulation[1] = modulated.g;
|
||||
push_constant.modulation[2] = modulated.b;
|
||||
push_constant.modulation[3] = modulated.a;
|
||||
|
||||
push_constant.src_rect[0] = src_rect.position.x;
|
||||
push_constant.src_rect[1] = src_rect.position.y;
|
||||
|
@ -618,10 +625,15 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
|
|||
}
|
||||
}
|
||||
|
||||
push_constant.modulation[0] = np->color.r * base_color.r;
|
||||
push_constant.modulation[1] = np->color.g * base_color.g;
|
||||
push_constant.modulation[2] = np->color.b * base_color.b;
|
||||
push_constant.modulation[3] = np->color.a * base_color.a;
|
||||
Color modulated = np->color * base_color;
|
||||
if (use_linear_colors) {
|
||||
modulated = modulated.srgb_to_linear();
|
||||
}
|
||||
|
||||
push_constant.modulation[0] = modulated.r;
|
||||
push_constant.modulation[1] = modulated.g;
|
||||
push_constant.modulation[2] = modulated.b;
|
||||
push_constant.modulation[3] = modulated.a;
|
||||
|
||||
push_constant.src_rect[0] = src_rect.position.x;
|
||||
push_constant.src_rect[1] = src_rect.position.y;
|
||||
|
@ -676,10 +688,15 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
|
|||
|
||||
_bind_canvas_texture(p_draw_list, polygon->texture, current_filter, current_repeat, last_texture, push_constant, texpixel_size);
|
||||
|
||||
push_constant.modulation[0] = base_color.r;
|
||||
push_constant.modulation[1] = base_color.g;
|
||||
push_constant.modulation[2] = base_color.b;
|
||||
push_constant.modulation[3] = base_color.a;
|
||||
Color color = base_color;
|
||||
if (use_linear_colors) {
|
||||
color = color.srgb_to_linear();
|
||||
}
|
||||
|
||||
push_constant.modulation[0] = color.r;
|
||||
push_constant.modulation[1] = color.g;
|
||||
push_constant.modulation[2] = color.b;
|
||||
push_constant.modulation[3] = color.a;
|
||||
|
||||
for (int j = 0; j < 4; j++) {
|
||||
push_constant.src_rect[j] = 0;
|
||||
|
@ -718,6 +735,9 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
|
|||
push_constant.uvs[j * 2 + 0] = primitive->uvs[j].x;
|
||||
push_constant.uvs[j * 2 + 1] = primitive->uvs[j].y;
|
||||
Color col = primitive->colors[j] * base_color;
|
||||
if (use_linear_colors) {
|
||||
col = col.srgb_to_linear();
|
||||
}
|
||||
push_constant.colors[j * 2 + 0] = (uint32_t(Math::make_half_float(col.g)) << 16) | Math::make_half_float(col.r);
|
||||
push_constant.colors[j * 2 + 1] = (uint32_t(Math::make_half_float(col.a)) << 16) | Math::make_half_float(col.b);
|
||||
}
|
||||
|
@ -732,6 +752,9 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
|
|||
push_constant.uvs[j * 2 + 0] = primitive->uvs[j + 1].x;
|
||||
push_constant.uvs[j * 2 + 1] = primitive->uvs[j + 1].y;
|
||||
Color col = primitive->colors[j + 1] * base_color;
|
||||
if (use_linear_colors) {
|
||||
col = col.srgb_to_linear();
|
||||
}
|
||||
push_constant.colors[j * 2 + 0] = (uint32_t(Math::make_half_float(col.g)) << 16) | Math::make_half_float(col.r);
|
||||
push_constant.colors[j * 2 + 1] = (uint32_t(Math::make_half_float(col.a)) << 16) | Math::make_half_float(col.b);
|
||||
}
|
||||
|
@ -849,10 +872,15 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
|
|||
uint32_t surf_count = mesh_storage->mesh_get_surface_count(mesh);
|
||||
static const PipelineVariant variant[RS::PRIMITIVE_MAX] = { PIPELINE_VARIANT_ATTRIBUTE_POINTS, PIPELINE_VARIANT_ATTRIBUTE_LINES, PIPELINE_VARIANT_ATTRIBUTE_LINES_STRIP, PIPELINE_VARIANT_ATTRIBUTE_TRIANGLES, PIPELINE_VARIANT_ATTRIBUTE_TRIANGLE_STRIP };
|
||||
|
||||
push_constant.modulation[0] = base_color.r * modulate.r;
|
||||
push_constant.modulation[1] = base_color.g * modulate.g;
|
||||
push_constant.modulation[2] = base_color.b * modulate.b;
|
||||
push_constant.modulation[3] = base_color.a * modulate.a;
|
||||
Color modulated = modulate * base_color;
|
||||
if (use_linear_colors) {
|
||||
modulated = modulated.srgb_to_linear();
|
||||
}
|
||||
|
||||
push_constant.modulation[0] = modulated.r;
|
||||
push_constant.modulation[1] = modulated.g;
|
||||
push_constant.modulation[2] = modulated.b;
|
||||
push_constant.modulation[3] = modulated.a;
|
||||
|
||||
for (int j = 0; j < 4; j++) {
|
||||
push_constant.src_rect[j] = 0;
|
||||
|
@ -1113,8 +1141,9 @@ void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_co
|
|||
if (material_data->shader_data->version.is_valid() && material_data->shader_data->valid) {
|
||||
pipeline_variants = &material_data->shader_data->pipeline_variants;
|
||||
// Update uniform set.
|
||||
if (material_data->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(material_data->uniform_set)) { // Material may not have a uniform set.
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, material_data->uniform_set, MATERIAL_UNIFORM_SET);
|
||||
RID uniform_set = texture_storage->render_target_is_using_hdr(p_to_render_target) ? material_data->uniform_set : material_data->uniform_set_srgb;
|
||||
if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { // Material may not have a uniform set.
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set, MATERIAL_UNIFORM_SET);
|
||||
material_data->set_as_used();
|
||||
}
|
||||
} else {
|
||||
|
@ -2235,12 +2264,14 @@ RendererRD::MaterialStorage::ShaderData *RendererCanvasRenderRD::_create_shader_
|
|||
|
||||
bool RendererCanvasRenderRD::CanvasMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
|
||||
RendererCanvasRenderRD *canvas_singleton = static_cast<RendererCanvasRenderRD *>(RendererCanvasRender::singleton);
|
||||
|
||||
return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, canvas_singleton->shader.canvas_shader.version_get_shader(shader_data->version, 0), MATERIAL_UNIFORM_SET, false);
|
||||
bool uniform_set_changed = update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, canvas_singleton->shader.canvas_shader.version_get_shader(shader_data->version, 0), MATERIAL_UNIFORM_SET, true, false, RD::BARRIER_MASK_ALL_BARRIERS);
|
||||
bool uniform_set_srgb_changed = update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set_srgb, canvas_singleton->shader.canvas_shader.version_get_shader(shader_data->version, 0), MATERIAL_UNIFORM_SET, false, false, RD::BARRIER_MASK_ALL_BARRIERS);
|
||||
return uniform_set_changed || uniform_set_srgb_changed;
|
||||
}
|
||||
|
||||
RendererCanvasRenderRD::CanvasMaterialData::~CanvasMaterialData() {
|
||||
free_parameters_uniform_set(uniform_set);
|
||||
free_parameters_uniform_set(uniform_set_srgb);
|
||||
}
|
||||
|
||||
RendererRD::MaterialStorage::MaterialData *RendererCanvasRenderRD::_create_material_func(CanvasShaderData *p_shader) {
|
||||
|
|
|
@ -75,6 +75,8 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
|
|||
FLAGS_CLIP_RECT_UV = (1 << 9),
|
||||
FLAGS_TRANSPOSE_RECT = (1 << 10),
|
||||
|
||||
FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR = (1 << 11),
|
||||
|
||||
FLAGS_NINEPACH_DRAW_CENTER = (1 << 12),
|
||||
FLAGS_USING_PARTICLES = (1 << 13),
|
||||
|
||||
|
@ -195,6 +197,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
|
|||
struct CanvasMaterialData : public RendererRD::MaterialStorage::MaterialData {
|
||||
CanvasShaderData *shader_data = nullptr;
|
||||
RID uniform_set;
|
||||
RID uniform_set_srgb;
|
||||
|
||||
virtual void set_render_priority(int p_priority) {}
|
||||
virtual void set_next_pass(RID p_pass) {}
|
||||
|
|
|
@ -81,6 +81,7 @@ void RendererCompositorRD::blit_render_targets_to_screen(DisplayServer::WindowID
|
|||
blit.push_constant.k2 = p_render_targets[i].lens_distortion.k2;
|
||||
blit.push_constant.upscale = p_render_targets[i].lens_distortion.upscale;
|
||||
blit.push_constant.aspect_ratio = p_render_targets[i].lens_distortion.aspect_ratio;
|
||||
blit.push_constant.convert_to_srgb = texture_storage->render_target_is_using_hdr(p_render_targets[i].render_target);
|
||||
|
||||
RD::get_singleton()->draw_list_set_push_constant(draw_list, &blit.push_constant, sizeof(BlitPushConstant));
|
||||
RD::get_singleton()->draw_list_draw(draw_list, true);
|
||||
|
@ -171,7 +172,7 @@ void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color
|
|||
|
||||
RID texture = texture_storage->texture_allocate();
|
||||
texture_storage->texture_2d_initialize(texture, p_image);
|
||||
RID rd_texture = texture_storage->texture_get_rd_texture(texture);
|
||||
RID rd_texture = texture_storage->texture_get_rd_texture(texture, false);
|
||||
|
||||
RD::SamplerState sampler_state;
|
||||
sampler_state.min_filter = p_use_filter ? RD::SAMPLER_FILTER_LINEAR : RD::SAMPLER_FILTER_NEAREST;
|
||||
|
@ -237,6 +238,7 @@ void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color
|
|||
blit.push_constant.k2 = 0;
|
||||
blit.push_constant.upscale = 1.0;
|
||||
blit.push_constant.aspect_ratio = 1.0;
|
||||
blit.push_constant.convert_to_srgb = false;
|
||||
|
||||
RD::get_singleton()->draw_list_set_push_constant(draw_list, &blit.push_constant, sizeof(BlitPushConstant));
|
||||
RD::get_singleton()->draw_list_draw(draw_list, true);
|
||||
|
|
|
@ -80,7 +80,7 @@ protected:
|
|||
float upscale;
|
||||
float aspect_ratio;
|
||||
uint32_t layer;
|
||||
uint32_t pad1;
|
||||
uint32_t convert_to_srgb;
|
||||
};
|
||||
|
||||
struct Blit {
|
||||
|
|
|
@ -552,6 +552,8 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
|
|||
tonemap.luminance_multiplier = _render_buffers_get_luminance_multiplier();
|
||||
tonemap.view_count = rb->get_view_count();
|
||||
|
||||
tonemap.convert_to_srgb = !texture_storage->render_target_is_using_hdr(render_target);
|
||||
|
||||
RID dest_fb;
|
||||
if (fsr && can_use_effects && rb->get_scaling_3d_mode() == RS::VIEWPORT_SCALING_3D_MODE_FSR) {
|
||||
// If we use FSR to upscale we need to write our result into an intermediate buffer.
|
||||
|
@ -647,6 +649,8 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr
|
|||
tonemap.luminance_multiplier = _render_buffers_get_luminance_multiplier();
|
||||
tonemap.view_count = rb->get_view_count();
|
||||
|
||||
tonemap.convert_to_srgb = !texture_storage->render_target_is_using_hdr(rb->get_render_target());
|
||||
|
||||
tone_mapper->tonemapper(draw_list, p_source_texture, RD::get_singleton()->framebuffer_get_format(p_framebuffer), tonemap);
|
||||
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
|
|
|
@ -45,7 +45,7 @@ layout(push_constant, std140) uniform Pos {
|
|||
float upscale;
|
||||
float aspect_ratio;
|
||||
uint layer;
|
||||
uint pad1;
|
||||
bool convert_to_srgb;
|
||||
}
|
||||
data;
|
||||
|
||||
|
@ -59,6 +59,13 @@ layout(binding = 0) uniform sampler2DArray src_rt;
|
|||
layout(binding = 0) uniform sampler2D src_rt;
|
||||
#endif
|
||||
|
||||
vec3 linear_to_srgb(vec3 color) {
|
||||
// If going to srgb, clamp from 0 to 1.
|
||||
color = clamp(color, vec3(0.0), vec3(1.0));
|
||||
const vec3 a = vec3(0.055f);
|
||||
return mix((vec3(1.0f) + a) * pow(color.rgb, vec3(1.0f / 2.4f)) - a, 12.92f * color.rgb, lessThan(color.rgb, vec3(0.0031308f)));
|
||||
}
|
||||
|
||||
void main() {
|
||||
#ifdef APPLY_LENS_DISTORTION
|
||||
vec2 coords = uv * 2.0 - 1.0;
|
||||
|
@ -94,4 +101,8 @@ void main() {
|
|||
#else
|
||||
color = texture(src_rt, uv);
|
||||
#endif
|
||||
|
||||
if (data.convert_to_srgb) {
|
||||
color.rgb = linear_to_srgb(color.rgb); // Regular linear -> SRGB conversion.
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,12 @@ layout(set = 1, binding = 0, std140) uniform MaterialUniforms{
|
|||
|
||||
#GLOBALS
|
||||
|
||||
#ifdef USE_ATTRIBUTES
|
||||
vec3 srgb_to_linear(vec3 color) {
|
||||
return mix(pow((color.rgb + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)), color.rgb * (1.0 / 12.92), lessThan(color.rgb, vec3(0.04045)));
|
||||
}
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
vec4 instance_custom = vec4(0.0);
|
||||
#ifdef USE_PRIMITIVE
|
||||
|
@ -65,7 +71,11 @@ void main() {
|
|||
#elif defined(USE_ATTRIBUTES)
|
||||
|
||||
vec2 vertex = vertex_attrib;
|
||||
vec4 color = color_attrib * draw_data.modulation;
|
||||
vec4 color = color_attrib;
|
||||
if (bool(draw_data.flags & FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR)) {
|
||||
color.rgb = srgb_to_linear(color.rgb);
|
||||
}
|
||||
color *= draw_data.modulation;
|
||||
vec2 uv = uv_attrib;
|
||||
|
||||
uvec4 bones = bone_attrib;
|
||||
|
@ -563,9 +573,6 @@ void main() {
|
|||
}
|
||||
|
||||
vec4 base_color = color;
|
||||
if (bool(draw_data.flags & FLAGS_USING_LIGHT_MASK)) {
|
||||
color = vec4(0.0); //invisible by default due to using light mask
|
||||
}
|
||||
|
||||
#ifdef MODE_LIGHT_ONLY
|
||||
float light_only_alpha = 0.0;
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
#define FLAGS_CLIP_RECT_UV (1 << 9)
|
||||
#define FLAGS_TRANSPOSE_RECT (1 << 10)
|
||||
#define FLAGS_USING_LIGHT_MASK (1 << 11)
|
||||
#define FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR (1 << 11)
|
||||
#define FLAGS_NINEPACH_DRAW_CENTER (1 << 12)
|
||||
#define FLAGS_USING_PARTICLES (1 << 13)
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ layout(r32f, set = 3, binding = 0) uniform restrict writeonly image2D dest_buffe
|
|||
#elif defined(DST_IMAGE_8BIT)
|
||||
layout(rgba8, set = 3, binding = 0) uniform restrict writeonly image2D dest_buffer;
|
||||
#else
|
||||
layout(rgba32f, set = 3, binding = 0) uniform restrict writeonly image2D dest_buffer;
|
||||
layout(rgba16f, set = 3, binding = 0) uniform restrict writeonly image2D dest_buffer;
|
||||
#endif
|
||||
|
||||
#ifdef MODE_GAUSSIAN_BLUR
|
||||
|
|
|
@ -57,14 +57,21 @@ layout(set = 3, binding = 0) uniform sampler2D source_color_correction;
|
|||
layout(set = 3, binding = 0) uniform sampler3D source_color_correction;
|
||||
#endif
|
||||
|
||||
#define FLAG_USE_BCS (1 << 0)
|
||||
#define FLAG_USE_GLOW (1 << 1)
|
||||
#define FLAG_USE_AUTO_EXPOSURE (1 << 2)
|
||||
#define FLAG_USE_COLOR_CORRECTION (1 << 3)
|
||||
#define FLAG_USE_FXAA (1 << 4)
|
||||
#define FLAG_USE_DEBANDING (1 << 5)
|
||||
#define FLAG_CONVERT_TO_SRGB (1 << 6)
|
||||
|
||||
layout(push_constant, std430) uniform Params {
|
||||
vec3 bcs;
|
||||
bool use_bcs;
|
||||
uint flags;
|
||||
|
||||
bool use_glow;
|
||||
bool use_auto_exposure;
|
||||
bool use_color_correction;
|
||||
vec2 pixel_size;
|
||||
uint tonemapper;
|
||||
uint pad;
|
||||
|
||||
uvec2 glow_texture_size;
|
||||
float glow_intensity;
|
||||
|
@ -77,10 +84,6 @@ layout(push_constant, std430) uniform Params {
|
|||
float white;
|
||||
float auto_exposure_scale;
|
||||
float luminance_multiplier;
|
||||
|
||||
vec2 pixel_size;
|
||||
bool use_fxaa;
|
||||
bool use_debanding;
|
||||
}
|
||||
params;
|
||||
|
||||
|
@ -318,10 +321,12 @@ vec3 apply_glow(vec3 color, vec3 glow) { // apply glow using the selected blendi
|
|||
if (params.glow_mode == GLOW_MODE_ADD) {
|
||||
return color + glow;
|
||||
} else if (params.glow_mode == GLOW_MODE_SCREEN) {
|
||||
//need color clamping
|
||||
// Needs color clamping.
|
||||
glow.rgb = clamp(glow.rgb, vec3(0.0f), vec3(1.0f));
|
||||
return max((color + glow) - (color * glow), vec3(0.0));
|
||||
} else if (params.glow_mode == GLOW_MODE_SOFTLIGHT) {
|
||||
//need color clamping
|
||||
// Needs color clamping.
|
||||
glow.rgb = clamp(glow.rgb, vec3(0.0f), vec3(1.0f));
|
||||
glow = glow * vec3(0.5f) + vec3(0.5f);
|
||||
|
||||
color.r = (glow.r <= 0.5f) ? (color.r - (1.0f - 2.0f * glow.r) * color.r * (1.0f - color.r)) : (((glow.r > 0.5f) && (color.r <= 0.25f)) ? (color.r + (2.0f * glow.r - 1.0f) * (4.0f * color.r * (4.0f * color.r + 1.0f) * (color.r - 1.0f) + 7.0f * color.r)) : (color.r + (2.0f * glow.r - 1.0f) * (sqrt(color.r) - color.r)));
|
||||
|
@ -439,7 +444,7 @@ void main() {
|
|||
float exposure = params.exposure;
|
||||
|
||||
#ifndef SUBPASS
|
||||
if (params.use_auto_exposure) {
|
||||
if (bool(params.flags & FLAG_USE_AUTO_EXPOSURE)) {
|
||||
exposure *= 1.0 / (texelFetch(source_auto_exposure, ivec2(0, 0), 0).r * params.luminance_multiplier / params.auto_exposure_scale);
|
||||
}
|
||||
#endif
|
||||
|
@ -448,12 +453,12 @@ void main() {
|
|||
|
||||
// Early Tonemap & SRGB Conversion
|
||||
#ifndef SUBPASS
|
||||
if (params.use_fxaa) {
|
||||
if (bool(params.flags & FLAG_USE_FXAA)) {
|
||||
// FXAA must be performed before glow to preserve the "bleed" effect of glow.
|
||||
color.rgb = do_fxaa(color.rgb, exposure, uv_interp);
|
||||
}
|
||||
|
||||
if (params.use_glow && params.glow_mode == GLOW_MODE_MIX) {
|
||||
if (bool(params.flags & FLAG_USE_GLOW) && params.glow_mode == GLOW_MODE_MIX) {
|
||||
vec3 glow = gather_glow(source_glow, uv_interp) * params.luminance_multiplier;
|
||||
if (params.glow_map_strength > 0.001) {
|
||||
glow = mix(glow, texture(glow_map, uv_interp).rgb * glow, params.glow_map_strength);
|
||||
|
@ -464,11 +469,12 @@ void main() {
|
|||
|
||||
color.rgb = apply_tonemapping(color.rgb, params.white);
|
||||
|
||||
color.rgb = linear_to_srgb(color.rgb); // regular linear -> SRGB conversion
|
||||
|
||||
if (bool(params.flags & FLAG_CONVERT_TO_SRGB)) {
|
||||
color.rgb = linear_to_srgb(color.rgb); // Regular linear -> SRGB conversion.
|
||||
}
|
||||
#ifndef SUBPASS
|
||||
// Glow
|
||||
if (params.use_glow && params.glow_mode != GLOW_MODE_MIX) {
|
||||
if (bool(params.flags & FLAG_USE_GLOW) && params.glow_mode != GLOW_MODE_MIX) {
|
||||
vec3 glow = gather_glow(source_glow, uv_interp) * params.glow_intensity * params.luminance_multiplier;
|
||||
if (params.glow_map_strength > 0.001) {
|
||||
glow = mix(glow, texture(glow_map, uv_interp).rgb * glow, params.glow_map_strength);
|
||||
|
@ -476,7 +482,9 @@ void main() {
|
|||
|
||||
// high dynamic range -> SRGB
|
||||
glow = apply_tonemapping(glow, params.white);
|
||||
glow = linear_to_srgb(glow);
|
||||
if (bool(params.flags & FLAG_CONVERT_TO_SRGB)) {
|
||||
glow = linear_to_srgb(glow);
|
||||
}
|
||||
|
||||
color.rgb = apply_glow(color.rgb, glow);
|
||||
}
|
||||
|
@ -484,15 +492,15 @@ void main() {
|
|||
|
||||
// Additional effects
|
||||
|
||||
if (params.use_bcs) {
|
||||
if (bool(params.flags & FLAG_USE_BCS)) {
|
||||
color.rgb = apply_bcs(color.rgb, params.bcs);
|
||||
}
|
||||
|
||||
if (params.use_color_correction) {
|
||||
if (bool(params.flags & FLAG_USE_COLOR_CORRECTION)) {
|
||||
color.rgb = apply_color_correction(color.rgb);
|
||||
}
|
||||
|
||||
if (params.use_debanding) {
|
||||
if (bool(params.flags & FLAG_USE_DEBANDING)) {
|
||||
// Debanding should be done at the end of tonemapping, but before writing to the LDR buffer.
|
||||
// Otherwise, we're adding noise to an already-quantized image.
|
||||
color.rgb += screen_space_dither(gl_FragCoord.xy);
|
||||
|
|
|
@ -751,7 +751,7 @@ MaterialStorage::MaterialData::~MaterialData() {
|
|||
}
|
||||
}
|
||||
|
||||
void MaterialStorage::MaterialData::update_textures(const HashMap<StringName, Variant> &p_parameters, const HashMap<StringName, HashMap<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) {
|
||||
void MaterialStorage::MaterialData::update_textures(const HashMap<StringName, Variant> &p_parameters, const HashMap<StringName, HashMap<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color, bool p_3d_material) {
|
||||
TextureStorage *texture_storage = TextureStorage::get_singleton();
|
||||
MaterialStorage *material_storage = MaterialStorage::get_singleton();
|
||||
|
||||
|
@ -917,7 +917,7 @@ void MaterialStorage::MaterialData::update_textures(const HashMap<StringName, Va
|
|||
if (tex) {
|
||||
rd_texture = (srgb && tex->rd_texture_srgb.is_valid()) ? tex->rd_texture_srgb : tex->rd_texture;
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (tex->detect_3d_callback && p_use_linear_color) {
|
||||
if (tex->detect_3d_callback && p_3d_material) {
|
||||
tex->detect_3d_callback(tex->detect_3d_callback_ud);
|
||||
}
|
||||
if (tex->detect_normal_callback && (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL || p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL)) {
|
||||
|
@ -986,7 +986,7 @@ void MaterialStorage::MaterialData::free_parameters_uniform_set(RID p_uniform_se
|
|||
}
|
||||
}
|
||||
|
||||
bool MaterialStorage::MaterialData::update_parameters_uniform_set(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, bool p_use_linear_color, uint32_t p_barrier) {
|
||||
bool MaterialStorage::MaterialData::update_parameters_uniform_set(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, bool p_use_linear_color, bool p_3d_material, uint32_t p_barrier) {
|
||||
if ((uint32_t)ubo_data.size() != p_ubo_size) {
|
||||
p_uniform_dirty = true;
|
||||
if (uniform_buffer.is_valid()) {
|
||||
|
@ -1033,7 +1033,7 @@ bool MaterialStorage::MaterialData::update_parameters_uniform_set(const HashMap<
|
|||
}
|
||||
|
||||
if (p_textures_dirty && tex_uniform_count) {
|
||||
update_textures(p_parameters, p_default_texture_params, p_texture_uniforms, texture_cache.ptrw(), p_use_linear_color);
|
||||
update_textures(p_parameters, p_default_texture_params, p_texture_uniforms, texture_cache.ptrw(), p_use_linear_color, p_3d_material);
|
||||
}
|
||||
|
||||
if (p_ubo_size == 0 && (p_texture_uniforms.size() == 0)) {
|
||||
|
|
|
@ -78,7 +78,7 @@ public:
|
|||
struct MaterialData {
|
||||
Vector<RendererRD::TextureStorage::RenderTarget *> render_target_cache;
|
||||
void update_uniform_buffer(const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const HashMap<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color);
|
||||
void update_textures(const HashMap<StringName, Variant> &p_parameters, const HashMap<StringName, HashMap<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color);
|
||||
void update_textures(const HashMap<StringName, Variant> &p_parameters, const HashMap<StringName, HashMap<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color, bool p_3d_material);
|
||||
void set_as_used();
|
||||
|
||||
virtual void set_render_priority(int p_priority) = 0;
|
||||
|
@ -87,7 +87,7 @@ public:
|
|||
virtual ~MaterialData();
|
||||
|
||||
//to be used internally by update_parameters, in the most common configuration of material parameters
|
||||
bool update_parameters_uniform_set(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, bool p_use_linear_color, uint32_t p_barrier = RD::BARRIER_MASK_ALL_BARRIERS);
|
||||
bool update_parameters_uniform_set(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &r_uniform_set, RID p_shader, uint32_t p_shader_uniform_set, bool p_use_linear_color, bool p_3d_material, uint32_t p_barrier = RD::BARRIER_MASK_ALL_BARRIERS);
|
||||
void free_parameters_uniform_set(RID p_uniform_set);
|
||||
|
||||
private:
|
||||
|
|
|
@ -1629,7 +1629,7 @@ MaterialStorage::ShaderData *ParticlesStorage::_create_particles_shader_func() {
|
|||
}
|
||||
|
||||
bool ParticlesStorage::ParticleProcessMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
|
||||
return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, ParticlesStorage::get_singleton()->particles_shader.shader.version_get_shader(shader_data->version, 0), 3, true);
|
||||
return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, ParticlesStorage::get_singleton()->particles_shader.shader.version_get_shader(shader_data->version, 0), 3, true, false);
|
||||
}
|
||||
|
||||
ParticlesStorage::ParticleProcessMaterialData::~ParticleProcessMaterialData() {
|
||||
|
|
|
@ -46,9 +46,11 @@ void TextureStorage::CanvasTexture::clear_sets() {
|
|||
}
|
||||
for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
|
||||
for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
|
||||
if (RD::get_singleton()->uniform_set_is_valid(uniform_sets[i][j])) {
|
||||
RD::get_singleton()->free(uniform_sets[i][j]);
|
||||
uniform_sets[i][j] = RID();
|
||||
for (int k = 0; k < 2; k++) {
|
||||
if (RD::get_singleton()->uniform_set_is_valid(uniform_sets[i][j][k])) {
|
||||
RD::get_singleton()->free(uniform_sets[i][j][k]);
|
||||
uniform_sets[i][j][k] = RID();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -641,7 +643,7 @@ void TextureStorage::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS:
|
|||
ct->clear_sets();
|
||||
}
|
||||
|
||||
bool TextureStorage::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular) {
|
||||
bool TextureStorage::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, bool p_use_srgb, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular) {
|
||||
MaterialStorage *material_storage = MaterialStorage::get_singleton();
|
||||
|
||||
CanvasTexture *ct = nullptr;
|
||||
|
@ -674,7 +676,7 @@ bool TextureStorage::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasIte
|
|||
RS::CanvasItemTextureRepeat repeat = ct->texture_repeat != RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT ? ct->texture_repeat : p_base_repeat;
|
||||
ERR_FAIL_COND_V(repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, false);
|
||||
|
||||
RID uniform_set = ct->uniform_sets[filter][repeat];
|
||||
RID uniform_set = ct->uniform_sets[filter][repeat][int(p_use_srgb)];
|
||||
if (!RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
|
||||
//create and update
|
||||
Vector<RD::Uniform> uniforms;
|
||||
|
@ -688,7 +690,7 @@ bool TextureStorage::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasIte
|
|||
u.append_id(texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE));
|
||||
ct->size_cache = Size2i(1, 1);
|
||||
} else {
|
||||
u.append_id(t->rd_texture);
|
||||
u.append_id(t->rd_texture_srgb.is_valid() && (p_use_srgb) ? t->rd_texture_srgb : t->rd_texture);
|
||||
ct->size_cache = Size2i(t->width_2d, t->height_2d);
|
||||
if (t->render_target) {
|
||||
t->render_target->was_used = true;
|
||||
|
@ -741,7 +743,7 @@ bool TextureStorage::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasIte
|
|||
}
|
||||
|
||||
uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_base_shader, p_base_set);
|
||||
ct->uniform_sets[filter][repeat] = uniform_set;
|
||||
ct->uniform_sets[filter][repeat][int(p_use_srgb)] = uniform_set;
|
||||
ct->cleared_cache = false;
|
||||
}
|
||||
|
||||
|
@ -1268,7 +1270,35 @@ Ref<Image> TextureStorage::texture_2d_get(RID p_texture) const {
|
|||
#endif
|
||||
Vector<uint8_t> data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0);
|
||||
ERR_FAIL_COND_V(data.size() == 0, Ref<Image>());
|
||||
Ref<Image> image = Image::create_from_data(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data);
|
||||
Ref<Image> image;
|
||||
|
||||
// Expand RGB10_A2 into RGBAH. This is needed for capturing viewport data
|
||||
// when using the mobile renderer with HDR mode on.
|
||||
if (tex->rd_format == RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32) {
|
||||
Vector<uint8_t> new_data;
|
||||
new_data.resize(data.size() * 2);
|
||||
uint16_t *ndp = (uint16_t *)new_data.ptr();
|
||||
|
||||
uint32_t *ptr = (uint32_t *)data.ptr();
|
||||
uint32_t num_pixels = data.size() / 4;
|
||||
|
||||
for (uint32_t ofs = 0; ofs < num_pixels; ofs++) {
|
||||
uint32_t px = ptr[ofs];
|
||||
uint32_t r = (px & 0x3FF);
|
||||
uint32_t g = ((px >> 10) & 0x3FF);
|
||||
uint32_t b = ((px >> 20) & 0x3FF);
|
||||
uint32_t a = ((px >> 30) & 0x3);
|
||||
|
||||
ndp[ofs * 4 + 0] = Math::make_half_float(float(r) / 1023.0);
|
||||
ndp[ofs * 4 + 1] = Math::make_half_float(float(g) / 1023.0);
|
||||
ndp[ofs * 4 + 2] = Math::make_half_float(float(b) / 1023.0);
|
||||
ndp[ofs * 4 + 3] = Math::make_half_float(float(a) / 3.0);
|
||||
}
|
||||
image = Image::create_from_data(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, new_data);
|
||||
} else {
|
||||
image = Image::create_from_data(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data);
|
||||
}
|
||||
|
||||
ERR_FAIL_COND_V(image->is_empty(), Ref<Image>());
|
||||
if (tex->format != tex->validated_format) {
|
||||
image->convert(tex->format);
|
||||
|
@ -3020,10 +3050,15 @@ void TextureStorage::_update_render_target(RenderTarget *rt) {
|
|||
if (rt->size.width == 0 || rt->size.height == 0) {
|
||||
return;
|
||||
}
|
||||
//until we implement support for HDR monitors (and render target is attached to screen), this is enough.
|
||||
rt->color_format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
|
||||
rt->color_format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
|
||||
rt->image_format = rt->is_transparent ? Image::FORMAT_RGBA8 : Image::FORMAT_RGB8;
|
||||
if (rt->use_hdr) {
|
||||
rt->color_format = RendererSceneRenderRD::get_singleton()->_render_buffers_get_color_format();
|
||||
rt->color_format_srgb = rt->color_format;
|
||||
rt->image_format = rt->is_transparent ? Image::FORMAT_RGBAH : Image::FORMAT_RGBH;
|
||||
} else {
|
||||
rt->color_format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
|
||||
rt->color_format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
|
||||
rt->image_format = rt->is_transparent ? Image::FORMAT_RGBA8 : Image::FORMAT_RGB8;
|
||||
}
|
||||
|
||||
RD::TextureFormat rd_color_attachment_format;
|
||||
RD::TextureView rd_view;
|
||||
|
@ -3106,6 +3141,7 @@ void TextureStorage::_update_render_target(RenderTarget *rt) {
|
|||
tex->rd_format = rt->color_format;
|
||||
tex->rd_format_srgb = rt->color_format_srgb;
|
||||
tex->format = rt->image_format;
|
||||
tex->validated_format = rt->use_hdr ? Image::FORMAT_RGBAH : Image::FORMAT_RGBA8;
|
||||
|
||||
Vector<RID> proxies = tex->proxies; //make a copy, since update may change it
|
||||
for (int i = 0; i < proxies.size(); i++) {
|
||||
|
@ -3328,6 +3364,25 @@ RS::ViewportMSAA TextureStorage::render_target_get_msaa(RID p_render_target) con
|
|||
return rt->msaa;
|
||||
}
|
||||
|
||||
void TextureStorage::render_target_set_use_hdr(RID p_render_target, bool p_use_hdr) {
|
||||
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
|
||||
ERR_FAIL_COND(!rt);
|
||||
|
||||
if (p_use_hdr == rt->use_hdr) {
|
||||
return;
|
||||
}
|
||||
|
||||
rt->use_hdr = p_use_hdr;
|
||||
_update_render_target(rt);
|
||||
}
|
||||
|
||||
bool TextureStorage::render_target_is_using_hdr(RID p_render_target) const {
|
||||
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
|
||||
ERR_FAIL_COND_V(!rt, false);
|
||||
|
||||
return rt->use_hdr;
|
||||
}
|
||||
|
||||
RID TextureStorage::render_target_get_rd_framebuffer(RID p_render_target) {
|
||||
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
|
||||
ERR_FAIL_COND_V(!rt, RID());
|
||||
|
@ -3404,7 +3459,7 @@ bool TextureStorage::render_target_is_clear_requested(RID p_render_target) {
|
|||
Color TextureStorage::render_target_get_clear_request_color(RID p_render_target) {
|
||||
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
|
||||
ERR_FAIL_COND_V(!rt, Color());
|
||||
return rt->clear_color;
|
||||
return rt->use_hdr ? rt->clear_color.srgb_to_linear() : rt->clear_color;
|
||||
}
|
||||
|
||||
void TextureStorage::render_target_disable_clear_request(RID p_render_target) {
|
||||
|
@ -3420,7 +3475,7 @@ void TextureStorage::render_target_do_clear_request(RID p_render_target) {
|
|||
return;
|
||||
}
|
||||
Vector<Color> clear_colors;
|
||||
clear_colors.push_back(rt->clear_color);
|
||||
clear_colors.push_back(rt->use_hdr ? rt->clear_color.srgb_to_linear() : rt->clear_color);
|
||||
RD::get_singleton()->draw_list_begin(rt->get_framebuffer(), RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, clear_colors);
|
||||
RD::get_singleton()->draw_list_end();
|
||||
rt->clear_requested = false;
|
||||
|
@ -3735,7 +3790,7 @@ void TextureStorage::render_target_copy_to_back_buffer(RID p_render_target, cons
|
|||
// TODO figure out stereo support here
|
||||
|
||||
if (RendererSceneRenderRD::get_singleton()->_render_buffers_can_be_storage()) {
|
||||
copy_effects->copy_to_rect(rt->color, rt->backbuffer_mipmap0, region, false, false, false, true, true);
|
||||
copy_effects->copy_to_rect(rt->color, rt->backbuffer_mipmap0, region, false, false, false, !rt->use_hdr, true);
|
||||
} else {
|
||||
copy_effects->copy_to_fb_rect(rt->color, rt->backbuffer_fb, region, false, false, false, false, RID(), false, true);
|
||||
}
|
||||
|
@ -3759,7 +3814,7 @@ void TextureStorage::render_target_copy_to_back_buffer(RID p_render_target, cons
|
|||
|
||||
RID mipmap = rt->backbuffer_mipmaps[i];
|
||||
if (RendererSceneRenderRD::get_singleton()->_render_buffers_can_be_storage()) {
|
||||
copy_effects->gaussian_blur(prev_texture, mipmap, region, texture_size, true);
|
||||
copy_effects->gaussian_blur(prev_texture, mipmap, region, texture_size, !rt->use_hdr);
|
||||
} else {
|
||||
copy_effects->gaussian_blur_raster(prev_texture, mipmap, region, texture_size);
|
||||
}
|
||||
|
@ -3789,9 +3844,9 @@ void TextureStorage::render_target_clear_back_buffer(RID p_render_target, const
|
|||
}
|
||||
}
|
||||
|
||||
//single texture copy for backbuffer
|
||||
// Single texture copy for backbuffer.
|
||||
if (RendererSceneRenderRD::get_singleton()->_render_buffers_can_be_storage()) {
|
||||
copy_effects->set_color(rt->backbuffer_mipmap0, p_color, region, true);
|
||||
copy_effects->set_color(rt->backbuffer_mipmap0, p_color, region, !rt->use_hdr);
|
||||
} else {
|
||||
copy_effects->set_color_raster(rt->backbuffer_mipmap0, p_color, region);
|
||||
}
|
||||
|
@ -3833,7 +3888,7 @@ void TextureStorage::render_target_gen_back_buffer_mipmaps(RID p_render_target,
|
|||
RID mipmap = rt->backbuffer_mipmaps[i];
|
||||
|
||||
if (RendererSceneRenderRD::get_singleton()->_render_buffers_can_be_storage()) {
|
||||
copy_effects->gaussian_blur(prev_texture, mipmap, region, texture_size, true);
|
||||
copy_effects->gaussian_blur(prev_texture, mipmap, region, texture_size, !rt->use_hdr);
|
||||
} else {
|
||||
copy_effects->gaussian_blur_raster(prev_texture, mipmap, region, texture_size);
|
||||
}
|
||||
|
|
|
@ -96,7 +96,7 @@ private:
|
|||
|
||||
RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT;
|
||||
RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT;
|
||||
RID uniform_sets[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
|
||||
RID uniform_sets[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX][2];
|
||||
|
||||
Size2i size_cache = Size2i(1, 1);
|
||||
bool use_normal_cache = false;
|
||||
|
@ -341,6 +341,7 @@ private:
|
|||
Image::Format image_format = Image::FORMAT_L8;
|
||||
|
||||
bool is_transparent = false;
|
||||
bool use_hdr = false;
|
||||
|
||||
bool sdf_enabled = false;
|
||||
|
||||
|
@ -474,7 +475,7 @@ public:
|
|||
virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) override;
|
||||
virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override;
|
||||
|
||||
bool canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular);
|
||||
bool canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, bool p_use_srgb, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular);
|
||||
|
||||
/* Texture API */
|
||||
|
||||
|
@ -717,6 +718,8 @@ public:
|
|||
virtual void render_target_set_as_unused(RID p_render_target) override;
|
||||
virtual void render_target_set_msaa(RID p_render_target, RS::ViewportMSAA p_msaa) override;
|
||||
virtual RS::ViewportMSAA render_target_get_msaa(RID p_render_target) const override;
|
||||
virtual void render_target_set_use_hdr(RID p_render_target, bool p_use_hdr) override;
|
||||
virtual bool render_target_is_using_hdr(RID p_render_target) const override;
|
||||
|
||||
void render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region, bool p_gen_mipmaps);
|
||||
void render_target_clear_back_buffer(RID p_render_target, const Rect2i &p_region, const Color &p_color);
|
||||
|
|
|
@ -1163,6 +1163,17 @@ void RendererViewport::viewport_set_msaa_3d(RID p_viewport, RS::ViewportMSAA p_m
|
|||
_configure_3d_render_buffers(viewport);
|
||||
}
|
||||
|
||||
void RendererViewport::viewport_set_use_hdr_2d(RID p_viewport, bool p_use_hdr_2d) {
|
||||
Viewport *viewport = viewport_owner.get_or_null(p_viewport);
|
||||
ERR_FAIL_COND(!viewport);
|
||||
|
||||
if (viewport->use_hdr_2d == p_use_hdr_2d) {
|
||||
return;
|
||||
}
|
||||
viewport->use_hdr_2d = p_use_hdr_2d;
|
||||
RSG::texture_storage->render_target_set_use_hdr(viewport->render_target, p_use_hdr_2d);
|
||||
}
|
||||
|
||||
void RendererViewport::viewport_set_screen_space_aa(RID p_viewport, RS::ViewportScreenSpaceAA p_mode) {
|
||||
Viewport *viewport = viewport_owner.get_or_null(p_viewport);
|
||||
ERR_FAIL_COND(!viewport);
|
||||
|
|
|
@ -116,6 +116,7 @@ public:
|
|||
RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED;
|
||||
|
||||
bool transparent_bg = false;
|
||||
bool use_hdr_2d = false;
|
||||
|
||||
uint32_t canvas_cull_mask = 0xffffffff;
|
||||
|
||||
|
@ -157,6 +158,7 @@ public:
|
|||
update_mode = RS::VIEWPORT_UPDATE_WHEN_VISIBLE;
|
||||
clear_mode = RS::VIEWPORT_CLEAR_ALWAYS;
|
||||
transparent_bg = false;
|
||||
use_hdr_2d = false;
|
||||
|
||||
viewport_to_screen = DisplayServer::INVALID_WINDOW_ID;
|
||||
shadow_atlas_size = 0;
|
||||
|
@ -250,6 +252,7 @@ public:
|
|||
void viewport_remove_canvas(RID p_viewport, RID p_canvas);
|
||||
void viewport_set_canvas_transform(RID p_viewport, RID p_canvas, const Transform2D &p_offset);
|
||||
void viewport_set_transparent_background(RID p_viewport, bool p_enabled);
|
||||
void viewport_set_use_hdr_2d(RID p_viewport, bool p_use_hdr_2d);
|
||||
|
||||
void viewport_set_global_canvas_transform(RID p_viewport, const Transform2D &p_transform);
|
||||
void viewport_set_canvas_stacking(RID p_viewport, RID p_canvas, int p_layer, int p_sublayer);
|
||||
|
|
|
@ -629,6 +629,7 @@ public:
|
|||
FUNC2(viewport_remove_canvas, RID, RID)
|
||||
FUNC3(viewport_set_canvas_transform, RID, RID, const Transform2D &)
|
||||
FUNC2(viewport_set_transparent_background, RID, bool)
|
||||
FUNC2(viewport_set_use_hdr_2d, RID, bool)
|
||||
FUNC2(viewport_set_snap_2d_transforms_to_pixel, RID, bool)
|
||||
FUNC2(viewport_set_snap_2d_vertices_to_pixel, RID, bool)
|
||||
|
||||
|
|
|
@ -151,6 +151,8 @@ public:
|
|||
virtual void render_target_set_as_unused(RID p_render_target) = 0;
|
||||
virtual void render_target_set_msaa(RID p_render_target, RS::ViewportMSAA p_msaa) = 0;
|
||||
virtual RS::ViewportMSAA render_target_get_msaa(RID p_render_target) const = 0;
|
||||
virtual void render_target_set_use_hdr(RID p_render_target, bool p_use_hdr) = 0;
|
||||
virtual bool render_target_is_using_hdr(RID p_render_target) const = 0;
|
||||
|
||||
virtual void render_target_request_clear(RID p_render_target, const Color &p_clear_color) = 0;
|
||||
virtual bool render_target_is_clear_requested(RID p_render_target) = 0;
|
||||
|
|
|
@ -2231,6 +2231,7 @@ void RenderingServer::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("viewport_set_positional_shadow_atlas_quadrant_subdivision", "viewport", "quadrant", "subdivision"), &RenderingServer::viewport_set_positional_shadow_atlas_quadrant_subdivision);
|
||||
ClassDB::bind_method(D_METHOD("viewport_set_msaa_3d", "viewport", "msaa"), &RenderingServer::viewport_set_msaa_3d);
|
||||
ClassDB::bind_method(D_METHOD("viewport_set_msaa_2d", "viewport", "msaa"), &RenderingServer::viewport_set_msaa_2d);
|
||||
ClassDB::bind_method(D_METHOD("viewport_set_use_hdr_2d", "viewport", "enabled"), &RenderingServer::viewport_set_use_hdr_2d);
|
||||
ClassDB::bind_method(D_METHOD("viewport_set_screen_space_aa", "viewport", "mode"), &RenderingServer::viewport_set_screen_space_aa);
|
||||
ClassDB::bind_method(D_METHOD("viewport_set_use_taa", "viewport", "enable"), &RenderingServer::viewport_set_use_taa);
|
||||
ClassDB::bind_method(D_METHOD("viewport_set_use_debanding", "viewport", "enable"), &RenderingServer::viewport_set_use_debanding);
|
||||
|
|
|
@ -863,6 +863,7 @@ public:
|
|||
virtual void viewport_remove_canvas(RID p_viewport, RID p_canvas) = 0;
|
||||
virtual void viewport_set_canvas_transform(RID p_viewport, RID p_canvas, const Transform2D &p_offset) = 0;
|
||||
virtual void viewport_set_transparent_background(RID p_viewport, bool p_enabled) = 0;
|
||||
virtual void viewport_set_use_hdr_2d(RID p_viewport, bool p_use_hdr) = 0;
|
||||
virtual void viewport_set_snap_2d_transforms_to_pixel(RID p_viewport, bool p_enabled) = 0;
|
||||
virtual void viewport_set_snap_2d_vertices_to_pixel(RID p_viewport, bool p_enabled) = 0;
|
||||
|
||||
|
|
Loading…
Reference in New Issue