Mapas de rugas no The Blacksmith

Ao planejar The Blacksmith nunca priorizamos um sombreador de pele personalizado o suficiente para que ele tivesse alguma chance realista de ser escolhido como tarefa. No entanto, ainda queríamos ver se havia algo simples que pudéssemos fazer para dar um pouco mais de vida às expressões do Challenger. Depois de um rápido brainstorming, decidimos tentar adicionar ao projeto mapas de rugas orientados por blendshape.
Para adicionar detalhes e profundidade às expressões, decidimos que o sombreador Standard nos daria o melhor retorno se permitíssemos que as rugas afetassem os normais e a oclusão. Também queríamos um método para restringir a influência de determinadas expressões a partes específicas do rosto.
Digite Wrinkle Maps Driver
Criamos um componente que permitia ao animador definir as camadas de rugas, uma camada por forma de mistura na malha. As definições de camada continham mapeamentos de textura e modificadores de força, bem como um conjunto de pesos de mascaramento que seriam combinados com uma textura de mascaramento de parte da face. Usando os pesos de mascaramento, camadas específicas de rugas podem afetar de uma a quatro partes do rosto mascarado, cada uma com uma influência diferente.

Como queríamos poder mesclar até quatro expressões diferentes a qualquer momento, só a mesclagem exigiu 11 samplers de textura com todos os recursos ativados (duas texturas de base, oito texturas de detalhes e uma textura de máscara). A única opção realista para isso era compor os mapas de rugas combinados em uma passagem de pré-renderização fora da tela. Descobrimos que o formato de textura de renderização ARGB2101010 era perfeito para nós, pois nos permitiria empacotar os normais em dois dos canais de 10 bits, com o canal restante recebendo a oclusão. A cada quadro, o componente de mapa de rugas encontrava os quatro blendshapes mais influentes e atribuía pesos de renderização de camadas de acordo.

Depois que todos os dados de rugas foram compostos no espaço da tela, a única coisa que restou a fazer foi redirecionar as entradas de dados normais e de oclusão no sombreador padrão que estávamos usando para renderizar o rosto. Na prática, isso significou apenas adicionar algumas linhas à função principal do sombreador de superfície.
// Sample occlusion and normals from screen-space buffer when wrinkle maps are active
#ifdef WRINKLE_MAPS
float3 normalOcclusion =
tex2D(_NormalAndOcclusion, IN.screenPos.xy / IN.screenPos.w).rgb;
o.Occlusion = normalOcclusion.r;
#ifdef _NORMALMAP
o.Normal.xy = normalOcclusion.gb * 2.f - 1.f;
o.Normal.z = sqrt(saturate(1.f - dot(o.Normal.xy, o.Normal.xy)));
#endif
#endifResultados finais
A comparação da cabeça de base com a forma de mescla - exagerada - irritada com peso total ilustra o detalhe adicional adicionado pelos mapas de rugas mescladas:


Também adicionamos vários modos de saída de depuração que nos permitiram visualizar facilmente a oclusão totalmente combinada e os mapas normais. Isso foi muito útil para descobrir exatamente qual componente contribuiu para o quê no resultado final.

Dividimos esse recurso em um projeto de exemplo que o senhor pode obter na Asset Store. Basicamente, é apenas a cabeça do Challenger com algumas das expressões que usamos em The Blacksmith, mas deve servir como um ponto de partida útil para colocar esse sistema em funcionamento em seus próprios projetos.
