Renderização correta de cores de retroconsoles em emuladores



Quase todos os retro-consoles de jogos geram cores em algumas opções de codificação RGB.

Mas essas cores de pixel geralmente são projetadas para telas completamente diferentes daquelas em que os emuladores geralmente trabalham. Neste artigo, falarei sobre a importância da emulação de cores, darei alguns exemplos de código e capturas de tela.

O tipo mais comum de telas hoje em dia são os painéis LCD. Eles são conhecidos por terem níveis muito baixos de preto. As diferenças entre TN, PVA e IPS não afetam muito isso.

Alguns fãs jogam em monitores CRT, e as telas OLED estão ganhando cada vez mais popularidade, especialmente em telefones e tablets. Porém, neste artigo, consideraremos principalmente as telas de LCD, embora essa técnica seja importante para exibições de qualquer tipo.

Precisão de cores


O primeiro detalhe importante: a maioria dos computadores opera no modo de cores de 24 bits, fornecendo detalhes de cores de 8 bits para os canais vermelho, verde e azul. Mas na maioria dos sistemas de jogos antigos, as cores não são definidas com tanta precisão.

Por exemplo, o Sega Genesis codifica cores de 9 bits, o que fornece 3 bits por canal.

A solução mais ingênua seria colocar 3 bits nos 3 bits mais altos da saída e deixar os 5 bits inferiores em branco, mas a cor branca se tornaria um pouco cinza.

Um exemplo:

  000 000 000 -> 000'00000 000'00000 000'00000
 111 111 111 -> 111'00000 111'00000 111'00000 



Se você as preencher com unidades, o preto ficará muito claro.

Um exemplo:

  000 000 000 -> 000'11111 000'11111 000'11111
 111 111 111 -> 111'11111 111'11111 111'11111 



A solução é repetir os bits originais para que eles preencham todos os bits de saída.

Um exemplo:

  000 -> 000 000 00 ...
 010 -> 010 010 01 ...
 011 -> 011 011 01 ...
 111 -> 111 111 11 ... 

Sob a forma de código:

  uint8 vermelho = r << 5 |  r << 2 |  r >> 1
 // rrr00000 |  000rrr00  000000rr -> rrrrrrrr 

Emulação de tela


Os sistemas de jogos retro não foram projetados para funcionar em monitores modernos de computador LCD. Normalmente, os consoles domésticos eram projetados para telas CRT, e os consoles portáteis usavam painéis LCD muito mais antigos e menos precisos.

Neste artigo, não consideraremos artefatos de tela, como curvatura da tela, linhas de varredura, aberração cromática, mesclagem entre quadros, grades de abertura, etc .: por enquanto, focaremos apenas as cores dos pixels individuais.

Monitores para PC


Os monitores têm uma gama bastante ampla de cores, porque apenas alguns deles são calibrados profissionalmente para padrões como SRGB, mas, em geral, o melhor que podemos fazer é emular cores como se estivéssemos usando um monitor SRGB calibrado corretamente.

Emulação CRT: Super Nintendo


A principal diferença entre telas CRT e monitores LCD de computadores é o nível de preto significativamente reduzido, que pode ser apenas ligeiramente compensado pela curva de correção gama:

  // As cores do SNES estão no formato RGB555, então existem 32 níveis para cada canal
 const estática u8 gammaRamp [32] = {
   0x00,0x01,0x03,0x06,0x0a 0x0f 0x15,0x1c
   0x24, 0x2d, 0x37, 0x42, 0x4e, 0x5b, 0x69, 0x78,
   0x88,0x90,0x98,0xa0,0xa8,0xb0,0xb8,0xc0
   0xc8,0xd0,0xd8,0xe0,0xe8,0xf0,0xf8,0xff
 }; 

Esta tabela é emprestada de Overload of Super Sleuth / Kindred. Ele obscurece a metade inferior da paleta de cores, mantendo a parte superior inalterada.

Isso tem um efeito incrível na imagem durante a emulação: o original é mostrado à esquerda, a imagem com correção de gama aplicada à direita:





Emulação de LCD: Game Boy Advance


A Game Boy Advance tinha uma das piores telas de LCD com cores completamente desbotadas. Os desenvolvedores astutos perceberam que, ao exagerar significativamente as cores, é possível obter resultados mais agradáveis ​​em equipamentos reais.

Obviamente, se você usar essas cores em um monitor LCD padrão, o resultado será um pesadelo colorido. Felizmente, podemos compensar isso criando cores bastante naturais:

  lcdGamma duplo = 4,0, outGamma = 2,2;
 lb duplo = pow (B / 31.0, lcdGamma);
 lg duplo = pow (G / 31.0, lcdGamma);
 lr duplo = pow (R / 31.0, lcdGamma);
 r = pow ((0 * lb + 50 * log + 255 * lr) / 255, 1 / outGamma) * (0xffff * 255/280);
 g = pow ((30 * lb + 230 * lg + 10 * lr) / 255, 1 / outGamma) * (0xffff * 255/280);
 b = pow ((220 * lb + 10 * log + 50 * lr) / 255, 1 / outGamma) * (0xffff * 255/280); 

Este pedaço de código foi escrito por Talarubi.

Um contraste muito mais impressionante em comparação com um CRT - o topo é o original, o fundo é a versão com correção de cores:





Emulação de LCD: Game Boy Color


A tela Game Boy Color foi surpreendentemente melhor na reprodução de cores, e apenas um leve borrão de cor pode estar presente na imagem final.

O algoritmo a seguir é bastante popular nos emuladores Game Boy Color:

  R = (r * 26 + g * 4 + b * 2);
 G = (g * 24 + b * 8);
 B = (r * 6 + g * 4 + b * 22);
 R = min (960, R) >> 2;
 G = min (960, G) >> 2;
 B = min (960, B) >> 2; 

Infelizmente, não sei quem escreveu o algoritmo. Se você souber, me avise para que eu possa indicar autoria!

Como antes, o original à esquerda, a versão com correção de cores - à direita:



Este exemplo foi escolhido especialmente: embora o original pareça mais animado e preferível, se você olhar com atenção, poderá observar o padrão de xadrez ao redor do personagem, que é mais claro que o fundo.

Provavelmente, foi um descuido por parte dos desenvolvedores, porque no jogo real
Os tons Boy Color em branco ficam embaçados e dois tons diferentes se mesclam quase sem falhas.

Em conclusão


Existem muitos outros sistemas que ainda carecem de bons filtros de emulação de cores.
Eles são muito difíceis de configurar. Entre os exemplos mais importantes estão WonderSwan e Neo Geo Pocket, que na época desta redação não possuíam bons filtros para a aproximação de cores.

Os consoles portáteis são ainda mais complicados porque geralmente não têm luz de fundo (e às vezes luz frontal!). E há várias maneiras de alterar o contraste, portanto, não há um valor de cor real para um valor RGB específico.

Um caso de fronteira particularmente interessante é o WonderSwan Color, que possui um sinalizador definido por software para aumentar o contraste da imagem exibida.
Ainda não sabemos como imitar esse comportamento de maneira confiável, e não está claro se podemos fazê-lo.

A emulação de cores é uma área que requer mais atenção; portanto, se você é especialista em matemática e análise de cores, sua ajuda seria muito útil para a cena de emulação!

Source: https://habr.com/ru/post/pt467581/


All Articles