MonoGame - Tiling Texture2D with SpriteBatch on iOS - c#

Right now I'm tiling a Texture2D with 2 for-loops similar to an example from the MonoGame samples.
I was doing some reading, and I was seeing that using power of two textures (2, 4, 8, 16, 32, etc. on width & height) can be tiled with one SpriteBatch.Draw call.
Is this supported with MonoGame on iOS?
I gave it several tries, and no matter what it merely stretches the image instead of tiling it.
I am using SamplerState.LinearWrap on my SpriteBatch.Begin(), and tried using a 2048x128 png and tried it 1/4 size at 512x32, but with no luck. (Using large sizes, b/c our game runs at 2400xSomething zoomed out, b/c you can zoom in with the camera by 2.5 multiplication)

You can use the SourceRectangle parameter in the draw method. To define what part of the Texture you want to display. Lets say you have a 128x128 Texture. If you supply Rect(0, 0, 128, 128) you tell the draw method to use the whole texture, the same if you would pass null to the draw method. If you supply Rect(0, 0, 64, 64) you would use the upper left part of the texture. Your sprite will display this portion, no matter how big the sprite itself is. So if your sprite is drawn with the size of 128x128 the 64x64 texture part would be scaled.
Now you can use that for animations. If you store in your texture a sequence of animation like this, you just need to recalc the source rectangle everytime you want to display the next image in your sequence.
Besides that, you could pass in a bigger value, than your source texture. XNA now needs to wrap or clamp your texture. That way you can achieve a simple tiling. If you need more than that my guess is you need to use a manual approach, like your foreach loops.
Please note that Wrap is only supported if you use power of two textures.

Related

Monogame: Render only inside specified area

This may be a strange question, but I'm trying to find a way to render sprites only inside a specific allowed area rather then the entire buffer/texture.
Like so:
Basically allowing me to draw to the buffer or texture2D as I normally would, but with actual drawing happening only inside this specified area and remaining pixels outside of it remaining untouched.
Why this is needed - I'm building my own UI system and I would like to avoid using intermediary buffers as it is quite slow when there are many UI components on the screen (and each has to draw to their own buffer to prevent child elements being drawn outside of parent bounds).
And just to clarify - this is all for simple 2D rendering, not 3D.
If your UI is actually drawn with SpriteBatch you can use ScissorRectangle
GraphicsDevice.RasterizerState.ScissorTestEnable = true;
spriteBatch.GraphicsDevice.ScissorRectangle = ...
In 3D, you can render to a texture and draw just a portion of it - or with a shader (you could actually just send in the dimensions as parameter and set it to black in PixelShader if the Pixel is outside that Rectangle (or whatever you want to accomplish)
You can use:
spriteBatch.Draw(yourTexture,
//where and the size of what you want to draw on screen
//for example, new Rectangle(100, 100, 50, 50)//position and width, height
destinationRectangle,
//the area you want to draw from the original texture
//for example, new Rectangle(0, 0, 50, 50)//position and width, height
sourceRectangle,
Color.White);
Then it will only draw the area that you chose before. Hope this helps!

Getting color range of pixel block in video texture in Unity

I'm trying to get an average color from a specific 4x4 area in a video texture on every update. It can either be black or white, but because I'm streaming the video and the resolution differs from time to time it might also be grayish. I need to find out more precisely if it's "almost black" or more on the white/light gray side of the spectrum.
I'm very new to c# and unity. I found Texture2D.GetPixel or Texture2D.GetPixels32 might be better, but I'm really not sure how I can do that from a video texture.
Thanks to anyone who can help.
Take a look at this post. It looks like you are doing the-same thing as that person which is to get Texture from an image and average the pixel.
The reason I don't consider this a duplicate is because you want to get a pixels from specific(4x4) area not all pixels from the texture.
Texture2D.GetPixel or Texture2D.GetPixels32 might be better,
Because you want to do this on speficic pixels, you can't do it with Texture2D.GetPixel or Texture2D.GetPixels32. You don't even need the UniversalMediaPlayer plugin you are using.
You can do this with the GetPixels function. Notice the 's' at the end.
This is the function prototype:
Color[] GetPixels(int x, int y, int blockWidth, int blockHeight);
Depending on the position of the pixels you want to read from the Texture it should look something like this:
Color[] texColors = tex.GetPixels(0, 0, 4, 4);
You need to use that instead of Color32[] texColors = tex.GetPixels32(); from this answer.
Note:
You can still use your UniversalMediaPlayer video plugin if you prefer it over Unity's new VideoPlayer. The GetPixels solution should still work.

Mapping textures to DirectX sphere?

I am writing a virtual globe using DirectX similar to Google Earth. So far, I have completed tessellation, and have tested with a wrapped texture over the entire sphere, which was successful. I have written the texture coordinates to correspond with the latitude and longitude (90lat,-180lon = 0,0 and -90lat,180lon = 1,1).
For this project, I need to layer several image tiles over the sphere. For example, 8 images spanning 90 degrees by 90 degrees. These tiles may dynamically update (i.e. tiles may be added or removed as you pan around). I have thought about using a render target view and drawing the tiles directly to that, but I'm sure there is a better way.
How would I go about doing this? Is there a way to set the texture to only span a specific texture coordinate space? I.e. from (0, 0) to (0.25, 0.5)?
There are three straight-forward solutions (and possibly many more sopisticated ones).
You can create geometry that matches the part of the sphere covered by a tile and draw those subsequently, setting the correct texture before each draw call (if the tiles are laid out in a simple way, you can also generate this geometry using instancing and a single draw call).
You can write a pixel shader that evaluates the texture coordinates and chooses the appropriate texture using transformed texture coordinates.
Render all textures to a big texture and use that to render the sphere. Whenever a tile changes, bind the big texture as a render target and draw the new tile on top of it.

Cut holes in a Texture2D

I want to know how to remove part of a Texture from a Texture2D.
I have a simple game in which I want to blow up a planet piece by piece, when a bullet hits it "digs" into the planet.
The physics are already working but I am stuck on how to cut the texture properly.
I need to create a function that takes a Texture2D a position and a radius as input and returns the new Texture2D.
Here is an example of the Texture2D before and after what I want to accomplish.
http://img513.imageshack.us/img513/6749/redplanet512examplesmal.png
Also note that i drew a thin brown border around the crater hole. If this is possible it would be a great bonus.
After doing alot of googling on the subject it seems the best and fastest way to achieve the effect i want is to use pixel shaders.
More specifically a shader method called 'Alpha mapping'. Alpha mapping is done by using the original texture and another greyscale texture that defines what parts are visible or not.
The idea of the shader is to go through each pixel in the original texture and check how black each pixel in the greyscale image is at the same coordinate. The blacker the pixel in the greyscale picture is the higher the alpha value (more visible) the pixel in the original texture becomes. Since all this is done on the GPU it is lightning fast and leaves the CPU ready to do the actual logic for the game.
For my example I will create a black image to use as my greyscale image and then draw white circles on this corresponding to the parts i want to remove.
I've found a MSDN examples with working source code for XNA 4 that does this (the cat example):
http://create.msdn.com/en-US/education/catalog/sample/sprite_effects
EDIT:
I got this to work quite nicely. Created a small tutorial with source code here: http://syntaxwarriors.com/2012/xna-alpha-mapping-with-pixel-shaders/
A good way of doing this is to render a "hole texture" using alphablend on top of your planet texture. Think of it like drawing an invisibility circle over your original texture.
Take a look at this thread for a few nice links worms-style-destructible-terrain.
To achieve your brown edges I'd guess you'd need to take a similar approach. First render the hole to your terrain with say radius 10px. Then you render another circle from the same origin point but with a slightly larger radius, say 12px. You'd then need to set this circle to a blendmode that results in a brown color.
look at my class here:
http://www.codeproject.com/Articles/328894/XNA-Sprite-Class-with-useful-methods
1.Simply create an object of Sprite class for your planet
Sprite PlanetSprite = new Sprite(PlanetTexture2D , new Vector2(//yourPlanet.X, //yourPlanet.Y));
2.when the bullet hits the planet, make a circle texure2d by the center of collision point using "GetCollisionPoint(Sprite b)" method
-you can have a Circle.png with transparent corners
-or you can create a Circle using math(which is better if you want to have bullet power)
3.then create an Sprite object of your circle
4.now use the "GetCollisionArea(Sprite b)" to get the overlapped area
5.now use the "ChangeBatchPixelColor(List pixels, Color color)" where pixels is the overlapped area and color is Color.FromNonPremultiplied(0, 0, 0, 0)
-note you don't need to draw your circle at all, after using it you can destroy it, or leave it for further use

How to scale texture2d in XNA with window resizing

I'm developing an UI for a project for school, and I've tried similar methods to scaling my texture as listed here, but here is the issue:
Our project is developed at 1440 x 900, so I've made my own images that fit that screen resolution. When we have to demo our project in class, the projector can only render up to 1024 x 768, thus, many things on the screen goes missing. I have added window resizing capabilities, and I'm doing my scaling like this. I have my own class called "button" which has a texture 2d, and a Vector2 position contruscted by Button(Texture2d img, float width, float height).
My idea is to set the position of the image to a scalable % of the window width and height, so I'm attempting to set the position of the img to a number between 0-1 and then multiply by the window width and height to keep everything scaled properly.
(this code is not the proper syntax, i'm just trying to convey the point)
Button button = new Button(texture, .01, .01 );
int height = graphicsdevice.viewport.height * button.position.Y;
int width = graphicsdevice.viewport.width * button.position.X;
Rectangle rect = new Rectangle(0,0,width, height);
sprite.being()
sprite.draw (button.img, rect, color.white);
sprite.end
it doesn't end up scaling anything when i go to draw it and resize the window by dragging the mouse around. if i hard code in a different bufferheight and bufferwidth to begin with, the image stays around the same size regardless of resolution, except that the smaller the resolution is, the more pixelated the image looks.
what is the best way to design my program to allow for dynamic texture2d scaling?
As Hannesh said, if you run it in fullscreen you won't have these problems. However, you also have a fundamental problem with the way you are doing this. Instead of using the position of the sprite, which will not change at all during window resize, you must use the size of the sprite. I often do this using a property called Scale in my Sprite class. So instead of clamping the position of the sprite between 0 and 1, you should be clamping the Size property of the sprite between 0 and 1. Then as you rescale the window it will rescale the sprites.
In my opinion, a better way to do this is to have a default resolution, in your case 1440 x 900. Then, if the window is rescaled, just multiply all sprites' scaling factors by the ratio of the new screensize to the old screensize. This takes only 1 multiplication per resize, instead of a multiplication per update (which is what your method will do, because you have to convert from the clamped 0-1 value to the real scale every update).
Also, the effects you noticed during manual rescale of the sprites is normal. Rescaling images to arbitrary sizes causes artifacts in the rendered image because the graphics device doesn't know what to do at most sizes. A good way to get around this is by using filler art during the development process and then create the final art in the correct resolution(s). Obviously this doesn't apply in your situation because you are resizing a window to arbitrary size, but in games you will usually only be able to switch to certain fixed resolutions.

Categories