Como processar processualmente barras de saúde com formas irregulares?


35

A questão da barra de saúde tradicional retangular ou baseada no coração é algo bem compreendido e facilmente resolvido. Mas qual é a solução aceita para mais barras de saúde "de forma criativa", como a maquete que fiz abaixo?

Saúde vazia Saúde completa, saúde parcial

A maneira óbvia de fazer isso seria ter sprites "intermediários", para que a terceira imagem fosse seu próprio sprite, juntamente com muitas outras transições para diferentes níveis de saúde. Mas isso parece realmente deselegante e o número de entres necessários para criar uma transição suave entre os estados de saúde seria grande.

A única outra idéia que posso ter é sobrepor o sprite de "saúde completa" em cima do sprite de "saúde vazia" e pré-assar conjuntos de coordenadas de pixel para representar cada marca de saúde e torná-las opacas ou transparentes como saúde sobe ou desce.

Pretendo que esta pergunta seja independente da linguagem e da plataforma, mas fique à vontade para fornecer uma amostra concreta em qualquer idioma / biblioteca / estrutura, se isso ajudar na resposta.


5
"N̶a̶n̶o̶m̶a̶c̶h̶i̶n̶e̶s̶ Shaders, filho"
— Mukesh Ingham

Eu sinto que essa transição pode ser definida matematicamente, a partir daí você pode ter a calcular computador as coordenadas de pixel para exibir / ocultar em vez de prebaking deles
— Richard Tingle

Como a barra de saúde em forma de coração é "facilmente resolvida"?
— MooseBoys 28/02

11
@MooseBoys Eu estava falando sobre saúde baseada no coração, não em forma de coração. Pense nos jogos Legend of Zelda. Desculpe por não ser mais claro.
— 28416 msd7734

@RichardTingle, boa idéia :)
— Jon

Respostas:


48

Existe uma maneira muito simples de conseguir isso com shaders, você precisa de três * texturas: barra de saúde vazia, textura e barra de saúde vazias e máscara com gradiente de distribuição de saúde com um extremo (por exemplo, valor alfa mais escuro, não preto ou mais transparente alfa) em uma extremidade e o outro do outro lado. É melhor mostrado na imagem. Atualmente, não consigo desenhar gradiente curvo apenas um linear - mas tenho certeza de que seus artistas não terão problemas: insira a descrição da imagem aqui Agora, no shader, experimente ambas as texturas e limpe o valor da máscara, descartando todos os pixels que não são mais brilhante que o limite de entrada (com base na% de entrada de shader da saúde).
Você poderiause uma fórmula matemática para mascarar em vez de uma textura, mas se você fizer isso, ainda estará muito limitado às formas que você é capaz (= formas simples) de criar com as referidas fórmulas - e encontrar uma não é trivial.
* ver comentários


9
Em muitos casos (incluindo o exemplo do OP), usar uma textura separada para cores é um exagero. Na maioria dos casos, você pode remapear apenas o gradiente da máscara em escala de cinza para cores especificadas como uniformes no sombreador, enquanto ainda descarta qualquer valor da máscara abaixo de um determinado limite.
— bcrist

11
Na verdade, você não precisa mais escuro, nem preto; pode usar o canal alfa para filtrar os pixels que não deseja.
— Jack Aidley

11
@JackAidley com certeza seria possível, mas eu queria a solução o mais flexível possível - na maioria dos títulos AAA, você não tem o hp apenas "vermelho", mas é texturizado.
— 284166Preço

11
@bistist bom ponto, considerei sugeri-lo como uma otimização. Como não consegui desenhá-lo corretamente, decidi mantê-lo o mais simples possível e deixar a otimização para implementação.
— 284166Preço

@wondra Em muitos casos, incluindo a aparência de exemplo no OP, você pode usar um gradiente de procedimento ou uma pesquisa de cores unidimensional (com o nível da máscara como entrada), em vez de uma textura.
— Random832

34

Implementado matematicamente, como um pixel shader:

Na CPU, calcule o HealthDirection e seu 'produto pontual com V2 insira a descrição da imagem aqui

Na GPU, calcule uma direção normalizada para longe do ponto central de cada pixel. Compare cada produto de ponto com o HealthDirections 'para escolher se sombrear "fundo" ou em cores. insira a descrição da imagem aqui

Se você "inverteu" esse algoritmo e trabalhou na outra direção, poderá "desamarrar" a direção de cada pixel novamente em uma porcentagem e compará-los ao HealthPercent. Com o percentual de cada pixel calculado, a execução do desbotamento de vermelho para verde na GPU se torna trivial.

Desenhe a barra primeiro aplicando o algoritmo a um quad; cores de saída entre rangeMin e rangeMax (pode ser cozido) e clip () ou transparentes em todos os lugares. Em seguida, desenhe o sprite (modificado) sobre ele, usando alfa. Rastreei sua barra em CAD, a preenchi e depois "variei mágica" a forma da cor sólida no Paint para excluí-la. O meu parece uma merda devido à mistura manual do AutoCAD e do Paint; supondo que você combine as bordas internas com transparências, a sua ficará perfeita .

A borda branca é o limite do quad. Ele e os X vermelhos são apenas para referência:

insira a descrição da imagem aqui

O "sprite com furo" não precisa ser renderizado ao mesmo tempo que a barra de saúde. Eles devem ser instanciados e desenhados de uma só vez, depois que todas as barras de saúde estiverem completas. Como o algoritmo é independente no sombreador, você também pode adicionar instancias a ele e desenhar também todas as barras de saúde com uma chamada de instanciação. Desenhar todas as barras de saúde na tela deve receber 2 chamadas DrawInstanced (...) e ser "louco rápido".


11
Se você deseja mascarar de maneira circular como essa, pode implementá-lo de forma mais eficiente, alterando os triângulos que você planeja para um desbotamento circular.
— Jack Aidley

@JackAidley, por favor, seja mais específico, porque não considero essa máscara; a barra de progresso é totalmente renderizada, no lugar, em apenas dois triângulos, sem amostragem, após a primeira passagem. O sprite tem um buraco nele e "encanta" a coisa toda no final. (É uma máscara do tipo, mas não como parte integrante do algoritmo?) Obrigado
— Jon

O que você está fazendo é equivalente a desenhar uma versão mascarada colorida da barra colorida sobre um sprite de fundo que já tem a cor cinza no lugar. Como seu método requer um sombreador personalizado e grava em cada pixel, você acaba com um método mais lento do que desenhar apenas a parte desejada da forma.
— Jack Aidley

@JackAidley, mas não há sprite em segundo plano? O arco-íris é desenhado usando apenas quatro posições mundiais float3; sem UV, sem "sprite de fundo". Além disso, você está preocupado com o fato de o pixel shader ficar atolado trabalhando em alguns quadríceps minúsculos? Além disso, RangeMin e RangeMax cortam () a maioria desses fragmentos instantaneamente.
— 28416 Jon

Você precisará de um sprite de fundo para obter as bordas, como mostra a imagem original; se você os omitir, sim, os métodos são diferentes.
— Jack Aidley
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.