Using render border with real-time viewport Blender Internal rendering and DrawPixels Images Draw Method results in the wrong area being rendered
Open, ConfirmedPublic


Blender version 2.78rc2, but this is in 2.77 as well as a week-old git master.
OS: Arch Linux.

The same bug is present on an nVidia card with the proprietary 340 driver (it's a GTX 285, and nVidia's 340xx driver is the latest supported driver for the card) as well as Intel integrated graphics. I'm 90% sure this is a Blender bug, anyway.

When using border render in conjunction with real-time viewport rendering and DrawPixels (as opposed to 2D texture or GLSL), the x-y offset of the render border is at the lower left corner of the 3D view.

To reproduce:

(You need to have Images Draw Method in settings set to DrawPixels.)

  1. Set Blender Internal as the renderer.
  2. Make sure there's something visible in your scene; having a non-transparent world background is enough.
  3. Set a render border with Ctrl-B; make sure it doesn't reach the lower-left corner.
  4. Press Shift-Z to enable render preview.

I've also attached a test case file; all you have to do is open it and press Shift-Z.



No error for me (2.77a release)

Jon Ross (zlsa) changed the title from "Using Blender Internal render border with real-time rendering results in the wrong area being rendered" to "Using render border with real-time viewport Blender Internal rendering and DrawPixels Images Draw Method results in the wrong area being rendered".Sep 22 2016, 8:24 PM
Jon Ross (zlsa) edited the task description. (Show Details)
YAFU (YAFU) added a subscriber: YAFU (YAFU).EditedSep 22 2016, 8:57 PM

I can reproduce the problem if 'File > User Preferences > System > Images Draw Method > DrawPixels' is selected, in Blender 2.77a ( abf6f08 ) and blender from buildbot 2.78 ( 21e9db9 ).
Kubuntu Linux 14.04 64 bits, GTX 960 (370.28)

Julian Eisel (Severin) triaged this task as "Confirmed" priority.Sep 22 2016, 11:20 PM

This seems to do the trick:

diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c
index 93bac3f..79e9e3d 100644
--- a/source/blender/editors/screen/glutil.c
+++ b/source/blender/editors/screen/glutil.c
@@ -582,11 +582,10 @@ void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int fo
         * covers the entire screen).
        glGetFloatv(GL_SCISSOR_BOX, scissor);
-       draw_w = min_ii(img_w - off_x, ceil((scissor[2] - rast_x) / xzoom));
-       draw_h = min_ii(img_h - off_y, ceil((scissor[3] - rast_y) / yzoom));
+       draw_w = min_ii(img_w - off_x, ceil(scissor[2] / xzoom) + 1.0f);
+       draw_h = min_ii(img_h - off_y, ceil(scissor[3] / yzoom) + 1.0f);
        if (draw_w > 0 && draw_h > 0) {
                int bound_options;

Don't see why rast_x/y should be subtracted from scissor values, to me this would only make sense if scissor[2]/[3] were the max coords, but they are width/height. Added the + 1.0f to fix flickering in zoomed in images (with DrawPixels, open image in clip editor, zoom in really close).
Couldn't find any breakage but would still prefer a second pair of eyes to confirm before committing.

Subtracting rast_x/y make sense if you want to clip away the right/top part of the image that's outside the scissor box. Since the purpose of this code is to clamp the width/height to some reasonable value to work around a driver bug, the proposed fix should work fine even it we loose that exact clipping.

I think the mistake in the original code is assuming that rast_x/y are relative to GL_SCISSOR_BOX coordinates, while they are actually relative to GL_VIEWPORT coordinates. In other cases where this function is used (image editor) these coordinates are always the same, but here with border render the scissor box is a subset of the viewport. So an alternative fix would be to use GL_VIEWPORT coordinates instead of GL_SCISSOR_BOX.