Cycles: border render now works in the viewport, when looking through the
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Wed, 6 Jun 2012 23:27:43 +0000 (23:27 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Wed, 6 Jun 2012 23:27:43 +0000 (23:27 +0000)
camera, same as in render. It draws objects in solid draw mode outside of
the border.

intern/cycles/blender/blender_camera.cpp
intern/cycles/blender/blender_session.cpp
intern/cycles/blender/blender_sync.h
intern/cycles/render/buffers.cpp
intern/cycles/render/camera.cpp
intern/cycles/render/camera.h
intern/cycles/render/session.cpp
source/blender/editors/space_view3d/view3d_draw.c

index bdd02bb508601e882546c9706296be44ee83dbed..9bc82344fcc808a5a8b311cbc0f9bcfc1baa6308 100644 (file)
@@ -56,6 +56,11 @@ struct BlenderCamera {
        float sensor_width;
        float sensor_height;
 
+       float border_left;
+       float border_right;
+       float border_bottom;
+       float border_top;
+
        Transform matrix;
 };
 
@@ -70,6 +75,8 @@ static void blender_camera_init(BlenderCamera *bcam)
        bcam->sensor_height = 18.0f;
        bcam->sensor_fit = BlenderCamera::AUTO;
        bcam->shuttertime = 1.0f;
+       bcam->border_right = 1.0f;
+       bcam->border_top = 1.0f;
 }
 
 static float blender_camera_focal_distance(BL::Object b_ob, BL::Camera b_camera)
@@ -188,85 +195,94 @@ static Transform blender_camera_matrix(const Transform& tfm, CameraType type)
        return transform_clear_scale(result);
 }
 
-static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int height)
+static void blender_camera_viewplane(BlenderCamera *bcam, int width, int height,
+       float *left, float *right, float *bottom, float *top, float *aspectratio, float *sensor_size)
 {
-       /* copy camera to compare later */
-       Camera prevcam = *cam;
-
        /* dimensions */
        float xratio = width*bcam->pixelaspect.x;
        float yratio = height*bcam->pixelaspect.y;
 
        /* compute x/y aspect and ratio */
-       float aspectratio, xaspect, yaspect;
+       float xaspect, yaspect;
 
        /* sensor fitting */
        bool horizontal_fit;
-       float sensor_size;
-
-       cam->sensorwidth = bcam->sensor_width;
-       cam->sensorheight = bcam->sensor_height;
 
        if(bcam->sensor_fit == BlenderCamera::AUTO) {
                horizontal_fit = (xratio > yratio);
-               sensor_size = bcam->sensor_width;
+               *sensor_size = bcam->sensor_width;
        }
        else if(bcam->sensor_fit == BlenderCamera::HORIZONTAL) {
                horizontal_fit = true;
-               sensor_size = bcam->sensor_width;
+               *sensor_size = bcam->sensor_width;
        }
        else {
                horizontal_fit = false;
-               sensor_size = bcam->sensor_height;
+               *sensor_size = bcam->sensor_height;
        }
 
        if(horizontal_fit) {
-               aspectratio= xratio/yratio;
-               xaspect= aspectratio;
+               *aspectratio= xratio/yratio;
+               xaspect= *aspectratio;
                yaspect= 1.0f;
        }
        else {
-               aspectratio= yratio/xratio;
+               *aspectratio= yratio/xratio;
                xaspect= 1.0f;
-               yaspect= aspectratio;
+               yaspect= *aspectratio;
        }
 
        /* modify aspect for orthographic scale */
        if(bcam->type == CAMERA_ORTHOGRAPHIC) {
-               xaspect = xaspect*bcam->ortho_scale/(aspectratio*2.0f);
-               yaspect = yaspect*bcam->ortho_scale/(aspectratio*2.0f);
-               aspectratio = bcam->ortho_scale/2.0f;
+               xaspect = xaspect*bcam->ortho_scale/(*aspectratio*2.0f);
+               yaspect = yaspect*bcam->ortho_scale/(*aspectratio*2.0f);
+               *aspectratio = bcam->ortho_scale/2.0f;
        }
 
        if(bcam->type == CAMERA_PANORAMA) {
                /* set viewplane */
-               cam->left = 0.0f;
-               cam->right = 1.0f;
-               cam->bottom = 0.0f;
-               cam->top = 1.0f;
+               *left = 0.0f;
+               *right = 1.0f;
+               *bottom = 0.0f;
+               *top = 1.0f;
        }
        else {
                /* set viewplane */
-               cam->left = -xaspect;
-               cam->right = xaspect;
-               cam->bottom = -yaspect;
-               cam->top = yaspect;
+               *left = -xaspect;
+               *right = xaspect;
+               *bottom = -yaspect;
+               *top = yaspect;
 
                /* zoom for 3d camera view */
-               cam->left *= bcam->zoom;
-               cam->right *= bcam->zoom;
-               cam->bottom *= bcam->zoom;
-               cam->top *= bcam->zoom;
+               *left *= bcam->zoom;
+               *right *= bcam->zoom;
+               *bottom *= bcam->zoom;
+               *top *= bcam->zoom;
 
                /* modify viewplane with camera shift and 3d camera view offset */
-               float dx = 2.0f*(aspectratio*bcam->shift.x + bcam->offset.x*xaspect*2.0f);
-               float dy = 2.0f*(aspectratio*bcam->shift.y + bcam->offset.y*yaspect*2.0f);
+               float dx = 2.0f*(*aspectratio*bcam->shift.x + bcam->offset.x*xaspect*2.0f);
+               float dy = 2.0f*(*aspectratio*bcam->shift.y + bcam->offset.y*yaspect*2.0f);
 
-               cam->left += dx;
-               cam->right += dx;
-               cam->bottom += dy;
-               cam->top += dy;
+               *left += dx;
+               *right += dx;
+               *bottom += dy;
+               *top += dy;
        }
+}
+
+static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int height)
+{
+       /* copy camera to compare later */
+       Camera prevcam = *cam;
+       float aspectratio, sensor_size;
+
+       /* viewplane */
+       blender_camera_viewplane(bcam, width, height,
+               &cam->left, &cam->right, &cam->bottom, &cam->top, &aspectratio, &sensor_size);
+
+       /* sensor */
+       cam->sensorwidth = bcam->sensor_width;
+       cam->sensorheight = bcam->sensor_height;
 
        /* clipping distances */
        cam->nearclip = bcam->nearclip;
@@ -294,6 +310,12 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int
        cam->use_motion = false;
        cam->shuttertime = bcam->shuttertime;
 
+       /* border */
+       cam->border_left = bcam->border_left;
+       cam->border_right = bcam->border_right;
+       cam->border_bottom = bcam->border_bottom;
+       cam->border_top = bcam->border_top;
+
        /* set update flag */
        if(cam->modified(prevcam))
                cam->tag_update();
@@ -313,6 +335,14 @@ void BlenderSync::sync_camera(BL::Object b_override, int width, int height)
        bcam.pixelaspect.y = r.pixel_aspect_y();
        bcam.shuttertime = r.motion_blur_shutter();
 
+       /* border */
+       if(r.use_border()) {
+               bcam.border_left = r.border_min_x();
+               bcam.border_right = r.border_max_x();
+               bcam.border_bottom = r.border_min_y();
+               bcam.border_top = r.border_max_y();
+       }
+
        /* camera object */
        BL::Object b_ob = b_scene.camera();
 
@@ -348,67 +378,142 @@ void BlenderSync::sync_camera_motion(BL::Object b_ob, int motion)
 
 /* Sync 3D View Camera */
 
-void BlenderSync::sync_view(BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height)
+static void blender_camera_from_view(BlenderCamera *bcam, BL::Scene b_scene, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height)
 {
-       BlenderCamera bcam;
-       blender_camera_init(&bcam);
-
        /* 3d view parameters */
-       bcam.nearclip = b_v3d.clip_start();
-       bcam.farclip = b_v3d.clip_end();
-       bcam.lens = b_v3d.lens();
-       bcam.shuttertime = b_scene.render().motion_blur_shutter();
+       bcam->nearclip = b_v3d.clip_start();
+       bcam->farclip = b_v3d.clip_end();
+       bcam->lens = b_v3d.lens();
+       bcam->shuttertime = b_scene.render().motion_blur_shutter();
 
        if(b_rv3d.view_perspective() == BL::RegionView3D::view_perspective_CAMERA) {
                /* camera view */
                BL::Object b_ob = (b_v3d.lock_camera_and_layers())? b_scene.camera(): b_v3d.camera();
 
                if(b_ob) {
-                       blender_camera_from_object(&bcam, b_ob);
+                       blender_camera_from_object(bcam, b_ob);
 
                        /* magic zoom formula */
-                       bcam.zoom = (float)b_rv3d.view_camera_zoom();
-                       bcam.zoom = (1.41421f + bcam.zoom/50.0f);
-                       bcam.zoom *= bcam.zoom;
-                       bcam.zoom = 2.0f/bcam.zoom;
+                       bcam->zoom = (float)b_rv3d.view_camera_zoom();
+                       bcam->zoom = (1.41421f + bcam->zoom/50.0f);
+                       bcam->zoom *= bcam->zoom;
+                       bcam->zoom = 2.0f/bcam->zoom;
 
                        /* offset */
-                       bcam.offset = get_float2(b_rv3d.view_camera_offset());
+                       bcam->offset = get_float2(b_rv3d.view_camera_offset());
                }
        }
        else if(b_rv3d.view_perspective() == BL::RegionView3D::view_perspective_ORTHO) {
                /* orthographic view */
-               bcam.farclip *= 0.5;
-               bcam.nearclip = -bcam.farclip;
+               bcam->farclip *= 0.5;
+               bcam->nearclip = -bcam->farclip;
 
-               bcam.type = CAMERA_ORTHOGRAPHIC;
-               bcam.ortho_scale = b_rv3d.view_distance();
+               bcam->type = CAMERA_ORTHOGRAPHIC;
+               bcam->ortho_scale = b_rv3d.view_distance();
        }
 
-       bcam.zoom *= 2.0f;
+       bcam->zoom *= 2.0f;
 
        /* 3d view transform */
-       bcam.matrix = transform_inverse(get_transform(b_rv3d.view_matrix()));
+       bcam->matrix = transform_inverse(get_transform(b_rv3d.view_matrix()));
+}
+
+static void blender_camera_border(BlenderCamera *bcam, BL::Scene b_scene, BL::SpaceView3D b_v3d,
+       BL::RegionView3D b_rv3d, int width, int height)
+{
+       BL::RenderSettings r = b_scene.render();
+
+       if(!r.use_border())
+               return;
+
+       /* camera view? */
+       if(!(b_rv3d && b_rv3d.view_perspective() == BL::RegionView3D::view_perspective_CAMERA))
+               return;
+
+       BL::Object b_ob = (b_v3d.lock_camera_and_layers())? b_scene.camera(): b_v3d.camera();
+
+       if(!b_ob)
+               return;
+
+       bcam->border_left = r.border_min_x();
+       bcam->border_right = r.border_max_x();
+       bcam->border_bottom = r.border_min_y();
+       bcam->border_top = r.border_max_y();
+
+       float cam_left, cam_right, cam_bottom, cam_top;
+       float view_left, view_right, view_bottom, view_top;
+       float view_aspect, cam_aspect, sensor_size;
+
+       /* get viewport viewplane */
+       BlenderCamera view_bcam;
+       blender_camera_init(&view_bcam);
+       blender_camera_from_view(&view_bcam, b_scene, b_v3d, b_rv3d, width, height);
+
+       blender_camera_viewplane(&view_bcam, width, height,
+               &view_left, &view_right, &view_bottom, &view_top, &view_aspect, &sensor_size);
+
+       view_left /= view_aspect;
+       view_right /= view_aspect;
+       view_bottom /= view_aspect;
+       view_top /= view_aspect;
+
+       /* get camera viewplane */
+       BlenderCamera cam_bcam;
+       blender_camera_init(&cam_bcam);
+       blender_camera_from_object(&cam_bcam, b_ob);
+
+       width = (int)(r.resolution_x()*r.resolution_percentage()/100);
+       height = (int)(r.resolution_y()*r.resolution_percentage()/100);
+
+       blender_camera_viewplane(&cam_bcam, width, height,
+               &cam_left, &cam_right, &cam_bottom, &cam_top, &cam_aspect, &sensor_size);
+
+       cam_left /= cam_aspect;
+       cam_right /= cam_aspect;
+       cam_bottom /= cam_aspect;
+       cam_top /= cam_aspect;
+
+       /* determine viewport subset matching camera border */
+       float tmp_left = ((cam_left - view_left) / (view_right - view_left));
+       float tmp_right = ((cam_right - view_left) / (view_right - view_left));
+       float tmp_bottom = ((cam_bottom - view_bottom) / (view_top - view_bottom));
+       float tmp_top = ((cam_top - view_bottom) / (view_top - view_bottom));
+
+       bcam->border_left = tmp_left + bcam->border_left*(tmp_right - tmp_left);
+       bcam->border_right = tmp_left + bcam->border_right*(tmp_right - tmp_left);
+       bcam->border_bottom = tmp_bottom + bcam->border_bottom*(tmp_top - tmp_bottom);
+       bcam->border_top = tmp_bottom + bcam->border_top*(tmp_top - tmp_bottom);
+
+       /* clamp */
+       bcam->border_left = max(bcam->border_left, 0.0f);
+       bcam->border_right = min(bcam->border_right, 1.0f);
+       bcam->border_bottom = max(bcam->border_bottom, 0.0f);
+       bcam->border_top = min(bcam->border_top, 1.0f);
+}
+
+void BlenderSync::sync_view(BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height)
+{
+       BlenderCamera bcam;
+       blender_camera_init(&bcam);
+       blender_camera_from_view(&bcam, b_scene, b_v3d, b_rv3d, width, height);
+       blender_camera_border(&bcam, b_scene, b_v3d, b_rv3d, width, height);
 
-       /* sync */
        blender_camera_sync(scene->camera, &bcam, width, height);
 }
 
-BufferParams BlenderSync::get_buffer_params(BL::Scene b_scene, BL::RegionView3D b_rv3d, int width, int height)
+BufferParams BlenderSync::get_buffer_params(BL::Scene b_scene, Camera *cam, int width, int height)
 {
        BufferParams params;
 
        params.full_width = width;
        params.full_height = height;
 
-       /* border render */
-       BL::RenderSettings r = b_scene.render();
-
-       if(!b_rv3d && r.use_border()) {
-               params.full_x = r.border_min_x()*width;
-               params.full_y = r.border_min_y()*height;
-               params.width = (int)(r.border_max_x()*width) - params.full_x;
-               params.height = (int)(r.border_max_y()*height) - params.full_y;
+       if(b_scene.render().use_border()) {
+               /* border render */
+               params.full_x = cam->border_left*width;
+               params.full_y = cam->border_bottom*height;
+               params.width = (int)(cam->border_right*width) - params.full_x;
+               params.height = (int)(cam->border_top*height) - params.full_y;
        }
        else {
                params.width = width;
index 997909f1b9287d3722e836a24840ac380a014664..9726f7b94cf3a7e08851a20dc967acd0eaed9db7 100644 (file)
@@ -106,7 +106,7 @@ void BlenderSession::create_session()
        session->set_pause(BlenderSync::get_session_pause(b_scene, background));
 
        /* set buffer parameters */
-       BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_rv3d, width, height);
+       BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, scene->camera, width, height);
        session->reset(buffer_params, session_params.samples);
 }
 
@@ -181,7 +181,7 @@ void BlenderSession::render()
 {
        /* get buffer parameters */
        SessionParams session_params = BlenderSync::get_session_params(b_userpref, b_scene, background);
-       BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_rv3d, width, height);
+       BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, scene->camera, width, height);
        int w = buffer_params.width, h = buffer_params.height;
 
        /* create render result */
@@ -326,7 +326,7 @@ void BlenderSession::synchronize()
 
        /* reset if needed */
        if(scene->need_reset()) {
-               BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_rv3d, width, height);
+               BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, scene->camera, width, height);
                session->reset(buffer_params, session_params.samples);
        }
 }
@@ -364,7 +364,7 @@ bool BlenderSession::draw(int w, int h)
                /* reset if requested */
                if(reset) {
                        SessionParams session_params = BlenderSync::get_session_params(b_userpref, b_scene, background);
-                       BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_rv3d, width, height);
+                       BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, scene->camera, w, h);
 
                        session->reset(buffer_params, session_params.samples);
                }
@@ -374,7 +374,7 @@ bool BlenderSession::draw(int w, int h)
        update_status_progress();
 
        /* draw */
-       BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_rv3d, width, height);
+       BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, scene->camera, width, height);
 
        return !session->draw(buffer_params);
 }
index 10afd468850cd530c4b8ed18da8795b8b4263cf0..bc6258d35ac0ca4740410aa2bb647bd1b868511e 100644 (file)
@@ -63,7 +63,7 @@ public:
        static SceneParams get_scene_params(BL::Scene b_scene, bool background);
        static SessionParams get_session_params(BL::UserPreferences b_userpref, BL::Scene b_scene, bool background);
        static bool get_session_pause(BL::Scene b_scene, bool background);
-       static BufferParams get_buffer_params(BL::Scene b_scene, BL::RegionView3D b_rv3d, int width, int height);
+       static BufferParams get_buffer_params(BL::Scene b_scene, Camera *cam, int width, int height);
 
 private:
        /* sync */
index a80851b945a14746414609cdf4d2b553058332b7..a7fd47c94cf895e039f41abdb7ad730756ca213b 100644 (file)
@@ -311,8 +311,14 @@ void DisplayBuffer::draw_set(int width, int height)
 
 void DisplayBuffer::draw(Device *device)
 {
-       if(draw_width != 0 && draw_height != 0)
+       if(draw_width != 0 && draw_height != 0) {
+               glPushMatrix();
+               glTranslatef(params.full_x, params.full_y, 0.0f);
+
                device->draw_pixels(rgba, 0, draw_width, draw_height, 0, params.width, params.height, transparent);
+
+               glPopMatrix();
+       }
 }
 
 bool DisplayBuffer::draw_ready()
index 3ecffab7cbc4398d7bdb693d4db8092fbaf4b6a9..ed239074cd452be4d0145df4a7b8ef32b10df7b9 100644 (file)
@@ -58,6 +58,11 @@ Camera::Camera()
        bottom = -1.0f;
        top = 1.0f;
 
+       border_left = 0.0f;
+       border_right = 1.0f;
+       border_bottom = 0.0f;
+       border_top = 1.0f;
+
        screentoworld = transform_identity();
        rastertoworld = transform_identity();
        ndctoworld = transform_identity();
@@ -248,6 +253,10 @@ bool Camera::modified(const Camera& cam)
                (right == cam.right) &&
                (bottom == cam.bottom) &&
                (top == cam.top) &&
+               (border_left == cam.border_left) &&
+               (border_right == cam.border_right) &&
+               (border_bottom == cam.border_bottom) &&
+               (border_top == cam.border_top) &&
                (matrix == cam.matrix) &&
                (motion == cam.motion) &&
                (use_motion == cam.use_motion) &&
index 7a09b5981e4042800dc491d121a96dca84d25e09..647423d88baf8bfc2a282d69134fd48f7294efd5 100644 (file)
@@ -67,6 +67,9 @@ public:
        int width, height;
        float left, right, bottom, top;
 
+       /* border */
+       float border_left, border_right, border_bottom, border_top;
+
        /* transformation */
        Transform matrix;
 
index 34a0c0ff877771fd04e30783aa75fce6061277b2..173d73ea2c77f460c6ca31d08cbbf886812ce797 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "util_foreach.h"
 #include "util_function.h"
+#include "util_opengl.h"
 #include "util_task.h"
 #include "util_time.h"
 
index 7c12816741d54acd3ef66cd0175091196e097648..a36c14151e61179f1300fc2901784b0077eee679 100644 (file)
@@ -1146,7 +1146,6 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
 
        /* border */
        if (scene->r.mode & R_BORDER) {
-               
                cpack(0);
                x3 = x1 + scene->r.border.xmin * (x2 - x1);
                y3 = y1 + scene->r.border.ymin * (y2 - y1);
@@ -2735,12 +2734,15 @@ static void draw_viewport_fps(Scene *scene, ARegion *ar)
        BLF_draw_default_ascii(22,  ar->winy - 17, 0.0f, printable, sizeof(printable));
 }
 
-static int view3d_main_area_draw_engine(const bContext *C, ARegion *ar)
+static void view3d_main_area_draw_objects(const bContext *C, ARegion *ar, const char **grid_unit);
+
+static int view3d_main_area_draw_engine(const bContext *C, ARegion *ar, int draw_border)
 {
        Scene *scene = CTX_data_scene(C);
        View3D *v3d = CTX_wm_view3d(C);
        RegionView3D *rv3d = CTX_wm_region_view3d(C);
        RenderEngineType *type;
+       GLint scissor[4];
 
        /* create render engine */
        if (!rv3d->render_engine) {
@@ -2757,17 +2759,48 @@ static int view3d_main_area_draw_engine(const bContext *C, ARegion *ar)
        view3d_main_area_setup_view(scene, v3d, ar, NULL, NULL);
 
        /* background draw */
+       ED_region_pixelspace(ar);
+
+       if (draw_border) {
+               /* for border draw, we only need to clear a subset of the 3d view */
+               rctf viewborder;
+               rcti cliprct;
+
+               ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewborder, FALSE);
+
+               cliprct.xmin = viewborder.xmin + scene->r.border.xmin * (viewborder.xmax - viewborder.xmin);
+               cliprct.ymin = viewborder.ymin + scene->r.border.ymin * (viewborder.ymax - viewborder.ymin);
+               cliprct.xmax = viewborder.xmin + scene->r.border.xmax * (viewborder.xmax - viewborder.xmin);
+               cliprct.ymax = viewborder.ymin + scene->r.border.ymax * (viewborder.ymax - viewborder.ymin);
+
+               cliprct.xmin += ar->winrct.xmin;
+               cliprct.xmax += ar->winrct.xmin;
+               cliprct.ymin += ar->winrct.ymin;
+               cliprct.ymax += ar->winrct.ymin;
+
+               cliprct.xmin = MAX2(cliprct.xmin, ar->winrct.xmin);
+               cliprct.ymin = MAX2(cliprct.ymin, ar->winrct.ymin);
+               cliprct.xmax = MIN2(cliprct.xmax, ar->winrct.xmax);
+               cliprct.ymax = MIN2(cliprct.ymax, ar->winrct.ymax);
+
+               glGetIntegerv(GL_SCISSOR_BOX, scissor);
+               glScissor(cliprct.xmin, cliprct.ymin, cliprct.xmax - cliprct.xmin, cliprct.ymax - cliprct.ymin);
+       }
+
        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
-       ED_region_pixelspace(ar);
-
-       /* render result draw */
        if (v3d->flag & V3D_DISPBGPICS)
                view3d_draw_bgpic(scene, ar, v3d, FALSE, TRUE);
        else
                fdrawcheckerboard(0, 0, ar->winx, ar->winy);
 
+       if (draw_border) {
+               /* restore scissor as it was before */
+               glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
+       }
+
+       /* render result draw */
        type = rv3d->render_engine->type;
        type->view_draw(rv3d->render_engine, C);
 
@@ -3028,15 +3061,21 @@ static void view3d_main_area_draw_info(const bContext *C, ARegion *ar, const cha
 
 void view3d_main_area_draw(const bContext *C, ARegion *ar)
 {
+       Scene *scene = CTX_data_scene(C);
        View3D *v3d = CTX_wm_view3d(C);
+       RegionView3D *rv3d = CTX_wm_region_view3d(C);
        const char *grid_unit = NULL;
+       int draw_border = (rv3d->persp == RV3D_CAMOB && (scene->r.mode & R_BORDER));
 
-       /* draw viewport using external renderer? */
-       if (!(v3d->drawtype == OB_RENDER && view3d_main_area_draw_engine(C, ar))) {
-               /* draw viewport using opengl */
+       /* draw viewport using opengl */
+       if (v3d->drawtype != OB_RENDER || draw_border) {
                view3d_main_area_draw_objects(C, ar, &grid_unit);
                ED_region_pixelspace(ar);
        }
+
+       /* draw viewport using external renderer */
+       if (v3d->drawtype == OB_RENDER)
+               view3d_main_area_draw_engine(C, ar, draw_border);
        
        view3d_main_area_draw_info(C, ar, grid_unit);