Skip to content

Commit

Permalink
Merge pull request #27527 from BastiaanOlij/render_ext_target
Browse files Browse the repository at this point in the history
Add option to have viewport render into supplied texture (VR)
  • Loading branch information
akien-mga authored Apr 7, 2019
2 parents f4f244e + 8349d4f commit 4942e96
Show file tree
Hide file tree
Showing 19 changed files with 340 additions and 38 deletions.
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

0 comments on commit 4942e96

Please sign in to comment.