Zobrazení poloprůhledného textu

Stránky aktualizovány :
Datum vytvoření stránky :

shrnutí

Zajistěte, aby text vypadal jako poloprůhledný.

半透明の文字を表示する

Provozní prostředí

Požadavky

Podporované verze XNA
  • 4.0
Podporované platformy
  • Windows (XP SP2 nebo novější, Vista, 7)
  • Xbox 360
  • Windows Phone 7
Požadovaná verze Vertex Shader systému Windows 2.0
Windows Požadovaná verze pixel shaderu 2.0

Provozní prostředí

nástupiště
  • Systém Windows 7
  • Xbox 360
  • Emulátor systému Windows Phone 7

hmota

Použitím krytí 0,0~1,0 na Color strukturu určenou metodou SpriteBatch.DrawString můžete text vykreslit v poloprůhlednosti. Většina barev, které jsou již definovány ve vlastnostech struktury Color, není nastavena jako neprůhledná, takže je lze použitím krytí nastavit jako poloprůhledné.

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

Color konstruktor

Nastavte barvu. K dispozici je také konstruktor 0.0~1.0 float.

r bajt Určete červenou barvu od 0~255.
g bajt Zadejte zelenou barvu jako 0~255.
b bajt Určete modrou barvu od 0~255.
a bajt Určete krytí (alfa složka) od 0~255.

Mimochodem, metoda určování průsvitné barvy sprajtů se od XNA Framework 4.0 změnila a abyste mohli určit formát jako "new Color(255, 255, 255, 192)" použitý v XNA Framewrok 3.1 a starších, musíte určit stav prolnutí SpriteBatch pomocí "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));

Protože však byl změněn vzorec pro výpočet výstupní barvy, okraj znaku se zobrazí ve ztmaveném stavu.

O výstupní barvě

V předchozích tipech jsme použili dva vzory prolnutí k zobrazení textu jako příkladu. Na druhou stranu krásný průsvitný text se zobrazil podle očekávání. Na druhou stranu byly okraje textu ztmaveny. Je to proto, že vzorec pro výstup barvy se liší v závislosti na použitém stavu prolnutí.

Nastavte parametry výrazu na

  • výsledek: Výsledná výstupní barva
  • zdroj : Barva textury, kterou se pokoušíte nakreslit
  • destination : Barva pozadí destinace
  • RGBA: Složky R (červená), G (zelená), B (modrá) a A (alfa (krytí))

A jak je definováno, výpočetní vzorec pro dva stavy prolnutí je následující.

BlendState.AlphaBlend (výchozí hodnota null) (vynásobená alfa)
result = source.rgb + destination.rgb * (1 - source.a) // Zdroj.rgb je však již použit v alfa verzi.
BlendState.NonPremultiplied (interpolovaný alfa)
result = source.rgb * source.a + destination.rgb * (1 - source.a)

Ve skutečnosti, pokud to najdete pomocí tohoto vzorce, hodnota výsledku bude v obou případech stejná. Pokud ale používáte bilineární filtrování, výše uvedené výpočty se provedou po barevné interpolaci se sousedními obrazovými body v pixel shaderu, takže konečný výstupní výsledek bude jiný.

Rád bych kvůli tomu udělal nějaké výpočty. Pokud je barva textu bílá (Color.White), bude každá barevná složka pixelu, ve kterém je text zobrazen (r:255, g:255, b:255, a:255). Obrazové body, které nezobrazují text, jsou (r:0, g:0, b:0, a:0). Pokud uděláme text poloprůhledný na 50 % a interpolujeme jej mezihodnotou těchto dvou pixelů (tj. okrajem znaku), jak výše uvedené dvě rovnice změní výsledek?

Mimochodem, barva pozadí je (r:0, g:0, b:255, a:255). (Výpočty se provádějí na bílém textu a modrém pozadí)

Interpolace pomocí BlendState.AlphaBlend (vynásobená alfa)

Vzhledem k tomu, že alfa je aplikována na každý prvek barvy textu předem, barva textu se sníží na polovinu o 255 (r:128, g:128, b:128, a:128) (Color.White * 0,5f"). Obrazové body, které nemají zobrazený text, se ponechají tak, jak jsou (r:0, g:0, b:0, a:0).

Vzhledem k tomu, že vzorec bilineárního filtru se provádí před tím, než stav prolnutí vypočítá barvu pozadí, barva okraje textu je (r:64, g:64, b:64, a:64), což je střední hodnota mezi (r:128, g:128, b:128, a:128) a (r:0, g:0, b:0, a:0).

Zde výraz

  • result = zdroj.rgb + cíl.rgb * (1 - zdroj.a)

Pokud jej použijete na:

  • výsledek = (r:64, g:64, b:64) + (r:0, g:0, b:255) * (1 - 0,25)      // 0,25 znamená, že a:64 je 25 % z a:255

a výsledná složená barva s barvou pozadí je (r:64, g:64, b:255).

Interpolace pomocí metody BlendState.NonPremultiplied (interpolovaná alfa)

Barva textu je bílá (r:255, g:255, b:255) a pouze alfa je zmenšena na polovinu, aby byl poloprůhledný, takže hodnota obrazového bodu, ve kterém je znak zobrazen, je (r:255, g:255, b:255, a:128) (nová barva(255, 255, 255, 128)). Obrazové body, které nezobrazují text, zůstávají stejné (r:0, g:0, b:0, a:0).

Vzhledem k tomu, že vzorec bilineárního filtru se provádí před tím, než stav prolnutí vypočítá barvu pozadí, barva okraje textu je (r:128, g:128, b:128, a:64), což je střední hodnota mezi (r:0, g:0, b:0, a:0).

Zde výraz

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

Pokud jej použijete na:

  • výsledek = (r:128, g:128, b:128) * 0,25 + (r:0, g:0, b:255) * (1 - 0,25)

a výsledná složená barva s barvou pozadí je (r:32, g:32, b:224).

úvaha

Vzhledem k tomu, že barva pozadí je (r:0, g:0, b:255), interpolace pomocí metody BlendState.AlphaBlend (r:64, g:64, b:255) umožňuje krásně vyjádřit průhlednou barvu textu bez ztráty pigmentu barvy pozadí. V případě interpolace pomocí metody BlendState.NonPremultiplied (r:32, g:32, b:224) je však modrá složka tmavší než barva pozadí, takže okraje textu se zdají být ztmavlé (samozřejmě).
Červená, zelená je tmavší než BlendState.AlphaBlend.)

Tato výchozí násobená alfa verze z XNA Framework 4.0 je podrobně popsána v blogu "Hinikeni XNA", takže pokud se chcete dozvědět více, podívejte se na odkaz níže. Tam je to popsáno jako příklad kreslení červeného prvku na bílém pozadí.

Všechny kódy

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