Implement ability to render viewports directly to screen
This commit is contained in:
parent
86a74e2cb3
commit
65c211d303
18 changed files with 178 additions and 4 deletions
|
@ -253,6 +253,9 @@
|
|||
<member name="physics_object_picking" type="bool" setter="set_physics_object_picking" getter="get_physics_object_picking">
|
||||
If [code]true[/code], the objects rendered by viewport become subjects of mouse picking process. Default value: [code]false[/code].
|
||||
</member>
|
||||
<member name="render_direct_to_screen" type="bool" setter="set_use_render_direct_to_screen" getter="is_using_render_direct_to_screen">
|
||||
If [code]true[/code], renders the Viewport directly to the screen instead of to the root viewport. Only available in GLES2. This is a low-level optimization and should not be used in most cases. If used, reading from the Viewport or from [code]SCREEN_TEXTURE[/code] becomes unavailable. For more information see [method VisualServer.viewport_set_render_direct_to_screen]. Default value: [code]false[/code].
|
||||
</member>
|
||||
<member name="render_target_clear_mode" type="int" setter="set_clear_mode" getter="get_clear_mode" enum="Viewport.ClearMode">
|
||||
The clear mode when viewport used as a render target. Default value: [code]CLEAR_MODE_ALWAYS[/code].
|
||||
</member>
|
||||
|
|
|
@ -3590,7 +3590,14 @@
|
|||
<argument index="2" name="screen" type="int" default="0">
|
||||
</argument>
|
||||
<description>
|
||||
Attaches a viewport to a screen.
|
||||
Copies viewport to a region of the screen specified by [code]rect[/code]. If Viewport.[member Viewport.render_direct_to_screen] is [code]true[/code], then viewport does not use a framebuffer and the contents of the viewport are rendered directly to screen. However, note that the root viewport is drawn last, therefore it will draw over the screen. Accordingly, you must set the root viewport to an area that does not cover the area that you have attached this viewport to.
|
||||
For example, you can set the root viewport to not render at all with the following code:
|
||||
[codeblock]
|
||||
func _ready():
|
||||
get_viewport().set_attach_to_screen_rect(Rect2())
|
||||
$Viewport.set_attach_to_screen_rect(Rect2(0, 0, 600, 600))
|
||||
[/codeblock]
|
||||
Using this can result in significant optimization, especially on lower-end devices. However, it comes at the cost of having to manage your viewports manually. For a further optimization see, [method set_render_direct_to_screen].
|
||||
</description>
|
||||
</method>
|
||||
<method name="viewport_create">
|
||||
|
@ -3789,6 +3796,17 @@
|
|||
Sets the viewport's parent to another viewport.
|
||||
</description>
|
||||
</method>
|
||||
<method name="viewport_set_render_direct_to_screen">
|
||||
<return type="void">
|
||||
</return>
|
||||
<argument index="0" name="viewport" type="RID">
|
||||
</argument>
|
||||
<argument index="1" name="enabled" type="bool">
|
||||
</argument>
|
||||
<description>
|
||||
If [code]true[/code], render the contents of the viewport directly to screen. This allows a low-level optimization where you can skip drawing a viewport to the root viewport. While this optimization can result in a significant increase in speed (especially on older devices), it comes at a cost of usability. When this is enabled, you cannot read from the viewport or from the [code]SCREEN_TEXTURE[/code]. You also lose the benefit of certain window settings, such as the various stretch modes. Another consequence to be aware of is that in 2D the rendering happens in window coordinates, so if you have a viewport that is double the size of the window, and you set this, then only the portion that fits within the window will be drawn, no automatic scaling is possible, even if your game scene is significantly larger than the window size.
|
||||
</description>
|
||||
</method>
|
||||
<method name="viewport_set_scenario">
|
||||
<return type="void">
|
||||
</return>
|
||||
|
|
|
@ -692,6 +692,7 @@ public:
|
|||
/* RENDER TARGET */
|
||||
|
||||
RID render_target_create() { return RID(); }
|
||||
void render_target_set_position(RID p_render_target, int p_x, int p_y) {}
|
||||
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) {}
|
||||
|
|
|
@ -113,9 +113,22 @@ void RasterizerCanvasGLES2::canvas_begin() {
|
|||
|
||||
state.canvas_shader.bind();
|
||||
state.using_transparent_rt = false;
|
||||
int viewport_x, viewport_y, viewport_width, viewport_height;
|
||||
|
||||
if (storage->frame.current_rt) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo);
|
||||
state.using_transparent_rt = storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT];
|
||||
|
||||
if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_DIRECT_TO_SCREEN]) {
|
||||
// set Viewport and Scissor when rendering directly to screen
|
||||
viewport_width = storage->frame.current_rt->width;
|
||||
viewport_height = storage->frame.current_rt->height;
|
||||
viewport_x = storage->frame.current_rt->x;
|
||||
viewport_y = OS::get_singleton()->get_window_size().height - viewport_height - storage->frame.current_rt->y;
|
||||
glScissor(viewport_x, viewport_y, viewport_width, viewport_height);
|
||||
glViewport(viewport_x, viewport_y, viewport_width, viewport_height);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
}
|
||||
}
|
||||
|
||||
if (storage->frame.clear_request) {
|
||||
|
@ -179,6 +192,14 @@ void RasterizerCanvasGLES2::canvas_end() {
|
|||
glDisableVertexAttribArray(i);
|
||||
}
|
||||
|
||||
if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_DIRECT_TO_SCREEN]) {
|
||||
//reset viewport to full window size
|
||||
int viewport_width = OS::get_singleton()->get_window_size().width;
|
||||
int viewport_height = OS::get_singleton()->get_window_size().height;
|
||||
glViewport(0, 0, viewport_width, viewport_height);
|
||||
glScissor(0, 0, viewport_width, viewport_height);
|
||||
}
|
||||
|
||||
state.using_texture_rect = false;
|
||||
state.using_skeleton = false;
|
||||
state.using_ninepatch = false;
|
||||
|
@ -1192,6 +1213,11 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
|
|||
|
||||
void RasterizerCanvasGLES2::_copy_screen(const Rect2 &p_rect) {
|
||||
|
||||
if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_DIRECT_TO_SCREEN]) {
|
||||
ERR_PRINT_ONCE("Cannot use screen texture copying in render target set to render direct to screen");
|
||||
return;
|
||||
}
|
||||
|
||||
if (storage->frame.current_rt->copy_screen_effect.color == 0) {
|
||||
ERR_EXPLAIN("Can't use screen texture copying in a render target configured without copy buffers");
|
||||
ERR_FAIL();
|
||||
|
|
|
@ -2694,6 +2694,7 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
|
|||
Environment *env = NULL;
|
||||
|
||||
int viewport_width, viewport_height;
|
||||
int viewport_x, viewport_y;
|
||||
bool probe_interior = false;
|
||||
bool reverse_cull = false;
|
||||
|
||||
|
@ -2733,6 +2734,13 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
|
|||
|
||||
viewport_width = storage->frame.current_rt->width;
|
||||
viewport_height = storage->frame.current_rt->height;
|
||||
viewport_x = storage->frame.current_rt->x;
|
||||
|
||||
if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_DIRECT_TO_SCREEN]) {
|
||||
viewport_y = OS::get_singleton()->get_window_size().height - viewport_height - storage->frame.current_rt->y;
|
||||
} else {
|
||||
viewport_y = storage->frame.current_rt->y;
|
||||
}
|
||||
}
|
||||
|
||||
state.used_screen_texture = false;
|
||||
|
@ -2798,7 +2806,13 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
|
|||
// other stuff
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, current_fb);
|
||||
glViewport(0, 0, viewport_width, viewport_height);
|
||||
glViewport(viewport_x, viewport_y, viewport_width, viewport_height);
|
||||
|
||||
if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_DIRECT_TO_SCREEN]) {
|
||||
|
||||
glScissor(viewport_x, viewport_y, viewport_width, viewport_height);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
}
|
||||
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
glDepthMask(GL_TRUE);
|
||||
|
@ -2832,6 +2846,10 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
|
|||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_DIRECT_TO_SCREEN]) {
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
}
|
||||
|
||||
glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1);
|
||||
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
|
|
|
@ -4568,9 +4568,16 @@ void RasterizerStorageGLES2::instance_remove_dependency(RID p_base, RasterizerSc
|
|||
|
||||
void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) {
|
||||
|
||||
// do not allocate a render target with no size
|
||||
if (rt->width <= 0 || rt->height <= 0)
|
||||
return;
|
||||
|
||||
// do not allocate a render target that is attached to the screen
|
||||
if (rt->flags[RENDER_TARGET_DIRECT_TO_SCREEN]) {
|
||||
rt->fbo = RasterizerStorageGLES2::system_fbo;
|
||||
return;
|
||||
}
|
||||
|
||||
GLuint color_internal_format;
|
||||
GLuint color_format;
|
||||
GLuint color_type = GL_UNSIGNED_BYTE;
|
||||
|
@ -4779,6 +4786,10 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) {
|
|||
|
||||
void RasterizerStorageGLES2::_render_target_clear(RenderTarget *rt) {
|
||||
|
||||
// there is nothing to clear when DIRECT_TO_SCREEN is used
|
||||
if (rt->flags[RENDER_TARGET_DIRECT_TO_SCREEN])
|
||||
return;
|
||||
|
||||
if (rt->fbo) {
|
||||
glDeleteFramebuffers(1, &rt->fbo);
|
||||
glDeleteTextures(1, &rt->color);
|
||||
|
@ -4873,6 +4884,15 @@ RID RasterizerStorageGLES2::render_target_create() {
|
|||
return render_target_owner.make_rid(rt);
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES2::render_target_set_position(RID p_render_target, int p_x, int p_y) {
|
||||
|
||||
RenderTarget *rt = render_target_owner.getornull(p_render_target);
|
||||
ERR_FAIL_COND(!rt);
|
||||
|
||||
rt->x = p_x;
|
||||
rt->y = p_y;
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES2::render_target_set_size(RID p_render_target, int p_width, int p_height) {
|
||||
|
||||
RenderTarget *rt = render_target_owner.getornull(p_render_target);
|
||||
|
@ -5002,6 +5022,14 @@ void RasterizerStorageGLES2::render_target_set_flag(RID p_render_target, RenderT
|
|||
RenderTarget *rt = render_target_owner.getornull(p_render_target);
|
||||
ERR_FAIL_COND(!rt);
|
||||
|
||||
// When setting DIRECT_TO_SCREEN, you need to clear before the value is set, but allocate after as
|
||||
// those functions change how they operate depending on the value of DIRECT_TO_SCREEN
|
||||
if (p_flag == RENDER_TARGET_DIRECT_TO_SCREEN && p_value != rt->flags[RENDER_TARGET_DIRECT_TO_SCREEN]) {
|
||||
_render_target_clear(rt);
|
||||
rt->flags[p_flag] = p_value;
|
||||
_render_target_allocate(rt);
|
||||
}
|
||||
|
||||
rt->flags[p_flag] = p_value;
|
||||
|
||||
switch (p_flag) {
|
||||
|
|
|
@ -1175,7 +1175,7 @@ public:
|
|||
}
|
||||
} external;
|
||||
|
||||
int width, height;
|
||||
int x, y, width, height;
|
||||
|
||||
bool flags[RENDER_TARGET_FLAG_MAX];
|
||||
|
||||
|
@ -1192,6 +1192,8 @@ public:
|
|||
multisample_color(0),
|
||||
multisample_depth(0),
|
||||
multisample_active(false),
|
||||
x(0),
|
||||
y(0),
|
||||
width(0),
|
||||
height(0),
|
||||
used_in_frame(false),
|
||||
|
@ -1209,6 +1211,7 @@ public:
|
|||
void _render_target_allocate(RenderTarget *rt);
|
||||
|
||||
virtual RID render_target_create();
|
||||
virtual void render_target_set_position(RID p_render_target, int p_x, int p_y);
|
||||
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);
|
||||
|
|
|
@ -7268,6 +7268,10 @@ RID RasterizerStorageGLES3::render_target_create() {
|
|||
return render_target_owner.make_rid(rt);
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES3::render_target_set_position(RID p_render_target, int p_x, int p_y) {
|
||||
//only used in GLES2
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES3::render_target_set_size(RID p_render_target, int p_width, int p_height) {
|
||||
|
||||
RenderTarget *rt = render_target_owner.getornull(p_render_target);
|
||||
|
|
|
@ -1394,6 +1394,7 @@ public:
|
|||
void _render_target_allocate(RenderTarget *rt);
|
||||
|
||||
virtual RID render_target_create();
|
||||
virtual void render_target_set_position(RID p_render_target, int p_x, int p_y);
|
||||
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);
|
||||
|
|
|
@ -2765,6 +2765,19 @@ Rect2 Viewport::get_attach_to_screen_rect() const {
|
|||
return to_screen_rect;
|
||||
}
|
||||
|
||||
void Viewport::set_use_render_direct_to_screen(bool p_render_direct_to_screen) {
|
||||
|
||||
if (p_render_direct_to_screen == render_direct_to_screen)
|
||||
return;
|
||||
|
||||
render_direct_to_screen = p_render_direct_to_screen;
|
||||
VS::get_singleton()->viewport_set_render_direct_to_screen(viewport, p_render_direct_to_screen);
|
||||
}
|
||||
|
||||
bool Viewport::is_using_render_direct_to_screen() const {
|
||||
return render_direct_to_screen;
|
||||
}
|
||||
|
||||
void Viewport::set_physics_object_picking(bool p_enable) {
|
||||
|
||||
physics_object_picking = p_enable;
|
||||
|
@ -3030,6 +3043,8 @@ void Viewport::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_as_audio_listener_2d", "enable"), &Viewport::set_as_audio_listener_2d);
|
||||
ClassDB::bind_method(D_METHOD("is_audio_listener_2d"), &Viewport::is_audio_listener_2d);
|
||||
ClassDB::bind_method(D_METHOD("set_attach_to_screen_rect", "rect"), &Viewport::set_attach_to_screen_rect);
|
||||
ClassDB::bind_method(D_METHOD("set_use_render_direct_to_screen", "enable"), &Viewport::set_use_render_direct_to_screen);
|
||||
ClassDB::bind_method(D_METHOD("is_using_render_direct_to_screen"), &Viewport::is_using_render_direct_to_screen);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_mouse_position"), &Viewport::get_mouse_position);
|
||||
ClassDB::bind_method(D_METHOD("warp_mouse", "to_position"), &Viewport::warp_mouse);
|
||||
|
@ -3084,6 +3099,7 @@ void Viewport::_bind_methods() {
|
|||
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");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "usage", PROPERTY_HINT_ENUM, "2D,2D No-Sampling,3D,3D No-Effects"), "set_usage", "get_usage");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "render_direct_to_screen"), "set_use_render_direct_to_screen", "is_using_render_direct_to_screen");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "debug_draw", PROPERTY_HINT_ENUM, "Disabled,Unshaded,Overdraw,Wireframe"), "set_debug_draw", "get_debug_draw");
|
||||
ADD_GROUP("Render Target", "render_target_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "render_target_v_flip"), "set_vflip", "get_vflip");
|
||||
|
@ -3166,6 +3182,8 @@ Viewport::Viewport() {
|
|||
texture_rid = VisualServer::get_singleton()->viewport_get_texture(viewport);
|
||||
texture_flags = 0;
|
||||
|
||||
render_direct_to_screen = false;
|
||||
|
||||
default_texture.instance();
|
||||
default_texture->vp = const_cast<Viewport *>(this);
|
||||
viewport_textures.insert(default_texture.ptr());
|
||||
|
|
|
@ -182,6 +182,7 @@ private:
|
|||
|
||||
Size2 size;
|
||||
Rect2 to_screen_rect;
|
||||
bool render_direct_to_screen;
|
||||
|
||||
RID contact_2d_debug;
|
||||
RID contact_3d_debug_multimesh;
|
||||
|
@ -481,6 +482,9 @@ public:
|
|||
void set_attach_to_screen_rect(const Rect2 &p_rect);
|
||||
Rect2 get_attach_to_screen_rect() const;
|
||||
|
||||
void set_use_render_direct_to_screen(bool p_render_direct_to_screen);
|
||||
bool is_using_render_direct_to_screen() const;
|
||||
|
||||
Vector2 get_mouse_position() const;
|
||||
void warp_mouse(const Vector2 &p_pos);
|
||||
|
||||
|
|
|
@ -550,10 +550,12 @@ public:
|
|||
RENDER_TARGET_NO_SAMPLING,
|
||||
RENDER_TARGET_HDR,
|
||||
RENDER_TARGET_KEEP_3D_LINEAR,
|
||||
RENDER_TARGET_DIRECT_TO_SCREEN,
|
||||
RENDER_TARGET_FLAG_MAX
|
||||
};
|
||||
|
||||
virtual RID render_target_create() = 0;
|
||||
virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) = 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;
|
||||
|
|
|
@ -454,6 +454,7 @@ public:
|
|||
BIND2(viewport_set_clear_mode, RID, ViewportClearMode)
|
||||
|
||||
BIND3(viewport_attach_to_screen, RID, const Rect2 &, int)
|
||||
BIND2(viewport_set_render_direct_to_screen, RID, bool)
|
||||
BIND1(viewport_detach, RID)
|
||||
|
||||
BIND2(viewport_set_update_mode, RID, ViewportUpdateMode)
|
||||
|
|
|
@ -343,7 +343,7 @@ void VisualServerViewport::draw_viewports() {
|
|||
vp->render_info[VS::VIEWPORT_RENDER_INFO_SURFACE_CHANGES_IN_FRAME] = VSG::storage->get_captured_render_info(VS::INFO_SURFACE_CHANGES_IN_FRAME);
|
||||
vp->render_info[VS::VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME] = VSG::storage->get_captured_render_info(VS::INFO_DRAW_CALLS_IN_FRAME);
|
||||
|
||||
if (vp->viewport_to_screen_rect != Rect2()) {
|
||||
if (vp->viewport_to_screen_rect != Rect2() && (!vp->viewport_render_direct_to_screen || !VSG::rasterizer->is_low_end())) {
|
||||
//copy to screen if set as such
|
||||
VSG::rasterizer->set_current_render_target(RID());
|
||||
VSG::rasterizer->blit_render_target_to_screen(vp->render_target, vp->viewport_to_screen_rect, vp->viewport_to_screen);
|
||||
|
@ -368,6 +368,7 @@ RID VisualServerViewport::viewport_create() {
|
|||
viewport->hide_canvas = false;
|
||||
viewport->render_target = VSG::storage->render_target_create();
|
||||
viewport->shadow_atlas = VSG::scene_render->shadow_atlas_create();
|
||||
viewport->viewport_render_direct_to_screen = false;
|
||||
|
||||
return rid;
|
||||
}
|
||||
|
@ -424,14 +425,55 @@ void VisualServerViewport::viewport_attach_to_screen(RID p_viewport, const Rect2
|
|||
Viewport *viewport = viewport_owner.getornull(p_viewport);
|
||||
ERR_FAIL_COND(!viewport);
|
||||
|
||||
// If using GLES2 we can optimize this operation by rendering directly to system_fbo
|
||||
// instead of rendering to fbo and copying to system_fbo after
|
||||
if (VSG::rasterizer->is_low_end() && viewport->viewport_render_direct_to_screen) {
|
||||
|
||||
VSG::storage->render_target_set_size(viewport->render_target, p_rect.size.x, p_rect.size.y);
|
||||
VSG::storage->render_target_set_position(viewport->render_target, p_rect.position.x, p_rect.position.y);
|
||||
}
|
||||
|
||||
viewport->viewport_to_screen_rect = p_rect;
|
||||
viewport->viewport_to_screen = p_screen;
|
||||
}
|
||||
|
||||
void VisualServerViewport::viewport_set_render_direct_to_screen(RID p_viewport, bool p_enable) {
|
||||
Viewport *viewport = viewport_owner.getornull(p_viewport);
|
||||
ERR_FAIL_COND(!viewport);
|
||||
|
||||
if (p_enable == viewport->viewport_render_direct_to_screen)
|
||||
return;
|
||||
|
||||
// if disabled, reset render_target size and position
|
||||
if (!p_enable) {
|
||||
|
||||
VSG::storage->render_target_set_position(viewport->render_target, 0, 0);
|
||||
VSG::storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y);
|
||||
}
|
||||
|
||||
VSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_DIRECT_TO_SCREEN, p_enable);
|
||||
viewport->viewport_render_direct_to_screen = p_enable;
|
||||
|
||||
// if attached to screen already, setup screen size and position, this needs to happen after setting flag to avoid an unneccesary buffer allocation
|
||||
if (VSG::rasterizer->is_low_end() && viewport->viewport_to_screen_rect != Rect2() && p_enable) {
|
||||
|
||||
VSG::storage->render_target_set_size(viewport->render_target, viewport->viewport_to_screen_rect.size.x, viewport->viewport_to_screen_rect.size.y);
|
||||
VSG::storage->render_target_set_position(viewport->render_target, viewport->viewport_to_screen_rect.position.x, viewport->viewport_to_screen_rect.position.y);
|
||||
}
|
||||
}
|
||||
|
||||
void VisualServerViewport::viewport_detach(RID p_viewport) {
|
||||
|
||||
Viewport *viewport = viewport_owner.getornull(p_viewport);
|
||||
ERR_FAIL_COND(!viewport);
|
||||
|
||||
// if render_direct_to_screen was used, reset size and position
|
||||
if (VSG::rasterizer->is_low_end() && viewport->viewport_render_direct_to_screen) {
|
||||
|
||||
VSG::storage->render_target_set_position(viewport->render_target, 0, 0);
|
||||
VSG::storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y);
|
||||
}
|
||||
|
||||
viewport->viewport_to_screen_rect = Rect2();
|
||||
viewport->viewport_to_screen = 0;
|
||||
}
|
||||
|
|
|
@ -58,6 +58,7 @@ public:
|
|||
|
||||
int viewport_to_screen;
|
||||
Rect2 viewport_to_screen_rect;
|
||||
bool viewport_render_direct_to_screen;
|
||||
|
||||
bool hide_scenario;
|
||||
bool hide_canvas;
|
||||
|
@ -158,6 +159,7 @@ public:
|
|||
void viewport_set_size(RID p_viewport, int p_width, int p_height);
|
||||
|
||||
void viewport_attach_to_screen(RID p_viewport, const Rect2 &p_rect = Rect2(), int p_screen = 0);
|
||||
void viewport_set_render_direct_to_screen(RID p_viewport, bool p_enable);
|
||||
void viewport_detach(RID p_viewport);
|
||||
|
||||
void viewport_set_active(RID p_viewport, bool p_active);
|
||||
|
|
|
@ -381,6 +381,7 @@ public:
|
|||
FUNC2(viewport_set_clear_mode, RID, ViewportClearMode)
|
||||
|
||||
FUNC3(viewport_attach_to_screen, RID, const Rect2 &, int)
|
||||
FUNC2(viewport_set_render_direct_to_screen, RID, bool)
|
||||
FUNC1(viewport_detach, RID)
|
||||
|
||||
FUNC2(viewport_set_update_mode, RID, ViewportUpdateMode)
|
||||
|
|
|
@ -1876,6 +1876,7 @@ void VisualServer::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("viewport_set_active", "viewport", "active"), &VisualServer::viewport_set_active);
|
||||
ClassDB::bind_method(D_METHOD("viewport_set_parent_viewport", "viewport", "parent_viewport"), &VisualServer::viewport_set_parent_viewport);
|
||||
ClassDB::bind_method(D_METHOD("viewport_attach_to_screen", "viewport", "rect", "screen"), &VisualServer::viewport_attach_to_screen, DEFVAL(Rect2()), DEFVAL(0));
|
||||
ClassDB::bind_method(D_METHOD("viewport_set_render_direct_to_screen", "viewport", "enabled"), &VisualServer::viewport_set_render_direct_to_screen);
|
||||
ClassDB::bind_method(D_METHOD("viewport_detach", "viewport"), &VisualServer::viewport_detach);
|
||||
ClassDB::bind_method(D_METHOD("viewport_set_update_mode", "viewport", "update_mode"), &VisualServer::viewport_set_update_mode);
|
||||
ClassDB::bind_method(D_METHOD("viewport_set_vflip", "viewport", "enabled"), &VisualServer::viewport_set_vflip);
|
||||
|
|
|
@ -610,6 +610,7 @@ public:
|
|||
virtual void viewport_set_parent_viewport(RID p_viewport, RID p_parent_viewport) = 0;
|
||||
|
||||
virtual void viewport_attach_to_screen(RID p_viewport, const Rect2 &p_rect = Rect2(), int p_screen = 0) = 0;
|
||||
virtual void viewport_set_render_direct_to_screen(RID p_viewport, bool p_enable) = 0;
|
||||
virtual void viewport_detach(RID p_viewport) = 0;
|
||||
|
||||
enum ViewportUpdateMode {
|
||||
|
|
Loading…
Reference in a new issue