1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-04 12:00:25 +00:00

Merge pull request #83976 from BastiaanOlij/gles3_msaa_scaler

Add 3D MSAA and scaling support to GLES3
This commit is contained in:
Rémi Verschelde
2023-12-07 14:36:42 +01:00
committed by GitHub
13 changed files with 832 additions and 55 deletions

View File

@@ -2238,9 +2238,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;
@@ -2360,8 +2358,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);
@@ -2463,25 +2463,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);
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 (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);
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);
}
}
glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo);
// Bound framebuffer may have changed, so change it back
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
}
RENDER_TIMESTAMP("Render 3D Transparent Pass");
@@ -2498,14 +2521,110 @@ 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);
glActiveTexture(GL_TEXTURE0);
}
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());
RID render_target = rb->get_render_target();
Size2i internal_size = rb->get_internal_size();
Size2i target_size = rb->get_target_size();
uint32_t view_count = rb->get_view_count();
// bool msaa2d_needs_resolve = texture_storage->render_target_get_msaa(render_target) != RS::VIEWPORT_MSAA_DISABLED && !GLES3::Config::get_singleton()->rt_msaa_supported;
bool msaa3d_needs_resolve = rb->get_msaa_needs_resolve();
GLuint fbo_msaa_3d = rb->get_msaa3d_fbo();
GLuint fbo_int = rb->get_internal_fbo();
GLuint fbo_rt = texture_storage->render_target_get_fbo(render_target); // TODO if MSAA 2D is enabled and we're not using rt_msaa, get 2D render target here.
if (view_count == 1) {
// Resolve if needed.
if (fbo_msaa_3d != 0 && msaa3d_needs_resolve) {
// We can use blit to copy things over
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_msaa_3d);
if (fbo_int != 0) {
// We can't combine resolve and scaling, so resolve into our internal buffer
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_int);
} 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 (fbo_int != 0) {
// 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_int);
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);
}
glBindFramebuffer(GL_FRAMEBUFFER, fbo_rt);
} else if ((fbo_msaa_3d != 0 && msaa3d_needs_resolve) || (fbo_int != 0)) {
// TODO investigate if it's smarter to cache these FBOs
GLuint fbos[2]; // read and write
glGenFramebuffers(2, fbos);
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbos[0]);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[1]);
if (fbo_msaa_3d != 0 && msaa3d_needs_resolve) {
GLuint read_color = rb->get_msaa3d_color();
GLuint read_depth = rb->get_msaa3d_depth();
GLuint write_color = 0;
GLuint write_depth = 0;
if (fbo_int != 0) {
write_color = rb->get_internal_color();
write_depth = rb->get_internal_depth();
} else {
write_color = texture_storage->render_target_get_color(render_target);
write_depth = texture_storage->render_target_get_depth(render_target);
}
for (uint32_t v = 0; v < view_count; v++) {
glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, read_color, 0, v);
glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, read_depth, 0, v);
glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, write_color, 0, v);
glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, write_depth, 0, v);
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 (fbo_int != 0) {
GLuint read_color = rb->get_internal_color();
GLuint read_depth = rb->get_internal_depth();
GLuint write_color = texture_storage->render_target_get_color(render_target);
GLuint write_depth = texture_storage->render_target_get_depth(render_target);
for (uint32_t v = 0; v < view_count; v++) {
glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, read_color, 0, v);
glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, read_depth, 0, v);
glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, write_color, 0, v);
glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, write_depth, 0, v);
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);
}
}
glBindFramebuffer(GL_FRAMEBUFFER, fbo_rt);
glDeleteFramebuffers(2, fbos);
}
}
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();
@@ -3125,7 +3244,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();
@@ -3202,8 +3321,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)));