Estou trabalhando em um jogo tipo Megaman , onde preciso alterar a cor de certos pixels em tempo de execução. Para referência : no Megaman, quando você muda sua arma selecionada, a paleta do personagem principal muda para refletir a arma selecionada. Nem todas as cores do sprite mudam, apenas algumas mudam .
Esse tipo de efeito era comum e bastante fácil de executar no NES, pois o programador tinha acesso à paleta e ao mapeamento lógico entre pixels e índices da paleta. No hardware moderno, porém, isso é um pouco mais desafiador, porque o conceito de paletas não é o mesmo.
Todas as minhas texturas são de 32 bits e não usam paletas.
Existem duas maneiras de obter o efeito desejado, mas estou curioso para saber se existem maneiras melhores de obter esse efeito facilmente. As duas opções que conheço são:
- Use um sombreador e escreva um GLSL para executar o comportamento de "troca de paleta".
- Se shaders não estiverem disponíveis (por exemplo, porque a placa gráfica não os suporta), é possível clonar as texturas "originais" e gerar versões diferentes com as alterações de cores pré-aplicadas.
Idealmente, eu gostaria de usar um sombreador, pois parece simples e requer pouco trabalho adicional em oposição ao método de textura duplicada. Eu me preocupo que duplicar texturas apenas para mudar uma cor esteja desperdiçando VRAM - não devo me preocupar com isso?
Edit : Acabei usando a técnica da resposta aceita e aqui está o meu shader para referência.
uniform sampler2D texture;
uniform sampler2D colorTable;
uniform float paletteIndex;
void main()
{
vec2 pos = gl_TexCoord[0].xy;
vec4 color = texture2D(texture, pos);
vec2 index = vec2(color.r + paletteIndex, 0);
vec4 indexedColor = texture2D(colorTable, index);
gl_FragColor = indexedColor;
}
Ambas as texturas são de 32 bits, uma textura é usada como tabela de pesquisa, contendo várias paletas do mesmo tamanho (no meu caso, 6 cores). Eu uso o canal vermelho do pixel de origem como um índice para a tabela de cores. Isso funcionou como um encanto para alcançar a troca de paletas tipo Megaman!