Problem
When the spritebatch class is improperly used to draw a large number of imagesProgramIt will become very slow.
Solution
As mentioned in tutorial 3-1, creating a new spritebatch class for each frame, or enabling and disabling the spritebatch class when drawing each image will greatly affect the performance. But there are more subtle things to consider.
Working principle performance optimization: SPRITE sorting Modes
The sprin method of the spritebatch class allows you to set the spritesortmode. Before discussing different modes, you need to know what the graphics card prefers to work in and out.
Drawing a 2D image on the screen is achieved by drawing two triangles and filling them into colors sampled from one texture. Graphics cards like to draw a large number of triangles at a time. But when you need to change the texture, You need to disturb the video card. In other words, it is much faster to draw 100 images from the same texture than to draw 100 images from 100 textures. Therefore, changing the current texture as little as possible can improve the performance.
With this concept, you can learn the sprite sorting mode that can be specified as a parameter in the spritebatch. Begin method:
-
- Deferred: This is the default spritesortmode. Although you almost never use it because it has no sorting. You only need to add a sprite to batch through the spritebatch. Draw method. This Sprite is simply added to the top of the stack. When the spritebatch. End method is called, all the Sprite in the stack will be drawn according to the order in which it enters the stack.
-
- Texture: This mode is usually used based on performance optimization and ease of use. When the spritebatch. End method is called, all images in the stack are sorted by texture before xNa actually requires the video card to draw the image. In this way, the video card can use the same texture to draw many triangles in one round, you can reduce the number of times the video card changes the texture. However, this mode may be difficult to use when using alpha transparency. You need to use one of the following modes.
- Backtofront: When Alpha is used, you want to draw the nearest object first. You need to know why the previous tutorial is visible. The spritebatch. Draw method that adds an image to the spritebatch class has an overloaded method that accepts the layerdepth parameter. With this float parameter, you can specify the layer on which the image is located. 1.0f indicates the farthest layer (for example, containing lawns) and 0.0f indicates the closest layer (for example, drawing rocks on this layer ). You can specify any value between the two. When using the backtofront mode, you only need to call the spritebatch. End method. The image in spritebatch is sorted so that the farthest layer is drawn first.
-
- Fronttoback: This mode is the opposite of the previous mode, so the image of the closest layer is first drawn. Because all the pixels drawn on the screen will never be overwritten (because all the subsequent images are after this), this will lead to the best performance. However, using alpha blending cannot work (see the previous tutorial) and will achieve the best performance only when all images use the same texture! If you need to swap 10 textures to draw the most recent layer, the performance will be much lower than that in texture mode.
-
- Immediate: compared to other modes, xNa does not wait to call the spritebatch. End method to draw all images in this mode. If you call the spritebatch. Draw method to add images with the same texture to spritebatch, spritebatch pushes them into the stack. When you use another texture to draw a Sprite, the Sprite in the current stack will be drawn immediately.
When the first four modes are used, the Sprite is sorted only when the spritebatch. End method is called, the rendering status is set, and the triangle and texture are transmitted to the video card. This allows you to use multiple spritebatch class objects to add new sprite objects in random order, or even 3D objects in the same rendering state. However, when the immediate mode is used, the rendering status is called when the spritebatch. Begin method is called. Sprite is drawn after the spritebatch. Draw method is called. This means you can change the rendering State between the two methods! In this way, you can access more Alpha hybrid modes or use a custom pixel shader to draw Sprite! However, when you use the Immediate Mode to draw an image, you cannot draw other things, such as a 3D object, because you may change the rendering state. When you want to continue sprite painting with spritebatch, the rendering status has not been reset, so you will use the rendering status of 3D objects and pixel shader to draw Sprite.
Performance Optimization: Sort multiple images in one image file
As mentioned above, when drawing a large number of Sprite, you want to change the current texture as little as possible. Spritesortingmode. texture can help a lot, but in a complete game, you often need several hundred different images, which will lead to a video card switching between textures hundreds of times.
A useful method is to store interconnected images in a large image, as shown in the left-side figure of 3-4. In this way, you can use the sourcerectangle parameter of the spritebatch. Draw method to specify which part of the large image to be drawn, such asCode.
As shown in 3-4, each sub-image is 40x40 pixels. The code in tutorial 3-3 defines some rectangles that represent positions in large images. Using these rectangles as the third parameter of the spritebatch. Draw method causes only this sub-image to be drawn on the screen.
Use multiple spritebatche
Spritebatch is a powerful object. You can add the entire game image to a separate spritebatch at a time to sort and draw. However, in some cases, you may want to use multiple spritebatch classes.
For example, you can create an Air Combat Game to launch missiles between planes. Of course you have multiple types of aircraft and missiles. You can store all the rotating conditions of aircraft and missiles in a large texture, which can reduce the number of textures required.
You also want to have smoke at the back of the aircraft engine, which will slowly dissipate, and there will also be a lot of smoke on the missile track. If you use a spritebatch to draw all of these images, you will encounter a problem: You want all the images to be sorted by texture for optimized performance. However, planes and missiles should be drawn first so that smoke Sprite can be drawn later. This requires sprite to be sorted by depth!
The solution is to use two spritebatch class objects: planebatch and smokebatch. At the beginning of the draw method, call the begin Method of Two spritebatch classes. Then, the aircraft and missile images are added to planebatch for each aircraft and missile, and the smoke images after the aircraft and missile are added to smokebatch.
The planebatch sorting mode is texture, and smokebatch uses backtofront mode. After all the images are added to batch, call the planebatch end method first, which will sort all aircraft and missiles by texture and draw them to the screen with optimal performance. Then. Call the end method of smokebatch, which causes the smoke sprite to mix well on the image.
In this way, you have drawn an airplane with optimized performance and the mix is correct.