Skip to main content
GameDev.net gamedev.net
🔒 Locked

[XNA] ScissorRectangle not working

Started by harlock1975 Oct 16, 2011 at 8:56 AM 4 replies 4.6k views
Original Post
harlock1975
harlock1975
Hi everyone, I am new here but I am afraid I will be bothering you often in the near future
In the last couple of months I started to develop a simple "match 3" 2D game in XNA but I am now stuck with the following problem.
Long story short, the main game screen has a background and a "board area" where all the tiles are drawn, everything is working but I'd like to clip the board area so that objects that move out of it are not drawn over the background but are clipped.
I read that I could use the ScissorRectangle BUT I cannot manage it to work.
I tried the following approaches
- use the same SpriteBatch and set RasterizerState (with ScissorTestEnable set to true) -> no clipping occurs
- use a nested SpriteBatch for the board (even without ScissorRectangle set) -> board is not drawn!!!
So actually I have two questions
1. how can I have the ScissorRectangle working?
2. is there an explanation/tutorial/sample on how the various parameters of a SpriteBatch object affect rendering?
Thanks in advance, I hope to post some screenshots soon!!!
Cygon
Cygon
Are you using the SpriteBatch.Begin() overload the allows you to specify a RasterizerState or are you setting it manually?

Enabling scissor testing separately from the SpriteBatch does, for some reason, not work. Probably the SpriteBatch applies its own RasterizerState immediately before drawing.

I have used the aforementioned SpriteBatch.Begin() overload sucessfully im my GUI library to clip controls like this:

[source lang="csharp"]
// Initialization
this.rasterizerState = new RasterizerState() {
ScissorTestEnable = true
};

// Each frame
this.spriteBatch.Begin(
SpriteSortMode.Deferred, BlendState.AlphaBlend, null, null, this.rasterizerState
);
this.graphics.ScissorRectangle = clipRegion;
// ...drawing code...
this.spriteBatch.End();
[/source]
Professional C++ and .NET developer trying to break into indie game development.
Follow my progress: http://blog.nuclex-games.com/ or Twitter - Topics: Ogre3D, Blender, game architecture tips & code snippets.
Starnick
Starnick
Aye, Spritebatch has its own default render states it sets if you do not pass in a custom one. Another thing to remember is that sprite batch will -not- reset states after End() is called. XNA 4.0 follows and encourages a "only set the states you need" paradigm in this respect. The default states are:

BlendState.AlphaBlend
SamplerState.LinearClamp
DepthStencilState.None
RasterizerState.CullCounterClockwise

Additionally, the MSDN docs help with stuff like this.

As for your approaches...what do you mean by a "nested" sprite batch? It is not advised to have two sprite batches calling Begin() after each other, each drawing, then each calling End() because one of them is going to be interfering with the other in what states are set, etc.
harlock1975
harlock1975
First of all thanks to both!


Are you using the SpriteBatch.Begin() overload the allows you to specify a RasterizerState or are you setting it manually?

Actually, I tried both.
In board constructor, I created a custom RasterizerState. I tried to set it using the properties in GraphicsDevice (so, reusing the SpriteBatch object I created in the main Draw method), but it is ignored.
Then I tried to create a new SpriteBatch object in order to pass the RasterizerState to the Begin overload, but it is ignored as well.
The code you posted is similar to the one I used, probably the only difference is that the Begin method I call is of a new SpriteBatch (first, I do need to draw an unclipped fullscreen background, then the clipped board).


Aye, Spritebatch has its own default render states it sets if you do not pass in a custom one. Another thing to remember is that sprite batch will -not- reset states after End() is called.
...
As for your approaches...what do you mean by a "nested" sprite batch? It is not advised to have two sprite batches calling Begin() after each other, each drawing, then each calling End() because one of them is going to be interfering with the other in what states are set, etc.

That's exactly what I read in MSDN, that's why I made a "backup" of the RasterizerState before setting it.
I also read that I should not use more than one SpriteBatch object, but how can I pass my rasterizer to the Begin() method if I have not called End() yet?
Are you suggesting that I should End() the same SpriteBatch and then Begin() passing my rasterizer?

I didn't think of that, I will give it a try.
Thanks again!
Cygon
Cygon
Actually, I tried both.
In board constructor, I created a custom RasterizerState. I tried to set it using the properties in GraphicsDevice (so, reusing the SpriteBatch object I created in the main Draw method), but it is ignored.
Then I tried to create a new SpriteBatch object in order to pass the RasterizerState to the Begin overload, but it is ignored as well.
The code you posted is similar to the one I used, probably the only difference is that the Begin method I call is of a new SpriteBatch (first, I do need to draw an unclipped fullscreen background, then the clipped board).


Well, I can guarantee that the code I posted is working - it's copied straight out of my GUI library which clips fine on WP7, Xbox360 and Win.

If you want to mix clipped stuff with unclipped stuff, just .End() your SpriteBatch, then .Begin() it again without the RasterizerState -- and vice versa if you want to turn clipping back on. That will guarantee all vertices in the SpriteBatch have been flushed. Using two SpriteBatches at the same time is asking for trouble - in terms of drawing order and applied render states.

Also make sure you go through the .End() .. .Begin() ritual when you modify the clipping region. The SpriteBatch will collect vertices until it either decides that it has enough to send to the GPU or you force it by calling .End(). If you leave it up to the SpriteBatch, everything will be clipped by whatever scissor rectangle you have set when the SpriteBatch decides to flush its buffers.
Professional C++ and .NET developer trying to break into indie game development.
Follow my progress: http://blog.nuclex-games.com/ or Twitter - Topics: Ogre3D, Blender, game architecture tips & code snippets.
harlock1975
harlock1975
Guess what? It works!!!
So it's true, nested spritebatches are evil
Thank you very much to both!

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.