Puoliläpinäkyvän tekstin näyttäminen

Sivu päivitetty :
Sivun luontipäivämäärä :

yhteenveto

Tee tekstistä puoliläpinäkyvä.

半透明の文字を表示する

Toimintaympäristö

Edellytykset

Tuetut XNA-versiot
  • 4.0
Tuetut alustat
  • Windows (XP SP2 tai uudempi, Vista, 7)
  • Xbox 360
  • Windows Phone 7
Windowsin vaatima Vertex Shader -versio 2.0
Windowsin vaatima Pixel Shader -versio 2.0

Toimintaympäristö

lava
  • Windows 7
  • Xbox 360
  • Windows Phone 7 -emulaattori

aine

Käyttämällä peittävyyttä 0,0 ~ 1,0 SpriteBatch.DrawString-menetelmän määrittämään värirakenteeseen voit piirtää tekstin puoliläpinäkyvänä. Suurinta osaa värirakenteen ominaisuuksissa jo määritellyistä väreistä ei ole asetettu läpinäkymättömiksi, joten ne voidaan tehdä puoliksi läpinäkyviksi peittävyyden avulla.

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

Color rakentaja

Aseta väri. Siellä on myös 0.0 ~ 1.0 kelluva rakentaja.

r tavu Määritä punainen väri 0 ~ 255: stä.
g tavu Määritä vihreäksi väriksi 0 ~ 255.
b tavu Määritä sininen väri 0 ~ 255.
a tavu Määritä opasiteetti (alfakomponentti) arvosta 0 ~ 255.

Muuten, menetelmä spritien läpikuultavan värin määrittämiseksi on muuttunut XNA Framework 4.0: n jälkeen, ja jotta voidaan määrittää muoto, kuten "new Color(255, 255, 255, 192)", jota käytetään XNA Framewrok 3.1: ssä ja aikaisemmin, sinun on määritettävä SpriteBatchin sekoitustila "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));

Koska lähtövärin laskentakaavaa on kuitenkin muutettu, merkin reuna näytetään tummennetussa tilassa.

Tietoja tulostusväristä

Edellisissä vinkeissä käytimme kahta sekoitusmallia tekstin näyttämiseen esimerkkinä. Toisaalta kaunis läpikuultava teksti näytettiin odotetusti. Toisaalta tekstin reunat tummenivat. Tämä johtuu siitä, että värin tulostuskaava vaihtelee käytetyn sekoitustilan mukaan.

Määritä lausekkeen parametreiksi

  • tulos: Lopullinen tulostusväri
  • lähde : Piirrettävän tekstuurin väri
  • kohde : kohteen taustaväri
  • RGBA: R:n (punainen), G:n (vihreä), B:n (sininen) ja A:n (alfa (opasiteetti)) komponentit

Ja kuten määritelty, kahden sekoitustilan laskentakaava on seuraava.

BlendState.AlphaBlend (oletusarvoinen nolla) (kerrottu alfa)
tulos = source.rgb + destination.rgb * (1 - source.a) // Source.rgb on kuitenkin jo alfa-käytössä
BlendState.NonPremultiplied (interpoloitu alfa)
tulos = source.rgb * source.a + destination.rgb * (1 - source.a)

Itse asiassa, jos löydät sen tällä kaavalla, tuloksen arvo on sama molemmissa tapauksissa. Jos kuitenkin käytät bilineaarista suodatusta, yllä olevat laskelmat suoritetaan värien interpoloinnin jälkeen vierekkäisten pikselien kanssa pikselivarjostimessa, joten lopullinen lähtötulos on erilainen.

Haluaisin tehdä joitakin laskelmia sen vuoksi. Jos tekstin väri on valkoinen (Color.White), jokainen tekstiruudun värikomponentti, jossa teksti näytetään, on (r:255, g:255, b:255, a:255). Pikselit, jotka eivät näytä tekstiä, ovat (r:0, g:0, b:0, a:0). Jos teemme tekstistä puoliksi läpinäkyvän 50%: lla ja interpoloimme sen näiden kahden pikselin väliarvoon (eli merkin reunaan), miten yllä olevat kaksi yhtälöä muuttavat tulosta?

Taustaväri on muuten (r:0, g:0, b:255, a:255). (Laskelmat suoritetaan valkoisella tekstillä ja sinisellä taustalla)

Interpolointi BlendState.AlphaBlendin kanssa (kerrottu alfa)

Koska alfaa käytetään tekstin värin jokaiseen elementtiin etukäteen, tekstin väri puolittuu 255: llä (r: 128, g: 128, b: 128, a: 128) (väri.valkoinen * 0.5f"). Pikselit, joissa ei näy tekstiä, jätetään ennalleen (r:0, g:0, b:0, a:0).

Koska bilineaarinen suodatinkaava suoritetaan ennen kuin sekoitustila laskee taustavärin, tekstin reunan väri on (r:64, g:64, b:64, a:64), joka on väliarvo (r:128, g:128, b:128, a:128) ja (r:0, g:0, b:0, a:0).

Tässä ilmaisu

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

Jos käytät sitä:

  • tulos = (r:64, g:64, b:64) + (r:0, g:0, b:255) * (1 - 0,25)      // 0,25 osoittaa, että a:64 on 25% arvosta a:255

ja lopullinen yhdistelmäväri taustavärin kanssa on (R:64, G:64, B:255).

Interpolointi BlendState.NonPremultipliedin kanssa (interpoloitu alfa)

Tekstin väri on valkoinen (r:255, g:255, b:255), ja vain alfa puolitetaan, jotta se olisi puoliksi läpinäkyvä, joten pikselin arvo, jossa merkki näytetään, on (r:255, g:255, b:255, a:128) (uusi väri(255, 255, 255, 128)). Pikselit, jotka eivät näytä tekstiä, pysyvät samoina (r:0, g:0, b:0, a:0).

Koska bilineaarinen suodatinkaava suoritetaan ennen kuin sekoitustila laskee taustavärin, tekstin reunan väri on (r:128, g:128, b:128, b:128, a:64), joka on väliarvo välillä (r:0, g:0, b:0, a:0).

Tässä ilmaisu

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

Jos käytät sitä:

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

Ja viimeinen komposiittiväri taustavärin kanssa on (R:32, G:32, B:224).

harkinta

Koska taustaväri on (r:0, g:0, b:255), interpolointi BlendState.AlphaBlendin (r:64, g:64, b:255) kanssa mahdollistaa tekstin läpinäkyvän värin kauniin ilmaisun menettämättä taustavärin pigmenttiä. Kuitenkin, jos interpoloidaan BlendState.NonPremultipliedin kanssa (r:32, g:32, b:224), sininen komponentti on tummempi kuin taustaväri, joten tekstin reunat näyttävät tummuneen (tietysti).
Punainen, vihreä on tummempi kuin BlendState.AlphaBlend.)

Tämä XNA Framework 4.0: n oletuskerroin alfa on kuvattu yksityiskohtaisesti blogissa "Hinikeni XNA", joten jos haluat tietää enemmän, katso alla oleva linkki. Siellä sitä kuvataan esimerkkinä punaisen elementin piirtämisestä valkoista taustaa vasten.

Kaikki koodit

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