Merge pull request #27527 from BastiaanOlij/render_ext_target
Add option to have viewport render into supplied texture (VR)
This commit is contained in:
commit
4942e96897
|
@ -692,6 +692,7 @@ public:
|
|||
RID render_target_create() { return RID(); }
|
||||
void render_target_set_size(RID p_render_target, int p_width, int p_height) {}
|
||||
RID render_target_get_texture(RID p_render_target) const { return RID(); }
|
||||
void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) {}
|
||||
void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) {}
|
||||
bool render_target_was_used(RID p_render_target) { return false; }
|
||||
void render_target_clear_used(RID p_render_target) {}
|
||||
|
@ -781,7 +782,7 @@ public:
|
|||
void initialize() {}
|
||||
void begin_frame(double frame_step) {}
|
||||
void set_current_render_target(RID p_render_target) {}
|
||||
void restore_render_target() {}
|
||||
void restore_render_target(bool p_3d_was_drawn) {}
|
||||
void clear_render_target(const Color &p_color) {}
|
||||
void blit_render_target_to_screen(RID p_render_target, const Rect2 &p_screen_rect, int p_screen = 0) {}
|
||||
void output_lens_distorted_to_screen(RID p_render_target, const Rect2 &p_screen_rect, float p_k1, float p_k2, const Vector2 &p_eye_center, float p_oversample) {}
|
||||
|
|
|
@ -321,7 +321,7 @@ void RasterizerGLES2::set_current_render_target(RID p_render_target) {
|
|||
}
|
||||
}
|
||||
|
||||
void RasterizerGLES2::restore_render_target() {
|
||||
void RasterizerGLES2::restore_render_target(bool p_3d_was_drawn) {
|
||||
ERR_FAIL_COND(storage->frame.current_rt == NULL);
|
||||
RasterizerStorageGLES2::RenderTarget *rt = storage->frame.current_rt;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo);
|
||||
|
@ -410,7 +410,11 @@ void RasterizerGLES2::blit_render_target_to_screen(RID p_render_target, const Re
|
|||
glDisable(GL_BLEND);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES2::system_fbo);
|
||||
glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 1);
|
||||
glBindTexture(GL_TEXTURE_2D, rt->color);
|
||||
if (rt->external.fbo != 0) {
|
||||
glBindTexture(GL_TEXTURE_2D, rt->external.color);
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, rt->color);
|
||||
}
|
||||
|
||||
// TODO normals
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ public:
|
|||
virtual void initialize();
|
||||
virtual void begin_frame(double frame_step);
|
||||
virtual void set_current_render_target(RID p_render_target);
|
||||
virtual void restore_render_target();
|
||||
virtual void restore_render_target(bool p_3d_was_drawn);
|
||||
virtual void clear_render_target(const Color &p_color);
|
||||
virtual void blit_render_target_to_screen(RID p_render_target, const Rect2 &p_screen_rect, int p_screen = 0);
|
||||
virtual void output_lens_distorted_to_screen(RID p_render_target, const Rect2 &p_screen_rect, float p_k1, float p_k2, const Vector2 &p_eye_center, float p_oversample);
|
||||
|
|
|
@ -2681,7 +2681,11 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
|
|||
|
||||
} else {
|
||||
state.render_no_shadows = false;
|
||||
current_fb = storage->frame.current_rt->fbo;
|
||||
if (storage->frame.current_rt->external.fbo != 0) {
|
||||
current_fb = storage->frame.current_rt->external.fbo;
|
||||
} else {
|
||||
current_fb = storage->frame.current_rt->fbo;
|
||||
}
|
||||
env = environment_owner.getornull(p_environment);
|
||||
|
||||
viewport_width = storage->frame.current_rt->width;
|
||||
|
|
|
@ -4664,6 +4664,23 @@ void RasterizerStorageGLES2::_render_target_clear(RenderTarget *rt) {
|
|||
rt->fbo = 0;
|
||||
}
|
||||
|
||||
if (rt->external.fbo != 0) {
|
||||
// free this
|
||||
glDeleteFramebuffers(1, &rt->external.fbo);
|
||||
|
||||
// clean up our texture
|
||||
Texture *t = texture_owner.get(rt->external.texture);
|
||||
t->alloc_height = 0;
|
||||
t->alloc_width = 0;
|
||||
t->width = 0;
|
||||
t->height = 0;
|
||||
t->active = false;
|
||||
texture_owner.free(rt->external.texture);
|
||||
memdelete(t);
|
||||
|
||||
rt->external.fbo = 0;
|
||||
}
|
||||
|
||||
if (rt->depth) {
|
||||
if (config.support_depth_texture) {
|
||||
glDeleteTextures(1, &rt->depth);
|
||||
|
@ -4742,7 +4759,108 @@ RID RasterizerStorageGLES2::render_target_get_texture(RID p_render_target) const
|
|||
RenderTarget *rt = render_target_owner.getornull(p_render_target);
|
||||
ERR_FAIL_COND_V(!rt, RID());
|
||||
|
||||
return rt->texture;
|
||||
if (rt->external.fbo == 0) {
|
||||
return rt->texture;
|
||||
} else {
|
||||
return rt->external.texture;
|
||||
}
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES2::render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) {
|
||||
RenderTarget *rt = render_target_owner.getornull(p_render_target);
|
||||
ERR_FAIL_COND(!rt);
|
||||
|
||||
if (p_texture_id == 0) {
|
||||
if (rt->external.fbo != 0) {
|
||||
// free this
|
||||
glDeleteFramebuffers(1, &rt->external.fbo);
|
||||
|
||||
// clean up our texture
|
||||
Texture *t = texture_owner.get(rt->external.texture);
|
||||
t->alloc_height = 0;
|
||||
t->alloc_width = 0;
|
||||
t->width = 0;
|
||||
t->height = 0;
|
||||
t->active = false;
|
||||
texture_owner.free(rt->external.texture);
|
||||
memdelete(t);
|
||||
|
||||
rt->external.fbo = 0;
|
||||
rt->external.color = 0;
|
||||
}
|
||||
} else {
|
||||
Texture *t;
|
||||
|
||||
if (rt->external.fbo == 0) {
|
||||
// create our fbo
|
||||
glGenFramebuffers(1, &rt->external.fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, rt->external.fbo);
|
||||
|
||||
// allocate a texture
|
||||
t = memnew(Texture);
|
||||
|
||||
t->type = VS::TEXTURE_TYPE_2D;
|
||||
t->flags = 0;
|
||||
t->width = 0;
|
||||
t->height = 0;
|
||||
t->alloc_height = 0;
|
||||
t->alloc_width = 0;
|
||||
t->format = Image::FORMAT_RGBA8;
|
||||
t->target = GL_TEXTURE_2D;
|
||||
t->gl_format_cache = 0;
|
||||
t->gl_internal_format_cache = 0;
|
||||
t->gl_type_cache = 0;
|
||||
t->data_size = 0;
|
||||
t->compressed = false;
|
||||
t->srgb = false;
|
||||
t->total_data_size = 0;
|
||||
t->ignore_mipmaps = false;
|
||||
t->mipmaps = 1;
|
||||
t->active = true;
|
||||
t->tex_id = 0;
|
||||
t->render_target = rt;
|
||||
|
||||
rt->external.texture = texture_owner.make_rid(t);
|
||||
} else {
|
||||
// bind our frame buffer
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, rt->external.fbo);
|
||||
|
||||
// find our texture
|
||||
t = texture_owner.get(rt->external.texture);
|
||||
}
|
||||
|
||||
// set our texture
|
||||
t->tex_id = p_texture_id;
|
||||
rt->external.color = p_texture_id;
|
||||
|
||||
// size shouldn't be different
|
||||
t->width = rt->width;
|
||||
t->height = rt->height;
|
||||
t->alloc_height = rt->width;
|
||||
t->alloc_width = rt->height;
|
||||
|
||||
// is there a point to setting the internal formats? we don't know them..
|
||||
|
||||
// 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
|
||||
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES2::system_fbo);
|
||||
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
||||
printf("framebuffer fail, status: %x\n", status);
|
||||
}
|
||||
|
||||
ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE);
|
||||
}
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES2::render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) {
|
||||
|
|
|
@ -1156,6 +1156,16 @@ public:
|
|||
|
||||
Effect copy_screen_effect;
|
||||
|
||||
struct External {
|
||||
GLuint fbo;
|
||||
GLuint color;
|
||||
RID texture;
|
||||
|
||||
External() :
|
||||
fbo(0) {
|
||||
}
|
||||
} external;
|
||||
|
||||
int width, height;
|
||||
|
||||
bool flags[RENDER_TARGET_FLAG_MAX];
|
||||
|
@ -1176,6 +1186,7 @@ public:
|
|||
for (int i = 0; i < RENDER_TARGET_FLAG_MAX; ++i) {
|
||||
flags[i] = false;
|
||||
}
|
||||
external.fbo = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1187,6 +1198,7 @@ public:
|
|||
virtual RID render_target_create();
|
||||
virtual void render_target_set_size(RID p_render_target, int p_width, int p_height);
|
||||
virtual RID render_target_get_texture(RID p_render_target) const;
|
||||
virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id);
|
||||
|
||||
virtual void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value);
|
||||
virtual bool render_target_was_used(RID p_render_target);
|
||||
|
|
|
@ -253,11 +253,16 @@ void RasterizerGLES3::set_current_render_target(RID p_render_target) {
|
|||
}
|
||||
}
|
||||
|
||||
void RasterizerGLES3::restore_render_target() {
|
||||
void RasterizerGLES3::restore_render_target(bool p_3d_was_drawn) {
|
||||
|
||||
ERR_FAIL_COND(storage->frame.current_rt == NULL);
|
||||
RasterizerStorageGLES3::RenderTarget *rt = storage->frame.current_rt;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo);
|
||||
if (p_3d_was_drawn && rt->external.fbo != 0) {
|
||||
// our external render buffer is now leading, render 2d into that.
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, rt->external.fbo);
|
||||
} else {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo);
|
||||
}
|
||||
glViewport(0, 0, rt->width, rt->height);
|
||||
}
|
||||
|
||||
|
@ -339,7 +344,11 @@ void RasterizerGLES3::blit_render_target_to_screen(RID p_render_target, const Re
|
|||
#if 1
|
||||
|
||||
Size2 win_size = OS::get_singleton()->get_window_size();
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, rt->fbo);
|
||||
if (rt->external.fbo != 0) {
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, rt->external.fbo);
|
||||
} else {
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, rt->fbo);
|
||||
}
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
|
||||
glBlitFramebuffer(0, 0, rt->width, rt->height, p_screen_rect.position.x, win_size.height - p_screen_rect.position.y - p_screen_rect.size.height, p_screen_rect.position.x + p_screen_rect.size.width, win_size.height - p_screen_rect.position.y, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
|
|
|
@ -56,7 +56,7 @@ public:
|
|||
virtual void initialize();
|
||||
virtual void begin_frame(double frame_step);
|
||||
virtual void set_current_render_target(RID p_render_target);
|
||||
virtual void restore_render_target();
|
||||
virtual void restore_render_target(bool p_3d_was_drawn);
|
||||
virtual void clear_render_target(const Color &p_color);
|
||||
virtual void blit_render_target_to_screen(RID p_render_target, const Rect2 &p_screen_rect, int p_screen = 0);
|
||||
virtual void output_lens_distorted_to_screen(RID p_render_target, const Rect2 &p_screen_rect, float p_k1, float p_k2, const Vector2 &p_eye_center, float p_oversample);
|
||||
|
|
|
@ -3660,7 +3660,11 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p
|
|||
|
||||
if (!env || storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT] || storage->frame.current_rt->width < 4 || storage->frame.current_rt->height < 4) { //no post process on small render targets
|
||||
//no environment or transparent render, simply return and convert to SRGB
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo);
|
||||
if (storage->frame.current_rt->external.fbo != 0) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->external.fbo);
|
||||
} else {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo);
|
||||
}
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color);
|
||||
storage->shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, true);
|
||||
|
@ -4003,7 +4007,11 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p
|
|||
glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height);
|
||||
}
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo);
|
||||
if (storage->frame.current_rt->external.fbo != 0) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->external.fbo);
|
||||
} else {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo);
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, composite_from);
|
||||
|
|
|
@ -6794,6 +6794,24 @@ void RasterizerStorageGLES3::_render_target_clear(RenderTarget *rt) {
|
|||
glDeleteTextures(1, &rt->exposure.color);
|
||||
rt->exposure.fbo = 0;
|
||||
}
|
||||
|
||||
if (rt->external.fbo != 0) {
|
||||
// free this
|
||||
glDeleteFramebuffers(1, &rt->external.fbo);
|
||||
|
||||
// clean up our texture
|
||||
Texture *t = texture_owner.get(rt->external.texture);
|
||||
t->alloc_height = 0;
|
||||
t->alloc_width = 0;
|
||||
t->width = 0;
|
||||
t->height = 0;
|
||||
t->active = false;
|
||||
texture_owner.free(rt->external.texture);
|
||||
memdelete(t);
|
||||
|
||||
rt->external.fbo = 0;
|
||||
}
|
||||
|
||||
Texture *tex = texture_owner.get(rt->texture);
|
||||
tex->alloc_height = 0;
|
||||
tex->alloc_width = 0;
|
||||
|
@ -7249,7 +7267,99 @@ RID RasterizerStorageGLES3::render_target_get_texture(RID p_render_target) const
|
|||
RenderTarget *rt = render_target_owner.getornull(p_render_target);
|
||||
ERR_FAIL_COND_V(!rt, RID());
|
||||
|
||||
return rt->texture;
|
||||
if (rt->external.fbo == 0) {
|
||||
return rt->texture;
|
||||
} else {
|
||||
return rt->external.texture;
|
||||
}
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES3::render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) {
|
||||
RenderTarget *rt = render_target_owner.getornull(p_render_target);
|
||||
ERR_FAIL_COND(!rt);
|
||||
|
||||
if (p_texture_id == 0) {
|
||||
if (rt->external.fbo != 0) {
|
||||
// free this
|
||||
glDeleteFramebuffers(1, &rt->external.fbo);
|
||||
|
||||
// clean up our texture
|
||||
Texture *t = texture_owner.get(rt->external.texture);
|
||||
t->alloc_height = 0;
|
||||
t->alloc_width = 0;
|
||||
t->width = 0;
|
||||
t->height = 0;
|
||||
t->active = false;
|
||||
texture_owner.free(rt->external.texture);
|
||||
memdelete(t);
|
||||
|
||||
rt->external.fbo = 0;
|
||||
}
|
||||
} else {
|
||||
Texture *t;
|
||||
|
||||
if (rt->external.fbo == 0) {
|
||||
// create our fbo
|
||||
glGenFramebuffers(1, &rt->external.fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, rt->external.fbo);
|
||||
|
||||
// allocate a texture
|
||||
t = memnew(Texture);
|
||||
|
||||
t->type = VS::TEXTURE_TYPE_2D;
|
||||
t->flags = 0;
|
||||
t->width = 0;
|
||||
t->height = 0;
|
||||
t->alloc_height = 0;
|
||||
t->alloc_width = 0;
|
||||
t->format = Image::FORMAT_RGBA8;
|
||||
t->target = GL_TEXTURE_2D;
|
||||
t->gl_format_cache = 0;
|
||||
t->gl_internal_format_cache = 0;
|
||||
t->gl_type_cache = 0;
|
||||
t->data_size = 0;
|
||||
t->compressed = false;
|
||||
t->srgb = false;
|
||||
t->total_data_size = 0;
|
||||
t->ignore_mipmaps = false;
|
||||
t->mipmaps = 1;
|
||||
t->active = true;
|
||||
t->tex_id = 0;
|
||||
t->render_target = rt;
|
||||
|
||||
rt->external.texture = texture_owner.make_rid(t);
|
||||
} else {
|
||||
// bind our frame buffer
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, rt->external.fbo);
|
||||
|
||||
// find our texture
|
||||
t = texture_owner.get(rt->external.texture);
|
||||
}
|
||||
|
||||
// set our texture
|
||||
t->tex_id = p_texture_id;
|
||||
|
||||
// size shouldn't be different
|
||||
t->width = rt->width;
|
||||
t->height = rt->height;
|
||||
t->alloc_height = rt->width;
|
||||
t->alloc_width = rt->height;
|
||||
|
||||
// is there a point to setting the internal formats? we don't know them..
|
||||
|
||||
// set our texture as the destination for our framebuffer
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p_texture_id, 0);
|
||||
|
||||
// check status and unbind
|
||||
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
|
||||
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
||||
printf("framebuffer fail, status: %x\n", status);
|
||||
}
|
||||
|
||||
ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE);
|
||||
}
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES3::render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) {
|
||||
|
|
|
@ -1345,6 +1345,15 @@ public:
|
|||
fbo(0) {}
|
||||
} exposure;
|
||||
|
||||
// External FBO to render our final result to (mostly used for ARVR)
|
||||
struct External {
|
||||
GLuint fbo;
|
||||
RID texture;
|
||||
|
||||
External() :
|
||||
fbo(0) {}
|
||||
} external;
|
||||
|
||||
uint64_t last_exposure_tick;
|
||||
|
||||
int width, height;
|
||||
|
@ -1366,6 +1375,7 @@ public:
|
|||
msaa(VS::VIEWPORT_MSAA_DISABLED) {
|
||||
exposure.fbo = 0;
|
||||
buffers.fbo = 0;
|
||||
external.fbo = 0;
|
||||
for (int i = 0; i < RENDER_TARGET_FLAG_MAX; i++) {
|
||||
flags[i] = false;
|
||||
}
|
||||
|
@ -1383,6 +1393,7 @@ public:
|
|||
virtual RID render_target_create();
|
||||
virtual void render_target_set_size(RID p_render_target, int p_width, int p_height);
|
||||
virtual RID render_target_get_texture(RID p_render_target) const;
|
||||
virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id);
|
||||
|
||||
virtual void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value);
|
||||
virtual bool render_target_was_used(RID p_render_target);
|
||||
|
|
|
@ -198,6 +198,17 @@ CameraMatrix ARVRInterfaceGDNative::get_projection_for_eye(ARVRInterface::Eyes p
|
|||
return cm;
|
||||
}
|
||||
|
||||
unsigned int ARVRInterfaceGDNative::get_external_texture_for_eye(ARVRInterface::Eyes p_eye) {
|
||||
|
||||
ERR_FAIL_COND_V(interface == NULL, 0);
|
||||
|
||||
if ((interface->version.major > 1) || ((interface->version.major) == 1 && (interface->version.minor >= 1))) {
|
||||
return (unsigned int)interface->get_external_texture_for_eye(data, (godot_int)p_eye);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ARVRInterfaceGDNative::commit_for_eye(ARVRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) {
|
||||
|
||||
ERR_FAIL_COND(interface == NULL);
|
||||
|
|
|
@ -78,6 +78,7 @@ public:
|
|||
// and a CameraMatrix version to ARVRServer
|
||||
virtual CameraMatrix get_projection_for_eye(ARVRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far);
|
||||
|
||||
virtual unsigned int get_external_texture_for_eye(ARVRInterface::Eyes p_eye);
|
||||
virtual void commit_for_eye(ARVRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect);
|
||||
|
||||
virtual void process();
|
||||
|
|
|
@ -42,7 +42,7 @@ extern "C" {
|
|||
|
||||
// Use these to populate version in your plugin
|
||||
#define GODOTVR_API_MAJOR 1
|
||||
#define GODOTVR_API_MINOR 0
|
||||
#define GODOTVR_API_MINOR 1
|
||||
|
||||
typedef struct {
|
||||
godot_gdnative_api_version version; /* version of our API */
|
||||
|
@ -61,6 +61,8 @@ typedef struct {
|
|||
void (*fill_projection_for_eye)(void *, godot_real *, godot_int, godot_real, godot_real, godot_real);
|
||||
void (*commit_for_eye)(void *, godot_int, godot_rid *, godot_rect2 *);
|
||||
void (*process)(void *);
|
||||
// only in 1.1 onwards
|
||||
godot_int (*get_external_texture_for_eye)(void *, godot_int);
|
||||
} godot_arvr_interface_gdnative;
|
||||
|
||||
void GDAPI godot_arvr_register_interface(const godot_arvr_interface_gdnative *p_interface);
|
||||
|
|
|
@ -123,6 +123,11 @@ ARVRInterface::ARVRInterface() {
|
|||
|
||||
ARVRInterface::~ARVRInterface(){};
|
||||
|
||||
// optional render to external texture which enhances performance on those platforms that require us to submit our end result into special textures.
|
||||
unsigned int ARVRInterface::get_external_texture_for_eye(ARVRInterface::Eyes p_eye) {
|
||||
return 0;
|
||||
};
|
||||
|
||||
/** these will only be implemented on AR interfaces, so we want dummies for VR **/
|
||||
bool ARVRInterface::get_anchor_detection_is_enabled() const {
|
||||
return false;
|
||||
|
|
|
@ -108,6 +108,7 @@ public:
|
|||
virtual bool is_stereo() = 0; /* returns true if this interface requires stereo rendering (for VR HMDs) or mono rendering (for mobile AR) */
|
||||
virtual Transform get_transform_for_eye(ARVRInterface::Eyes p_eye, const Transform &p_cam_transform) = 0; /* get each eyes camera transform, also implement EYE_MONO */
|
||||
virtual CameraMatrix get_projection_for_eye(ARVRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far) = 0; /* get each eyes projection matrix */
|
||||
virtual unsigned int get_external_texture_for_eye(ARVRInterface::Eyes p_eye); /* if applicable return external texture to render to */
|
||||
virtual void commit_for_eye(ARVRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) = 0; /* output the left or right eye */
|
||||
|
||||
virtual void process() = 0;
|
||||
|
|
|
@ -554,6 +554,7 @@ public:
|
|||
virtual RID render_target_create() = 0;
|
||||
virtual void render_target_set_size(RID p_render_target, int p_width, int p_height) = 0;
|
||||
virtual RID render_target_get_texture(RID p_render_target) const = 0;
|
||||
virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) = 0;
|
||||
virtual void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) = 0;
|
||||
virtual bool render_target_was_used(RID p_render_target) = 0;
|
||||
virtual void render_target_clear_used(RID p_render_target) = 0;
|
||||
|
@ -1101,7 +1102,7 @@ public:
|
|||
virtual void initialize() = 0;
|
||||
virtual void begin_frame(double frame_step) = 0;
|
||||
virtual void set_current_render_target(RID p_render_target) = 0;
|
||||
virtual void restore_render_target() = 0;
|
||||
virtual void restore_render_target(bool p_3d) = 0;
|
||||
virtual void clear_render_target(const Color &p_color) = 0;
|
||||
virtual void blit_render_target_to_screen(RID p_render_target, const Rect2 &p_screen_rect, int p_screen = 0) = 0;
|
||||
virtual void output_lens_distorted_to_screen(RID p_render_target, const Rect2 &p_screen_rect, float p_k1, float p_k2, const Vector2 &p_eye_center, float p_oversample) = 0;
|
||||
|
|
|
@ -62,6 +62,16 @@ static Transform2D _canvas_get_transform(VisualServerViewport::Viewport *p_viewp
|
|||
return xf;
|
||||
}
|
||||
|
||||
void VisualServerViewport::_draw_3d(Viewport *p_viewport, ARVRInterface::Eyes p_eye) {
|
||||
Ref<ARVRInterface> arvr_interface = ARVRServer::get_singleton()->get_primary_interface();
|
||||
|
||||
if (p_viewport->use_arvr && arvr_interface.is_valid()) {
|
||||
VSG::scene->render_camera(arvr_interface, p_eye, p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
|
||||
} else {
|
||||
VSG::scene->render_camera(p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
|
||||
}
|
||||
}
|
||||
|
||||
void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::Eyes p_eye) {
|
||||
|
||||
/* Camera should always be BEFORE any other 3D */
|
||||
|
@ -89,13 +99,7 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E
|
|||
}
|
||||
|
||||
if (!scenario_draw_canvas_bg && can_draw_3d) {
|
||||
Ref<ARVRInterface> arvr_interface = ARVRServer::get_singleton()->get_primary_interface();
|
||||
|
||||
if (p_viewport->use_arvr && arvr_interface.is_valid()) {
|
||||
VSG::scene->render_camera(arvr_interface, p_eye, p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
|
||||
} else {
|
||||
VSG::scene->render_camera(p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
|
||||
}
|
||||
_draw_3d(p_viewport, p_eye);
|
||||
}
|
||||
|
||||
if (!p_viewport->hide_canvas) {
|
||||
|
@ -201,17 +205,13 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E
|
|||
//VSG::canvas_render->reset_canvas();
|
||||
}
|
||||
|
||||
VSG::rasterizer->restore_render_target();
|
||||
VSG::rasterizer->restore_render_target(!scenario_draw_canvas_bg && can_draw_3d);
|
||||
|
||||
if (scenario_draw_canvas_bg && canvas_map.front() && canvas_map.front()->key().get_layer() > scenario_canvas_max_layer) {
|
||||
Ref<ARVRInterface> arvr_interface = ARVRServer::get_singleton()->get_primary_interface();
|
||||
|
||||
if (!can_draw_3d) {
|
||||
VSG::scene->render_empty_scene(p_viewport->scenario, p_viewport->shadow_atlas);
|
||||
} else if (p_viewport->use_arvr && arvr_interface.is_valid()) {
|
||||
VSG::scene->render_camera(arvr_interface, p_eye, p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
|
||||
} else {
|
||||
VSG::scene->render_camera(p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
|
||||
_draw_3d(p_viewport, p_eye);
|
||||
}
|
||||
scenario_draw_canvas_bg = false;
|
||||
}
|
||||
|
@ -237,14 +237,10 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E
|
|||
i++;
|
||||
|
||||
if (scenario_draw_canvas_bg && E->key().get_layer() >= scenario_canvas_max_layer) {
|
||||
Ref<ARVRInterface> arvr_interface = ARVRServer::get_singleton()->get_primary_interface();
|
||||
|
||||
if (!can_draw_3d) {
|
||||
VSG::scene->render_empty_scene(p_viewport->scenario, p_viewport->shadow_atlas);
|
||||
} else if (p_viewport->use_arvr && arvr_interface.is_valid()) {
|
||||
VSG::scene->render_camera(arvr_interface, p_eye, p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
|
||||
} else {
|
||||
VSG::scene->render_camera(p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
|
||||
_draw_3d(p_viewport, p_eye);
|
||||
}
|
||||
|
||||
scenario_draw_canvas_bg = false;
|
||||
|
@ -252,14 +248,10 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E
|
|||
}
|
||||
|
||||
if (scenario_draw_canvas_bg) {
|
||||
Ref<ARVRInterface> arvr_interface = ARVRServer::get_singleton()->get_primary_interface();
|
||||
|
||||
if (!can_draw_3d) {
|
||||
VSG::scene->render_empty_scene(p_viewport->scenario, p_viewport->shadow_atlas);
|
||||
} else if (p_viewport->use_arvr && arvr_interface.is_valid()) {
|
||||
VSG::scene->render_camera(arvr_interface, p_eye, p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
|
||||
} else {
|
||||
VSG::scene->render_camera(p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
|
||||
_draw_3d(p_viewport, p_eye);
|
||||
}
|
||||
|
||||
scenario_draw_canvas_bg = false;
|
||||
|
@ -308,12 +300,22 @@ void VisualServerViewport::draw_viewports() {
|
|||
|
||||
// render mono or left eye first
|
||||
ARVRInterface::Eyes leftOrMono = arvr_interface->is_stereo() ? ARVRInterface::EYE_LEFT : ARVRInterface::EYE_MONO;
|
||||
|
||||
// check for an external texture destination for our left eye/mono
|
||||
VSG::storage->render_target_set_external_texture(vp->render_target, arvr_interface->get_external_texture_for_eye(leftOrMono));
|
||||
|
||||
// set our render target as current
|
||||
VSG::rasterizer->set_current_render_target(vp->render_target);
|
||||
|
||||
// and draw left eye/mono
|
||||
_draw_viewport(vp, leftOrMono);
|
||||
arvr_interface->commit_for_eye(leftOrMono, vp->render_target, vp->viewport_to_screen_rect);
|
||||
|
||||
// render right eye
|
||||
if (leftOrMono == ARVRInterface::EYE_LEFT) {
|
||||
// check for an external texture destination for our right eye
|
||||
VSG::storage->render_target_set_external_texture(vp->render_target, arvr_interface->get_external_texture_for_eye(ARVRInterface::EYE_RIGHT));
|
||||
|
||||
// commit for eye may have changed the render target
|
||||
VSG::rasterizer->set_current_render_target(vp->render_target);
|
||||
|
||||
|
@ -324,6 +326,7 @@ void VisualServerViewport::draw_viewports() {
|
|||
// and for our frame timing, mark when we've finished committing our eyes
|
||||
ARVRServer::get_singleton()->_mark_commit();
|
||||
} else {
|
||||
VSG::storage->render_target_set_external_texture(vp->render_target, 0);
|
||||
VSG::rasterizer->set_current_render_target(vp->render_target);
|
||||
|
||||
VSG::scene_render->set_debug_draw_mode(vp->debug_draw);
|
||||
|
|
|
@ -147,6 +147,7 @@ public:
|
|||
|
||||
private:
|
||||
Color clear_color;
|
||||
void _draw_3d(Viewport *p_viewport, ARVRInterface::Eyes p_eye);
|
||||
void _draw_viewport(Viewport *p_viewport, ARVRInterface::Eyes p_eye = ARVRInterface::EYE_MONO);
|
||||
|
||||
public:
|
||||
|
|
Loading…
Reference in New Issue