Add MSAA support for WebXR
This commit is contained in:
parent
a311a4b162
commit
275c496bc8
|
@ -99,8 +99,14 @@ Config::Config() {
|
||||||
msaa_supported = extensions.has("GL_EXT_framebuffer_multisample");
|
msaa_supported = extensions.has("GL_EXT_framebuffer_multisample");
|
||||||
#endif
|
#endif
|
||||||
#ifndef IOS_ENABLED
|
#ifndef IOS_ENABLED
|
||||||
|
#ifdef WEB_ENABLED
|
||||||
|
msaa_multiview_supported = extensions.has("OCULUS_multiview");
|
||||||
|
rt_msaa_multiview_supported = msaa_multiview_supported;
|
||||||
|
#else
|
||||||
msaa_multiview_supported = extensions.has("GL_EXT_multiview_texture_multisample");
|
msaa_multiview_supported = extensions.has("GL_EXT_multiview_texture_multisample");
|
||||||
multiview_supported = extensions.has("GL_OVR_multiview2") || extensions.has("GL_OVR_multiview");
|
#endif
|
||||||
|
|
||||||
|
multiview_supported = extensions.has("OCULUS_multiview") || extensions.has("GL_OVR_multiview2") || extensions.has("GL_OVR_multiview");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ANDROID_ENABLED
|
#ifdef ANDROID_ENABLED
|
||||||
|
|
|
@ -51,10 +51,42 @@ RenderSceneBuffersGLES3::~RenderSceneBuffersGLES3() {
|
||||||
free_render_buffer_data();
|
free_render_buffer_data();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderSceneBuffersGLES3::_rt_attach_textures(GLuint p_color, GLuint p_depth, GLsizei p_samples, uint32_t p_view_count) {
|
||||||
|
if (p_view_count > 1) {
|
||||||
|
if (p_samples > 1) {
|
||||||
|
#if defined(ANDROID_ENABLED) || defined(WEB_ENABLED)
|
||||||
|
glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, p_color, 0, p_samples, 0, p_view_count);
|
||||||
|
glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, p_depth, 0, p_samples, 0, p_view_count);
|
||||||
|
#else
|
||||||
|
ERR_PRINT_ONCE("Multiview MSAA isn't supported on this platform.");
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
#ifndef IOS_ENABLED
|
||||||
|
glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, p_color, 0, 0, p_view_count);
|
||||||
|
glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, p_depth, 0, 0, p_view_count);
|
||||||
|
#else
|
||||||
|
ERR_PRINT_ONCE("Multiview isn't supported on this platform.");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (p_samples > 1) {
|
||||||
|
#ifdef ANDROID_ENABLED
|
||||||
|
glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p_color, 0, p_samples);
|
||||||
|
glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, p_depth, 0, p_samples);
|
||||||
|
#else
|
||||||
|
ERR_PRINT_ONCE("MSAA via EXT_multisampled_render_to_texture isn't supported on this platform.");
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p_color, 0);
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, p_depth, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GLuint RenderSceneBuffersGLES3::_rt_get_cached_fbo(GLuint p_color, GLuint p_depth, GLsizei p_samples, uint32_t p_view_count) {
|
GLuint RenderSceneBuffersGLES3::_rt_get_cached_fbo(GLuint p_color, GLuint p_depth, GLsizei p_samples, uint32_t p_view_count) {
|
||||||
FBDEF new_fbo;
|
FBDEF new_fbo;
|
||||||
|
|
||||||
#ifdef ANDROID_ENABLED
|
#if defined(ANDROID_ENABLED) || defined(WEB_ENABLED)
|
||||||
// There shouldn't be more then 3 entries in this...
|
// There shouldn't be more then 3 entries in this...
|
||||||
for (const FBDEF &cached_fbo : msaa3d.cached_fbos) {
|
for (const FBDEF &cached_fbo : msaa3d.cached_fbos) {
|
||||||
if (cached_fbo.color == p_color && cached_fbo.depth == p_depth) {
|
if (cached_fbo.color == p_color && cached_fbo.depth == p_depth) {
|
||||||
|
@ -68,13 +100,7 @@ GLuint RenderSceneBuffersGLES3::_rt_get_cached_fbo(GLuint p_color, GLuint p_dept
|
||||||
glGenFramebuffers(1, &new_fbo.fbo);
|
glGenFramebuffers(1, &new_fbo.fbo);
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, new_fbo.fbo);
|
glBindFramebuffer(GL_FRAMEBUFFER, new_fbo.fbo);
|
||||||
|
|
||||||
if (p_view_count > 1) {
|
_rt_attach_textures(p_color, p_depth, p_samples, p_view_count);
|
||||||
glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, p_color, 0, p_samples, 0, p_view_count);
|
|
||||||
glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, p_depth, 0, p_samples, 0, p_view_count);
|
|
||||||
} else {
|
|
||||||
glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p_color, 0, p_samples);
|
|
||||||
glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, p_depth, 0, p_samples);
|
|
||||||
}
|
|
||||||
|
|
||||||
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||||
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
||||||
|
@ -317,8 +343,6 @@ void RenderSceneBuffersGLES3::configure(const RenderSceneBuffersConfiguration *p
|
||||||
// hence we'll use our FBO cache here.
|
// hence we'll use our FBO cache here.
|
||||||
msaa3d.needs_resolve = false;
|
msaa3d.needs_resolve = false;
|
||||||
msaa3d.check_fbo_cache = true;
|
msaa3d.check_fbo_cache = true;
|
||||||
#endif
|
|
||||||
#ifdef ANDROID_ENABLED
|
|
||||||
} else if (use_internal_buffer) {
|
} else if (use_internal_buffer) {
|
||||||
// We can combine MSAA and scaling/effects.
|
// We can combine MSAA and scaling/effects.
|
||||||
msaa3d.needs_resolve = false;
|
msaa3d.needs_resolve = false;
|
||||||
|
@ -329,13 +353,7 @@ void RenderSceneBuffersGLES3::configure(const RenderSceneBuffersConfiguration *p
|
||||||
glGenFramebuffers(1, &msaa3d.fbo);
|
glGenFramebuffers(1, &msaa3d.fbo);
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, msaa3d.fbo);
|
glBindFramebuffer(GL_FRAMEBUFFER, msaa3d.fbo);
|
||||||
|
|
||||||
if (use_multiview) {
|
_rt_attach_textures(internal3d.color, internal3d.depth, msaa3d.samples, view_count);
|
||||||
glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, internal3d.color, 0, msaa3d.samples, 0, view_count);
|
|
||||||
glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, internal3d.depth, 0, msaa3d.samples, 0, view_count);
|
|
||||||
} else {
|
|
||||||
glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, internal3d.color, 0, msaa3d.samples);
|
|
||||||
glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, internal3d.depth, 0, msaa3d.samples);
|
|
||||||
}
|
|
||||||
|
|
||||||
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||||
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
||||||
|
@ -515,13 +533,14 @@ void RenderSceneBuffersGLES3::free_render_buffer_data() {
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint RenderSceneBuffersGLES3::get_render_fbo() {
|
GLuint RenderSceneBuffersGLES3::get_render_fbo() {
|
||||||
if (msaa3d.check_fbo_cache) {
|
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
|
||||||
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
|
GLuint rt_fbo = 0;
|
||||||
|
|
||||||
|
if (msaa3d.check_fbo_cache) {
|
||||||
GLuint color = texture_storage->render_target_get_color(render_target);
|
GLuint color = texture_storage->render_target_get_color(render_target);
|
||||||
GLuint depth = texture_storage->render_target_get_depth(render_target);
|
GLuint depth = texture_storage->render_target_get_depth(render_target);
|
||||||
|
|
||||||
return _rt_get_cached_fbo(color, depth, msaa3d.samples, view_count);
|
rt_fbo = _rt_get_cached_fbo(color, depth, msaa3d.samples, view_count);
|
||||||
} else if (msaa3d.fbo != 0) {
|
} else if (msaa3d.fbo != 0) {
|
||||||
// We have an MSAA fbo, render to our MSAA buffer
|
// We have an MSAA fbo, render to our MSAA buffer
|
||||||
return msaa3d.fbo;
|
return msaa3d.fbo;
|
||||||
|
@ -529,10 +548,19 @@ GLuint RenderSceneBuffersGLES3::get_render_fbo() {
|
||||||
// We have an internal buffer, render to our internal buffer!
|
// We have an internal buffer, render to our internal buffer!
|
||||||
return internal3d.fbo;
|
return internal3d.fbo;
|
||||||
} else {
|
} else {
|
||||||
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
|
rt_fbo = texture_storage->render_target_get_fbo(render_target);
|
||||||
|
|
||||||
return texture_storage->render_target_get_fbo(render_target);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (texture_storage->render_target_is_reattach_textures(render_target)) {
|
||||||
|
GLuint color = texture_storage->render_target_get_color(render_target);
|
||||||
|
GLuint depth = texture_storage->render_target_get_depth(render_target);
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, rt_fbo);
|
||||||
|
_rt_attach_textures(color, depth, msaa3d.samples, view_count);
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, texture_storage->system_fbo);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rt_fbo;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // GLES3_ENABLED
|
#endif // GLES3_ENABLED
|
||||||
|
|
|
@ -95,6 +95,7 @@ private:
|
||||||
void _clear_intermediate_buffers();
|
void _clear_intermediate_buffers();
|
||||||
void _clear_back_buffers();
|
void _clear_back_buffers();
|
||||||
|
|
||||||
|
void _rt_attach_textures(GLuint p_color, GLuint p_depth, GLsizei p_samples, uint32_t p_view_count);
|
||||||
GLuint _rt_get_cached_fbo(GLuint p_color, GLuint p_depth, GLsizei p_samples, uint32_t p_view_count);
|
GLuint _rt_get_cached_fbo(GLuint p_color, GLuint p_depth, GLsizei p_samples, uint32_t p_view_count);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -2320,6 +2320,20 @@ GLuint TextureStorage::render_target_get_depth(RID p_render_target) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextureStorage::render_target_set_reattach_textures(RID p_render_target, bool p_reattach_textures) const {
|
||||||
|
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
|
||||||
|
ERR_FAIL_NULL(rt);
|
||||||
|
|
||||||
|
rt->reattach_textures = p_reattach_textures;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TextureStorage::render_target_is_reattach_textures(RID p_render_target) const {
|
||||||
|
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
|
||||||
|
ERR_FAIL_NULL_V(rt, false);
|
||||||
|
|
||||||
|
return rt->reattach_textures;
|
||||||
|
}
|
||||||
|
|
||||||
void TextureStorage::render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) {
|
void TextureStorage::render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) {
|
||||||
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
|
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
|
||||||
ERR_FAIL_NULL(rt);
|
ERR_FAIL_NULL(rt);
|
||||||
|
|
|
@ -365,6 +365,7 @@ struct RenderTarget {
|
||||||
|
|
||||||
bool used_in_frame = false;
|
bool used_in_frame = false;
|
||||||
RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED;
|
RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED;
|
||||||
|
bool reattach_textures = false;
|
||||||
|
|
||||||
struct RTOverridden {
|
struct RTOverridden {
|
||||||
bool is_overridden = false;
|
bool is_overridden = false;
|
||||||
|
@ -639,6 +640,8 @@ public:
|
||||||
GLuint render_target_get_fbo(RID p_render_target) const;
|
GLuint render_target_get_fbo(RID p_render_target) const;
|
||||||
GLuint render_target_get_color(RID p_render_target) const;
|
GLuint render_target_get_color(RID p_render_target) const;
|
||||||
GLuint render_target_get_depth(RID p_render_target) const;
|
GLuint render_target_get_depth(RID p_render_target) const;
|
||||||
|
void render_target_set_reattach_textures(RID p_render_target, bool p_reattach_textures) const;
|
||||||
|
bool render_target_is_reattach_textures(RID p_render_target) const;
|
||||||
|
|
||||||
virtual void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) override;
|
virtual void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) override;
|
||||||
virtual Rect2i render_target_get_sdf_rect(RID p_render_target) const override;
|
virtual Rect2i render_target_get_sdf_rect(RID p_render_target) const override;
|
||||||
|
|
|
@ -309,7 +309,7 @@ void WebXRInterfaceJS::uninitialize() {
|
||||||
|
|
||||||
godot_webxr_uninitialize();
|
godot_webxr_uninitialize();
|
||||||
|
|
||||||
GLES3::TextureStorage *texture_storage = dynamic_cast<GLES3::TextureStorage *>(RSG::texture_storage);
|
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
|
||||||
if (texture_storage != nullptr) {
|
if (texture_storage != nullptr) {
|
||||||
for (KeyValue<unsigned int, RID> &E : texture_cache) {
|
for (KeyValue<unsigned int, RID> &E : texture_cache) {
|
||||||
// Forcibly mark as not part of a render target so we can free it.
|
// Forcibly mark as not part of a render target so we can free it.
|
||||||
|
@ -438,16 +438,11 @@ Projection WebXRInterfaceJS::get_projection_for_view(uint32_t p_view, double p_a
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebXRInterfaceJS::pre_draw_viewport(RID p_render_target) {
|
bool WebXRInterfaceJS::pre_draw_viewport(RID p_render_target) {
|
||||||
GLES3::TextureStorage *texture_storage = dynamic_cast<GLES3::TextureStorage *>(RSG::texture_storage);
|
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
|
||||||
if (texture_storage == nullptr) {
|
if (texture_storage == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLES3::RenderTarget *rt = texture_storage->get_render_target(p_render_target);
|
|
||||||
if (rt == nullptr) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cache the resources so we don't have to get them from JS twice.
|
// Cache the resources so we don't have to get them from JS twice.
|
||||||
color_texture = _get_color_texture();
|
color_texture = _get_color_texture();
|
||||||
depth_texture = _get_depth_texture();
|
depth_texture = _get_depth_texture();
|
||||||
|
@ -460,23 +455,9 @@ bool WebXRInterfaceJS::pre_draw_viewport(RID p_render_target) {
|
||||||
//
|
//
|
||||||
// See: https://immersive-web.github.io/layers/#xropaquetextures
|
// See: https://immersive-web.github.io/layers/#xropaquetextures
|
||||||
//
|
//
|
||||||
// This is why we're doing this sort of silly check: if the color and depth
|
// So, even if the color and depth textures have the same GLuint as the last
|
||||||
// textures are the same this frame as last frame, we need to attach them
|
// frame, we need to re-attach them again.
|
||||||
// again, despite the fact that the GLuint for them hasn't changed.
|
texture_storage->render_target_set_reattach_textures(p_render_target, true);
|
||||||
if (rt->overridden.is_overridden && rt->overridden.color == color_texture && rt->overridden.depth == depth_texture) {
|
|
||||||
GLES3::Config *config = GLES3::Config::get_singleton();
|
|
||||||
bool use_multiview = rt->view_count > 1 && config->multiview_supported;
|
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo);
|
|
||||||
if (use_multiview) {
|
|
||||||
glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, rt->color, 0, 0, rt->view_count);
|
|
||||||
glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, rt->depth, 0, 0, rt->view_count);
|
|
||||||
} else {
|
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0);
|
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->depth, 0);
|
|
||||||
}
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, texture_storage->system_fbo);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -484,7 +465,12 @@ bool WebXRInterfaceJS::pre_draw_viewport(RID p_render_target) {
|
||||||
Vector<BlitToScreen> WebXRInterfaceJS::post_draw_viewport(RID p_render_target, const Rect2 &p_screen_rect) {
|
Vector<BlitToScreen> WebXRInterfaceJS::post_draw_viewport(RID p_render_target, const Rect2 &p_screen_rect) {
|
||||||
Vector<BlitToScreen> blit_to_screen;
|
Vector<BlitToScreen> blit_to_screen;
|
||||||
|
|
||||||
// We don't need to do anything here.
|
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
|
||||||
|
if (texture_storage == nullptr) {
|
||||||
|
return blit_to_screen;
|
||||||
|
}
|
||||||
|
|
||||||
|
texture_storage->render_target_set_reattach_textures(p_render_target, false);
|
||||||
|
|
||||||
return blit_to_screen;
|
return blit_to_screen;
|
||||||
};
|
};
|
||||||
|
@ -513,7 +499,7 @@ RID WebXRInterfaceJS::_get_texture(unsigned int p_texture_id) {
|
||||||
return cache->get();
|
return cache->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
GLES3::TextureStorage *texture_storage = dynamic_cast<GLES3::TextureStorage *>(RSG::texture_storage);
|
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
|
||||||
if (texture_storage == nullptr) {
|
if (texture_storage == nullptr) {
|
||||||
return RID();
|
return RID();
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,9 +44,11 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void godot_webgl2_glFramebufferTextureMultiviewOVR(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews);
|
void godot_webgl2_glFramebufferTextureMultiviewOVR(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews);
|
||||||
|
void godot_webgl2_glFramebufferTextureMultisampleMultiviewOVR(GLenum target, GLenum attachment, GLuint texture, GLint level, GLsizei samples, GLint baseViewIndex, GLsizei numViews);
|
||||||
void godot_webgl2_glGetBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data);
|
void godot_webgl2_glGetBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data);
|
||||||
|
|
||||||
#define glFramebufferTextureMultiviewOVR godot_webgl2_glFramebufferTextureMultiviewOVR
|
#define glFramebufferTextureMultiviewOVR godot_webgl2_glFramebufferTextureMultiviewOVR
|
||||||
|
#define glFramebufferTextureMultisampleMultiviewOVR godot_webgl2_glFramebufferTextureMultisampleMultiviewOVR
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,3 +34,19 @@ OVR_multiview2.prototype.FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR;
|
||||||
* @return {void}
|
* @return {void}
|
||||||
*/
|
*/
|
||||||
OVR_multiview2.prototype.framebufferTextureMultiviewOVR = function(target, attachment, texture, level, baseViewIndex, numViews) {};
|
OVR_multiview2.prototype.framebufferTextureMultiviewOVR = function(target, attachment, texture, level, baseViewIndex, numViews) {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor OCULUS_multiview
|
||||||
|
*/
|
||||||
|
function OCULUS_multiview() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {number} target
|
||||||
|
* @param {number} attachment
|
||||||
|
* @param {WebGLTexture} texture
|
||||||
|
* @param {number} level
|
||||||
|
* @param {number} baseViewIndex
|
||||||
|
* @param {number} numViews
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
OCULUS_multiview.prototype.framebufferTextureMultisampleMultiviewOVR = function(target, attachment, texture, level, samples, baseViewIndex, numViews) {};
|
||||||
|
|
|
@ -61,6 +61,23 @@ const GodotWebGL2 = {
|
||||||
const /** OVR_multiview2 */ ext = context.multiviewExt;
|
const /** OVR_multiview2 */ ext = context.multiviewExt;
|
||||||
ext.framebufferTextureMultiviewOVR(target, attachment, GL.textures[texture], level, base_view_index, num_views);
|
ext.framebufferTextureMultiviewOVR(target, attachment, GL.textures[texture], level, base_view_index, num_views);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
godot_webgl2_glFramebufferTextureMultisampleMultiviewOVR__deps: ['emscripten_webgl_get_current_context'],
|
||||||
|
godot_webgl2_glFramebufferTextureMultisampleMultiviewOVR__proxy: 'sync',
|
||||||
|
godot_webgl2_glFramebufferTextureMultisampleMultiviewOVR__sig: 'viiiiiii',
|
||||||
|
godot_webgl2_glFramebufferTextureMultisampleMultiviewOVR: function (target, attachment, texture, level, samples, base_view_index, num_views) {
|
||||||
|
const context = GL.currentContext;
|
||||||
|
if (typeof context.oculusMultiviewExt === 'undefined') {
|
||||||
|
const /** OCULUS_multiview */ ext = context.GLctx.getExtension('OCULUS_multiview');
|
||||||
|
if (!ext) {
|
||||||
|
GodotRuntime.error('Trying to call glFramebufferTextureMultisampleMultiviewOVR() without the OCULUS_multiview extension');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
context.oculusMultiviewExt = ext;
|
||||||
|
}
|
||||||
|
const /** OCULUS_multiview */ ext = context.oculusMultiviewExt;
|
||||||
|
ext.framebufferTextureMultisampleMultiviewOVR(target, attachment, GL.textures[texture], level, samples, base_view_index, num_views);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
autoAddDeps(GodotWebGL2, '$GodotWebGL2');
|
autoAddDeps(GodotWebGL2, '$GodotWebGL2');
|
||||||
|
|
Loading…
Reference in New Issue