Paparkan teks separa telus
Ringkasan
Jadikan teks kelihatan separa telus.
Persekitaran operasi
Prasyarat
Versi XNA yang Disokong |
|
Platform yang Disokong |
|
Versi Vertex Shader yang Diperlukan Windows | 2.0 |
Windows Versi Pixel Shader Diperlukan | 2.0 |
Persekitaran operasi
Platform |
|
Bahan
Dengan menggunakan kelegapan 0.0~1.0 pada struktur Warna yang ditentukan oleh kaedah SpriteBatch.DrawString, anda boleh melukis teks dalam separa ketelusan. Kebanyakan warna yang telah ditakrifkan dalam sifat struktur Warna tidak ditetapkan kepada legap, jadi ia boleh dibuat separa telus dengan menggunakan kelegapan.
// 半透明の文字(75%)
this.spriteBatch.DrawString(this.font,
"Draw transparent text. (75%)",
new Vector2(50.0f, 100.0f), Color.White * 0.75f);
Color
Constructor
Tetapkan warna. Terdapat juga pembina apungan 0.0~1.0.
r | Bait | Tentukan warna merah dari 0 ~ 255. |
g | Bait | Tentukan warna hijau sebagai 0~255. |
b | Bait | Tentukan warna biru dari 0~255. |
a | Bait | Tentukan kelegapan (komponen alfa) dari 0~255. |
Dengan cara ini, kaedah menentukan warna lut sinar sprite telah berubah sejak XNA Framework 4.0, dan untuk menentukan format seperti "new Color(255, 255, 255, 192)
" yang digunakan dalam XNA Framewrok 3.1 dan lebih awal, anda perlu menentukan keadaan campuran SpriteBatch dengan "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));
Walau bagaimanapun, kerana formula untuk mengira warna output telah diubah, tepi aksara akan dipaparkan dalam keadaan gelap.
Mengenai warna keluaran
Dalam Petua sebelumnya, kami menggunakan dua corak campuran untuk memaparkan teks sebagai contoh. Sebaliknya, teks lut sinar yang cantik dipaparkan seperti yang dijangkakan. Sebaliknya, tepi teks telah digelapkan. Ini kerana formula untuk mengeluarkan warna berbeza bergantung pada keadaan adunan yang digunakan.
Tetapkan parameter ungkapan kepada
- keputusan : Warna keluaran akhir
- sumber : Warna tekstur yang anda cuba lukis
- destinasi : Warna latar belakang destinasi
- RGBA: Komponen R (merah), G (hijau), B (biru), dan A (alfa (kelegapan)) masing-masing
Dan seperti yang ditakrifkan, formula pengiraan untuk kedua-dua keadaan campuran adalah seperti berikut.
- BlendState.AlphaBlend (lalai nol) (alfa didarab)
- result = source.rgb + destination.rgb * (1 - source.a) // Walau bagaimanapun, source.rgb sudah digunakan alfa
- BlendState.NonPremultiplied (Alfa Interpolasi)
- hasil = sumber.rgb * sumber.a + tujuan.rgb * (1 - sumber.a)
Malah, jika anda menemuinya dengan formula ini, nilai hasil akan sama dalam kedua-dua kes. Walau bagaimanapun, jika anda menggunakan penapisan bilinear, pengiraan di atas dilakukan selepas interpolasi warna dengan piksel bersebelahan dalam shader piksel, jadi hasil output akhir akan berbeza.
Saya ingin melakukan beberapa pengiraan demi itu. Jika warna teks putih (Color.White), setiap komponen warna piksel di mana teks dipaparkan ialah (r:255, g:255, b:255, a:255). Piksel yang tidak memaparkan teks ialah (r:0, g:0, b:0, a:0). Jika kita membuat teks separa telus pada 50% dan menginterpolasinya dengan nilai perantaraan kedua-dua piksel ini (iaitu, tepi aksara), bagaimanakah dua persamaan di atas mengubah keputusan?
By the way, warna latar belakang ialah (r:0, g:0, b:255, a:255). (Pengiraan dilakukan pada teks putih dan latar belakang biru)
Interpolasi dengan BlendState.AlphaBlend (alfa berganda)
Oleh kerana alfa digunakan pada setiap elemen warna teks terlebih dahulu, warna teks dikurangkan separuh sebanyak 255 (r:128, g:128, b:128, a:128) (Color.White * 0.5f"). Piksel yang tidak mempunyai teks yang dipaparkan dibiarkan seperti sedia ada (r:0, g:0, b:0, a:0).
Memandangkan formula penapis bilinear dilakukan sebelum keadaan campuran mengira warna latar belakang, warna tepi teks ialah (r:64, g:64, b:64, a:64), yang merupakan nilai perantaraan antara (r:128, g:128, b:128, a:128) dan (r:0, g:0, b:0, a:0).
Di sini ungkapan
- hasil = sumber.rgb + tujuan.rgb * (1 - sumber.a)
Jika anda menggunakannya untuk:
- hasil = (r:64, g:64, b:64) + (r:0, g:0, b:255) * (1 - 0.25) // 0.25 menunjukkan bahawa a:64 ialah 25% daripada a:255
dan warna komposit akhir dengan warna latar belakang ialah (r:64, g:64, b:255).
Interpolasi dengan BlendState.NonPremultiplied (alfa interpolasi)
Warna teks adalah putih (r:255, g:255, b:255), dan hanya alfa yang dikurangkan separuh untuk menjadikannya separa telus, jadi nilai piksel di mana aksara dipaparkan ialah (r:255, g:255, b:255, a:128) (warna baru( 255, 255, 255, 128)). Piksel yang tidak memaparkan teks kekal sama (r:0, g:0, b:0, a:0).
Memandangkan formula penapis bilinear dilakukan sebelum keadaan campuran mengira warna latar belakang, warna tepi teks ialah (r:128, g:128, b:128, b:128, a:64), yang merupakan nilai perantaraan antara (r:0, g:0, b:0, a:0).
Di sini ungkapan
- hasil = sumber.rgb * sumber.a + tujuan.rgb * (1 - sumber.a)
Jika anda menggunakannya untuk:
- hasil = (r:128, g:128, b:128) * 0.25 + (r:0, g:0, b:255) * (1 - 0.25)
dan warna komposit akhir dengan warna latar belakang ialah (R:32, G:32, B:224).
Pertimbangan
Oleh kerana warna latar belakang ialah (r:0, g:0, b:255), interpolasi dengan BlendState.AlphaBlend (r:64, g:64, b:255) membolehkan warna telus teks dinyatakan dengan indah tanpa kehilangan pigmen warna latar belakang. Walau bagaimanapun, dalam kes interpolasi dengan BlendState.NonPremultiplied (r:32, g:32, b:224), komponen biru lebih gelap daripada warna latar belakang, jadi tepi teks kelihatan gelap (sudah tentu).
Merah, Hijau lebih gelap daripada BlendState.AlphaBlend.)
Alfa darab lalai ini daripada Rangka Kerja XNA 4.0 diterangkan secara terperinci dalam blog "Hinikeni XNA", jadi jika anda ingin mengetahui lebih lanjut, sila rujuk pautan di bawah. Di sana, ia digambarkan sebagai contoh melukis elemen merah dengan latar belakang putih.
Semua Kod
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);
}
}
}