¿Cuál es un buen método para colorear texturas basadas en una paleta en XNA?

8

He estado tratando de trabajar en un juego con el aspecto de un juego de 8 bits usando XNA, específicamente usando el NES como guía.

El NES tiene una paleta muy específica y cada sprite puede usar hasta 4 colores de esa paleta. ¿Cómo podría emular esto? La forma actual de lograr esto es que tengo una textura con valores definidos que actúan como índices de una matriz de colores que paso a la GPU. Me imagino que debe haber una mejor manera que esta, pero ¿tal vez esta es la mejor manera?

No quiero simplemente asegurarme de dibujar cada sprite con los colores correctos porque quiero poder alterar dinámicamente la paleta. También preferiría no alterar la textura directamente usando la CPU.

Beto
fuente

Respuestas:

7

Creo que lo que estás haciendo está bien.

Si tuviera más de cuatro colores, le sugiero que haga una lectura de textura dependiente: en lugar de usar el valor de la textura para buscar una matriz de colores (supongo que los pasa como parámetros de sombreado), puede usarlo para buscar un color en otra textura 1D que contiene su paleta.

Pero esto tiene algunas implicaciones de rendimiento, y creo que lo limita a PS 2.0.

(Hay algunas otras optimizaciones furtivas posibles si tienes que cambiar paletas cada sprite y todos los lotes adicionales están matando el rendimiento. Pero imagino que en un juego similar a NES este no es el caso).

Creo que lo que podría ser útil en su situación es usar la canalización de contenido XNA para tomar una versión en color fácilmente editable del sprite, verificar que solo use cuatro colores, convertirlo en una textura con sus cuatro niveles de escala de grises (utilizable por su sombreador), y quizás también muestre la paleta de colores original junto con la textura.

Las muestras de Creators Club para la canalización de contenido podrían ser un buen lugar para comenzar.

Andrew Russell
fuente
1
+1 La canalización de contenido puede ser tu amigo a veces. Úselo para su ventaja.
Michael Coleman el
1

Sería lento para crear una clase compuesta que pueda contener hasta 4 objetos que son uno de cada color para el sprite y combinarlo en el sprite que se dibuja. Entonces cada sprite es un compuesto de hasta 4 sprites combinados y luego dibujados.

Entonces podría cambiar 1 color a través de esa clase y todo el sprite cambiaría.

(nota, no he hecho XNA pero esto podría generar algunas ideas contigo).

Ólafur Waage
fuente
1

Si no le importa en absoluto el rendimiento de la memoria, puede almacenar sus sprites sin comprimir de modo que los píxeles con el color 0 sean rojo puro, 1 sea verde puro, 2 sean azul puro y 3 sean alfa puro.

Cuando esté a punto de representar un sprite, establezca un sombreador de píxeles de matriz constante formado por cuatro vectores que correspondan a los colores 0, 1, 2, 3. En el sombreador de píxeles, ejecute el siguiente código para volver a colorear el texto del sprite:

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

Esto funciona porque cuando un píxel es de color 0, es de color rojo puro, por lo que terminará como

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

o

1 * palette[0]

y lo mismo se aplica a los colores 1, 2 y 3.

Si le importa el rendimiento de la memoria, guarde su paleta NES como una textura sin comprimir RGB de 256x1, configure el filtrado de textura en el vecino más cercano, almacene sus sprites como texturas de un solo canal sin comprimir de 8 bits y haga un código de sombreador como este :

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