[Solved] Weird Display Issue Using a Rectangle

Are you rendering to a RenderTarget then drawing that RenderTarget to the backbuffer with a different SamplerState?

1 Like

I don’t use any “RenderTarget” ( I never use them, I should try… ), this is what I use to render the game
“spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, Transform);”

(Transform is just a matrix)

I’m not experiencing this problem in a fresh project. The video and screenshots indicate that there is something going on that’s not rendering the sprites with PointClamp. How are you making your matrix?

Which MG platform are you using?
There are two project types for the windows desktop, using DirectX and OpenGL.

could this be related to this?

1 Like

I make a windows desktop using DirectX. My pc is a Window 10 and I use visual studio 2017.

and here is the code of my matrix, but I don’t think this impact the problem.
" Transform = Matrix.CreateTranslation(new Vector3(-centre.X, centre.Y, 0)) *
Matrix.CreateRotationZ((float)Rotation.Direction) *
Matrix.CreateScale(new Vector3(Ratio.X, Ratio.Y, 0)) *
Matrix.CreateTranslation(new Vector3(View.Width / 2, View.Height / 2, 0));"

OK , openGL is ruled out.

How do you import the texture? Do you see any difference when you enable/disable the GenerateMipmaps option?

1 Like

In addition to mipmaps, make sure the sprite’s TextureFormat is set to Color.

The scale is incorrect; the Z should be 1.

2 Likes

I use the classic monogame Content.mgcb, I try to enable/disable the GenerateMipmaps, and it change nothings. The sprite’s texture format is already set on Color. I also remove the Z scale ( and also try with/without the GenerateMipmaps), nothings change.

(I remove my old message because I didn’t reply on the topic but only at nkast)

I think I found the origin of this glitch : When I’m trying to display an picture on some float value with a lot of decimal, sometime few pixel of the sprite above appear.

I make an other tiny project and I reproduce the same glitch with few line of code : here the link.

Important note : I try to share the file on dropbox but some folder failed to be shared on dropbox server. If the project doesn’t work : you just need create a new “windows desktop using DirectX” and copy/past the “Game1.cs” file from the link below in this new project, and add this texture in the monogame pipeline and call it “player”.

You will the sprite above in the 10-15 seconds after launch the project.

By the way, I try the project with and without using matrix, it change nothings.

http://community.monogame.net/uploads/default/original/2X/c/cfbfa9a668ffd116205421c95a2b0ffbf8f6b923.png

I didn’t find any solution for the moment, but I hope this project will help me to find any solution.

In theory, I can simply display the sprite by using “Math.Round()” of the position (because the screen is made of “whole number” (is this the good word ?) of pixels, so if I tell to the game to display the sprite at a “new Vector2(1.0123456789f,1.0123456789f)” or a “new Vector2(1f,1f)”, the same things should happen ?).

But how can I do that with a matrix ?

I think this is just a misunderstanding of what I usually refer to as “partial pixels”. Say you scale a texture that is 25x25 by 3.5, the result would be a texture that is 87.5x87.5. Since there is no such thing as a 0.5 pixel, Monogame will simply draw an extra pixel, and gathers what the pixel’s content should be based on the source image. So, if you were drawing just a single texture like this, it would work fine, since the outsides of a single texture (or a single sprite) would just be blank/transparent pixels. However, since you’re using a spritesheet, no pixel-wrap method is going to help you because you haven’t gotten to the edge of your original texture yet. So, it gathers the nearest rows/columns of pixels when it is adding that pixel. This could be why you see a portion of your sprite above, when you scale the sprite below to a size that it’s original resolution is not divisible by. Therefore, the solution is to give your sprites 1px padding between them. That’s one solution anyway, and probably the easiest.

1 Like

The UV is defined as (0,32) to (31,63) and the GPU interpolates between those values.
So, when you are drawing on a half pixel are you saying that the GPU is sampling the texture at (0,31.5) below the defined bound of V?

1 Like

@nkast Yes that what I try to say.

@TheKelsam If I don’t find any solution, I will give to my sprites 1 pixel padding between them (even if I don’t like this solution)

But if I’m scaling a texture that is 25x25 by 3.5, the result would be a texture that is 87.5x87.5 as you said TheKelsam.
But is there a way with a matrix to make the floor of the final texture and display it on a 87*87 area instead of a 87.5x87.5 area to avoid o display a bit of the sprite above ?

For the moment I will do a 1 padding pixel between my sprite. Thank for help me : )

Without doing the 1px padding, and while using the Matrix, a solution off the top of my head would be to first draw the sprite at it’s original scale to a RenderTarget, then use that RenderTarget as the source texture to draw the scaled up version. That would allow monogame to sample the bleed pixels from the non-existent outside of the sprite without collecting from other sprites. This method would come with a pretty steep performance hit though, I’d assume.

1 Like

Without looking too deeply into your code, I have an idea of what is likely the issue.
Your “source rectangle” is
new Rectangle(0,32,32,32)
and your sprite sheet, I’m guessing, is 64x48? That’s what it looks like in your image.
Anyway, 32/48 is .666…, which, when stored as a binary float, actually comes out to be 5592405/2^23, or 0.66666662693023681640625. Notice that this is less than 32/48’s true value. As such, the sampler grabs part of the pixel above.
If this is indeed the issue, one easy way to overcome it is to make your sprite sheet a power of 2 in each dimension (like 64x64), as then it won’t have any awkward “decimal” values to deal with. 32/64, for example, is .5, nice and easy!

Yep clamp only applys to the edges of a texture which means 0 to image Width or in Uv coordinates 0 to 1f meaning the gpu wont sample below 0 or beyond a value of image.Width -1

This means for a sprite sheet setting the uv texture address mode to clamp simply doesn’t apply to source rectangles in the middle of a texture reliably without padding between the images.

2 pixels of padding is safer (without going into the whys) where a color like red might work to prove that. Mostly i choose rgba = 0
Most spritesheets simply have that as a background color with sprites that don’t fill the whole sprite rectangle. So there is naturally padding but for fully opaque images that fill the entire sprite sheet its easy to forget you need padded lines around the sprite as well.

Also note if you want to use antialising sampling aka linear or ansiostropic and you dont want point sampling this padding should be even wider.

So far the issue was about scaled up sprites without mipmaping and/or anisotropic sampling, but since you brought it up, I have an Atlas/Sprite importer that will import sprites with mipmaping that wont bleed color between sprites. Each sprite is re-sampled individually and the atlas is recombined on each mip level. check it out:
https://twitter.com/nkast/status/865321646449725442

@ed022
The spritesheet is 32*32 pixels.

@nkast Thank you for the Atlas/Sprite importer :slight_smile:, but I also have another software that do the job ^^

After trying several solutions ( like the 2 pixels padding and more…), I finally choose to use a Render Target for my game. And then each element is render on the Render Target. And by scaling only the Render Target, I avoid this glitch and making a 2 pixels padding between my sprites.

Thank to everyone for helping me with this issue.

Are you sure it’s 32x32? That would imply that each individual sprite (in the original picture above) is only 8x8 pixels, and that seems impossible.

Sorry if I wasn’t clear, the texture is 256256 and each sprite is 3232, but I dont think that matter