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

Description

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;
                GPU_BASIC_SHADER_DISABLE_AND_STORE(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.

I can confirm that @Julian Eisel (Severin)'s fix works properly for me.