הצגת טקסט שקוף למחצה

עודכן דף :
תאריך יצירת דף :

תקציר

גרום לטקסט להיראות שקוף למחצה.

半透明の文字を表示する

סביבת הפעלה

דרישות מוקדמות

גרסאות XNA נתמכות
  • 4.0
פלטפורמות נתמכות
  • Windows (XP SP2 ואילך, Vista, 7)
  • Xbox 360
  • Windows Phone 7
Windows נדרש Vertex Shader גירסה 2.0
גירסת Pixel Shader נדרשת של Windows 2.0

סביבת הפעלה

פלטפורמה
  • חלונות 7
  • Xbox 360
  • אמולטור Windows Phone 7

חומר

על-ידי החלת אטימות של 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(255255255192));

עם זאת, מאחר שהנוסחה לחישוב צבע הפלט השתנתה, קצה התו יוצג במצב כהה.

אודות צבע הפלט

בעצות הקודמות, השתמשנו בשתי תבניות מיזוג כדי להציג טקסט כדוגמה. מצד שני, טקסט שקוף יפה הוצג כצפוי. מצד שני, שולי הטקסט הוחשכו. הסיבה לכך היא שהנוסחה להפקת הצבע משתנה בהתאם למצב המיזוג שנעשה בו שימוש.

הגדר את הפרמטרים של הביטוי ל

  • תוצאה : צבע פלט סופי
  • מקור : צבע המרקם שאתה מנסה לצייר
  • יעד : צבע הרקע של היעד
  • RGBA: רכיבים של R (אדום), G (ירוק), B (כחול) ו-A (אלפא (אטימות)) בהתאמה

וכפי שהוגדר, נוסחת החישוב עבור שני מצבי המיזוג היא כדלקמן.

BlendState.AlphaBlend (ברירת המחדל של null) (אלפא מוכפל)
תוצאה = source.rgb + destination.rgb * (1 - source.a) // עם זאת, source.rgb כבר מוחל אלפא
BlendState.NonPremultiplied (אלפא באינטרפולציה)
תוצאה = source.rgb * source.a + destination.rgb * (1 - source.a)

למעשה, אם אתה מוצא את זה עם נוסחה זו, הערך של התוצאה יהיה זהה בשני המקרים. עם זאת, אם אתה משתמש בסינון ביליארי, החישובים לעיל מבוצעים לאחר אינטרפולציה של צבע עם פיקסלים סמוכים ב- Shader של הפיקסלים, כך שתוצאת הפלט הסופית תהיה שונה.

אני רוצה לעשות כמה חישובים לשם כך. אם צבע הטקסט הוא לבן (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);
        }
    }
}