Есть ли альфа-значение, которое делает белый невидимым? - PullRequest
7 голосов
/ 03 октября 2010

Если я использую следующее

for(int i = 255; i > 0; i--)
{
    Color transparentBlack = new Color(0, 0, 0, i);
}

У меня есть эффект от объекта, использующего этот цвет для рисования при переходе от черного к светло-серому, а затем невидимого, когда значение альфа уменьшается до нуля. Однако, если я начну со значения белого:

new Color(255, 255, 255, i);

Объекты никогда не становятся невидимыми и остаются только белыми. Я также заметил, что если я использую значение, которое немного светлее черного (скажем, 50, 50, 50), рисунок переходит от Темного, к невидимому, к Белому.

Полагаю, я просто не понимаю, как работает альфа-смешение, но есть ли способ заставить белый цвет исчезнуть до полупрозрачности?

Редактировать: Фон, на котором я рисую, - это Color.CornflowerBlue (100,149,237,255)

Редактировать: Пример программы XNA, воспроизводящей объяснение. Использовать; создайте новый проект XNA Game Studio 4.0 - Windows Game (4.0), назовите его AlphaBlendTest - & В проекте содержимого добавьте новый SpriteFont и назовите его testfont

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;

namespace AlphaBlendTest
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;


    SpriteFont font;

    public Game1()
    {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";
    }

    /// <summary>
    /// Allows the game to perform any initialization it needs to before starting to run.
    /// This is where it can query for any required services and load any non-graphic
    /// related content.  Calling base.Initialize will enumerate through any components
    /// and initialize them as well.
    /// </summary>
    protected override void Initialize()
    {
        // TODO: Add your initialization logic here

        base.Initialize();
    }

    /// <summary>
    /// LoadContent will be called once per game and is the place to load
    /// all of your content.
    /// </summary>
    protected override void LoadContent()
    {
        // Create a new SpriteBatch, which can be used to draw textures.
        spriteBatch = new SpriteBatch(GraphicsDevice);

        font = Content.Load<SpriteFont>("testfont");
    }

    /// <summary>
    /// UnloadContent will be called once per game and is the place to unload
    /// all content.
    /// </summary>
    protected override void UnloadContent()
    {
        // TODO: Unload any non ContentManager content here
    }

    /// <summary>
    /// Allows the game to run logic such as updating the world,
    /// checking for collisions, gathering input, and playing audio.
    /// </summary>
    /// <param name="gameTime">Provides a snapshot of timing values.</param>
    protected override void Update(GameTime gameTime)
    {
        // Allows the game to exit
        if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
            this.Exit();

        // TODO: Add your update logic here

        base.Update(gameTime);
    }

    /// <summary>
    /// This is called when the game should draw itself.
    /// </summary>
    /// <param name="gameTime">Provides a snapshot of timing values.</param>
    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);
        spriteBatch.Begin();

        //spriteBatch.Draw(tR, new Rectangle(100, 100, 100, 100), Color.Red);

        Vector2 v2 = new Vector2(0, 0);
        spriteBatch.DrawString(font, "Test - White", v2, Color.White);

        v2.Y = v2.Y + 50;

        spriteBatch.DrawString(font, "Test - Black", v2, Color.Black);

        v2.Y = v2.Y + 50;

        Color BlackTransparent = new Color(0, 0, 0, 0);
        spriteBatch.DrawString(font, "Test - Black Transparent", v2, BlackTransparent);

        v2.Y = v2.Y + 50;
        Color WhiteTransparent = new Color(255, 255, 255, 0);
        spriteBatch.DrawString(font, "Test - White Transparent", v2, WhiteTransparent);

        spriteBatch.End();

        base.Draw(gameTime);
    }
}
}

Редактировать: Это изображение, которое рисует этот код: alt text

Редактировать: Один из комментариев касается того, что это текстовая «особенность» окон. Я использовал текст в качестве примера, чтобы демонстрационная программа была маленькой; тестирование с изображением дает тот же результат. alt text

Чтобы добавить квадрат в демонстрационную программу; создайте квадратное белое изображение PNG и добавьте его в каталог содержимого (используйте значения по умолчанию для конвейера содержимого). Затем добавьте это в класс:

Texture2D tWhiteBox;

Добавьте это к методу загрузки:

tWhiteBox = Content.Load<Texture2D>("whitebox");

Затем в розыгрыше добавьте следующие остальные операторы розыгрыша:

v2.Y = v2.Y + 50;
spriteBatch.Draw(tWhiteBox, v2, WhiteTransparent);

Ответы [ 4 ]

11 голосов
/ 03 октября 2010

Серый цвет - это то, что вы получите в XNA 4.0 (или полностью белый, если вы попытаетесь просто настроить альфа-канал без настройки каналов RGB).Прозрачность выполняется (по умолчанию) с использованием предварительно умноженной альфы.Если вы ищете старое поведение, не относящееся к pre-mul XNA 3.1, посмотрите этот пост от Шона Харгривза: http://blogs.msdn.com/b/shawnhar/archive/2010/04/08/premultiplied-alpha-in-xna-game-studio-4-0.aspx.В нижней части поста рассказывается, как это сделать.

Я бы порекомендовал прочитать все его посты с предварительно умноженной альфа-версией перед тем, как сделать это (вы можете использовать ссылку "Индекс блога"слева вверху страницы) - премуль действительно намного лучше и намного логичнее.

2 голосов
/ 03 октября 2010

Это историческое ограничение, по крайней мере, для Windows.Примитивы GDI, такие как DrawTextEx, не поддерживают прозрачность.Они будут просто игнорировать альфа-канал.Это ограничение устраняется графическими библиотеками, такими как GDI + и Milcore.Но есть только один рендерер TrueType, и он делает работу слишком нетривиальной, чтобы ее легко было заменить.На скриншоте показано, что он работает в обычном окне Windows, поэтому весьма вероятно, что оно будет применено.Не уверен, что на консоли это не так.

Возможный обходной путь - использовать функцию, аналогичную GraphicsPath.AddString ().Однако вы потеряете эффект сглаживания ClearType.Не уверен, что это важно в XNA.Я не знаю этого достаточно хорошо, чтобы предложить эквивалент GraphicsPath.

1 голос
/ 03 октября 2010

Я думаю, что это как-то связано с настройками альфа-смешивания для SpriteBatch.

По умолчанию BlendState.AplhaBlend. Это имеет формулу BackgroundColor * (1-альфа) + ForegroundColor. Это объясняет различное поведение с черным и белым.

Попробуйте использовать другой метод spriteBatch.Begin с BlendState.NonPremultiplied, чтобы получить желаемый результат. Это приведет к: BackgroundColor * (1-альфа) + ForegroundColor * Aplha, делая даже белый полностью прозрачным.

0 голосов
/ 03 октября 2010

Если черный становится «светло-серым», когда он полупрозрачный, это говорит о том, что у вас есть белый фон ... в этот момент полностью прозрачный белый цвет, нанесенный поверх него, все равно будет белым.

Попробуйте использовать белый объект на другом цветном фоне, скажем, красном, что должно сделать его белым (альфа = 255), розовым (альфа = 127) и красным (альфа = 0).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...