Faire fondre toute la scène en niveaux de gris

20

Lorsque le joueur perd toute sa vie, je veux que tout l'écran du jeu passe en niveaux de gris, mais ne cesse pas de mettre à jour immédiatement. Je préférerais également qu'il se fane en niveaux de gris au lieu de perdre soudainement toute couleur. Tout ce que j'ai trouvé jusqu'à présent consiste soit à prendre une capture d'écran et à la rendre en niveaux de gris, soit à créer une texture spécifique en niveaux de gris. Existe-t-il un moyen de changer l'ensemble du terrain de jeu et tous les objets à l'intérieur en niveaux de gris sans itérer à travers tout?

Fibericon
la source

Réponses:

23

La façon la plus simple de le faire est de créer un shader (voir le code ci-dessous). Dessinez tout sur une cible de rendu, puis utilisez le shader pour le dessiner dans votre tampon arrière

Dans votre enregistrement de code de jeu lorsque le joueur meurt, puis dans les rendus suivants, interpolez un paramètre de shader entre 1 (couleur) et 0 (pleine échelle de gris) selon
CurrentTime-DeadTime / FadeTime

float ColourAmount;
Texture coloredTexture;

sampler coloredTextureSampler = sampler_state
{
    texture = <coloredTexture>;
};

float4 GreyscalePixelShaderFunction(float2 textureCoordinate : TEXCOORD0) : COLOR0
{
    float4 color = tex2D(coloredTextureSampler, textureCoordinate); 
    float3 colrgb = color.rgb;
    float greycolor = dot(colrgb, float3(0.3, 0.59, 0.11));

    colrgb.rgb = lerp(dot(greycolor, float3(0.3, 0.59, 0.11)), colrgb, ColourAmount);

    return float4(colrgb.rgb, color.a);
}

technique Grayscale
{
    pass GreyscalePass
    {
        PixelShader = compile ps_2_0 GreyscalePixelShaderFunction();
    }
}

La raison de 0,3, 0,59 et 0,11 est que l'œil humain ne traite pas les couleurs de la même manière, ces valeurs donnent une meilleure image en niveaux de gris.

George Duckett
la source
Il y a quelque temps, je convertissais rgb en gris mais je n'ai pas trouvé de source fiable, j'ai donc utilisé 1.0 / 3,1.0 / 3,1.0 / 3 ... Pouvez-vous fournir une source pour les constantes numériques 0.2.0.59,0.11?
Trevor Boyd Smith
J'ai essayé de trouver d'où je tirais le code, mais je n'ai pas pu le trouver. Voici une page de développeur de valve qui utilise des valeurs différentes (mais vaguement similaires) (0,222, 0,707, 0,071).
George Duckett
1
Voici une référence pour les valeurs qui prend en charge les numéros de vanne mais répertorie les deux. poynton.com/notes/colour_and_gamma/ColorFAQ.html#RTFToC9
Adam
1
Il y a une question sur les coefficients de niveaux de gris sur stackoverflow: stackoverflow.com/questions/5311774/…
Exilyth
je peux confirmer que ce shader a fonctionné pour moi dans XNA 4.0
Roboblob
0

MODIFIER

Après y avoir pensé, si vous ne mettez pas de teinte sur quoi que ce soit, mais en utilisant les couleurs originales des graphiques, vous pouvez simplement avoir (comme je le dis ci-dessous) toutes vos couleurs d'objets dessinés définies sur une variable de couleur déclarée définie sur blanc. (Color NoTint = Color.White;) puis Lerp que si le joueur vit est égal à zéro. Chaque objet dessiné avec la couleur NoTint changera lentement (selon votre taux d'interpolation mentionné ci-dessous) en ce que vous le lirez.

Cependant, si vous avez des teintes différentes sur différents objets, la boucle foreach ci-dessous peut fonctionner.

Fin de la modification

À ma connaissance limitée, j'essaierais ceci: Déclarez les couleurs que vous utilisez pour dessiner des objets spécifiques, ex. Couleur catColor = Color.Brown, puis ajoutez toutes les couleurs de vos jeux à une liste.

public static Color catColor = Color.Brown;
List<Color> colorList = new List<Color>(){ catColor }; // and other colors
float interpolation = 0f;
float interpolationRate = .01f;
.
.
.
if(playerLives == 0) 
{
   interpolation += interpolationRate;
   if (interpolation >= 1)
      {interpolation = 1;}

   foreach(Color c in colorList)
   {
      Color.Lerp(c, Color.Gray, interpolation);
   }
}

Vous pouvez même le faire pour les éléments que vous dessinez sans teinte et lerp le Color.White à un Color.Gray. (nommez quelque chose comme Color NoTint = Color.White et mettez-le sur tous vos objets dessinés)

Il y a probablement une meilleure façon, même si j'espère que cela aide!

AndrewAchilles
la source
1
-1 Cela ferait fondre tout l'écran en une seule couleur unie, pas la transformerait en niveaux de gris. L'échelle de gris mesure une couleur par sa luminosité (la couleur percevant différentes couleurs comme ayant des luminosités différentes), elle n'est pas seulement à mi-chemin entre une couleur et le gris (qui a toujours de la couleur).
doppelgreener
Excellent. J'espère que quelqu'un d'autre en tirera des leçons comme moi. Merci!
AndrewAchilles