¿Cómo puedo procesar procesalmente barras de salud de forma irregular?

35

El problema de la barra de salud tradicional rectangular o basada en el corazón es algo bien entendido y fácil de resolver. Pero, ¿cuál es la solución aceptada para más barras de salud de "forma creativa", como la maqueta que he hecho a continuación?

Salud vacía Salud completa, salud parcial

La forma obvia de hacer esto sería tener sprites "intermedios", por lo que la tercera imagen sería su propio sprite, junto con muchas otras transiciones para diferentes niveles de salud. Pero eso parece realmente poco elegante y el número de intermedios necesarios para crear una transición sin problemas entre los estados de salud sería grande.

La única otra idea que se me ocurre es superponer el sprite de "salud completa" en la parte superior del sprite de "salud vacía" y pre-hornear conjuntos de coordenadas de píxeles para representar cada tick de salud y luego hacerlos opacos o transparentes como salud. sube o baja

Tengo la intención de que esta pregunta sea independiente del lenguaje y la plataforma, pero siéntase libre de proporcionar una muestra concreta en cualquier idioma / biblioteca / marco si ayuda a la respuesta.

msd7734
fuente
55
"N̶a̶n̶o̶m̶a̶c̶h̶i̶n̶e̶s̶ Shaders, hijo"
Mukesh Ingham
Siento que esa transición podría definirse matemáticamente, a partir de ahí puede hacer que la computadora calcule las coordenadas de píxeles para mostrar / ocultar en lugar de pre
Richard Tingle
¿Cómo se "resuelve fácilmente" la barra de salud en forma de corazón?
MooseBoys
1
@MooseBoys Estaba hablando de salud basada en el corazón, no en forma de corazón. Piensa en los juegos de Legend of Zelda. Perdón por no ser más claro.
msd7734
@ RichardTingle, buena idea :)
Jon

Respuestas:

48

Hay una manera muy simple de lograr esto con sombreadores, necesita tres texturas *: barra de salud vacía, textura de barra de salud y máscara con gradiente de distribución de salud con un extremo (por ejemplo, el valor alfa más oscuro no negro o más transparente) en un extremo y el otro en otro extremo. Se muestra mejor en la imagen, actualmente no puedo dibujar un degradado curvo solo lineal, pero estoy seguro de que sus artistas no tendrán ningún problema: ingrese la descripción de la imagen aquí ahora, en la muestra de sombreado, ambas texturas y el umbral del valor de máscara, descartan todos los píxeles que no son más brillante que el umbral de entrada (basado en la entrada de salud% shader).
Usted podriause una fórmula matemática para enmascarar en lugar de una textura, pero si lo hiciera, todavía estaría muy limitado a las formas que puede (= simples) crear con dichas fórmulas, y encontrar una no es trivial.
* ver comentarios

wondra
fuente
99
En muchos casos (incluido el ejemplo del OP), usar una textura separada para el color es excesivo. En la mayoría de los casos, podría reasignar el degradado de la máscara de escala de grises a los colores especificados como uniformes en el sombreador, sin dejar de descartar los valores de máscara por debajo de un cierto umbral.
bcrist
1
En realidad, no necesita el más oscuro, no el negro, puede usar el canal alfa para eliminar los píxeles que no desea.
Jack Aidley
1
@JackAidley estaba seguro de que eso sería posible, pero quería que la solución fuera lo más flexible posible: en la mayoría de los títulos AAA no tienes HP solo "rojo" pero tiene textura.
wondra
1
@bcrist buen punto, consideré sugerirlo como una optimización. Pero no pude dibujarlo correctamente, así que decidí mantenerlo lo más simple posible y dejar la optimización para la implementación.
wondra
@wondra Para muchos casos, incluido el aspecto de ejemplo en el OP, puede usar un gradiente de procedimiento o una búsqueda de color unidimensional (con el nivel de máscara como entrada), en lugar de una textura.
Random832
34

Implementado matemáticamente, como un sombreador de píxeles:

En la CPU, calcule HealthDirection y su 'producto de punto con V2 ingrese la descripción de la imagen aquí

En la GPU, calcule una dirección normalizada lejos del punto central para cada píxel. Compare cada producto de puntos con HealthDirections 'para elegir si desea sombrear el "fondo" o el color. ingrese la descripción de la imagen aquí

Si "invirtió" este algoritmo y trabajó desde la otra dirección, podría "desangrar" la dirección de cada píxel nuevamente en un porcentaje y compararlos con HealthPercent. Con el porcentaje de cada píxel calculado, realizar el desvanecimiento de rojo a verde en la GPU se vuelve trivial.

Dibuje la barra primero aplicando el algoritmo a un quad; los colores de salida entre rangeMin y rangeMax (se pueden hornear) y clip () o salida transparente en cualquier otro lugar. Luego, dibuja el sprite (modificado) sobre él, usando alfa. Rastreé su barra en CAD, la llené de inundación, luego "la magia vagó" la forma de color sólido en Paint para eliminarla. El mío se ve como basura debido a la mezcla de AutoCAD y Paint, a mano; suponiendo que mezcle los bordes internos con transparente, el suyo se verá perfecto .

El borde blanco es el límite del quad. Esta y las X rojas son solo de referencia:

ingrese la descripción de la imagen aquí

El "sprite con agujero" no necesita ser renderizado al mismo tiempo que la barra de salud. Deben ser instanciados y dibujados todos a la vez, después de que todas las barras de salud estén completas. Dado que el algoritmo es autónomo en el sombreador, también puede agregar instancias y luego, también, dibujar todas las barras de salud con una llamada de dibujo instanciada. Dibujar cada barra de salud en la pantalla debe tomar 2 llamadas DrawInstanced (...) y ser "loco rápido".

Jon
fuente
1
Si vas a enmascarar de manera circular como esta, puedes implementarlo de manera más eficiente simplemente alterando los triángulos que trazas para un desvanecimiento circular.
Jack Aidley
@JackAidley, por favor sea más específico, porque no considero este enmascaramiento; la barra de progreso se representa completamente, en su lugar, en solo dos triángulos, sin muestreo, después de la primera pasada. El sprite simplemente tiene un agujero y "embellece" todo al final. (¿Es una especie de máscara, pero no como parte integral del algoritmo?) Gracias
Jon
Lo que está haciendo es equivalente a dibujar una versión enmascarada coloreada de la barra de color sobre un sprite de fondo que ya tiene el color gris en su lugar. Debido a que su método requiere un sombreador personalizado y escribe en cada píxel, termina con un método más lento que dibujar solo la parte deseada de la forma.
Jack Aidley
@JackAidley, pero no hay sprite de fondo? El arcoíris se dibuja utilizando solo cuatro posiciones mundiales float3; sin UV, sin "sprite de fondo". Además, ¿le preocupa que el sombreador de píxeles se empantane trabajando en algunos quads pequeños? Además, RangeMin y RangeMax recortan () la mayoría de esos fragmentos, al instante.
Jon
Necesitará un sprite de fondo para obtener los bordes como se muestra en la imagen original; Si está omitiendo estos, entonces, sí, los métodos son diferentes.
Jack Aidley