[SOLVED] How to "grab" a part of the displayed graphic

Hi all

I’m new on monogame.
I have to “grab” a part of the graphic displayed on the screen ?
The formis not a problem as it’s a rectangle.
But how to do that ?

Thanks

Pit

I think you are looking for GraphicsDevice.ScissorRectangle

From https://github.com/MonoGame/MonoGame/issues/217

RasterizerState rasterizerState = new RasterizerState() { MultiSampleAntiAlias = false, ScissorTestEnable = true };
            Texture2D whitePixel = new Texture2D(GraphicsDevice, 1, 1);
            whitePixel.SetData<Color>(new Color[] { Color.White });

            Rectangle scissorRectangle = new Rectangle(0, 0, GraphicsDevice.PresentationParameters.BackBufferWidth, GraphicsDevice.PresentationParameters.BackBufferHeight);
            Rectangle scissorRectangle2 = new Rectangle(0, 0, GraphicsDevice.PresentationParameters.BackBufferWidth / 2, GraphicsDevice.PresentationParameters.BackBufferHeight / 2);

            this.SpriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.LinearClamp, DepthStencilState.None, rasterizerState);
            this.GraphicsDevice.ScissorRectangle = scissorRectangle;
            this.SpriteBatch.Draw(whitePixel, new Rectangle(0, 0, GraphicsDevice.PresentationParameters.BackBufferWidth, GraphicsDevice.PresentationParameters.BackBufferHeight), Color.White);
            this.GraphicsDevice.ScissorRectangle = scissorRectangle2;
            this.SpriteBatch.End();

I’m not sure this is what I need
i have the impression that this is done to display something in a rect of the screen
but I need first to grab a part of the screen
I don’t see in this code how to do this ?

pit

Never used it :open_mouth:
Use a viewport then?

If I understand you correctly, you’re looking for GraphicsDevice.GetBackbufferData. it allows you to get the pixel colors rendered to the backbuffer.

thanks !
I will look at this !

Pit

I’ve never used GraphicsDevice.GetBackBufferData, but if that works as one would expect, I think Jjagg’s suggestion is the best approach since I don’t think it would incur any additional overhead.

If it doesn’t though, a couple alternatives…

  1. Render the current frame to a render target in addition to the screen. Then grab the colour array from the render target and get the data you need.

  2. A bit of an optimization to (1), create a render target of the size you need and then transform your world by the offset of the rectangle’s position, then render to the render target.

The downside there is that you do a double render.

Hi

I try to use getbackbufferdata
but it seems that this method is not available at least for IOS…

Pit

It was not yet implemented in 3.6. it should be available in a develop version.

My bad… I’ve always thought scissors were like a “cut and paste” feature

Hi all

it seems clear that, without “getbackbufferdata” the solution for me is to work with getdata and setdata method from Texture2D.
so the last question is: how to transform the content of my screen in a Texture2D ?

pit

The solution would be to use a RenderTarget2D the size of the back buffer and render to that. Then render that render target to the backbuffer with a SpriteBatch.Draw call like @Trinith said. But like I said in my previous comment you should be able to use GetBackbufferData with a develop version.

Is there any reason why not to just render that part into render target and be done with it? Since using getdata / setdata isn’t exactly fast approach.

That’s a good point. If the use case is to render whatever is on the back buffer again you really shouldn’t be using GetBackbufferData or GetData/SetData. Would be useful if you can elaborate on what you want to achieve @Pierre_Durant.

Also don’t forget that rendering part of RT is trivial through use of source rectangle. So unless you need to access pixel values on CPU there is really no reason to use get/set.

Hi

no I don’t really need to access the pixel datas.
My purpose is:

  • to “copy” a little part of the screen (something like a square 100x100)
  • to display it on the same screen (but enlarging it in order to have a “magnifying glass” effect)

pit

Oh, in that case, I think a RenderTarget is definitely what you’re after here since you want to do some effects on it. You can render to a different RenderTarget and use a scaling operation at the same time while doing it to get the effect you’re after.

1 Like

Initially draw your scene to a render target.
Change the device to the back buffer.
Use the spritebatch.draw overload that accepts a source and destination rectangle as parameters.
Pass the render target as the texture parameter to the function as well (typecast if necessary).
This allows you to take the portion of the render target you define by the source rectangle and draw it to the destination rectangle you define to be the drawing area on screen.
You can redraw the entire scene to screen from the rt part of it or resize or both you can in this way change the color with the color parameter of the method. The transparency via device settings .alphablend a color with low alpha ect.

THANKS GUYS !!!

It was THE solution !
everything work fine !

thanks to you, I’m now a bit less newbie in monogame :slight_smile:

Pit

1 Like