diff --git a/doc/classes/VisualServer.xml b/doc/classes/VisualServer.xml
index b95b970816f..18b08421a13 100644
--- a/doc/classes/VisualServer.xml
+++ b/doc/classes/VisualServer.xml
@@ -4238,6 +4238,12 @@
Multisample antialiasing is set to 16×.
+
+ Multisample antialiasing is set to 2× on external texture. Special mode for GLES2 VR for the Oculus Quest.
+
+
+ Multisample antialiasing is set to 4× on external texture. Special mode for GLES2 VR for the Oculus Quest.
+
The Viewport does not render 3D but samples.
diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp
index 9d9bceb243d..82cb1ef90b5 100644
--- a/drivers/gles2/rasterizer_storage_gles2.cpp
+++ b/drivers/gles2/rasterizer_storage_gles2.cpp
@@ -4694,7 +4694,7 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) {
/* For MSAA */
#ifndef JAVASCRIPT_ENABLED
- if (rt->msaa != VS::VIEWPORT_MSAA_DISABLED && config.multisample_supported) {
+ if (rt->msaa >= VS::VIEWPORT_MSAA_2X && rt->msaa <= VS::VIEWPORT_MSAA_16X && config.multisample_supported) {
rt->multisample_active = true;
@@ -5090,6 +5090,11 @@ void RasterizerStorageGLES2::render_target_set_external_texture(RID p_render_tar
// free this
glDeleteFramebuffers(1, &rt->external.fbo);
+ // and this
+ if (rt->external.depth != 0) {
+ glDeleteRenderbuffers(1, &rt->external.depth);
+ }
+
// clean up our texture
Texture *t = texture_owner.get(rt->external.texture);
t->alloc_height = 0;
@@ -5102,6 +5107,7 @@ void RasterizerStorageGLES2::render_target_set_external_texture(RID p_render_tar
rt->external.fbo = 0;
rt->external.color = 0;
+ rt->external.depth = 0;
}
} else {
Texture *t;
@@ -5136,6 +5142,7 @@ void RasterizerStorageGLES2::render_target_set_external_texture(RID p_render_tar
t->render_target = rt;
rt->external.texture = texture_owner.make_rid(t);
+
} else {
// bind our frame buffer
glBindFramebuffer(GL_FRAMEBUFFER, rt->external.fbo);
@@ -5154,16 +5161,42 @@ void RasterizerStorageGLES2::render_target_set_external_texture(RID p_render_tar
t->alloc_height = rt->width;
t->alloc_width = rt->height;
- // is there a point to setting the internal formats? we don't know them..
+ // Switch our texture on our frame buffer
+#if ANDROID_ENABLED
+ if (rt->msaa >= VS::VIEWPORT_MSAA_EXT_2X && rt->msaa <= VS::VIEWPORT_MSAA_EXT_4X) {
+ // This code only applies to the Oculus Go and Oculus Quest. Due to the the tiled nature
+ // of the GPU we can do a single render pass by rendering directly into our texture chains
+ // texture and apply MSAA as we render.
- // set our texture as the destination for our framebuffer
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p_texture_id, 0);
+ // On any other hardware these two modes are ignored and we do not have any MSAA,
+ // the normal MSAA modes need to be used to enable our two pass approach
- // seeing we're rendering into this directly, better also use our depth buffer, just use our existing one :)
- if (config.support_depth_texture) {
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->depth, 0);
- } else {
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth);
+ static const int msaa_value[] = { 2, 4 };
+ int msaa = msaa_value[rt->msaa - VS::VIEWPORT_MSAA_EXT_2X];
+
+ if (rt->external.depth == 0) {
+ // create a multisample depth buffer, we're not reusing Godots because Godot's didn't get created..
+ glGenRenderbuffers(1, &rt->external.depth);
+ glBindRenderbuffer(GL_RENDERBUFFER, rt->external.depth);
+ glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, config.depth_internalformat, rt->width, rt->height);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->external.depth);
+ }
+
+ // and set our external texture as the texture...
+ glFramebufferTexture2DMultisample(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p_texture_id, 0, msaa);
+
+ } else
+#endif
+ {
+ // set our texture as the destination for our framebuffer
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p_texture_id, 0);
+
+ // seeing we're rendering into this directly, better also use our depth buffer, just use our existing one :)
+ if (config.support_depth_texture) {
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->depth, 0);
+ } else {
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth);
+ }
}
// check status and unbind
diff --git a/drivers/gles2/rasterizer_storage_gles2.h b/drivers/gles2/rasterizer_storage_gles2.h
index 27f06074ed2..6de530d8c33 100644
--- a/drivers/gles2/rasterizer_storage_gles2.h
+++ b/drivers/gles2/rasterizer_storage_gles2.h
@@ -1182,10 +1182,13 @@ public:
struct External {
GLuint fbo;
GLuint color;
+ GLuint depth;
RID texture;
External() :
- fbo(0) {
+ fbo(0),
+ color(0),
+ depth(0) {
}
} external;
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index f94020b9188..71737426a9c 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -6961,7 +6961,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) {
rt->buffers.active = true;
- static const int msaa_value[] = { 0, 2, 4, 8, 16 };
+ static const int msaa_value[] = { 0, 2, 4, 8, 16, 4, 16 }; // MSAA_EXT_nX is a GLES2 temporary hack ignored in GLES3 for now...
int msaa = msaa_value[rt->msaa];
int max_samples = 0;
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index 56530490607..78ceccfca20 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -2066,7 +2066,7 @@ SceneTree::SceneTree() {
int ref_atlas_subdiv = GLOBAL_DEF("rendering/quality/reflections/atlas_subdiv", 8);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/reflections/atlas_subdiv", PropertyInfo(Variant::INT, "rendering/quality/reflections/atlas_subdiv", PROPERTY_HINT_RANGE, "0,32,or_greater")); //next_power_of_2 will return a 0 as min value
int msaa_mode = GLOBAL_DEF("rendering/quality/filters/msaa", 0);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/filters/msaa", PropertyInfo(Variant::INT, "rendering/quality/filters/msaa", PROPERTY_HINT_ENUM, "Disabled,2x,4x,8x,16x"));
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/filters/msaa", PropertyInfo(Variant::INT, "rendering/quality/filters/msaa", PROPERTY_HINT_ENUM, "Disabled,2x,4x,8x,16x,External 2x,External 4x"));
root->set_msaa(Viewport::MSAA(msaa_mode));
GLOBAL_DEF("rendering/quality/depth/hdr", true);
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 1af88171f61..417652fe5de 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -2955,7 +2955,7 @@ int Viewport::gui_get_canvas_sort_index() {
void Viewport::set_msaa(MSAA p_msaa) {
- ERR_FAIL_INDEX(p_msaa, 5);
+ ERR_FAIL_INDEX(p_msaa, 7);
if (msaa == p_msaa)
return;
msaa = p_msaa;
@@ -3186,7 +3186,7 @@ void Viewport::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "transparent_bg"), "set_transparent_background", "has_transparent_background");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "handle_input_locally"), "set_handle_input_locally", "is_handling_input_locally");
ADD_GROUP("Rendering", "");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "msaa", PROPERTY_HINT_ENUM, "Disabled,2x,4x,8x,16x"), "set_msaa", "get_msaa");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "msaa", PROPERTY_HINT_ENUM, "Disabled,2x,4x,8x,16x,External 2x,External 4x"), "set_msaa", "get_msaa");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hdr"), "set_hdr", "get_hdr");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disable_3d"), "set_disable_3d", "is_3d_disabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "keep_3d_linear"), "set_keep_3d_linear", "get_keep_3d_linear");
diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp
index b095f242123..a1ba946d8c8 100644
--- a/servers/visual_server.cpp
+++ b/servers/visual_server.cpp
@@ -2171,6 +2171,8 @@ void VisualServer::_bind_methods() {
BIND_ENUM_CONSTANT(VIEWPORT_MSAA_4X);
BIND_ENUM_CONSTANT(VIEWPORT_MSAA_8X);
BIND_ENUM_CONSTANT(VIEWPORT_MSAA_16X);
+ BIND_ENUM_CONSTANT(VIEWPORT_MSAA_EXT_2X);
+ BIND_ENUM_CONSTANT(VIEWPORT_MSAA_EXT_4X);
BIND_ENUM_CONSTANT(VIEWPORT_USAGE_2D);
BIND_ENUM_CONSTANT(VIEWPORT_USAGE_2D_NO_SAMPLING);
diff --git a/servers/visual_server.h b/servers/visual_server.h
index 1c1b04f1989..b1daf87e566 100644
--- a/servers/visual_server.h
+++ b/servers/visual_server.h
@@ -658,6 +658,8 @@ public:
VIEWPORT_MSAA_4X,
VIEWPORT_MSAA_8X,
VIEWPORT_MSAA_16X,
+ VIEWPORT_MSAA_EXT_2X,
+ VIEWPORT_MSAA_EXT_4X,
};
virtual void viewport_set_msaa(RID p_viewport, ViewportMSAA p_msaa) = 0;