A melhor maneira de permitir que os jogadores “pintem” as imagens sem perder a qualidade da cor?

41

Estou criando um jogo isométrico 2.5D (imagens em 2D).

Eu quero que os jogadores possam "pintar" suas armaduras, roupas e outras coisas. Acho que tudo em escala de cinza leva a perder algumas das cores mais "naturais". Por exemplo, criar um dragão com escala de cinza vermelha / amarela e aplicar cor de sobreposição leva a um dragão puramente vermelho com toda a perda da cor secundária. Enquanto isso, morrer o mesmo dragão azul vermelho / amarelo torna azul / branco o que parece ótimo.

Os personagens do meu jogo não têm uma enorme variedade de equipamentos. O jogo está mais próximo de como League of Legends lida com personagens e gráficos. Pode haver um único tipo de personagem (por exemplo, herói), mas várias roupas para o personagem como opções. Eu quero que os jogadores possam ter o máximo de personalização possível no número limitado de "roupas" e personagens.

Então, eu quero que os jogadores possam selecionar um personagem, escolher uma das várias armas, alternar entre várias opções de roupas (colocadas em camadas nos personagens) e pintar a maioria de tudo (escolha uma cor metálica específica para armas, escolha qualquer cor para roupas).

Se eu pudesse usar a escala de cinza sem perder parte da coloração, usaria.

Aqui está um exemplo do que estou falando:

insira a descrição da imagem aqui insira a descrição da imagem aqui insira a descrição da imagem aqui

Nem é possível "tingir" o dragão, não importa o que eu use nas opções "Color Overlay" do Photoshop. Obviamente, estou fazendo errado se for possível colorir melhor usando a escala de cinza. Para uma cor como verde ou amarelo ou roxo mais claro, isso funciona bem. Para qualquer outra cor, destrói a arte.

No entanto, parece muito melhor se NÃO o fizer em escala de cinza e simplesmente aplicar uma cor "HUE" à imagem original (vermelho / amarelo).

Matiz vermelha insira a descrição da imagem aqui

Purple Hue insira a descrição da imagem aqui

Agora os jogadores poderiam pintar a cor do dragão de QUALQUER cor, e ainda ficaria ótimo! (O amarelo fica branco, enquanto o vermelho fica em qualquer cor do arco-íris.)

Isso significa que BRANCO ou PRETO é a melhor cor secundária? Em seguida, use algum tipo de método ou sombreador para mudar a cor branca (secundária) para algo diferente?

Existem artigos sobre esse método complexo de tirar uma única imagem e, com base na coloração, pintar pixels diferentes?

Para o dragão, funcionaria melhor como um dragão de alto contraste branco / preto? Vermelho / Amarelo é o melhor conjunto de cores? As imagens são muito melhores do que algumas outras cores que tentei. Escala de cinza ainda é superior?

As "Opções de mesclagem" do Photoshop não incluem o método para "tingir" adequadamente as imagens de um videogame? Existem Shaders / Métodos complexos que me permitem alcançar um sucesso melhor?

Nota: Se o GrayScale me permitir reduzir o consumo de RAM de minhas imagens ou impedir a perda de qualidade durante a compactação com perdas, isso seria algo que eu consideraria seriamente.

Carter81
fonte
5
Isso é legitimamente interessante. Vou votar e espero que receba mais atenção. A teoria das cores é um ótimo tópico.
Evan
A rotação de matiz é uma possibilidade, embora em 2D - não sei se funcionaria em 3D.
ashes999
Obrigado Evan. Também concordo que isso é extremamente interessante e um dos melhores tópicos que pesquisei em meu próprio tempo. Imagino que esse tipo de trabalho raramente seja feito porque exigiria um artista - mas não apenas qualquer artista - um artista que lida com a teoria das cores, sombreadores de videogame ou até mesmo um artista-codificador. Só posso imaginar que é raro encontrar alguém que se destaque em arte e programação. Não há pesquisas localizáveis ​​sobre esse assunto no google. Especialmente para alguém que não tem idéia de quais termos-chave para pesquisar. Eu certamente não sou um artista.
precisa saber é o seguinte

Respostas:

19

A mudança de matiz é uma possibilidade que permite obter uma variedade de cores sem perder os detalhes da cor. A idéia básica é converter cada pixel do espaço RGB em HSV, depois compensar a tonalidade em uma quantidade definida pelo usuário e depois converter novamente em RGB. Na verdade, isso pode ser feito com mais eficiência aplicando uma matriz de rotação aos valores RGB: crie uma matriz que gire em torno do eixo (1, 1, 1) pelo ângulo de matiz definido pelo usuário. Em seguida, você pode simplesmente aplicar essa matriz a cada valor RGB em seu pixel shader.

Isso permitirá que o dragão vermelho-amarelo seja deslocado para um dragão verde-amarelo, verde-ciano, azul-ciano, azul-magenta ou vermelho-magenta. Isso é um pouco restritivo, pois as duas cores não podem ser alteradas independentemente com essa abordagem. Eles manterão sua tonalidade relativa conforme são criados na imagem original. Existem também algumas cores que você não pode acessar, por exemplo, você não pode criar um dragão em preto e branco dessa maneira. Ainda assim, isso pode ser suficiente para seus propósitos.

Outra possibilidade: se seus modelos tiverem duas ou três "cores principais" (vermelho e amarelo aqui), você poderá criar a imagem original usando um canal de cores separado para cada cor principal. Nesse caso, você escreveria o dragão vermelho e verde, em vez de vermelho e amarelo, e se tivesse uma terceira cor, poderia escrevê-lo em azul. Em seguida, você pode permitir que o usuário escolha as três cores principais e use os valores de vermelho, verde e azul na imagem como quantidades dessas cores definidas pelo usuário para se misturar. Assim, seu pixel shader se parecerá com algo como

finalColor = image.r * userColor1 + image.g * userColor2 + image.b * userColor3;

Isso permitiria que os usuários escolhessem qualquer combinação de cores que desejassem, incluindo preto e branco ou roxo e dourado.

Nathan Reed
fonte
1
+1 para não apenas uma boa resposta, mas uma resposta sobre um tópico raro (teoria das cores). Não tenho ideia do porquê não pensei nisso antes. RGB. Azul verde vermelho. DUH! As melhores cores a serem usadas são provavelmente exatamente essas três cores, devido à capacidade de manipular os canais individuais.
precisa saber é o seguinte
1
A mudança de cor é um tópico muito difícil, porque a maioria das informações da imagem é transmitida pelo brilho, e a simples mudança de matiz não preserva o brilho. Tons diferentes têm diferentes valores de brilho inerentes. Você precisa de algoritmos mais sofisticados para isso.
API-Beast
10

O problema que você está enfrentando é que você não pode simplesmente "colorir" a imagem inteira, a aparência que você vê é mais do que apenas uma cor de base. Para um, você tem gradientes finos de um material para o outro, mas, mais importante, também possui reflexos, realces e sombras, que não são influenciados pela cor base. (Esses são basicamente adicionados a ele.)

Então você precisa decompor a imagem em seus componentes.

Um exemplo :

Imagem desconstruída Exemplos coloridos

Neste caso, temos 3 camadas:

  • O plano de fundo - contém os elementos que não devem ser coloridos.
  • A peça que deve ser colorida - é multiplicada pela cor. (O OpenGL se multiplica por padrão se você especificar uma cor diferente de branco.)
  • Os destaques - Estes são aditivos desenhados sobre toda a imagem. Não é branco, mas amarelo, para simular uma mudança de matiz. Os objetos não são apenas uma cor, o matiz muda junto com o brilho.
API-Beast
fonte
+1. Mas "você não pode simplesmente" pintar "toda a imagem" é um pouco enganador. Tudo depende da escolha do OP para o jogo dele. Por exemplo, Diablo II fez isso. Portanto, eu não seria tão rigoroso com as peças "você não pode / precisa". Essa é apenas uma das opções, com melhor aparência, mas consome mais RAM.
Kromster diz apoio Monica
1
@ KromStern Point é, parece horrível se você fizer isso, sempre.
API-Beast
Ótima resposta. Isso é possível através da automação? Se houver milhares de imagens animadas para um único caractere, não é possível selecionar manualmente cada camada ou decompor a imagem uma por vez. Ainda assim, posso ver algumas soluções alternativas para ajudar a automatizá-lo se renderizar em 3D usando mascaramento, mas, mesmo assim, ainda é uma ótima resposta.
Carter81
É potencialmente possível automatizá-lo localizando as cores dominantes e extraindo-as (usando um algoritmo "cor para alfa" reverso). Mas não é como se eu já tivesse implementado algo assim.
API-Beast
Para extrair os destaques, você pode pegar a máscara que você extraiu anteriormente e filtrá-la para ficar com os componentes mais brilhantes.
API-Beast
3

Pessoalmente, eu recomendaria o uso de texturas de máscara para conseguir o que deseja. Isso garantirá que a sua textura principal RGB24 mantenha sua qualidade de cor original sem sacrificar nenhuma precisão. Também lhe dará muita liberdade artística para misturar sua textura principal com sua máscara de cores.

Cada máscara pode ser vista como uma textura em escala de cinza que interpolará linearmente a cor da textura base com a cor personalizada. Digamos que você permita que seus usuários personalizem duas cores, o sombreador de pixels terá a seguinte aparência:

entradas: MainTexture (RGB), Mask1Texture (A), Mask2Texture (A), Colour1 (float), Colour2 (float)

saída: (Mask1Texture + Mask2Texture) -MainTexture + Colour1 * Mask1Texture + Colour2 * Mask2Texture

Isso sugere que, quanto mais uma máscara tiver um valor grande para um pixel, menos sua textura principal afetará a cor de saída desse pixel. Por exemplo, você pode converter sua textura de dragão em uma escala de cinza e apagar tudo, menos suas asas, para ter uma cor personalizada da asa, independentemente da cor do corpo.

Eu usei essa técnica para jogos para celular e ela não afetará seu desempenho geral. Pode custar 33% a mais de RAM por textura, mas a troca de qualidade provavelmente vale a pena.

Ps Se você está pensando em usar apenas uma cor personalizada, pode simplesmente usar o canal Alpha da sua textura principal RGBA32 como sua máscara.

MrXee
fonte
2

você pode usar paletas de cores e deixar o player editar a paleta. Se você usar shaders, poderá usar texturas 1D como paletas e o valor original em cinza como índice.

Para converter uma imagem em cores verdadeiras em uma imagem com 255 cores, você pode pegar todos os seus valores de cores de pixel e agrupá-los no espaço de cores 3d em 255 clusters com o algoritmo k-means. Ou use ferramentas genéricas de conversão de imagens. É importante mencionar que a interpolação da textura do valor de cinza será uma interpolação de índices nas texturas de cores. Isso pode levar a um resultado em que você tem várias cores entre dois texels da sua imagem original. Isso pode ser resolvido desativando a interpolação (acho que você não deseja fazer isso) ou classificando sua paleta de cores de uma maneira útil.

Arne
fonte
Isso é basicamente o que eu estava pensando também. Você pode expandir a resposta para algo um pouco mais completo. Basicamente, você permite que o usuário escolha duas cores (ou mais ou menos, mas, por uma questão de argumento, 2), faça uma textura 1D que desaparece das duas cores. Use uma textura em escala de cinza na geometria que serve como referência na textura 1D. Ainda é possível que o usuário defina cores feias, mas pelo menos ele tem a opção de fazer boas opções de cores contrastantes.
Wrossecrans
sim, você também pode derivar a paleta de 255 cores completa com menos cores do usuário, mas aqui só posso aconselhá-lo a experimentá-lo. Eu sei que muitos jogos antigos usavam mudanças na paleta de cores para fazer variações em seus monstros. Eu acho que Diablo fez isso.
22414 Arne
1

você pode converter a imagem em uma imagem cinza, mas ainda salvá-la com canais rgba. armazene um valor de peso no canal alfa e use-o para decidir quanto corante aplicar a um pixel. esse peso pode ser calculado com base na proximidade da cor do branco. quanto mais próximo do branco estiver o pixel, menos tinta deve ser aplicada ou menor o peso. isso deixará a maioria dos destaques com a leveza original, mas aplique um pouco do corante. a cor final do pixel pode ser encontrada calculando cada canal Ro + (Rd * Ao) em que Ro é o vermelho original, Rd é o vermelho na cor do corante e Ao é o Alfa do original. portanto, todos os pixels brancos não recebem nova cor e todos os pixels pretos assumem a cor da tinta.

Phil
fonte