Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to have viewport render into supplied texture (VR) #27527

Merged
merged 1 commit into from
Apr 7, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion drivers/dummy/rasterizer_dummy.h
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,7 @@ class RasterizerStorageDummy : public RasterizerStorage {
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) {}
Expand Down Expand Up @@ -781,7 +782,7 @@ class RasterizerDummy : public Rasterizer {
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) {}
Expand Down
8 changes: 6 additions & 2 deletions drivers/gles2/rasterizer_gles2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion drivers/gles2/rasterizer_gles2.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class RasterizerGLES2 : public Rasterizer {
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);
Expand Down
6 changes: 5 additions & 1 deletion drivers/gles2/rasterizer_scene_gles2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
120 changes: 119 additions & 1 deletion drivers/gles2/rasterizer_storage_gles2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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) {
Expand Down
12 changes: 12 additions & 0 deletions drivers/gles2/rasterizer_storage_gles2.h
Original file line number Diff line number Diff line change
Expand Up @@ -1156,6 +1156,16 @@ class RasterizerStorageGLES2 : public RasterizerStorage {

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];
Expand All @@ -1176,6 +1186,7 @@ class RasterizerStorageGLES2 : public RasterizerStorage {
for (int i = 0; i < RENDER_TARGET_FLAG_MAX; ++i) {
flags[i] = false;
}
external.fbo = 0;
}
};

Expand All @@ -1187,6 +1198,7 @@ class RasterizerStorageGLES2 : public RasterizerStorage {
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);
Expand Down
15 changes: 12 additions & 3 deletions drivers/gles3/rasterizer_gles3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion drivers/gles3/rasterizer_gles3.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class RasterizerGLES3 : public Rasterizer {
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);
Expand Down
12 changes: 10 additions & 2 deletions drivers/gles3/rasterizer_scene_gles3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
Loading