Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable post process with full precision using SubViewport #61667

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions doc/classes/RenderingServer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3185,6 +3185,15 @@
If [code]true[/code], rendering of a viewport's environment is disabled.
</description>
</method>
<method name="viewport_set_force_high_precision">
<return type="void" />
<param index="0" name="viewport" type="RID" />
<param index="1" name="enable" type="bool" />
<description>
If [code]true[/code] and using the Vulkan-Clustered or Vulkan-mobile renderer, high precision will be used in the 2D rendering pipeline (3D is always high precision) and [method viewport_get_texture] will return an image with the [constant Image.FORMAT_RGBAH] format.
Use with [method viewport_set_keep_linear] to obtain an accurate texture containing the rendering results from a frame.
</description>
</method>
<method name="viewport_set_fsr_sharpness">
<return type="void" />
<param index="0" name="viewport" type="RID" />
Expand All @@ -3201,6 +3210,14 @@
Sets the viewport's global transformation matrix.
</description>
</method>
<method name="viewport_set_keep_linear">
<return type="void" />
<param index="0" name="viewport" type="RID" />
<param index="1" name="enable" type="bool" />
<description>
If [code]true[/code], skip linear to sRGB conversion during tonemapping. If used without [method viewport_set_force_high_precision] this can result in significant banding in the rendered output.
</description>
</method>
<method name="viewport_set_measure_render_time">
<return type="void" />
<param index="0" name="viewport" type="RID" />
Expand Down
7 changes: 7 additions & 0 deletions doc/classes/Viewport.xml
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,9 @@
<member name="disable_3d" type="bool" setter="set_disable_3d" getter="is_3d_disabled" default="false">
Disable 3D rendering (but keep 2D rendering).
</member>
<member name="force_high_precision" type="bool" setter="set_force_high_precision" getter="is_forced_high_precision" default="false">
If [code]true[/code] and using the Vulkan-Clustered or Vulkan-mobile renderer, high precision will be used in the 2D rendering pipeline (3D is always high precision) and [method get_texture] will return an image with the [constant Image.FORMAT_RGBAH] format. Use with [member keep_linear] to obtain an accurate texture containing the rendering results from a frame.
</member>
<member name="fsr_sharpness" type="float" setter="set_fsr_sharpness" getter="get_fsr_sharpness" default="0.2">
Determines how sharp the upscaled image will be when using the FSR upscaling mode. Sharpness halves with every whole number. Values go from 0.0 (sharpest) to 2.0. Values above 2.0 won't make a visible difference.
To control this property on the root viewport, set the [member ProjectSettings.rendering/scaling_3d/fsr_sharpness] project setting.
Expand All @@ -213,6 +216,10 @@
</member>
<member name="handle_input_locally" type="bool" setter="set_handle_input_locally" getter="is_handling_input_locally" default="true">
</member>
<member name="keep_linear" type="bool" setter="set_keep_linear" getter="is_keeping_linear" default="false">
If [code]true[/code], skip linear to sRGB conversion during tonemapping.
[b]Note:[/b] If used without [member force_high_precision] this can result in significant banding in the rendered output.
</member>
<member name="mesh_lod_threshold" type="float" setter="set_mesh_lod_threshold" getter="get_mesh_lod_threshold" default="1.0">
The automatic LOD bias to use for meshes rendered within the [Viewport] (this is analogous to [member ReflectionProbe.mesh_lod_threshold]). Higher values will use less detailed versions of meshes that have LOD variations generated. If set to [code]0.0[/code], automatic LOD is disabled. Increase [member mesh_lod_threshold] to improve performance at the cost of geometry detail.
To control this property on the root viewport, set the [member ProjectSettings.rendering/mesh_lod/lod_change/threshold_pixels] project setting.
Expand Down
5 changes: 4 additions & 1 deletion drivers/gles3/rasterizer_scene_gles3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1398,6 +1398,7 @@ void RasterizerSceneGLES3::_setup_environment(const RenderDataGLES3 *p_render_da

//time global variables
scene_state.ubo.time = time;
scene_state.ubo.keep_linear = p_render_data->keep_linear;

if (is_environment(p_render_data->environment)) {
RS::EnvironmentBG env_bg = environment_get_background(p_render_data->environment);
Expand Down Expand Up @@ -1721,6 +1722,7 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData *
render_data.screen_mesh_lod_threshold = p_screen_mesh_lod_threshold;
}
render_data.render_info = r_render_info;
render_data.keep_linear = rb->keep_linear;
}

PagedArray<RID> empty;
Expand Down Expand Up @@ -2275,7 +2277,7 @@ RID RasterizerSceneGLES3::render_buffers_create() {
return render_buffers_owner.make_rid(rb);
}

void RasterizerSceneGLES3::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) {
void RasterizerSceneGLES3::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count, bool p_keep_linear) {
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();

RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
Expand All @@ -2291,6 +2293,7 @@ void RasterizerSceneGLES3::render_buffers_configure(RID p_render_buffers, RID p_
//rb->screen_space_aa = p_screen_space_aa;
//rb->use_debanding = p_use_debanding;
//rb->view_count = p_view_count;
rb->keep_linear = p_keep_linear;

_free_render_buffer_data(rb);

Expand Down
7 changes: 5 additions & 2 deletions drivers/gles3/rasterizer_scene_gles3.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ struct RenderDataGLES3 {
uint32_t spot_light_count = 0;
uint32_t omni_light_count = 0;

bool keep_linear = false;

RendererScene::RenderInfo *render_info = nullptr;
};

Expand Down Expand Up @@ -354,10 +356,10 @@ class RasterizerSceneGLES3 : public RendererSceneRender {

float radiance_inverse_xform[12];

bool keep_linear = false;
uint32_t directional_light_count;
float z_far;
float z_near;
float pad1;

uint32_t fog_enabled;
float fog_density;
Expand Down Expand Up @@ -502,6 +504,7 @@ class RasterizerSceneGLES3 : public RendererSceneRender {
//uint32_t view_count = 1;

bool is_transparent = false;
bool keep_linear = false;

RID render_target;
GLuint internal_texture = 0; // Used for rendering when post effects are enabled
Expand Down Expand Up @@ -762,7 +765,7 @@ class RasterizerSceneGLES3 : public RendererSceneRender {
}

RID render_buffers_create() override;
void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override;
void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count, bool p_keep_linear) override;
void gi_set_use_half_resolution(bool p_enable) override;

void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_curve) override;
Expand Down
18 changes: 11 additions & 7 deletions drivers/gles3/shaders/scene.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,10 @@ layout(std140) uniform SceneData { // ubo:2

mat3 radiance_inverse_xform;

bool keep_linear;
uint directional_light_count;
float z_far;
float z_near;
float pad;

bool fog_enabled;
float fog_density;
Expand Down Expand Up @@ -448,10 +448,10 @@ layout(std140) uniform SceneData { // ubo:2

mat3 radiance_inverse_xform;

bool keep_linear;
uint directional_light_count;
float z_far;
float z_near;
float pad;

bool fog_enabled;
float fog_density;
Expand Down Expand Up @@ -1032,8 +1032,10 @@ void main() {
#ifndef MODE_RENDER_DEPTH

// Convert colors to linear
albedo = srgb_to_linear(albedo);
emission = srgb_to_linear(emission);
if (!scene_data.keep_linear) {
albedo = srgb_to_linear(albedo);
emission = srgb_to_linear(emission);
}
// TODO Backlight and transmittance when used
#ifndef MODE_UNSHADED
vec3 f0 = F0(metallic, specular, albedo);
Expand Down Expand Up @@ -1248,10 +1250,12 @@ void main() {
}
#endif

// Tonemap before writing as we are writing to an sRGB framebuffer
frag_color.rgb *= exposure;
frag_color.rgb = apply_tonemapping(frag_color.rgb, white);
frag_color.rgb = linear_to_srgb(frag_color.rgb);
if (!scene_data.keep_linear) {
// Tonemap before writing as we are writing to an sRGB framebuffer
frag_color.rgb = apply_tonemapping(frag_color.rgb, white);
frag_color.rgb = linear_to_srgb(frag_color.rgb);
}

#ifdef USE_BCS
frag_color.rgb = apply_bcs(frag_color.rgb, bcs);
Expand Down
2 changes: 2 additions & 0 deletions drivers/gles3/storage/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,11 @@ Config::Config() {
etc2_supported = false;
s3tc_supported = true;
rgtc_supported = true; //RGTC - core since OpenGL version 3.0
framebuffer_float_supported = true;
#else
float_texture_supported = extensions.has("GL_ARB_texture_float") || extensions.has("GL_OES_texture_float");
etc2_supported = true;
framebuffer_float_supported = extensions.has("GL_EXT_color_buffer_float") && extensions.has("GL_EXT_color_buffer_half_float");
#if defined(ANDROID_ENABLED) || defined(IOS_ENABLED)
// Some Android devices report support for S3TC but we don't expect that and don't export the textures.
// This could be fixed but so few devices support it that it doesn't seem useful (and makes bigger APKs).
Expand Down
1 change: 1 addition & 0 deletions drivers/gles3/storage/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ class Config {
bool rgtc_supported = false;
bool bptc_supported = false;
bool etc2_supported = false;
bool framebuffer_float_supported = false;

bool force_vertex_shading = false;

Expand Down
25 changes: 20 additions & 5 deletions drivers/gles3/storage/texture_storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1186,6 +1186,7 @@ AABB TextureStorage::decal_get_aabb(RID p_decal) const {
GLuint TextureStorage::system_fbo = 0;

void TextureStorage::_update_render_target(RenderTarget *rt) {
Config *config = Config::get_singleton();
// do not allocate a render target with no size
if (rt->size.x <= 0 || rt->size.y <= 0) {
return;
Expand All @@ -1196,11 +1197,17 @@ void TextureStorage::_update_render_target(RenderTarget *rt) {
rt->fbo = system_fbo;
return;
}

rt->color_internal_format = rt->is_transparent ? GL_RGBA8 : GL_RGB10_A2;
rt->color_format = GL_RGBA;
rt->color_type = rt->is_transparent ? GL_BYTE : GL_UNSIGNED_INT_2_10_10_10_REV;
rt->image_format = Image::FORMAT_RGBA8;
if (rt->force_high_precision && config->framebuffer_float_supported) {
rt->color_internal_format = rt->is_transparent ? GL_RGBA16F : GL_RGB16F;
clayjohn marked this conversation as resolved.
Show resolved Hide resolved
rt->color_format = GL_RGBA;
rt->color_type = GL_HALF_FLOAT;
rt->image_format = Image::FORMAT_RGBAF;
} else {
rt->color_internal_format = rt->is_transparent ? GL_RGBA8 : GL_RGB10_A2;
rt->color_format = GL_RGBA;
rt->color_type = rt->is_transparent ? GL_BYTE : GL_UNSIGNED_INT_2_10_10_10_REV;
rt->image_format = Image::FORMAT_RGBA8;
}

glDisable(GL_SCISSOR_TEST);
glColorMask(1, 1, 1, 1);
Expand Down Expand Up @@ -1390,6 +1397,14 @@ void TextureStorage::render_target_free(RID p_rid) {
}
render_target_owner.free(p_rid);
}
void TextureStorage::render_target_set_force_high_precision(RID p_render_target, bool p_force_high_precision) {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND(!rt);
if (rt->force_high_precision != p_force_high_precision) {
rt->force_high_precision = p_force_high_precision;
_update_render_target(rt);
}
JonqsGames marked this conversation as resolved.
Show resolved Hide resolved
}

void TextureStorage::render_target_set_position(RID p_render_target, int p_x, int p_y) {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
Expand Down
4 changes: 4 additions & 0 deletions drivers/gles3/storage/texture_storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@ struct RenderTarget {

bool is_transparent = false;
bool direct_to_screen = false;
bool force_high_precision = false;

bool used_in_frame = false;
RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED;
Expand Down Expand Up @@ -518,6 +519,9 @@ class TextureStorage : public RendererTextureStorage {

virtual RID render_target_create() override;
virtual void render_target_free(RID p_rid) override;

virtual void render_target_set_force_high_precision(RID p_render_target, bool p_force_high_precision) override;

virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) override;
virtual void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) override;
Size2i render_target_get_size(RID p_render_target);
Expand Down
40 changes: 38 additions & 2 deletions scene/main/viewport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2947,6 +2947,34 @@ bool Viewport::is_using_occlusion_culling() const {
return use_occlusion_culling;
}

void Viewport::set_keep_linear(bool p_keep_linear) {
if (keep_linear == p_keep_linear) {
return;
}
keep_linear = p_keep_linear;
RS::get_singleton()->viewport_set_keep_linear(viewport, p_keep_linear);

notify_property_list_changed();
}

bool Viewport::is_keeping_linear() const {
return keep_linear;
}

void Viewport::set_force_high_precision(bool p_force_high_precision) {
if (force_high_precision == p_force_high_precision) {
return;
}
force_high_precision = p_force_high_precision;
RS::get_singleton()->viewport_set_force_high_precision(viewport, force_high_precision);

notify_property_list_changed();
}

bool Viewport::is_forced_high_precision() const {
return force_high_precision;
}

void Viewport::set_debug_draw(DebugDraw p_debug_draw) {
debug_draw = p_debug_draw;
RS::get_singleton()->viewport_set_debug_draw(viewport, RS::ViewportDebugDraw(p_debug_draw));
Expand Down Expand Up @@ -3590,7 +3618,6 @@ void Viewport::_propagate_exit_world_3d(Node *p_node) {
_propagate_exit_world_3d(p_node->get_child(i));
}
}

void Viewport::set_use_xr(bool p_use_xr) {
use_xr = p_use_xr;

Expand Down Expand Up @@ -3690,6 +3717,12 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_use_occlusion_culling", "enable"), &Viewport::set_use_occlusion_culling);
ClassDB::bind_method(D_METHOD("is_using_occlusion_culling"), &Viewport::is_using_occlusion_culling);

ClassDB::bind_method(D_METHOD("set_keep_linear", "enable"), &Viewport::set_keep_linear);
ClassDB::bind_method(D_METHOD("is_keeping_linear"), &Viewport::is_keeping_linear);

ClassDB::bind_method(D_METHOD("set_force_high_precision", "enable"), &Viewport::set_force_high_precision);
ClassDB::bind_method(D_METHOD("is_forced_high_precision"), &Viewport::is_forced_high_precision);

ClassDB::bind_method(D_METHOD("set_debug_draw", "debug_draw"), &Viewport::set_debug_draw);
ClassDB::bind_method(D_METHOD("get_debug_draw"), &Viewport::get_debug_draw);

Expand Down Expand Up @@ -3821,6 +3854,8 @@ void Viewport::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_taa"), "set_use_taa", "is_using_taa");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_debanding"), "set_use_debanding", "is_using_debanding");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_occlusion_culling"), "set_use_occlusion_culling", "is_using_occlusion_culling");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "keep_linear"), "set_keep_linear", "is_keeping_linear");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "force_high_precision"), "set_force_high_precision", "is_forced_high_precision");
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,Overdraw,Wireframe"), "set_debug_draw", "get_debug_draw");
#ifndef _3D_DISABLED
Expand Down Expand Up @@ -4145,6 +4180,7 @@ void SubViewport::_bind_methods() {
BIND_ENUM_CONSTANT(UPDATE_ALWAYS);
}

SubViewport::SubViewport() {}
SubViewport::SubViewport() {
}

SubViewport::~SubViewport() {}
10 changes: 9 additions & 1 deletion scene/main/viewport.h
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,9 @@ class Viewport : public Node {
float mesh_lod_threshold = 1.0;
bool use_occlusion_culling = false;

bool keep_linear = false;
bool force_high_precision = false;

Ref<ViewportTexture> default_texture;
HashSet<ViewportTexture *> viewport_textures;

Expand Down Expand Up @@ -552,6 +555,12 @@ class Viewport : public Node {
void set_use_occlusion_culling(bool p_us_occlusion_culling);
bool is_using_occlusion_culling() const;

void set_keep_linear(bool p_keep_linear);
bool is_keeping_linear() const;

void set_force_high_precision(bool p_force_high_precision);
bool is_forced_high_precision() const;

Vector2 get_camera_coords(const Vector2 &p_viewport_coords) const;
Vector2 get_camera_rect_size() const;

Expand Down Expand Up @@ -704,7 +713,6 @@ class Viewport : public Node {
bool is_using_own_world_3d() const;
void _propagate_enter_world_3d(Node *p_node);
void _propagate_exit_world_3d(Node *p_node);

void set_use_xr(bool p_use_xr);
bool is_using_xr();
#endif // _3D_DISABLED
Expand Down
2 changes: 1 addition & 1 deletion servers/rendering/dummy/rasterizer_scene_dummy.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ class RasterizerSceneDummy : public RendererSceneRender {
void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) override {}

RID render_buffers_create() override { return RID(); }
void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override {}
void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count, bool p_keep_linear) override {}
void gi_set_use_half_resolution(bool p_enable) override {}

void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_curve) override {}
Expand Down
1 change: 1 addition & 0 deletions servers/rendering/dummy/storage/texture_storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ class TextureStorage : public RendererTextureStorage {

virtual RID render_target_create() override { return RID(); }
virtual void render_target_free(RID p_rid) override {}
virtual void render_target_set_force_high_precision(RID p_render_target, bool p_force_high_precision) override {}
virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) override {}
virtual void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) override {}
virtual RID render_target_get_texture(RID p_render_target) override { return RID(); }
Expand Down
2 changes: 2 additions & 0 deletions servers/rendering/renderer_rd/effects/tone_mapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ void ToneMapper::tonemapper(RID p_source_color, RID p_dst_framebuffer, const Ton

tonemap.push_constant.use_fxaa = p_settings.use_fxaa;
tonemap.push_constant.use_debanding = p_settings.use_debanding;
tonemap.push_constant.keep_linear = p_settings.keep_linear;
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;

Expand Down Expand Up @@ -208,6 +209,7 @@ void ToneMapper::tonemapper(RD::DrawListID p_subpass_draw_list, RID p_source_col
tonemap.push_constant.use_color_correction = p_settings.use_color_correction;

tonemap.push_constant.use_debanding = p_settings.use_debanding;
tonemap.push_constant.keep_linear = p_settings.keep_linear;
tonemap.push_constant.luminance_multiplier = p_settings.luminance_multiplier;

RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
Expand Down
Loading