Comment puis-je rendre de façon procédurale des barres de santé de forme irrégulière?

35

Le problème des barres de santé traditionnelles rectangulaires ou cardiaques est bien compris et facilement résolu. Mais quelle est la solution acceptée pour des barres de santé plus "créatives", comme la maquette que j'ai faite ci-dessous?

Santé vide Santé complète, santé partielle

La manière évidente de le faire serait d’avoir des sprites «entre-deux», la troisième image serait donc son propre sprite, ainsi que de nombreuses autres transitions pour différents niveaux de santé. Mais cela semble vraiment inélégant et le nombre d'intermédiaires nécessaires pour créer une transition en douceur entre les états de santé serait élevé.

La seule autre idée que je puisse proposer est de superposer le sprite "santé complète" au-dessus du sprite "santé vide" et d'ensembles de coordonnées de pixels pré-cuisson pour représenter chaque tick de santé et les rendre ensuite opaques ou transparents. monte ou descend.

Je souhaite que cette question soit indépendante de la langue et de la plate-forme, mais n'hésitez pas à fournir un échantillon concret dans n'importe quelle langue / bibliothèque / structure si cela aide la réponse.

msd7734
la source
5
"Na̶n̶o̶m̶achi̶n̶e̶s Shaders, fils"
Mukesh Ingham Le
Je me sens comme cette transition pourrait être définie mathématiquement, à partir de là vous pouvez avoir le calcul de l' ordinateur les coordonnées de pixels pour afficher / masquer plutôt que de les précuisson
Richard Tingle
Comment la barre de santé en forme de coeur est-elle "facilement résolue"?
MooseBoys
1
@ MooseBoys Je parlais de santé basée sur le coeur, pas en forme de coeur. Pensez à la légende des jeux Zelda. Désolé de ne pas être plus clair.
msd7734
@RichardTingle, bonne idée :)
Jon Le

Réponses:

48

Il existe un moyen très simple de réaliser cela avec les shaders, il faut trois * textures: barre de santé vide, texture de barre de santé et masque avec un gradient de répartition de la santé avec un extrême (par exemple, la valeur alpha la plus sombre non noire ou la plus transparente) et autre à l'autre bout. C’est le mieux indiqué sur l’image. Je ne suis actuellement pas en mesure de dessiner un dégradé courbe linéaire, mais je suis sûr que vos artistes n’auront aucun problème: à entrez la description de l'image ici présent, dans le shader, échantillonnez les textures et limitez la valeur du masque, en supprimant plus lumineux que le seuil d'entrée (basé sur le pourcentage d'intégrité du shader).
Vous pourriezutilisez une formule mathématique pour masquer au lieu d'une texture, mais si vous agissiez ainsi, vous seriez toujours très limité aux formes que vous êtes capables (= simples) de créer avec lesdites formules - et en trouver une n'est pas trivial.
* voir les commentaires

mervera
la source
9
Dans de nombreux cas (y compris l'exemple du PO), utiliser une texture distincte pour la couleur est excessif. Dans la plupart des cas, vous pouvez simplement reconfigurer le dégradé du masque en niveaux de gris en couleurs spécifiées comme étant uniformes dans le shader, tout en ignorant les valeurs de masque inférieures à un certain seuil.
bcrist
1
En réalité, vous n'avez pas besoin du plus sombre ni du noir, vous pouvez utiliser le canal alpha pour éliminer les pixels que vous ne souhaitez pas.
Jack Aidley
1
@JackAidley, bien sûr, cela serait possible, mais je voulais une solution aussi flexible que possible - dans la plupart des titres AAA, vous n'avez pas seulement le hp «rouge», mais il est texturé.
Merveilleux
1
@bcrist bon point, j'ai envisagé de le suggérer comme une optimisation. Mais comme je ne pouvais pas le dessiner correctement, j'ai décidé de le garder aussi simple que possible et de laisser l'optimisation pour la mise en œuvre.
Merveilleux
@wondra Dans de nombreux cas, dont l'exemple dans l'OP, vous pouvez utiliser un dégradé de procédure ou une recherche de couleur unidimensionnelle (avec le niveau de masque en entrée), plutôt qu'une texture.
Random832
34

Implémenté mathématiquement, en tant que pixel shader:

Sur la CPU, calculez la HealthDirection et son produit scalaire avec V2 entrez la description de l'image ici

Sur le GPU, calculez une direction normalisée à l’écart du point central pour chaque pixel. Comparez chaque produit scalaire à HealthDirections pour choisir entre ombrer "fond" ou en couleur. entrez la description de l'image ici

Si vous "inversiez" cet algorithme et si vous travailliez dans l'autre sens, vous pourriez "dé-caler" la direction de chaque pixel en pourcentage et les comparer à HealthPercent à la place. Avec le pourcentage calculé de chaque pixel, le passage du rouge au vert sur le GPU devient trivial.

Dessinez d'abord la barre en appliquant l'algorithme à un quad; les couleurs de sortie entre rangeMin et rangeMax (peuvent être cuites) et clip () ou une sortie transparente partout. Ensuite, dessinez le sprite (modifié) dessus, en utilisant alpha. J'ai tracé votre barre en CAO, l'inondé, puis "magiquement" la forme de couleur unie dans Paint pour la supprimer. Le mien ressemble à de la merde à cause du mélange manuel d'AutoCAD et de Paint; en admettant que les bords intérieurs soient transparents, le vôtre sera parfait .

La bordure blanche correspond aux limites du quad. Il et les X rouges sont pour référence seulement:

entrez la description de l'image ici

Le "sprite avec trou" n'a pas besoin d'être rendu en même temps que la barre de santé. Ils devraient être instanciés et tirés au sort en même temps, une fois toutes les barres de santé remplies. Étant donné que l'algorithme est autonome dans le shader, vous pouvez également y ajouter une instance, puis dessiner toutes les barres de santé avec un seul appel de dessin instancié. Dessiner chaque barre de santé à l'écran devrait prendre 2 appels DrawInstanced (...) et être "fou rapide".

Jon
la source
1
Si vous envisagez de masquer de manière circulaire, vous pouvez le mettre en œuvre plus efficacement en modifiant simplement les triangles que vous tracez pour un fondu circulaire.
Jack Aidley
@JackAidley, veuillez être plus précis, car je ne considère pas ce masquage; la barre de progression est entièrement rendue, en place, sur deux triangles uniquement, sans échantillonnage, après le premier passage. Il se trouve que le lutin a un trou dans le trou et "met joliment" tout en place à la fin. (C'est un masque de toutes sortes, mais pas en tant que partie intégrante de l'algorithme?) Merci
Jon
Ce que vous faites équivaut à dessiner une version masquée de la barre de couleur sur un sprite d’arrière-plan qui a déjà la couleur grise en place. Parce que votre méthode nécessite un shader personnalisé et écrit sur chaque pixel, vous obtenez une méthode plus lente que de dessiner uniquement la partie souhaitée de la forme.
Jack Aidley
@ JackAidley, mais il n'y a pas de sprite de fond? L'arc-en-ciel est dessiné en utilisant seulement quatre positions mondiales float3; pas d'UV, pas de "sprite d'arrière-plan". De plus, vous craignez que le pixel shader ne s'embourbe pour travailler sur de minuscules quads? De plus, RangeMin et RangeMax coupent instantanément la plupart de ces fragments.
Jon
Vous aurez besoin d'un sprite d'arrière-plan pour obtenir les bordures indiquées dans l'image d'origine. si vous les omettez, alors, oui, les méthodes sont différentes.
Jack Aidley