Quelle est la bonne méthode pour colorer des textures basées sur une palette dans XNA?


8

J'ai essayé de travailler sur un jeu avec l'apparence d'un jeu 8 bits utilisant XNA, en utilisant spécifiquement NES comme guide.

Le NES a une palette très spécifique et chaque sprite peut utiliser jusqu'à 4 couleurs de cette palette. Comment pourrais-je imiter cela? La façon dont j'accomplis ceci est que j'ai une texture avec des valeurs définies qui agissent comme des index d'un tableau de couleurs que je passe au GPU. J'imagine qu'il doit y avoir un meilleur moyen que cela, mais c'est peut-être le meilleur moyen?

Je ne veux pas simplement m'assurer de dessiner chaque image-objet avec les bonnes couleurs, car je veux pouvoir modifier dynamiquement la palette. Je préférerais également ne pas modifier la texture directement en utilisant le CPU.

Réponses:


7

Je pense que ce que vous faites est très bien.

Si vous aviez plus de quatre couleurs, je pourrais suggérer de lire une texture dépendante: Au lieu d'utiliser la valeur de la texture pour rechercher un tableau de couleurs (je suppose que vous les passez comme paramètres de shader), vous pouvez l'utiliser pour rechercher une couleur dans une autre texture 1D contenant votre palette.

Mais cela a des implications en termes de performances - et je pense que cela vous limite à la PS 2.0.

(Il existe d'autres optimisations sournoises possibles si vous devez changer de palette à chaque sprite et que tous les lots supplémentaires réduisent les performances. Mais j'imagine que dans un jeu de type NES, ce n'est pas le cas.)

Je pense que ce qui pourrait être utile dans votre situation est d'utiliser le pipeline de contenu XNA pour prendre une version couleur facilement modifiable du sprite, vérifiez qu'il n'utilise que quatre couleurs, convertissez-le en une texture avec vos quatre niveaux de gris (utilisable par votre shader), et peut-être aussi sortir la palette de couleurs d'origine à côté de la texture.

Les exemples Creators Club pour le pipeline de contenu peuvent être un bon point de départ.


1
+1 Le pipeline de contenu peut parfois être votre ami. Utilisez-le à votre avantage.
Michael Coleman

1

Serait-ce trop lent pour créer une classe composite qui peut contenir jusqu'à 4 objets qui sont une de chaque couleur pour le sprite et combiner cela dans le sprite qui est dessiné. Ainsi, chaque sprite est un composite de jusqu'à 4 sprites combinés puis dessinés.

Ensuite, vous pouvez changer 1 couleur via cette classe et le sprite entier changerait.

(Remarque, je n'ai pas fait de XNA mais cela pourrait susciter des idées avec vous.)


1

Si vous ne vous souciez pas du tout des performances de la mémoire, vous pouvez stocker vos images-objets non compressées de sorte que les pixels de couleur 0 soient du rouge pur, 1 du vert pur, 2 du bleu pur et 3 de l'alpha pur.

Au moment de rendre un sprite, définissez une constante de pixel shader de matrice composée de quatre vecteurs qui correspondent aux couleurs 0, 1, 2, 3. Dans le pixel shader, exécutez le code suivant pour recolorer le texel de sprite:

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

Cela fonctionne parce que lorsqu'un pixel est de couleur 0, il est rouge pur, et il finira donc par

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

ou

1 * palette[0]

et il en va de même pour les couleurs 1, 2 et 3.

Si vous vous souciez des performances de la mémoire, stockez votre palette NES en tant que texture non compressée 256x1 RVB, définissez le filtrage de texture sur le plus proche voisin, stockez vos sprites en tant que textures monocanal 8 bits non compressées et faites du code shader quelque chose comme ceci :

float palette_index = tex2D( texture, uv );
float4 color = tex1D( palette, palette_index * 255 );
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.