2
votes

I am interested in simple rect clipping in Directx9. enter image description here On the top picture you see what I get. I want to get what is on the bottom picture without changing the coordinates and/or viewport. Meaning, I will draw the entire circle but Directx9 will just clip it.

It would be preferable that clip rect will be given in WINDOW coordinates, so it will not be affected by current state transformations. In additions, it should affect everything going from now on to window, including polygons, sprites, textures, text etc.

Can somone suggest how to do this?

2

2 Answers

3
votes

You're describing a scissor test, which is built into the directx device.

See Scissor Test

More specifically, you just set the rectangle in screen coordinates using SetScissorRect

And then enable the scissor test by calling

device->SetRenderState( D3DRS_SCISSORTESTENABLE , TRUE );
0
votes

I had the same question a month ago and I came up with a solution myself after trying to locate a clipping method, so I had to develop my own... This should work:

void Clip(LPDIRECT3DDEVICE9 device, LPDIRECT3DSURFACE9 surface, LPDIRECT3DSURFACE9 backbuffer, int x, int y, int width, int height, int destX, int destY, int destWidth, int destHeight)
{
    RECT source;

    if (x >= destX && (x+width) <= (destX+destWidth))
    {
        source.left = 0;
        source.right = width;
    }
    else if ( (x >= destX && x <= (destX+destWidth)) && ((x+width) > (destX+destWidth)))
    {
        source.left = 0;
        source.right = width - ((x+width) - (destX+destWidth));
        source.right = abs(source.right);
    }
    else if (x < destX && (x+width) < (destX+destWidth))
    {
        source.left = abs(x);
        source.right = width;
    }
    else if ( (x < destX) && ((x+width) > (destX+destWidth)))
    {
        source.left = abs(x);
        source.right = source.left + (destWidth);
    }
    else
    {   
        return;
    }


    if (y >= destY && (y+height) <= (destY+destHeight))
    {
        source.top = 0;
        source.bottom = height;
    }
    else if ( (y >= destY && y <= (destY+destHeight)) && ((y+height) > (destY+destHeight)) )
    {
        source.top = 0;
        source.bottom = height - ((y+height) - (destY+destHeight));
        source.bottom = abs(source.bottom);
    }
    else if (y < destY && (y+height) > destY && (y+height) <= (destY+destHeight))
    {
        source.top = abs(y);
        source.bottom = height;
    }
    else if ( (y < destY) && ((y+height) > (destY+destHeight)))
    {
        source.top = abs(y);    
        source.bottom = source.top + (destHeight);
    }
    else
    {
        return;
    }


    RECT destination;

    if (x >= destX && (x+width) <= (destX+destWidth))
    {
        destination.left = x;
        destination.right = x + width;
    }
    else if ( (x >= destX && x <= (destX+destWidth)) && ((x+width) > (destX+destWidth)))
    {
        destination.left = x;
        destination.right = (destX+destWidth);
    }
    else if ( (x < destX) && ((x+width) < (destX+destWidth)) && ((x+width) >= x))
    {
        destination.left = destX;
        destination.right = width - abs(x);
    }
    else if ( (x < destX) && ((x+width) > (destX+destWidth)))
    {
        destination.left = destX;
        destination.right = (destX+destWidth);
    }
    else
    {   
        return;
    }

    if (y >= destY && (y+height) <= (destY+destHeight))
    {
        destination.top = y;
        destination.bottom = y + height;
    }
    else if ( (y >= destY && y <= (destY+destHeight)) && (y+height) > (destY+destHeight))
    {
        destination.top = y;
        destination.bottom = (destY+destHeight);
    }
    else if (y < destY && (y+height) > destY && (y+height) <= (destY+destHeight))
    {
        destination.top = destY;
        destination.bottom = height - abs(y);
    }
    else if ( (y < destY) && ((y+height) > (destY+destHeight)))
    {
        destination.top = destY;
        destination.bottom = (destY+destHeight);
    }
    else
    {
        return;
    }

    device->StretchRect(surface, &source, backbuffer, &destination, D3DTEXF_NONE);      

    DeleteObject(&source);
    DeleteObject(&destination);
};