Je travaille sur un jeu ressemblant à Megaman où je dois changer la couleur de certains pixels au moment de l'exécution. Pour référence : dans Megaman, lorsque vous changez d'arme sélectionnée, la palette du personnage principal change pour refléter l'arme sélectionnée. Toutes les couleurs du sprite ne changent pas, seulement certaines changent .
Ce type d’effet était courant et assez facile à faire sur la NDA puisque le programmeur avait accès à la palette et au mappage logique entre les pixels et les index de la palette. Sur un matériel moderne, cependant, cela pose un peu plus de problèmes car le concept de palettes n’est pas le même.
Toutes mes textures sont en 32 bits et n'utilisent pas de palettes.
Je sais qu'il existe deux manières d'obtenir l'effet souhaité, mais je suis curieux de savoir s'il existe de meilleurs moyens d'obtenir cet effet facilement. Les deux options que je connais sont:
- Utilisez un shader et écrivez du GLSL pour effectuer le comportement "permutation de palette".
- Si les shaders ne sont pas disponibles (par exemple, car la carte graphique ne les prend pas en charge), il est alors possible de cloner les textures "originales" et de générer différentes versions avec les modifications de couleur pré-appliquées.
Idéalement, j'aimerais utiliser un shader, car il semble simple et nécessite peu de travail supplémentaire par rapport à la méthode de duplication de texture. Je crains que la duplication de textures juste pour changer une couleur en elles gaspille de la VRAM - ne devrais-je pas m'en inquiéter?
Edit : J'ai fini par utiliser la technique de la réponse acceptée et voici mon shader pour référence.
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;
}
Les deux textures sont 32 bits, une texture est utilisée comme table de correspondance contenant plusieurs palettes de la même taille (dans mon cas, 6 couleurs). J'utilise le canal rouge du pixel source comme index de la table des couleurs. Cela a fonctionné comme un charme pour réaliser la permutation de palette à la Megaman!
Je peux penser à cela de deux manières.
Voie n ° 1: GL_MODULATE
Vous pouvez faire le sprite en nuances de gris et
GL_MODULATE
la texture quand il est dessiné avec une seule couleur unie.Par exemple,
Cela ne vous permet pas beaucoup de souplesse, cependant, vous ne pouvez aller que dans les tons plus clairs et plus foncés de la même teinte.
Voie n ° 2:
if
énoncer (mauvais pour la performance)Vous pouvez également colorer vos textures avec des valeurs clés impliquant R, G et B. Ainsi, par exemple, la première couleur est (1,0,0), la deuxième couleur est (0,1,0), la troisième la couleur est (0,0,1).
Vous déclarez un couple d'uniformes comme
Ensuite, dans le shader, la couleur finale du pixel est similaire à
color1
,color2
,color3
, Sont uniformes afin qu'ils puissent être réglés avant l'exécution de shaders ( en fonction de ce que Megaman « costume » est), le Shader ne fonctionne tout simplement le reste.Vous pouvez également utiliser des
if
instructions si vous avez besoin de plus de couleurs, mais le contrôle d'égalité doit fonctionner correctement (les textures sont généralementR8G8B8
comprises entre 0 et 255 dans le fichier de texture, mais dans le shader, vous avez des flotteurs rgba).Voie n ° 3: Stockez simplement de manière redondante les différentes images colorées dans la carte des images-objets
C'est peut-être le moyen le plus simple, si vous n'essayez pas follement de conserver de la mémoire
la source
J'utiliserais des shaders. Si vous ne souhaitez pas les utiliser (ou ne pouvez pas les utiliser), choisissez une texture (ou une partie d'une texture) par couleur et n'utilisez que du blanc net. Cela vous permettra de teinter la texture (par exemple à travers
glColor()
) sans que vous ayez à vous soucier de créer des textures supplémentaires pour les couleurs. Vous pouvez même échanger des couleurs à la volée sans travail de texture supplémentaire.la source
"Toutes les couleurs du sprite ne changent pas, seulement certaines changent."
Les vieux jeux faisaient des tours de palette parce que c'était tout ce qu'ils avaient. De nos jours, vous pouvez utiliser plusieurs textures et les combiner de différentes manières.
Vous pouvez créer une texture de masque en niveaux de gris séparée que vous utiliserez pour déterminer les pixels qui changeront de couleur. Les zones blanches dans la texture reçoivent la modification complète de la couleur et les zones noires restent inchangées.
En langue de shader:
Vous pouvez également utiliser la multi-texturation à fonction fixe avec différents modes de combinateur de texture.
Il y a évidemment beaucoup de façons différentes de s'y prendre. vous pouvez placer des masques de différentes couleurs dans chacun des canaux RVB ou moduler les couleurs en décalant la teinte dans un espace colorimétrique HSV.
Une autre option, peut-être plus simple, consiste à dessiner simplement l'image-objet en utilisant une texture distincte pour chaque composant. Une texture pour les cheveux, une pour l'armure, une pour les bottes, etc. Chaque couleur peut être teinte séparément.
la source
Premièrement, on parle généralement de cyclisme (cycle de palette), ce qui pourrait donc aider votre Google-fu.
Cela dépendra exactement des effets que vous voulez produire et si vous utilisez du contenu 2D statique ou des éléments 3D dynamiques (par exemple, voulez-vous simplement gérer les effets de sélection / textures, ou restituer une scène 3D entière puis un échange de palette)? Aussi, si vous vous limitez à un nombre de couleurs ou utilisez la couleur.
Une approche plus complète, utilisant des shaders, consisterait à produire des images indexées par couleur avec une texture de palette. Faire une texture mais au lieu d'avoir des couleurs, avoir une couleur qui représente un index à rechercher puis une autre texture de couleurs qui est la plaque. Par exemple, le rouge pourrait être la coordonnée t des textures, et le vert pourrait être la coordonnée s. Utilisez un shader pour faire la recherche. Et animer / modifier les couleurs de cette texture de palette. Ce serait assez proche de l'effet rétro mais ne fonctionnerait que pour du contenu 2D statique tel que des sprites ou des textures. Si vous réalisez de véritables graphismes rétro, vous pourrez peut-être produire des sprites de couleur indexés réels et écrire quelque chose pour les importer et les palettes.
Vous voudrez également déterminer si vous allez utiliser une palette «globale». Comme si un ancien matériel fonctionnait, moins de mémoire pour les palettes car vous n’avez besoin que d’une seule, mais plus difficile à produire, car vous devez synchroniser la palette sur toutes les images) ou attribuer à chaque image sa propre palette. Cela vous donnerait plus de flexibilité mais utiliserait plus de mémoire. Bien sûr, vous pouvez faire les deux, mais vous ne pouvez utiliser que des palettes pour les éléments pour lesquels vous effectuez un cycle de couleurs. Déterminez également dans quelle mesure vous ne voudriez pas limiter vos couleurs, les anciens jeux en utilisant 256 couleurs par exemple. Si vous utilisez une texture, vous obtiendrez le nombre de pixels de sorte qu'un 256 * 256 vous donnera
Si vous voulez simplement un effet factice bon marché, tel que de l’eau qui coule, vous pouvez créer une seconde texture contenant un masque en niveaux de gris masquant la zone que vous souhaitez modifier, puis utilisez les textures mastiquées pour modifier la teinte / saturation / luminosité de la valeur dans le fond. texture de masque en niveaux de gris. Vous pouvez être encore plus paresseux et ne changer que la teinte / luminosité / saturation de tout ce qui se trouve dans une gamme de couleurs.
Si vous en aviez besoin en 3D, vous pourriez essayer de générer l'image indexée à la volée, mais le processus serait lent, car vous auriez à regarder la palette, vous seriez probablement limité dans la gamme de couleurs.
Sinon, vous pouvez simplement le simuler dans le shader, si l’échange de couleur ==, changez-le. Cela serait lent et ne fonctionnerait qu'avec un nombre limité de couleurs permutantes, mais il ne faut pas insister sur le matériel actuel, en particulier si vous ne vous occupez que de graphismes 2D et que vous pouvez toujours marquer les sprites dont les couleurs sont échangées et utiliser un shader différent.
Sinon, faites-leur vraiment beaucoup, faites un tas de textures animées pour chaque état.
Voici une excellente démonstration du cyclisme sur palette réalisée en HTML5 .
la source
Je pense que les ifs sont assez rapides pour que l'espace colorimétrique [0 ... 1] soit divisé en deux:
De cette façon, les valeurs de couleur comprises entre 0 et 0,5 sont réservées aux valeurs de couleur normales; et 0.5 - 1.0 sont réservés aux valeurs "modulées", où 0.5..1.0 est mappé sur toute plage sélectionnée par l'utilisateur.
Seule la résolution de couleur est tronquée de 256 valeurs par pixel à 128 valeurs.
On peut probablement utiliser des fonctions intégrées telles que max (color-0.5f, 0.0f) pour supprimer complètement les ifs (en les échangeant en multiplications par zéro ou un ...).
la source