Como faço para a transparência alfa corretamente no XNA 4.0?

14

Ok, eu li vários artigos, tutoriais e perguntas sobre isso. A maioria aponta para a mesma técnica que não resolve o meu problema. Eu preciso da capacidade de criar sprites semi-transparentes (texture2D's realmente) e tê-los sobrepondo outro sprite.

Posso conseguir isso de alguma forma com os exemplos de código que encontrei, mas não estou satisfeito com os resultados e sei que há uma maneira de fazer isso. Na programação móvel (BREW), fizemos a velha escola e, na verdade, verificamos cada pixel quanto à transparência antes da renderização.

Nesse caso, parece tornar o sprite abaixo dele misturado com o alfa acima dele. Isso pode ser um artefato de como estou renderizando a textura, mas, como eu disse antes, todos os exemplos apontam para essa técnica. Antes de prosseguir, vou colar o meu código de exemplo.

    public void Draw(SpriteBatch batch, Camera camera, float alpha)
    {
        int tileMapWidth = Width;
        int tileMapHeight = Height;

        batch.Begin(SpriteSortMode.Texture,
            BlendState.AlphaBlend,
            SamplerState.PointWrap,
            DepthStencilState.Default,
            RasterizerState.CullNone,
            null, camera.TransformMatrix);

        for (int x = 0; x < tileMapWidth; x++)
        {
            for (int y = 0; y < tileMapHeight; y++)
            {
                int tileIndex = _map[y, x];

                if (tileIndex != -1)
                {
                    Texture2D texture = _tileTextures[tileIndex];

                    batch.Draw(
                        texture,
                        new Rectangle(
                            (x * Engine.TileWidth),
                            (y * Engine.TileHeight),
                            Engine.TileWidth,
                            Engine.TileHeight),
                        new Color(new Vector4(1f, 1f, 1f, alpha )));
                }
            }
        }

        batch.End();

    }

Como você pode ver, neste código eu estou usando o método SpriteBatch.Begin sobrecarregado que leva, entre outras coisas, um estado de mistura. Estou quase certo de que esse é o meu problema. Eu não quero misturar os sprites, quero que eles sejam transparentes quando alfa for 0. Neste exemplo, eu posso definir alfa como 0, mas ainda renderiza os dois blocos, com o sprite z ordenado aparecendo, descolorido por causa do Misturando. Este não é um efeito desejado, quero que o sprite com ordem z mais elevado desapareça e não afete a cor abaixo dele dessa maneira.

Eu posso estar longe daqui, já que sou bastante novo no desenvolvimento do XNA, então fique à vontade para me orientar na direção correta no caso de estar descendo pela toca do coelho errada.

TIA

Soshimo
fonte
Por que é alfa 'adequado'? Existe suporte alfa, e nenhum suporte alfa, certo?
O pato comunista
Você deve poder editar o título pressionando 'editar' e, em seguida, o título deve estar no topo. A menos que algo mude.
The Duck Comunista

Respostas:

18

Se eu seguir o problema corretamente, tente ligar para Begin with BlendState.NonPremultiplied. Este artigo também pode ajudar a esclarecer como funciona a mistura alfa no XNA:

https://web.archive.org/web/20130208130323/http://blogs.msdn.com/b/shawnhar/archive/2010/04/08/premultiplied-alpha-in-xna-game-studio-4- 0.aspx

Alex Schearer
fonte
Sim, parece que o NonPremultiplied fará o truque (pelo menos de acordo com o link que você postou). Vou esperar e ver se funciona quando chego em casa hoje à noite antes de aceitar, mas parece que esta é a resposta. Obrigado!
Soshimo 05/01
esse foi o truque. Eu não sabia que eles mudaram isso na versão 4.0. Esse artigo que você vinculou foi muito ilustrativo. Obrigado.
Soshimo 6/01/11
1
+1 Obrigado! Eu estava procurando on-line tentando descobrir por que o alfa estava funcionando apenas parcialmente. Isso resolveu. Os termos que eu estava usando no google eram Spritebatch Opacity, espero que esses termos agora ajudem os gogglers a encontrar essa resposta.
AttackingHobo
6

Concordo plenamente com a resposta de Alex, embora, se você seguir o alfa pré-multiplicado, acredito que você também possa fazê-lo dessa maneira

new Color(new Vector4(alpha, alpha, alpha, alpha ))

Shawn também fez um post explicando a diferença entre alfa pré-multiplicado e não-multiplicado - http://blogs.msdn.com/b/shawnhar/archive/2009/11/06/premultiplied-alpha.aspx

earok
fonte