نمایش متن نیمه شفاف
خلاصه
متن را نیمه شفاف جلوه دهید.
محیط عملیاتی
پیش نیازها
نسخه های XNA پشتیبانی شده |
|
پلتفرم های پشتیبانی شده |
|
نسخه Vertex Shader مورد نیاز ویندوز | 2.0 |
ویندوز نسخه Pixel Shader مورد نیاز است | 2.0 |
محیط عملیاتی
بستر |
|
ماده
با اعمال کدورت 0.0~1.0 به ساختار رنگ مشخص شده توسط متد SpriteBatch.DrawString، می توانید متن را به صورت نیمه شفاف ترسیم کنید. اکثر رنگ هایی که قبلا در ویژگی های ساختار رنگ تعریف شده اند روی مات تنظیم نشده اند، بنابراین می توان با اعمال کدورت آنها را نیمه شفاف کرد.
// 半透明の文字(75%)
this.spriteBatch.DrawString(this.font,
"Draw transparent text. (75%)",
new Vector2(50.0f, 100.0f), Color.White * 0.75f);
Color
سازنده
رنگ را تنظیم کنید. همچنین یک سازنده شناور 0.0 ~ 1.0 وجود دارد.
r | بایت | رنگ قرمز را از 0 ~ 255 مشخص کنید. |
g | بایت | رنگ سبز را به صورت 0 ~ 255 مشخص کنید. |
b | بایت | رنگ آبی را از 0 ~ 255 مشخص کنید. |
a | بایت | کدورت (مؤلفه آلفا) را از 0 ~ 255 مشخص کنید. |
به هر حال، روش تعیین رنگ شفاف اسپرایت ها از زمان XNA Framework 4.0 تغییر کرده است و برای تعیین فرمتی مانند "new Color(255, 255, 255, 192)
" که در XNA Framewrok 3.1 و نسخه های قبلی استفاده می شود، باید حالت ترکیبی SpriteBatch را با "BlendState.NonPremultiplied" مشخص کنید.
// スプライトの描画準備
this.spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied);
// 半透明の文字(75%)
this.spriteBatch.DrawString(this.font,
"Draw transparent text. (75%)",
new Vector2(50.0f, 100.0f), new Color(255, 255, 255, 192));
با این حال، از آنجایی که فرمول محاسبه رنگ خروجی تغییر کرده است، لبه کاراکتر در حالت تاریک نمایش داده می شود.
درباره رنگ خروجی
در نکات قبلی، از دو الگوی ترکیبی برای نمایش متن به عنوان مثال استفاده کردیم. از سوی دیگر، متن شفاف زیبا همانطور که انتظار می رفت نمایش داده شد. از سوی دیگر، لبه های متن تیره شده بود. این به این دلیل است که فرمول خروجی رنگ بسته به حالت ترکیبی مورد استفاده متفاوت است.
پارامترهای عبارت را روی
- نتیجه: رنگ خروجی نهایی
- منبع : رنگ تکسچری که می خواهید ترسیم کنید
- مقصد : رنگ پس زمینه مقصد
- RGBA: اجزای R (قرمز)، G (سبز)، B (آبی) و A (آلفا (کدورت)) به ترتیب
و همانطور که تعریف شد، فرمول محاسبه برای دو حالت ترکیبی به شرح زیر است.
- BlendState.AlphaBlend (پیش فرض ته) (آلفای ضرب)
- نتیجه = source.rgb + destination.rgb * (1 - source.a) // با این حال، source.rgb در حال حاضر آلفا اعمال شده است
- BlendState.NonPremultiplied (آلفای درون یابی)
- نتیجه = source.rgb * source.a + destination.rgb * (1 - source.a)
در حقیقت ، اگر آن را با این فرمول پیدا کنید ، مقدار نتیجه در هر دو مورد یکسان خواهد بود. با این حال، اگر از فیلتر دو خطی استفاده می کنید، محاسبات فوق پس از درون یابی رنگ با پیکسل های مجاور در سایه زن پیکسل انجام می شود، بنابراین نتیجه خروجی نهایی متفاوت خواهد بود.
من می خواهم به خاطر آن محاسباتی انجام دهم. اگر رنگ متن سفید باشد (Color.White)، هر جزء رنگی پیکسلی که متن در آن نمایش داده می شود (r:255, g:255, b:255, a:255) است. پیکسل هایی که متن را نمایش نمی دهند عبارتند از (r:0, g:0, b:0, a:0). اگر متن را در 50 درصد نیمه شفاف کنیم و آن را با مقدار میانی این دو پیکسل (یعنی لبه کاراکتر) درهم آوریم، دو معادله بالا چگونه نتیجه را تغییر می دهند؟
به هر حال، رنگ پس زمینه (r:0, g:0, b:255, a:255) است. (محاسبات بر روی متن سفید و پس زمینه آبی انجام می شود)
درون یابی با BlendState.AlphaBlend (آلفای ضرب)
از آنجایی که آلفا از قبل برای هر عنصر از رنگ متن اعمال می شود، رنگ متن 255 (r:128، g:128، b:128، a:128) (Color.White * 0.5f") به نصف کاهش می یابد. پیکسل هایی که متن نمایش داده نمی شوند همانطور که هستند باقی می مانند (r:0، g:0، b:0، a:0).
از آنجایی که فرمول فیلتر دو خطی قبل از محاسبه رنگ پس زمینه توسط حالت ترکیبی انجام می شود، رنگ لبه متن (r:64، g:64، b:64، a:64) است که یک مقدار میانی بین (r:128، g:128، b:128، a:128) و (r:0، g:0، b:0، a:0) است.
در اینجا عبارت
- نتیجه = source.rgb + destination.rgb * (1 - source.a)
اگر آن را برای موارد زیر اعمال می کنید:
- نتیجه = (R:64, G:64, B:64) + (R:0, G:0, B:255) * (1 - 0.25) // 0.25 نشان می دهد که A:64 25٪ از A:255 است
و رنگ کامپوزیت نهایی با رنگ پس زمینه (R:64, G:64, B:255) است.
درون یابی با BlendState.NonPremultiplied (آلفای درون یابی)
رنگ متن سفید است (r:255, g:255, b:255) و فقط آلفا نصف می شود تا نیمه شفاف شود، بنابراین مقدار پیکسلی که کاراکتر در آن نمایش داده می شود (r:255, g:255, b:255, a:128) (رنگ جدید (255, 255, 255, 128)). پیکسل هایی که متن را نمایش نمی دهند ثابت می مانند (r:0, g:0, b:0, a:0).
از آنجایی که فرمول فیلتر دو خطی قبل از محاسبه رنگ پس زمینه توسط حالت ترکیبی انجام می شود، رنگ لبه متن (r:128، g:128، b:128، b:128، a:64) است که یک مقدار میانی بین (r:0، g:0، b:0، a:0) است.
در اینجا عبارت
- نتیجه = source.rgb * source.a + destination.rgb * (1 - source.a)
اگر آن را برای موارد زیر اعمال می کنید:
- نتیجه = (R:128, G:128, B:128) * 0.25 + (R:0, G:0, B:255) * (1 - 0.25)
و رنگ کامپوزیت نهایی با رنگ پس زمینه (R:32, G:32, B:224) است.
نظر گرفتن
از آنجایی که رنگ پس زمینه (r:0, g:0, b:255) است، درون یابی با BlendState.AlphaBlend (r:64, g:64, b:255) اجازه می دهد تا رنگ شفاف متن به زیبایی بدون از دست دادن رنگدانه رنگ پس زمینه بیان شود. با این حال، در مورد درون یابی با BlendState.NonPremultiplied (r:32, g:32, b:224)، مؤلفه آبی تیره تر از رنگ پس زمینه است، بنابراین لبه های متن تیره تر به نظر می رسد (البته).
قرمز، سبز تیره تر از BlendState.AlphaBlend است.)
این آلفای پیش فرض ضرب شده از XNA Framework 4.0 به طور مفصل در وبلاگ "Hinikeni XNA" توضیح داده شده است، بنابراین اگر می خواهید بیشتر بدانید، لطفا به لینک زیر مراجعه کنید. در آنجا ، به عنوان نمونه ای از ترسیم یک عنصر قرمز در پس زمینه سفید توصیف می شود.
همه کدها
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 TransparentText
{
<summary>
ゲームメインクラス
</summary>
public class GameMain : Microsoft.Xna.Framework.Game
{
<summary>
グラフィックデバイス管理クラス
</summary>
private GraphicsDeviceManager graphics = null;
<summary>
スプライトのバッチ化クラス
</summary>
private SpriteBatch spriteBatch = null;
<summary>
スプライトでテキストを描画するためのフォント
</summary>
private SpriteFont font = 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.font = this.Content.Load<SpriteFont>("Font");
}
<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();
// 通常の文字
this.spriteBatch.DrawString(this.font,
"Draw normal text.",
new Vector2(50.0f, 50.0f), Color.White);
// 半透明の文字(75%)
this.spriteBatch.DrawString(this.font,
"Draw transparent text. (75%)",
new Vector2(50.0f, 100.0f), Color.White * 0.75f);
// 半透明の文字(50%)
this.spriteBatch.DrawString(this.font,
"Draw transparent text. (50%)",
new Vector2(50.0f, 150.0f), Color.White * 0.5f);
// 半透明の文字(25%)
this.spriteBatch.DrawString(this.font,
"Draw transparent text. (25%)",
new Vector2(50.0f, 200.0f), Color.White * 0.25f);
// スプライトの一括描画
this.spriteBatch.End();
// 登録された DrawableGameComponent を描画する
base.Draw(gameTime);
}
}
}