what is source rectangle in spritebatch.draw in xna - xna

What is the purpose of the source rectangle parameter in the SpriteBatch.Draw() method?
MSDN says: A rectangle that specifies (in texels) the source texels from a texture. Use null to draw the entire texture.
What does that mean?

The idea of the sourceRectangle is to allow you to implement what is both a performance optimisation and an artist convenience by arranging multiple sprites into a single texture. This is known as a "Texture Atlas" or a "Sprite Sheet".
(source: andrewrussell.net)
I explain why it is a performance optimisation in this answer. Basically it lets you reduce the number of texture-swaps. (So in the case of my illustration, if you're only drawing an animated character once, using a sprite-sheet will not improve performance.)
It also lets you implement tacky 2D special effects, like having a sprite "wipe" in:
(source: andrewrussell.net)
A texel is more-or-less the same thing as a pixel in the texture (a "texture pixel", if you will). So, when you draw your sprite, you specify the top-left corner of your sprite within the texture, along with its width and height. (The same as if you selected it in an image editor.)
If you pass in null for your source rectangle, XNA will assume a source rectangle that covers the entire texture.
The origin you specify to Draw is also measured in texels from the upper-left corner of the source rectangle.

In a situation where you have a single texture that contains different frames (animated textures), you will want to specify the source rectangle, so that you can draw a single frame from a texture.
i.e.
Look at this spritesheet here

The source rectangle defines the area of the texture that will be displayed. So if you have a 40x40 texture, and your rectangle is (0, 0, 20, 20), only the top left corner of the texture will be displayed. If you specify null for the rectangle, you will draw the entire texture.
This can be helpful when drawing from a spritesheet (a collection of textures that are all put into one bigger texture), and also in image manipulation programs.

Related

What is the meaning of "nonuniformly scaled texture" in SpriteKit?

On SKCropNode class reference, some examples to specify a mask are given.
Here they are:
This means a crop node can use simple masks derived from a piece of artwork, but it can also use more sophisticated masks. For example, here are some ways you might specify a mask:
An untextured sprite that limits content to a rectangular portion of the scene.
A textured sprite is a precise per-pixel mask. But consider also the benefits of a nonuniformly scaled texture. You could use a nonuniformly scaled texture to create a mask for a resizable user-interface element (such as a health bar) and then fill the masked area with dynamic content.
A collection of nodes can dynamically generate a complex mask that changes each time the frame is rendered.
The second example introduce nonuniformly scaled texture: what's the meaning of this?
This does not help me to understand this second example!
A non-uniformly scaled texture is a texture that is applied to a sprite with xScale != yScale.

Considering the Stencil in depth

I'm using Orthographic projection to draw my objects.
Each object items is being added to different buffers and being drawn in several cycles.
Let's say that each object has an outline square and fill for the square (in different color).
So i'm drawing first the all the fillings, and then the outlines.
I'm using depth buffer to make sure that the outlines will not be over all the fills as shown at the picture
Now i'm facing a problem that each object contains another drawing item on it (such as text - points) which can be longer than this squares. So i'm using the stencil buffer for cutting this additional drawing over the square. Although, when doing this there is no consideration in the depth buffer.
Meaning that one text item can be drawn over the other square. as showed below.
Is there anyway\trick to make it happen ?
You should be able to set the stencil buffer to a different value for each of the squares (provided there is <= 255 squares, as you won't be able to get a more than 8-bit stencil buffer). Configure the stencil value to KEEP for pixels that fail the depth test, causing any stencil values written by quads that are further in front but have been drawn earlier to be retained.
This will allow clipping each text individually.
Another way is to use only the depth buffer and pass the pixel extents of the current quad into the text pixel shader, where you can discard any extra pixels. This requires less state changes.

Scaling RenderTarget2D doesn't scale SourceRectangles

I develop a 2D match3 game in XNA. The core logic and animations are done. I use RenderTarget2D to draw the entire board. The board has 8 rows and 8 columns with 64x64 textures (the tiles), which could be clicked and moved. To capture the mouse intersection, I use SourceRectangles for each tile. Of course the SourceRectangles have same size as textures - 64x64.
I would like to scale down the entire board, using the RenderTarget2D, to support different monitor resolutions and aspects. First I draw all tiles in the RenderTarget2D. Then I scale down the RenderTarget2D with a float coefficient. Finally I draw the RenderTarget2D on the screen. As a result the entire board is scaled down properly (all textures are scaled down from 64x64 to 50x50 for example), but the SourceRectagles are not scaled, they remain 64x64 and mouse intersections are not captured for the proper tiles.
Why scaling the RenderTarget2D doesn't handle this? How I can solve this problem?
You should approach this problem differently. Your source rectangles for textures are just that — don't try to use them as button rectangles, or you will get in trouble like this.
Instead, use a different Rectangle hitboxRectangle, which will be the same size as your source rectangle initially, but will scale with your game window, and check intersections against it.

Drawing a concave polygon in OpenGL

I have a concave polygon I need to draw in OpenGL.
The polygon is defined as a list of points which form its exterior ring, and a list of lists-of-points that define its interior rings (exclusion zones).
I can already deal with the exclusion zones, so a solution for how to draw a polygon without interior rings will be good too.
A solution with Boost.Geometry will be good, as I already use it heavily in my application.
I need this to work on the iPhone, namely OpenGL ES (the older version with fixed pipeline).
How can I do that?
Try OpenGL's tessellation facilities. You can use it to convert a complex polygon into a set of triangles, which you can render directly.
EDIT (in response to comment): OpenGL ES doesn't support tessellation functions. In this case, and if the polygon is static data, you could generate the tessellation offline using OpenGL on your desktop or notebook computer.
If the shape is dynamic, then you are out of luck with OpenGL ES. However, there are numerous libraries (e.g., CGAL) that will perform the same function.
It's a bit complicated, and resource-costly method, but any concave polygon can be drawn with the following steps (note this methos works surely on flat polygons, but I also assume you try to draw on flat surface, or in 2D orthogonal mode):
enable stencil test, use glStencilFunc(GL_ALWAYS,1,0xFFFF)
disable color mask to oprevent unwanted draws: glColorMask(0,0,0,0)
I think you have the vertices in an array of double, or in other form (strongly recommended as this method draws the same polygon multiple times, but using glList or glBegin-glEnd can be used as well)
set glStencilOp(GL_KEEP,GL_KEEP,GL_INCR)
draw the polygon as GL_TRIANGLE_FAN
Now on the stencil layer, you have bits set >0 where triangles of polygon were drawn. The trick is, that all the valid polygon area is filled with values having mod2=1, this is because the triangle fan drawing sweeps along polygon surface, and if the selected triangle has area outside the polygon, it will be drawn twice (once at the current sequence, then on next drawings when valid areas are drawn) This can happens many times, but in all cases, pixels outside the polygon are drawn even times, pixels inside are drawn odd times.
Some exceptions can happen, when order of pixels cause outside areas not to be drawn again. To filter these cases, the reverse directioned vertex array must be drawn (all these cases work properly when order is switched):
- set glStencilFunc(GL.GL_EQUAL,1,1) to prevent these errors happen in reverse direction (Can draw only areas inside the polygon drawn at first time, so errors happening in the other direction won't apperar, logically this generates the intersectoin of the two half-solution)
- draw polygon in reverse order, keeping glStencilFunc to increase sweeped pixel values
Now we have a correct stencil layer with pixel_value%2=1 where the pixel is truly inside the polygon. The last step is to draw the polygon itself:
- set glColorMask(1,1,1,1) to draw visible polygon
- keep glStencilFunc(GL_EQUAL,1,1) to draw the correct pixels
- draw polygon in the same mode (vertex arrays etc.), or if you draw without lighting/texturing, a single whole-screen-rectangle can be also drawn (faster than drawing all the vertices, and only the valid polygon pixels will be set)
If everything goes well, the polygon is correctly drawn, make sure that after this function you reset the stencil usage (stencil test) and/or clear stencil buffer if you also use it for another purpose.
Check out glues, which has tessellation functions that can handle concave polygons.
I wrote a java classe for a small graphical library that do exacly what you are looking for, you can check it here :
https://github.com/DzzD/TiGL/blob/main/android/src/fr/dzzd/tigl/PolygonTriangulate.java
It receive as input two float arrays (vertices & uvs) and return the same vertices and uvs reordered and ready to be drawn as a list of triangles.
If you want to exclude a zone (or many) you can simply connect your two polygones (the main one + the hole) in one by connecting them by a vertex, you will end with only one polygone that can be triangulate like any other with the same function.
Like this :
To better understand zoomed it will look like :
Finally it is just a single polygon.

Rotation of a part of sprite in XNA

I have a texture with 250px width and 2000px height. 250x250 part of it drawn on screen according to various conditions (some kind of sprite sheet, yes). All I want is to draw it within a fixed destination rectangle with some rotation. Is it possible?
Yes. Here's how to effectively rotate your destination rectangle:
Take a look at the overloads for SpriteBatch.Draw.
Notice that none of the overloads that take a Rectangle as a destination take a rotation parameter. It's because such a thing does not make much sense. It's ambiguous as to how you want the destination rotated.
But you can achieve the same effect as setting a destination rectangle by careful use of the position and scale parameters. Combine these with the origin (centroid of scaling and rotation, specified in pixels in relation to your sourceRectangle) and rotation parameters to achieve the effect you want.
(If, on the other hand, you want to "fit" to a rectangle - effectively scaling after rotating - you would have to also use the transformMatrix parameter to Begin.)
Now - your question isn't quite clear on this point: But if the effect you are after is more like rotating your source rectangle, this is not something you can achieve with plain ol' SpriteBatch.
The quick-and-dirty way to achieve this is to set a viewport that acts as your destination rectangle. Then draw your rotated sprite within it. Note that SpriteBatch's coordinate system is based on the viewport, not the screen.
The "nicer" (but much harder to implement) way to do it would be to not use SpriteBatch at all, but implement your own sprite drawing that will allow you to rotate the texture coordinates.

Resources