Nick Darnell

You know how in a panel if a child button runs off the side of the panel, it gets clipped. Does anyone know how one might go about doing that with XNA Or how they do it in OpenGL/DirectX Are they doing something with the stencil buffer


Re: XNA Framework Clipping Layered Sprites (UI Related)

tportz

You can use the GraphicsDevice.ScissorRectangle property to specify the bounds of the panel, then set the ScissorTestEnable render state to true to clip anything outside of the scissor rectangle.



Re: XNA Framework Clipping Layered Sprites (UI Related)

Nick Darnell

Okay, when i use this in conjunction with spritebatch, spritebatch goes crazy, and i set it to immediate sort. But my alpha blending becomes all screwed up, things don't appear in the right order, lots of bad ***. Is it because I'm not providing a depth




Re: XNA Framework Clipping Layered Sprites (UI Related)

bryanedds

You should only change ScissorRectangle between sprite batches. So each time you have a change in ScissorRect, you must end and restart your sprite batch. I know, it's a real pain. I put in a request to alleviate this behavior in the MS Connect here -

https://connect.microsoft.com/feedback/ViewFeedback.aspx FeedbackID=248087&SiteID=226






Re: XNA Framework Clipping Layered Sprites (UI Related)

Shawn Hargreaves - MSFT

I don't think it really makes sense to change renderstates like the scissor in the middle of a single sprite batch.

The whole logic of batching up sprites is to gather many individual draws into a single GPU call, for faster rendering. This is exactly what the begin/end grouping is for.

But when all the sprites are in a single GPU call, there is obviously no way to draw half of them with one render state, then the rest with a different state! That's not how the GPU works.

So really, there's no option but to end one batch and start another when you want to change renderstates.





Re: XNA Framework Clipping Layered Sprites (UI Related)

Nick Darnell

But the Begin/End has several problems when it comes to needing to nest controls, like what would happen in a UI system. Which is what I'm concerned about.

Don't tell me I'll have to create a new sprite batch for every control...




Re: XNA Framework Clipping Layered Sprites (UI Related)

Shawn Hargreaves - MSFT

You don't need a separate sprite batch per control, but you do need a separate begin/end pair for each block of things that you want to draw with a different renderstate.

If you are setting the scissor rectangle differently for each control, that means a separate begin/end pair per control.

Most game user interfaces I've worked with don't actually do that, though: the typical approach seems to be not to bother with that sort of generalized clipping, and just turn it on as a special case for whatever handful of things might really need this.





Re: XNA Framework Clipping Layered Sprites (UI Related)

Nick Darnell

How do you solve the problem of a needing to nest begin and ends Because the sprite batch blows up horribly if you try to start a new begin before closing the last one.




Re: XNA Framework Clipping Layered Sprites (UI Related)

Shawn Hargreaves - MSFT

I don't understand why you'd need this to be nested If you are sharing a single begin/end for all your UI elements (like all the game interfaces I've used in the past) just one works fine and there is no need for nesting. If you are using a separate batch per control, so you can set the scissor differently each time, just begin, draw, and end, within each control: still no need to nest anything in the rendering.





Re: XNA Framework Clipping Layered Sprites (UI Related)

Nick Darnell

Because it sounded like it was possible to use a single sprite batch. But for that to work, you must be able to nest begin and end statements because apparently that's the only time I can change rendering states. Which are required for every container control. ex. panels, frames. Even things like textboxes require it to have text lines that are cut off mid way.

And obviously you're going to have containers within containers, which would require nesting on if you were using a single sprite batch.

Okay, so, the simple answer is, if you need to have a scissored rectangle inside of another scissored rectangle, you have to use separate sprite batches.

Right




Re: XNA Framework Clipping Layered Sprites (UI Related)

bryanedds

Nick, Buttermilk (my game's open sourced engine) uses a RenderQueue which queues all the renderables in the game and sorts them by their render state (scissor rectangle included) so that they can be batched as much as possible. It complex, but you can check out how it does it for your own personal reference. Or you can just use Buttermilk for you GUI system without having to write your own (though it's still in progress).

http://www.codeplex.com/buttermilk






Re: XNA Framework Clipping Layered Sprites (UI Related)

Nick Darnell

Hmm. Okay, I'll take a look.




Re: XNA Framework Clipping Layered Sprites (UI Related)

alexzanders

wouldn't it be more efficient to use logic to decide if (for example) the text goes outside of the rectangle text input area then use the source parameter on spriteBatch to then stop it from drawing

e.g.
if (area.Right > text.Right) {
source.Width -= (text.Right - area.Right);
}

does that make sense, and wouldn't that be quicker to draw




Re: XNA Framework Clipping Layered Sprites (UI Related)

mattjb

This is the approach that i took, which seems to work just fine.

-MB





Re: XNA Framework Clipping Layered Sprites (UI Related)

Luhar

Would this work

Rectangle GetClippedRectangle(Rectangle rect, Rectangle clip)
{
    int clipX = Math.Min(clip.Right, Math.Max(clip.Left, rect.Left));
    int clipY = Math.Min(clip.Bottom, Math.Max(clip.Top, rect.Top));
    int clipWidth = Math.Min((clip.Right - clipX), (rect.Right - clipX));
    int clipHeight = Math.Min((clip.Bottom - clipY), (rect.Bottom - clipY));

    return new Rectangle(clipX, clipY, clipWidth, clipHeight);
}