2010-10-03 6 views
7

Si j'utilise les éléments suivantsY a-t-il une valeur alpha qui rend le blanc invisible?

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

Je l'effet de l'objet en utilisant cette couleur pour dessiner avec allant du noir à un gris clair et invisible lorsque la valeur alpha va à zéro. Cependant, si je commence par une valeur blanche:

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

Les objets ne deviennent jamais invisibles et restent uniquement blancs. J'ai aussi remarqué que si j'utilise une valeur un peu plus claire que le noir (disons 50, 50, 50) le dessin va de Dark, à invisible, à White.

Je suppose que je ne comprends pas comment fonctionne le mélange alpha, mais y a-t-il un moyen de faire passer la couleur blanche à la translucidité?

Edit: Le fond je dessine sur est Color.CornflowerBlue (100.149.237.255)

Edit: Exemple de programme XNA reproduisant l'explication. Utiliser; créer un nouveau projet XNA Game Studio 4.0 - Windows Game (4.0), appelez AlphaBlendTest - & Dans le projet de contenu ajouter un nouveau SpriteFont et appelez-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); 
    } 
} 
} 

Edit: Ceci est l'image de ce code dessine: Editer: L'un des commentaires est concerné par le fait qu'il s'agit d'une «fonctionnalité» liée au texte de Windows. J'ai utilisé le texte comme exemple pour garder le programme de démonstration petit; tester avec une image donne le même résultat. alt text

Pour ajouter la case carrée dans le programme de démonstration; Créez une image PNG carrée blanche et ajoutez-la au répertoire de contenu (utilisez les valeurs par défaut pour le pipeline de contenu). Puis ajouter à la classe:

Texture2D tWhiteBox; 

Ajouter ceci dans la méthode de charge:

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

ensuite au tirage au sort ajouter ce qui suit ci-dessous les autres déclarations draw:

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

Maintenant que vous avez de meilleures réponses, je suis tenté de supprimer le mien ... mais juste pour vérifier, est-ce que cela arrive avec des objets * autres que du texte *? –

+0

Oui; J'ai simplement utilisé Draw String dans l'exemple pour ne pas avoir besoin de télécharger une texture pour le programme de test simple ;-) Pour tester cela, j'ai utilisé une image qui est juste une boîte blanche et ensuite dessiner, en utilisant les différentes couleurs l'instruction draw changera alors sa couleur. –

Répondre

11

Le gris est ce que vous obtiendrez dans XNA 4.0 (ou blanc complet si vous essayez simplement d'ajuster le canal alpha sans ajuster les canaux RVB aussi). La transparence est effectuée (par défaut) en utilisant l'alpha pré-multiplié. Si vous recherchez l'ancien comportement XNA 3.1 non-pré-mul, consultez ce post de Shawn Hargreaves: http://blogs.msdn.com/b/shawnhar/archive/2010/04/08/premultiplied-alpha-in-xna-game-studio-4-0.aspx. Au bas du message, il vous indique comment le faire.

Je vous recommande de lire tous ses messages sur l'alpha pré-multiplié avant de le faire (vous pouvez utiliser le "Blog Index" lien sur le côté gauche près du haut de sa page) - pré-mul est vraiment un beaucoup mieux et beaucoup plus logiquement cohérent.

+2

Merci, cet article a eu la réponse. Si je remplace le code que j'utilise avec ceci: WhiteTransparent = Color.White * 0.5f; Je reçois une image blanche transparente à 50%. 0f entièrement transparent et 1f complètement blanc. De la poste Shawn indique que le code pour définir les couleurs de transparence a changé et l'ancien code devrait lancer une erreur de compilation; Cependant, aucune erreur de compilation n'est levée lors de la définition de la valeur alpha avec le reste de la couleur, selon le code avec lequel j'ai eu un problème. Merci pour votre aide. –

+0

Merci @SebastianGray pour l'épeler. –

0

Si le noir devient "gris clair" quand il est semi-transparent, ce qui suggère que vous avez un fond blanc ... à quel point, une couleur blanche entièrement transparente sur le dessus sera toujours blanche. Essayez d'utiliser votre objet blanc sur un fond de couleur différente - rouge, par exemple - ce qui devrait le faire passer du blanc (alpha = 255) au rose (alpha = 127) au rouge juste (alpha = 0).

+0

Pour tester le fond sur lequel je dessine est Color.CornflowerBlue (100,149,237,255). J'essaie de faire fonctionner quelque chose que je peux utiliser sur un fond multicolore. –

+0

Aussi j'ai testé sur un fond rouge et utilisé une valeur de couleur fixe de couleur (255, 255, 255, 0); La couleur de l'objet en cours de dessin était blanche. –

+0

@Sebastian: J'aurais * prévu * que ça se passe alors. Pourriez-vous nous fournir un programme de test court mais complet afin que nous puissions vérifier qu'il ne se passe rien d'autre? Si vous pouviez l'essayer sur une API plus simple à tester (par exemple WPF), cela serait également utile ... même si je comprends bien que nous devrons évidemment travailler sur WP7 aussi. –

2

Il s'agit d'une limitation historique, au moins sur Windows. Les primitives GDI, comme DrawTextEx ne prennent pas en charge la transparence. Ils vont simplement ignorer le canal alpha. Cette restriction est résolue par les bibliothèques graphiques comme GDI + et Milcore. Mais il n'y a qu'un seul moteur de rendu TrueType et il fait un travail trop trivial pour être facilement remplacé. Votre capture d'écran montre qu'il s'exécute dans une fenêtre Windows normale, donc la restriction est très susceptible de s'appliquer. Je ne sais pas si c'est différent sur une console.

Une solution de contournement possible consiste à utiliser une fonction similaire à GraphicsPath.AddString(). Vous perdrez cependant l'effet anti-aliasing ClearType. Pas si sûr que ça compte dans XNA.Je ne le connais pas assez pour suggérer l'équivalent de GraphicsPath.

+0

Je ne pense pas que la limitation à laquelle vous faites référence soit présente dans XNA. J'ai ajouté une capture d'écran mise à jour et le code du test pour utiliser une image. A l'origine j'ai remarqué ce comportement sur une image mais un exemple de texte est le plus petit projet de démo que je pourrais rapidement rassembler, merci quand même. –

1

Je pense que cela a quelque chose à voir avec les paramètres de bleding Alpha pour SpriteBatch.

La valeur par défaut est BlendState.AplhaBlend. Cela a la formule BackgroundColor * (1-Alpha) + ForegroundColor. Cela expliquerait différents comportements avec le noir et blanc. Essayez la méthode spriteBatch.Begin différente avec BlendState.NonPremultiplied pour obtenir le résultat souhaité. Cela se traduira par: BackgroundColor * (1-Alpha) + ForegroundColor * Aplha, rendant même blanc complètement transparent.

+0

Le démarrage de spriteBatch.Draw avec BlendState.NonPremultiplied a rendu les sprites totalement invisibles avec le canal alpha défini sur 255. –