Skip to content

Commit

Permalink
Add MSAA and scaling support to GLES3
Browse files Browse the repository at this point in the history
  • Loading branch information
BastiaanOlij committed Oct 27, 2023
1 parent 09946f7 commit 0f68664
Show file tree
Hide file tree
Showing 9 changed files with 529 additions and 57 deletions.
2 changes: 2 additions & 0 deletions doc/classes/ProjectSettings.xml
Expand Up @@ -2764,9 +2764,11 @@
</member>
<member name="xr/openxr/foveation_dynamic" type="bool" setter="" getter="" default="false">
If true and foveation is supported, will automatically adjust foveation level based on framerate up to the level set on [member xr/openxr/foveation_level].
[b]Note:[/b] Only works on compatibility renderer and can't be used in conjunction with MSAA, post effects nor scaling.
</member>
<member name="xr/openxr/foveation_level" type="int" setter="" getter="" default="&quot;0&quot;">
Applied foveation level if supported: 0 = off, 1 = low, 2 = medium, 3 = high.
[b]Note:[/b] Only works on compatibility renderer and can't be used in conjunction with MSAA, post effects nor scaling.
</member>
<member name="xr/openxr/reference_space" type="int" setter="" getter="" default="&quot;1&quot;">
Specify the default reference space.
Expand Down
128 changes: 100 additions & 28 deletions drivers/gles3/rasterizer_scene_gles3.cpp
Expand Up @@ -2233,9 +2233,7 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_

bool fb_cleared = false;

Size2i screen_size;
screen_size.x = rb->width;
screen_size.y = rb->height;
Size2i screen_size = rb->internal_size;

bool use_wireframe = get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME;

Expand Down Expand Up @@ -2355,8 +2353,10 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
}
}

glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo);
glViewport(0, 0, rb->width, rb->height);
GLuint fbo = rb->get_render_fbo();

glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glViewport(0, 0, rb->internal_size.x, rb->internal_size.y);

glCullFace(GL_BACK);
glEnable(GL_CULL_FACE);
Expand Down Expand Up @@ -2458,25 +2458,48 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
}

if (scene_state.used_screen_texture || scene_state.used_depth_texture) {
texture_storage->copy_scene_to_backbuffer(rt, scene_state.used_screen_texture, scene_state.used_depth_texture);
glBindFramebuffer(GL_READ_FRAMEBUFFER, rt->fbo);
glReadBuffer(GL_COLOR_ATTACHMENT0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, rt->backbuffer_fbo);
if (scene_state.used_screen_texture) {
glBlitFramebuffer(0, 0, rt->size.x, rt->size.y,
0, 0, rt->size.x, rt->size.y,
GL_COLOR_BUFFER_BIT, GL_NEAREST);
glActiveTexture(GL_TEXTURE0 + config->max_texture_image_units - 5);
glBindTexture(GL_TEXTURE_2D, rt->backbuffer);
}
if (scene_state.used_depth_texture) {
glBlitFramebuffer(0, 0, rt->size.x, rt->size.y,
0, 0, rt->size.x, rt->size.y,
GL_DEPTH_BUFFER_BIT, GL_NEAREST);
glActiveTexture(GL_TEXTURE0 + config->max_texture_image_units - 6);
glBindTexture(GL_TEXTURE_2D, rt->backbuffer_depth);
}
glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo);
Size2i size;
GLuint backbuffer_fbo = 0;
GLuint backbuffer = 0;
GLuint backbuffer_depth = 0;

if (rb->get_scaling_3d_mode() == RS::VIEWPORT_SCALING_3D_MODE_OFF) {
texture_storage->check_backbuffer(rt, scene_state.used_screen_texture, scene_state.used_depth_texture); // note, badly names, this just allocates!

size = rt->size;
backbuffer_fbo = rt->backbuffer_fbo;
backbuffer = rt->backbuffer;
backbuffer_depth = rt->backbuffer_depth;
} else {
rb->check_backbuffer(scene_state.used_screen_texture, scene_state.used_depth_texture);
size = rb->get_internal_size();
backbuffer_fbo = rb->get_backbuffer_fbo();
backbuffer = rb->get_backbuffer();
backbuffer_depth = rb->get_backbuffer_depth();
}

if (backbuffer_fbo != 0) {
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
glReadBuffer(GL_COLOR_ATTACHMENT0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, backbuffer_fbo);
if (scene_state.used_screen_texture) {
glBlitFramebuffer(0, 0, size.x, size.y,
0, 0, size.x, size.y,
GL_COLOR_BUFFER_BIT, GL_NEAREST);
glActiveTexture(GL_TEXTURE0 + config->max_texture_image_units - 5);
glBindTexture(GL_TEXTURE_2D, backbuffer);
}
if (scene_state.used_depth_texture) {
glBlitFramebuffer(0, 0, size.x, size.y,
0, 0, size.x, size.y,
GL_DEPTH_BUFFER_BIT, GL_NEAREST);
glActiveTexture(GL_TEXTURE0 + config->max_texture_image_units - 6);
glBindTexture(GL_TEXTURE_2D, backbuffer_depth);
}
}

// Bound framebuffer may have changed, so change it back
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
}

RENDER_TIMESTAMP("Render 3D Transparent Pass");
Expand All @@ -2493,12 +2516,58 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
}

if (rb.is_valid()) {
_render_buffers_debug_draw(rb, p_shadow_atlas);
_render_buffers_debug_draw(rb, p_shadow_atlas, fbo);
}
glDisable(GL_BLEND);

_render_post_processing(&render_data);

texture_storage->render_target_disable_clear_request(rb->render_target);
}

void RasterizerSceneGLES3::_render_post_processing(const RenderDataGLES3 *p_render_data) {
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
Ref<RenderSceneBuffersGLES3> rb = p_render_data->render_buffers;
ERR_FAIL_COND(rb.is_null());

GLuint fbo_3d = rb->get_render_fbo();
GLuint fbo_rt = texture_storage->render_target_get_fbo(rb->get_render_target()); // TODO if MSAA 2D is enabled, we should be getting that FBO here

if (fbo_3d == fbo_rt) {
// We're already rendering into the render target
return;
}

RS::ViewportScaling3DMode scaling_mode = rb->get_scaling_3d_mode();
RS::ViewportMSAA msaa3d = rb->get_msaa_3d();
Size2i internal_size = rb->get_internal_size();
Size2i target_size = rb->get_target_size();

// Resolve, post-process, scale if needed.
if (msaa3d != RS::VIEWPORT_MSAA_DISABLED) {
// We can use blit to copy things over
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_3d);

if (scaling_mode != RS::VIEWPORT_SCALING_3D_MODE_OFF) {
// We can't combine resolve and scaling, so resolve into our internal buffer
GLuint fbo_int = rb->get_internal_fbo();
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_int);
fbo_3d = fbo_int; // use this as our input for upscaling...
} else {
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_rt);
}
glBlitFramebuffer(0, 0, internal_size.x, internal_size.y, 0, 0, internal_size.x, internal_size.y, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
}

if (scaling_mode == RS::VIEWPORT_SCALING_3D_MODE_BILINEAR) {
// TODO If we have glow or other post processing, we upscale only depth here, post processing will also do scaling.
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_3d);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_rt);
glBlitFramebuffer(0, 0, internal_size.x, internal_size.y, 0, 0, target_size.x, target_size.y, GL_COLOR_BUFFER_BIT, GL_LINEAR);
glBlitFramebuffer(0, 0, internal_size.x, internal_size.y, 0, 0, target_size.x, target_size.y, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
}
}

template <PassMode p_pass_mode>
void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params, const RenderDataGLES3 *p_render_data, uint32_t p_from_element, uint32_t p_to_element, bool p_alpha_pass) {
GLES3::MeshStorage *mesh_storage = GLES3::MeshStorage::get_singleton();
Expand Down Expand Up @@ -3116,7 +3185,7 @@ Ref<RenderSceneBuffers> RasterizerSceneGLES3::render_buffers_create() {
return rb;
}

void RasterizerSceneGLES3::_render_buffers_debug_draw(Ref<RenderSceneBuffersGLES3> p_render_buffers, RID p_shadow_atlas) {
void RasterizerSceneGLES3::_render_buffers_debug_draw(Ref<RenderSceneBuffersGLES3> p_render_buffers, RID p_shadow_atlas, GLuint p_fbo) {
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
GLES3::LightStorage *light_storage = GLES3::LightStorage::get_singleton();
GLES3::CopyEffects *copy_effects = GLES3::CopyEffects::get_singleton();
Expand Down Expand Up @@ -3193,8 +3262,11 @@ void RasterizerSceneGLES3::_render_buffers_debug_draw(Ref<RenderSceneBuffersGLES
}
}
}
glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo);
glViewport(0, 0, rt->size.width, rt->size.height);

// Set back to FBO
glBindFramebuffer(GL_FRAMEBUFFER, p_fbo);
Size2i size = p_render_buffers->get_internal_size();
glViewport(0, 0, size.width, size.height);
glBindTexture(GL_TEXTURE_2D, shadow_atlas_texture);

copy_effects->copy_to_rect(Rect2(Vector2(), Vector2(0.5, 0.5)));
Expand Down
3 changes: 2 additions & 1 deletion drivers/gles3/rasterizer_scene_gles3.h
Expand Up @@ -518,6 +518,7 @@ class RasterizerSceneGLES3 : public RendererSceneRender {
void _fill_render_list(RenderListType p_render_list, const RenderDataGLES3 *p_render_data, PassMode p_pass_mode, bool p_append = false);
void _render_shadows(const RenderDataGLES3 *p_render_data, const Size2i &p_viewport_size = Size2i(1, 1));
void _render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_mesh_lod_threshold = 0.0, RenderingMethod::RenderInfo *p_render_info = nullptr, const Size2i &p_viewport_size = Size2i(1, 1));
void _render_post_processing(const RenderDataGLES3 *p_render_data);

template <PassMode p_pass_mode>
_FORCE_INLINE_ void _render_list_template(RenderListParameters *p_params, const RenderDataGLES3 *p_render_data, uint32_t p_from_element, uint32_t p_to_element, bool p_alpha_pass = false);
Expand All @@ -530,7 +531,7 @@ class RasterizerSceneGLES3 : public RendererSceneRender {
float screen_space_roughness_limiter_amount = 0.25;
float screen_space_roughness_limiter_limit = 0.18;

void _render_buffers_debug_draw(Ref<RenderSceneBuffersGLES3> p_render_buffers, RID p_shadow_atlas);
void _render_buffers_debug_draw(Ref<RenderSceneBuffersGLES3> p_render_buffers, RID p_shadow_atlas, GLuint p_fbo);

/* Camera Attributes */

Expand Down
4 changes: 0 additions & 4 deletions drivers/gles3/storage/material_storage.cpp
Expand Up @@ -2979,10 +2979,6 @@ void SceneShaderData::set_code(const String &p_code) {
WARN_PRINT_ONCE_ED("Transmittance is only available when using the Forward+ rendering backend.");
}

if (uses_depth_texture) {
WARN_PRINT_ONCE_ED("Reading from the depth texture is not supported when using the GL Compatibility backend yet. Support will be added in a future release.");
}

if (uses_normal_texture) {
WARN_PRINT_ONCE_ED("Reading from the normal-roughness texture is only available when using the Forward+ or Mobile rendering backends.");
}
Expand Down

0 comments on commit 0f68664

Please sign in to comment.