Hiển thị văn bản bán trong suốt

Trang Cập Nhật :
Ngày tạo trang :

tóm tắt

Làm cho văn bản xuất hiện nửa trong suốt.

半透明の文字を表示する

Môi trường hoạt động

Điều kiện tiên quyết

Các phiên bản XNA được hỗ trợ
  • 4.0
Nền tảng được hỗ trợ
  • Windows (XP SP2 trở lên, Vista, 7)
  • Xbox 360
  • Windows Phone 7
Phiên bản Vertex Shader yêu cầu của Windows 2.0
Phiên bản Pixel Shader yêu cầu của Windows 2.0

Môi trường hoạt động

nền tảng
  • Cửa sổ 7
  • Xbox 360
  • Trình giả lập Windows Phone 7

chất

Bằng cách áp dụng độ mờ 0.0~1.0 cho cấu trúc Color được chỉ định bởi phương thức SpriteBatch.DrawString, bạn có thể vẽ văn bản ở chế độ bán trong suốt. Hầu hết các màu đã được xác định trong các thuộc tính của cấu trúc Color không được đặt thành mờ đục, vì vậy chúng có thể được làm bán trong suốt bằng cách áp dụng độ mờ.

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

Color Constructor

Đặt màu. Ngoài ra còn có một hàm tạo float 0.0 ~ 1.0.

r byte Chỉ định màu đỏ từ 0 ~ 255.
g byte Chỉ định màu xanh lá cây là 0 ~ 255.
b byte Chỉ định màu xanh lam từ 0 ~ 255.
một byte Chỉ định độ mờ (thành phần alpha) từ 0 ~ 255.

Nhân tiện, phương pháp chỉ định màu mờ của sprite đã thay đổi kể từ XNA Framework 4.0 và để chỉ định một định dạng như ""new Color(255, 255, 255, 192) được sử dụng trong XNA Framewrok 3.1 trở về trước, bạn cần chỉ định trạng thái pha trộn của SpriteBatch với "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));

Tuy nhiên, vì công thức tính màu đầu ra đã được thay đổi, nên cạnh của ký tự sẽ được hiển thị ở trạng thái tối.

Về màu đầu ra

Trong các mẹo trước, chúng ta đã sử dụng hai mẫu pha trộn để hiển thị văn bản như một ví dụ. Mặt khác, văn bản mờ đẹp được hiển thị như mong đợi. Mặt khác, các cạnh của văn bản bị tối. Điều này là do công thức xuất màu khác nhau tùy thuộc vào trạng thái pha trộn được sử dụng.

Đặt các tham số của biểu thức thành

  • kết quả : Màu đầu ra cuối cùng
  • source : Màu của kết cấu bạn đang cố gắng vẽ
  • destination : Màu nền của điểm đến
  • RGBA: Các thành phần của R (đỏ), G (xanh lá cây), B (xanh lam) và A (alpha (mờ)) tương ứng

Và như đã định nghĩa, công thức tính cho hai trạng thái pha trộn như sau.

BlendState.AlphaBlend (mặc định rỗng) (alpha nhân)
result = source.rgb + destination.rgb * (1 - source.a) // Tuy nhiên, source.rgb đã được áp dụng alpha
BlendState.NonPremultiplied (Alpha nội suy)
kết quả = source.rgb * source.a + destination.rgb * (1 - source.a)

Trên thực tế, nếu bạn tìm thấy nó với công thức này, giá trị của kết quả sẽ giống nhau trong cả hai trường hợp. Tuy nhiên, nếu bạn sử dụng lọc song tuyến, các tính toán trên được thực hiện sau khi nội suy màu với các pixel liền kề trong pixel shader, vì vậy kết quả đầu ra cuối cùng sẽ khác nhau.

Tôi muốn thực hiện một số tính toán vì lợi ích của nó. Nếu màu của văn bản là màu trắng (Color.White), mỗi thành phần màu của pixel mà văn bản được hiển thị là (r: 255, g: 255, b: 255, a: 255). Các pixel không hiển thị văn bản là (r:0, g:0, b:0, a:0). Nếu chúng ta làm cho văn bản bán trong suốt ở mức 50% và nội suy nó với giá trị trung gian của hai pixel này (tức là cạnh của ký tự), hai phương trình trên thay đổi kết quả như thế nào?

Nhân tiện, màu nền là (r: 0, g: 0, b: 255, a: 255). (Tính toán được thực hiện trên văn bản màu trắng và nền xanh lam)

Nội suy với BlendState.AlphaBlend (nhân alpha)

Vì alpha được áp dụng cho từng phần tử của màu văn bản trước đó, màu văn bản được giảm một nửa 255 (r: 128, g: 128, b: 128, a: 128) (Color.White * 0.5f"). Các pixel không có văn bản được hiển thị sẽ được giữ nguyên (r:0, g:0, b:0, a:0).

Vì công thức bộ lọc lưỡng tuyến được thực hiện trước khi trạng thái pha trộn tính toán màu nền, nên màu của cạnh của văn bản là (r:64, g:64, b:64, a:64), là giá trị trung gian giữa (r:128, g:128, b:128, a:128) và (r:0, g:0, b:0, a:0).

Ở đây là biểu thức

  • kết quả = source.rgb + destination.rgb * (1 - source.a)

Nếu bạn áp dụng nó cho:

  • kết quả = (r:64, g:64, b:64) + (r:0, g:0, b:255) * (1 - 0,25)      // 0,25 cho biết a:64 là 25% của a:255

và màu tổng hợp cuối cùng với màu nền là (r: 64, g: 64, b: 255).

Nội suy với BlendState.NonPremultiplied (alpha nội suy)

Màu của văn bản là màu trắng (r: 255, g: 255, b: 255), và chỉ có alpha được giảm một nửa để làm cho nó bán trong suốt, vì vậy giá trị của pixel trong đó ký tự được hiển thị là (r: 255, g: 255, b: 255, a: 128) (màu mới (255, 255, 255, 128)). Các pixel không hiển thị văn bản vẫn giữ nguyên (r:0, g:0, b:0, a:0).

Vì công thức bộ lọc lưỡng tuyến được thực hiện trước khi trạng thái pha trộn tính toán màu nền, màu của cạnh văn bản là (r:128, g:128, b:128, b:128, a:64), là giá trị trung gian giữa (r:0, g:0, b:0, a:0).

Ở đây là biểu thức

  • kết quả = source.rgb * source.a + destination.rgb * (1 - source.a)

Nếu bạn áp dụng nó cho:

  • kết quả = (r:128, g:128, b:128) * 0,25 + (r:0, g:0, b:255) * (1 - 0,25)

và màu tổng hợp cuối cùng với màu nền là (r: 32, g: 32, b: 224).

Xem xét

Vì màu nền là (r:0, g:0, b:255), nên nội suy với BlendState.AlphaBlend (r:64, g:64, b:255) cho phép màu trong suốt của văn bản được thể hiện đẹp mắt mà không làm mất sắc tố của màu nền. Tuy nhiên, trong trường hợp nội suy với BlendState.NonPremultiplied (r:32, g:32, b:224), thành phần màu xanh lam đậm hơn màu nền, do đó các cạnh của văn bản có vẻ tối hơn (tất nhiên).
Đỏ, Xanh lá cây đậm hơn BlendState.AlphaBlend.)

Alpha nhân mặc định này từ XNA Framework 4.0 được mô tả chi tiết trong blog "Hinikeni XNA", vì vậy nếu bạn muốn biết thêm, vui lòng tham khảo liên kết bên dưới. Ở đó, nó được mô tả như một ví dụ về việc vẽ một yếu tố màu đỏ trên nền trắng.

Tất cả mã

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