Using Layer Parameters to Create Sprite Context
summary
Use the layer's depth value to specify the context of the sprite.
Operating environment
Prerequisites
Supported XNA Versions |
|
Supported Platforms |
|
Windows Required Vertex Shader Version | 2.0 |
Windows Required Pixel Shader Version | 2.0 |
Operating environment
platform |
|
substance
Normally, when you draw a sprite, it is drawn so that what you draw later is in front of you, but by sorting by depth value, you can make the context clear regardless of the order in which the SpriteBatch.Draw method is called.
To sort by sprite depth value, specify "SpriteSortMode.BackToFront" as the first argument to the "SpriteBatch.Begin" method. It is a processing method that draws from the sprite in the back and overwrites the sprite in the foreground.
// 一つでも半透明、透明要素があるスプライトの場合はこちらの引数を使用
this.spriteBatch.Begin(SpriteSortMode.BackToFront, null);
However, if you want to draw only a sprite that is semi-transparent or has no transparent elements at all, you can draw it faster by specifying the following.
// 深度バッファを使用して前後関係を有効にし描画するように指定
// 完全な不透明スプライトのみ描画する場合はこちらが高速
this.spriteBatch.Begin(SpriteSortMode.FrontToBack,
BlendState.Opaque,
null,
DepthStencilState.Default,
null);
The fourth argument is "DepthStencilState.Default", which also writes "depth" information to each pixel when the sprite is drawn. When the depth information is written, it is possible to determine that the object to be drawn (in pixels) after that position does not need to be written, so the drawing cost is greatly reduced.
For the above reasons, if you draw the sprite in the foreground first, the drawing cost of the sprite that overlaps behind it will decrease, so it is sorted so that it is drawn from the front by specifying "SpriteSortMode.FrontToBack" as the first argument to draw from the foreground.
However, this is only useful when drawing an opaque sprite with a completely negligible color element behind it. In the case of semi-transparent or opaque sprites, the depth value is written to each pixel even if it is a semi-transparent or transparent pixel, so if you draw from the front, the sprite behind you will not be displayed. This is why "SpriteSortMode.BackToFront" is specified in the character drawing. (Because pixels other than the shape of the text are transparent)
By the way, as a result of a test of drawing 30,000 sprites in my environment, it was about 3 times faster to draw from the front using the depth value than from the back. Of course, it depends on the number of sheets to be drawn, the degree of overlap, the size, etc., as well as the execution environment, so please try it yourself.
SpriteBatch.Begin
method
Call it before drawing the sprite. Internally, we are making the necessary settings for drawing sprites.
sortMode | SpriteSortMode | Specifies the order in which the sprites are drawn from the SpriteSortMode enumeration. If you want to draw from the back, specify SpriteSortMode.BackToFront. If you want to draw from the front, specify SpriteSortMode.FrontToBack. |
blendState | BlendState | How to blend the color of the sprite to be drawn with the background color. By default, BlendState.AlphaBlend is specified, but in this case, the sprite to be drawn is completely opaque, so BlendState.Opaque is specified without considering the background color. |
samplerState | SamplerState | How the texture is sampled. If null is specified, the default SamplerState.LinearClamp is specified. |
depthStencilState | DepthStencilState | Specifies how the depth-stencil buffer is used. If null is specified, DepthStencilState.None is used, which does not use a depth-stencil buffer. If you want to use a depth-stencil buffer, specify DepthStencilState.Default. |
rasterizerState | RasterizerState | Specifies a rasterization method, such as back culling. If null is specified, the default RasterizerState.CullCounterClockwise is specified. |
To draw a sprite, specify a depth value as the ninth argument to the SpriteBatch.Draw method. The values that can be set here are in the range of 0.0~1.0, with 0.0 being the foremost and 1.0 being the backmost.
// 最背面に描画(赤)
this.spriteBatch.Draw(this.texture, new Vector2(150.0f, 50.0f), null,
Color.Red, 0.0f, Vector2.Zero, 1.0f, SpriteEffects.None, 1.0f);
// 最前面に描画(緑)
this.spriteBatch.Draw(this.texture, new Vector2(110.0f, 90.0f), null,
Color.Green, 0.0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0.0f);
// 2つのスプライトの間に描画(青)
this.spriteBatch.Draw(this.texture, new Vector2(190.0f, 130.0f), null,
Color.Blue, 0.0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0.5f);
SpriteBatch.Draw
method
Adds a sprite to the sprite drawing batch list.
texture | Texture2D | Specifies the texture to display as a sprite. |
position | Vector2 | The position where the sprite should be displayed. Specify in screen coordinates relative to the top left of the screen. The origin of the sprite will be in the upper left position. |
sourceRectangle | Nullable<Rectangle> | Specifies the transfer area for the texture. If you want the entire texture to be displayed as a sprite, you can specify null. If you specify this parameter, you can make only an arbitrary area appear as a sprite. |
color | Color | Specifies the color to multiply the color of the sprite. If you specify Color.White, it is displayed in the primary color of the sprite. If Color.Black is specified, the sprite is displayed in full black, regardless of its color. The formula is "Result = sprite color * color". |
rotation | float | The rotation angle of the sprite. Units are specified in radian. The axis of rotation will be at the top left of the sprite. |
origin | Vector2 | Specifies the position of the axis of rotation when rotating the sprite. You specify which position of the sprite is the axis of rotation, but in reality, the position of the axis of rotation is fixed to the top left of the sprite, and the display position of the sprite is moved by -origin. |
scale | float | Specifies the magnification of the sprite. Scales vertically and horizontally relative to 1.0. The origin of the magnification will be in the upper left corner of the sprite. |
effects | SpriteEffects | Specifies the flip effect of the sprite. If you don't do anything else, specify SpriteEffects.None. |
layerDepth | float | Specifies the depth at which the sprite is displayed. It is mainly used to display sprites in the foreground and in the back. Specify in the range of 0.0~1.0, where 0.0 is the front and 1.0 is the back. |
In the above program, the SpriteBatch.Draw method is called in the order of "red", "green", and "blue", but each depth value is set to "red (1.0)", "green (0.0)", and "blue (0.5)", so you can see that red is drawn at the back and green is drawn in the foreground.
All Codes
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
#if WINDOWS_PHONE
using Microsoft.Xna.Framework.Input.Touch;
#endif
namespace LayerDepthSprite
{
<summary>
ゲームメインクラス
</summary>
public class GameMain : Microsoft.Xna.Framework.Game
{
<summary>
グラフィックデバイス管理クラス
</summary>
private GraphicsDeviceManager graphics = null;
<summary>
スプライトのバッチ化クラス
</summary>
private SpriteBatch spriteBatch = null;
<summary>
テクスチャー
</summary>
private Texture2D texture = null;
<summary>
GameMain コンストラクタ
</summary>
public GameMain()
{
// グラフィックデバイス管理クラスの作成
this.graphics = new GraphicsDeviceManager(this);
// ゲームコンテンツのルートディレクトリを設定
this.Content.RootDirectory = "Content";
#if WINDOWS_PHONE
// Windows Phone のデフォルトのフレームレートは 30 FPS
this.TargetElapsedTime = TimeSpan.FromTicks(333333);
// バックバッファサイズの設定
this.graphics.PreferredBackBufferWidth = 480;
this.graphics.PreferredBackBufferHeight = 800;
// フルスクリーン表示
this.graphics.IsFullScreen = true;
#endif
}
<summary>
ゲームが始まる前の初期化処理を行うメソッド
グラフィック以外のデータの読み込み、コンポーネントの初期化を行う
</summary>
protected override void Initialize()
{
// TODO: ここに初期化ロジックを書いてください
// コンポーネントの初期化などを行います
base.Initialize();
}
<summary>
ゲームが始まるときに一回だけ呼ばれ
すべてのゲームコンテンツを読み込みます
</summary>
protected override void LoadContent()
{
// テクスチャーを描画するためのスプライトバッチクラスを作成します
this.spriteBatch = new SpriteBatch(this.GraphicsDevice);
// テクスチャーをコンテンツパイプラインから読み込む
this.texture = this.Content.Load<Texture2D>("Texture");
}
<summary>
ゲームが終了するときに一回だけ呼ばれ
すべてのゲームコンテンツをアンロードします
</summary>
protected override void UnloadContent()
{
// TODO: ContentManager で管理されていないコンテンツを
// ここでアンロードしてください
}
<summary>
描画以外のデータ更新等の処理を行うメソッド
主に入力処理、衝突判定などの物理計算、オーディオの再生など
</summary>
<param name="gameTime">このメソッドが呼ばれたときのゲーム時間</param>
protected override void Update(GameTime gameTime)
{
// Xbox 360 コントローラ、Windows Phone の BACK ボタンを押したときに
// ゲームを終了させます
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
{
this.Exit();
}
// TODO: ここに更新処理を記述してください
// 登録された GameComponent を更新する
base.Update(gameTime);
}
<summary>
描画処理を行うメソッド
</summary>
<param name="gameTime">このメソッドが呼ばれたときのゲーム時間</param>
protected override void Draw(GameTime gameTime)
{
// 画面を指定した色でクリアします
this.GraphicsDevice.Clear(Color.CornflowerBlue);
// 深度バッファを使用して前後関係を有効にし描画するように指定
// 完全な不透明スプライトのみ描画する場合はこちらが高速
this.spriteBatch.Begin(SpriteSortMode.FrontToBack,
BlendState.Opaque,
null,
DepthStencilState.Default,
null);
// 一つでも半透明、透明要素があるスプライトの場合はこちらの引数を使用
//this.spriteBatch.Begin(SpriteSortMode.BackToFront, null);
// 最背面に描画(赤)
this.spriteBatch.Draw(this.texture, new Vector2(150.0f, 50.0f), null,
Color.Red, 0.0f, Vector2.Zero, 1.0f, SpriteEffects.None, 1.0f);
// 最前面に描画(緑)
this.spriteBatch.Draw(this.texture, new Vector2(110.0f, 90.0f), null,
Color.Green, 0.0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0.0f);
// 2つのスプライトの間に描画(青)
this.spriteBatch.Draw(this.texture, new Vector2(190.0f, 130.0f), null,
Color.Blue, 0.0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0.5f);
// スプライトの一括描画
this.spriteBatch.End();
// 登録された DrawableGameComponent を描画する
base.Draw(gameTime);
}
}
}