Menampilkan teks semi-transparan

Halaman Diperbarui :
Tanggal pembuatan halaman :

ringkasan

Buat teks tampak semi-transparan.

半透明の文字を表示する

Lingkungan operasi

Prasyarat

Versi XNA yang Didukung
  • 4.0
Platform yang Didukung
  • Windows (XP SP2 atau lebih baru, Vista, 7)
  • Xbox 360
  • Telepon Windows 7
Versi Vertex Shader yang Diperlukan Windows 2.0
Versi Pixel Shader yang Diperlukan Windows 2.0

Lingkungan operasi

balei-balei
  • Jendela 7
  • Xbox 360
  • Windows Phone 7 Emulator

zat

Dengan menerapkan opacity 0,0~1,0 ke struktur Color yang ditentukan oleh metode SpriteBatch.DrawString, Anda dapat menggambar teks dalam semi-transparansi. Sebagian besar warna yang sudah ditentukan dalam properti struktur Warna tidak diatur ke buram, sehingga dapat dibuat semi-transparan dengan menerapkan opasitas.

// 半透明の文字(75%)
this.spriteBatch.DrawString(this.font,
    "Draw transparent text. (75%)",
    new Vector2(50.0f, 100.0f), Color.White * 0.75f);

Color pembangun

Atur warnanya. Ada juga konstruktor float 0.0~1.0.

r byte Tentukan warna merah dari 0~255.
g byte Tentukan warna hijau sebagai 0~255.
b byte Tentukan warna biru dari 0~255.
sebuah byte Tentukan opacity (komponen alfa) dari 0~255.

Omong-omong, metode menentukan warna tembus cahaya sprite telah berubah sejak XNA Framework 4.0, dan untuk menentukan format seperti "new Color(255, 255, 255, 192)" yang digunakan di XNA Framewrok 3.1 dan sebelumnya, Anda perlu menentukan status 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(255255255192));

Namun, karena rumus untuk menghitung warna keluaran telah diubah, tepi karakter akan ditampilkan dalam keadaan gelap.

Tentang warna keluaran

Pada Tips sebelumnya, kami menggunakan dua pola campuran untuk menampilkan teks sebagai contoh. Di sisi lain, teks tembus pandang yang indah ditampilkan seperti yang diharapkan. Di sisi lain, tepi teks menjadi gelap. Ini karena rumus untuk mengeluarkan warna berbeda tergantung pada keadaan campuran yang digunakan.

Atur parameter ekspresi ke

  • hasil : Warna keluaran akhir
  • source : Warna tekstur yang Anda coba gambar
  • destination : Warna latar belakang tujuan
  • RGBA: Komponen R (merah), G (hijau), B (biru), dan A (alfa (opasitas)) masing-masing

Dan seperti yang didefinisikan, rumus perhitungan untuk dua keadaan campuran adalah sebagai berikut.

BlendState.AlphaBlend (default null) (alfa dikalikan)
result = source.rgb + destination.rgb * (1 - source.a) // Namun, source.rgb sudah diterapkan alfa
BlendState.NonPremultiplied (alfa yang diinterpolasi)
hasil = source.rgb * source.a + destination.rgb * (1 - source.a)

Bahkan, jika Anda menemukannya dengan rumus ini, nilai hasil akan sama dalam kedua kasus. Namun, jika Anda menggunakan pemfilteran bilinear, perhitungan di atas dilakukan setelah interpolasi warna dengan piksel yang berdekatan dalam shader piksel, sehingga hasil output akhir akan berbeda.

Saya ingin melakukan beberapa perhitungan demi itu. Jika warna teks berwarna putih (Color.White), setiap komponen warna piksel tempat teks ditampilkan adalah (r:255, g:255, b:255, a:255). Piksel yang tidak menampilkan teks adalah (r:0, g:0, b:0, a:0). Jika kita membuat teks semi-transparan pada 50% dan menginterpolasinya dengan nilai menengah dari dua piksel ini (yaitu, tepi karakter), bagaimana dua persamaan di atas mengubah hasilnya?

Ngomong-ngomong, warna latar belakangnya adalah (r:0, g:0, b:255, a:255). (Perhitungan dilakukan pada teks putih dan latar belakang biru)

Interpolasi dengan BlendState.AlphaBlend (alfa dikalikan)

Karena alfa diterapkan pada setiap elemen warna teks sebelumnya, warna teks dibagi dua oleh 255 (r:128, g:128, b:128, a:128) (Color.White * 0.5f"). Piksel yang tidak menampilkan teks dibiarkan apa adanya (r:0, g:0, b:0, a:0).

Karena rumus filter bilinear dilakukan sebelum status campuran menghitung warna latar belakang, warna tepi teks adalah (r:64, g:64, b:64, a:64), yang merupakan nilai perantara antara (r:128, g:128, b:128, a:128) dan (r:0, g:0, b:0, a:0).

Berikut ekspresinya

  • hasil = source.rgb + destination.rgb * (1 - source.a)

Jika Anda menerapkannya pada:

  • hasil = (r:64, g:64, b:64) + (r:0, g:0, b:255) * (1 - 0,25)      // 0,25 menunjukkan bahwa a:64 adalah 25% dari a:255

dan warna komposit akhir dengan warna latar belakang adalah (R:64, G:64, B:255).

Interpolasi dengan BlendState.NonPremultiplied (alfa yang diinterpolasi)

Warna teksnya putih (r:255, g:255, b:255), dan hanya alfa yang dibagi dua untuk membuatnya semi-transparan, sehingga nilai piksel di mana karakter ditampilkan adalah (r:255, g:255, b:255, a:128) (warna baru (255, 255, 255, 128)). Piksel yang tidak menampilkan teks tetap sama (r:0, g:0, b:0, a:0).

Karena rumus filter bilinear dilakukan sebelum status campuran menghitung warna latar belakang, warna tepi teks adalah (r:128, g:128, b:128, b:128, a:64), yang merupakan nilai perantara antara (r:0, g:0, b:0, a:0).

Berikut ekspresinya

  • hasil = source.rgb * source.a + destination.rgb * (1 - source.a)

Jika Anda menerapkannya pada:

  • 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 adalah (R:32, G:32, B:224).

Pertimbangan

Karena warna latar belakang adalah (r:0, g:0, b:255), interpolasi dengan BlendState.AlphaBlend (r:64, g:64, b:255) memungkinkan warna transparan teks diekspresikan dengan indah tanpa kehilangan pigmen warna latar belakang. Namun, dalam kasus interpolasi dengan BlendState.NonPremultiplied (r:32, g:32, b:224), komponen biru lebih gelap dari warna latar belakang, sehingga tepi teks tampak gelap (tentu saja).
Merah, Hijau lebih gelap dari BlendState.AlphaBlend.)

Alpha yang dikalikan default dari XNA Framework 4.0 ini dijelaskan secara rinci di blog "Hinikeni XNA", jadi jika Anda ingin tahu lebih banyak, silakan merujuk ke tautan di bawah ini. Di sana, digambarkan sebagai contoh menggambar elemen merah dengan latar belakang putih.

Semua Kode

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);
        }
    }
}