0

I'm trying to render a surface with a method that takes a Surface and X, Y position to render at. The problem is that when the surface is outside the screen by one small pixel, it doesn't render at all.

Why is that? I'm trying to search for DirectX clipping but can't find anything at all.

void Draw(LPDIRECT3DSURFACE9 src, int x, int y)
{
    D3DSURFACE_DESC desc;
    src->GetDesc(&desc);

    D3DVIEWPORT9 viewport;
    Device->GetViewport(&viewport);

    int vX = viewport.X;
    int vY = viewport.Y;
    int vWidth = viewport.X + viewport.Width;
    int vHeight = viewport.Y + viewport.Height;

    RECT source;
    source.left = max(x, vX);
    source.right = min(source.left + desc.Width, vWidth);
    source.top = max(y, vY);
    source.bottom = min(source.top + desc.Height, vHeight);

    RECT destination;
    destination.left = max(x, vX);
    destination.right = min(destination.left + desc.Width + x, vWidth);
    destination.top = max(y, vY);
    destination.bottom = min(destination.top + desc.Height + y, vHeight);

    Device->StretchRect(src, &source, BackBuffer, &destination, D3DTEXF_POINT);
};

...and X = 100, Y = 100 doesn't work but -100 does but it doesn't stretch it right.

Example image of desired effect: enter image description here

I've also been trying to set the *pSourceRect and *pDestRect to something that clips the surface but without any luck.

I'm using DirectX9.

Deukalion
  • 2,516
  • 9
  • 32
  • 50
  • Where do you use x and y in your code? In your example it isnt shown. Have your read the [documentation](http://msdn.microsoft.com/en-us/library/windows/desktop/bb174471%28v=vs.85%29.aspx) of `StrectRect`? There are many restrictions, a brief look from me havent seen something related, but maybe its there :) – Gnietschow Jan 12 '13 at 21:45
  • Have you tried activating the debug runtime? (See http://legalizeadulthood.wordpress.com/2009/06/28/direct3d-programming-tip-5-use-the-debug-runtime/) This produces good, clear messages via OutputDebugString, and it might have something to say about this case. (Though I'm afraid I don't... I've never used StretchRect.) – Tom Seddon Jan 12 '13 at 22:35
  • I've tried, but I've given up. Because if I set the X and Y coordinates in a source or a destination rectangle it doesn't render at all, like I said. I'm trying to find an algorithm to clip the surfaces size so that it fits the the Viewport's size but I can't find any solution. – Deukalion Jan 12 '13 at 22:59
  • Say the screen is 100, 100 and the X and Y position is -50, -50 and the surface width is 100 and height is 100. It should only render the bottomright corner of the surface, but it doesn't. – Deukalion Jan 12 '13 at 23:00
  • So the source rectangle is, the rectangle for the surface? The destination rectangle is, the rectangle for the viewport? I've tried a bunch of combinations with nothing but failure. – Deukalion Jan 12 '13 at 23:03
  • Added code what I've been using, but this only works with coordinate X = 0, Y = 0 (if the surface is the same size as the screen) – Deukalion Jan 12 '13 at 23:07

1 Answers1

1

I'm not sure, whether this works (haven't tested it), but theoretically you should solve your problem with the right rects. Choose them, so that it doesn't exceed the border and that only the overlapping part is copied. I tried to visualize the thought into following picture:

OverlappingRects

If I'm not mistaken it should be

RECT source;
source.left = max(min(-x, desc.Width - 1),0);
source.right = max(min(source.left + viewport.Width -1, desc.Width - 1),0);
source.top = max(min(-y, desc.Height - 1),0);
source.bottom = max(min(source.top + viewport.Height -1, desc.Width - 1),0);

RECT destination;
destination.left = max(min(x, viewport.Width - 1),0);
destination.right = max(min(destination.left + desc.Width -1, viewport.Width - 1),0);
destination.top = max(min(y, viewport.Height - 1),0);
destination.bottom = max(min(destination.top + desc.Height -1, viewport.Height - 1),0);

in your case. The target is that the rectangles don't exceed the related surface, so all coordinates of them must be clipped at the edges.

Gnietschow
  • 3,070
  • 1
  • 18
  • 28
  • Yes, this is exactly as I thought but when I do enter it manually exactly it doesn't work anyway. – Deukalion Jan 14 '13 at 04:19
  • Maybe with width-1 and height-1, because it starts at 0? And in your example code you use `vrc.right = viewport.X + viewport.Width;` shouldn't that be `vrc.right = viewport.Width-1;`, otherwise it would exceed the border. – Gnietschow Jan 14 '13 at 09:33
  • But in case the surface is smaller than the viewport, it should only render that part and not fully render the surface in the viewport. So if I have a screen of 500x500 and a surface of 250x250 I should be able to render it at the center without it expanding, and if I want to just show the bottomright corner (topleft corner of viewport) I should be able to provide -250 -250 coordinates. – Deukalion Jan 17 '13 at 01:33
  • Updated my post with my latest try to clip the surface to the viewport but it doesn't work. – Deukalion Jan 17 '13 at 03:17
  • Try my added code, hopefully it works or show at least something useful. – Gnietschow Jan 17 '13 at 17:51
  • With your example, the Surface is scaled and only works at X = 0, Y = 0, if I put anything else as X and Y it doesn't render at all. – Deukalion Jan 18 '13 at 05:26
  • ...and the error message isn't exactly forthcoming, it's just "Invalid call" – Deukalion Jan 18 '13 at 05:29
  • Here is the working code, very manual, but there has to be an easier way to calculate this: http://pastebin.com/7Z9c4bWw – Deukalion Jan 18 '13 at 06:21