Qual é um bom método para colorir texturas com base em uma paleta no XNA?

8

Eu tenho tentado trabalhar em um jogo com a aparência de um jogo de 8 bits usando o XNA, especificamente usando o NES como um guia.

O NES possui uma paleta muito específica e cada sprite pode usar até 4 cores dessa paleta. Como eu poderia imitar isso? A maneira atual de conseguir isso é que tenho uma textura com valores definidos que atuam como índices para uma matriz de cores que passo para a GPU. Eu imagino que deve haver uma maneira melhor do que isso, mas talvez seja a melhor maneira?

Eu não quero simplesmente garantir que eu desenhe todos os sprites com as cores certas, porque quero poder alterar dinamicamente a paleta. Eu também preferiria não alterar a textura diretamente usando a CPU.

Prumo
fonte

Respostas:

7

Eu acho que você está bem.

Se você tiver mais de quatro cores, sugiro fazer uma leitura dependente da textura: Em vez de usar o valor da textura para procurar uma matriz de cores (suponho que você esteja passando esses parâmetros como parâmetros de sombreador), você pode usá-lo para procurar uma cor em outra textura 1D contendo sua paleta.

Mas isso tem algumas implicações de desempenho - e acho que limita você ao PS 2.0.

(Existem outras otimizações sorrateiras possíveis se você tiver que mudar de paleta a cada sprite e todos os lotes extras estiverem prejudicando o desempenho. Mas eu imagino que em um jogo do tipo NES, esse não é o caso.)

Acho que o que pode ser útil na sua situação é usar o pipeline de conteúdo XNA para obter uma versão em cores do sprite facilmente editável, verifique se ele usa apenas quatro cores, converta-o em uma textura com seus quatro níveis de escala de cinza (utilizável pelo seu shader) e talvez também produza a paleta de cores original ao lado da textura.

As amostras do Clube dos criadores do pipeline de conteúdo podem ser um bom ponto de partida.

Andrew Russell
fonte
11
+1 O canal de conteúdo pode ser seu amigo algumas vezes. Use-o para sua vantagem.
22611 Michael Coleman
1

Seria mais lento criar uma classe composta que pode conter até 4 objetos que são uma de cada cor para o sprite e combiná-lo no sprite que é desenhado. Portanto, cada sprite é um composto de até 4 sprites combinados e desenhados.

Então você pode mudar uma cor por essa classe e todo o sprite mudará.

(observe, eu não fiz o XNA, mas isso pode gerar algumas idéias para você.)

Ólafur Waage
fonte
1

Se você não se importa com o desempenho da memória, pode armazenar seus sprites descompactados, de modo que os pixels com a cor 0 sejam vermelho puro, 1 verde puro, 2 azuis azuis e 3 alfa alfa.

Quando estiver prestes a renderizar um sprite, defina uma constante de sombreador de pixel da matriz composta por quatro vetores que correspondem às cores 0, 1, 2, 3. No sombreador de pixel, execute o seguinte código para recolorir o texel do sprite:

float4 unpaletted = tex2D( texture, uv );
float4 paletted = mul( unpaletted, paletteMatrix );

Isso funciona porque quando um pixel é da cor 0, é vermelho puro e, portanto, acaba como

1 * palette[0] + 0 * palette[1] + 0 * palette[2] + 0 * palette[3]

ou

1 * palette[0]

e o mesmo se aplica às cores 1, 2 e 3.

Se você se preocupa com o desempenho da memória, armazene sua paleta NES como uma textura não compactada RGB de 256x1, defina a filtragem de textura como a vizinha mais próxima, armazene seus sprites como texturas de canal único de 8 bits não compactadas e faça um código de sombreamento semelhante a isto :

float palette_index = tex2D( texture, uv );
float4 color = tex1D( palette, palette_index * 255 );
bmcnett
fonte