Fazendo a cena inteira desaparecer em escala de cinza

20

Quando o jogador perde a vida toda, quero que a tela do jogo fique em escala de cinza, mas não pare de atualizar imediatamente. Eu também preferiria desbotar em escala de cinza em vez de perder repentinamente todas as cores. Tudo o que encontrei até agora é sobre tirar uma captura de tela e torná-la em escala de cinza ou criar uma textura específica em escala de cinza. Existe uma maneira de alterar todo o campo de jogo e todos os objetos dentro para escala de cinza sem percorrer tudo?

Fibericon
fonte

Respostas:

23

A maneira mais fácil de fazer isso é criar um shader (consulte o código abaixo). Desenhe tudo para um destino de renderização e use o sombreador para desenhar isso no seu buffer traseiro

No registro do código do jogo, quando o jogador morre, nas renderizações subsequentes interpola um parâmetro de sombreador entre 1 (cores) e 0 (escala de cinza completa) de acordo com
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();
    }
}

A razão para 0,3, 0,59 e 0,11 é porque o olho humano não trata as cores da mesma forma; esses valores proporcionam uma imagem em escala de cinza melhor.

George Duckett
fonte
Há um tempo atrás eu estava convertendo rgb para cinza, mas não consegui encontrar uma fonte confiável, então usei 1.0 / 3,1.0 / 3,1.0 / 3 ... Você pode fornecer uma fonte para as constantes numéricas 0.2,0.59,0.11?
Trevor Boyd Smith
Eu tenho tentado encontrar de onde obtive o código, mas não consegui encontrá-lo. Aqui está uma página do desenvolvedor de válvulas que usa valores diferentes (mas vagamente semelhantes) (0,222, 0,707, 0,071).
George Duckett
1
Aqui está uma referência para os valores que suportam os números da válvula, mas lista ambos. poynton.com/notes/colour_and_gamma/ColorFAQ.html#RTFToC9
Adam
1
Há uma pergunta sobre os coeficientes de escala de cinza no stackoverflow: stackoverflow.com/questions/5311774/…
Exilyth
Posso confirmar este shader trabalhou para mim em XNA 4.0
Roboblob
0

EDITAR

Depois de pensar sobre isso, se você não estiver pintando nada, mas usando as cores originais dos gráficos, você poderá ter (como eu declaro abaixo) todas as cores de objetos desenhados configuradas para uma variável declarada Color definida como branca. (Color NoTint = Color.White;) e depois Lerp que, se o jogador vive, é igual a zero. Todo objeto desenhado com a cor NoTint muda lentamente (de acordo com a taxa de interpolação mencionada abaixo) para o que você estiver lendo.

No entanto, se você tiver matizes diferentes em objetos diferentes, o loop foreach abaixo poderá funcionar.

Finalizar edição

No meu conhecimento limitado, eu tentaria o seguinte: Declare as cores que você usa ao desenhar objetos específicos, ex. Cor catColor = Color.Brown e adicione todas as cores dos seus jogos a uma lista.

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

Você pode até fazer isso para itens desenhados sem matiz e ler novamente o Color.White para um Color.Gray. (nomeie algo como Color NoTint = Color.White e coloque isso em todos os seus objetos desenhados)

Provavelmente existe uma maneira melhor, independentemente, espero que isso ajude!

AndrewAchilles
fonte
1
-1 Isso desbota a tela inteira para uma cor sólida, não a torna em escala de cinza. A escala de cinza mede uma cor pelo seu brilho (com a cor percebendo cores diferentes como tendo brilho diferente), não fica apenas na metade do caminho entre uma cor e o cinza (que ainda possui cor).
Doppelgreener 19/03/12
Excelente. Espero que alguém aprenda com isso como eu. Obrigado!
AndrewAchilles