1. Introdução
Blueprint gerando edifícios processuais é uma idéia tentadora. O uso de módulos padronizados e o posicionamento automático são bastante lógicos, porque, afinal, essa é a mesma arquitetura. Mas como, ao texturizar, alcançamos a diversidade natural em vez da repetição?
Este edifício foi criado a partir de apenas um módulo,
copiado automaticamente para o Construction Blueprint . A idéia é que o material não exija quase nenhuma entrada manual de dados.
Apenas um material é usado para todo o edifício (excluindo janelas). Suas funções são usadas para controlar a randomização da cor dos vértices e a posição dos pixels no espaço do mundo.
O único módulo é tudo o que precisamosNenhum posicionamento ou script manual. Toda a randomização é feita no material.O material descrito neste tutorial:
- Possui uma camada de sujeira dependente da altura que cobre o objeto apenas até a altura absoluta especificada
- Seleciona a cor dos objetos para cada andar e segmento aleatoriamente
- Desloca ligeiramente a posição de objetos pequenos, também aleatoriamente
- Permite ao usuário selecionar 2 cores para as paredes, bem como o valor de sua destruição
Cor do vértice como dados
03:34Além das posições dos vértices e normais, os mecanismos de jogo geralmente fornecem acesso a outros valores, por exemplo, a cor dos vértices. Ao sombrear um triângulo de malha, a cor é interpolada entre os vértices. Você pode desenhá-lo em um editor 3D ou usar a guia
Paint no UE. Se você fizer isso no mecanismo, terá a oportunidade de modificar uma instância separada da malha no mundo. Expliquei esse caso de uso no
tutorial sobre desenho de vértices . No entanto, neste caso, manteremos a cor importada, porque decidi usar os canais RGB como
máscaras exatas que controlam a randomização.
Não esqueça que a cor nos gráficos 3D é apenas um
vetor de três componentes . Seus componentes são o brilho do vermelho, verde e azul no intervalo de 0 a 1. O valor é arbitrário, porque a cor do vértice é apenas dados. Em vez de usá-las diretamente para pintar texturas, decidi colocar as cores dos topos das máscaras em cada canal:
- O canal vermelho é a máscara das cores primárias e secundárias das paredes . Polígonos com o valor 0 usam a cor primária, com 1 - a cor secundária.
- Canal verde - usado para selecionar uma cor da paleta . Isso permite controlar a variação de cores de itens pequenos, como secar roupas. Um valor entre 0 e 1 é arredondado para o índice (posição UV) na textura da paleta.
- Canal azul - deslocamento das posições dos vértices para mover os vértices horizontalmente. Isso significa que 0 será usado para paredes (sem movimento) e valores até 1 podem ser atribuídos ao ar condicionado ou à roupa de cama. Este canal também controla a visibilidade (máscara de opacidade). Se o valor for maior que 0, será adicionado um valor aleatório, próprio para cada segmento do edifício, para criar variabilidade.
Em qualquer editor 3D sério, há uma função para pintar a cor dos vértices. Você pode encontrar facilmente instruções sobre como fazer isso no seu editor. Lembre-se de informar ao Unreal Engine na janela de importação de malha para que substitua (
Substitua ) a cor dos vértices (em vez de ignorá-la).
Como eu disse acima, a cor neste projeto é um conjunto de valores exatos. Para uma tarefa semelhante e quase qualquer tarefa técnica da arte do jogo, prefiro usar o
Houdini . No entanto, um resultado semelhante pode ser alcançado (com um pouco mais de esforço) em qualquer outro editor 3D. Apenas preste atenção ao que cada canal de cor deve indicar no shader.
Destacamos todo o processo de atribuição de valores aos canais de cores dos vértices em um tutorial separado:
Armazene dados na cor dos vértices usando o Houdini . Neste tutorial, uso as complicadas ferramentas Houdini para tornar o processo mais eficiente.
Projeto de construção
07:57O modelo que criei é simples. Simplesmente cria uma parede plana do edifício, duplicando a malha horizontal e verticalmente. Possui variáveis mutáveis
MeshWall (Static Mesh),
NumberOfFloors (número inteiro),
NumberOfSegments (número inteiro) e
Material .
O resultado da planta: 4 andares, 2 segmentos.Todo o processo é realizado no Script de Construção, ou seja, durante a edição de nível. Graças a isso, a malha resultante se comportará como qualquer outro objeto estático. Por exemplo, isso será levado em consideração na construção de iluminação.
As dimensões da malha são medidas primeiro. Comprimento da borda significa metade do tamanho do objeto. Podemos calcular uma vez e salvar, porque para todos os segmentos o valor será o mesmo.
O restante do código é executado em dois ciclos. O loop externo cria pisos como um todo, o loop interno cria segmentos no piso atual. A localização é calculada pelos índices de iteração do loop multiplicados pela largura e altura da malha.
Um novo componente de malha estática é adicionado a cada segmento. Em alguns casos, será útil usar instâncias. A adição de componentes leva a um aumento no número de chamadas de draw, o que em cenas "pesadas" pode causar problemas.
Isso é tudo. Ao definir novos
NumberOfFloors e
NumberOfSegments, o edifício será atualizado automaticamente.
Duas cores de parede mascaradas pela cor do vértice
21:16Ambas as cores são acessadas como parâmetros. O canal vermelho da cor dos vértices é usado como o coeficiente de mistura entre eles.
Embalagem e mistura de canais
14:22Queremos que as cores das paredes afetem apenas as próprias paredes, mas não afetem os caixilhos das janelas e os aparelhos de ar condicionado. Além disso, eles não devem afetar áreas danificadas. Isso pode ser feito envolvendo a máscara no canal alfa da cor base. Em outras palavras, a textura da cor base tem um fundo transparente e é aí que as cores das paredes são afetadas.
A propósito, empacotei as texturas metalidez, rugosidade e oclusão (todas em tons de cinza) nos canais R / G / B da mesma textura . Isso reduz o número de samplers, arquivos e Lerp em três vezes - uma ótima otimização que não requer compromissos. Um tutorial sobre essa técnica pode ser encontrado nas notas.
Ruído da textura
Esse padrão de ruído foi usado para se misturar entre o primeiro (limpo) e o segundo (danificado) conjunto de texturas. Em vez de calculá-lo em tempo real, o que, para ruídos de alta qualidade, será um procedimento caro, basta carregá-lo a partir da textura. O
nó WorldAlignedTexture o projeta de três lados (
gera coordenadas UV proceduralmente ).
Sujeira dependente da altura. Função Remapear
18:00A sujeira é uma cor plana aplicada por um gradiente no espaço do mundo. O componente Z da posição do pixel no mundo é convertido no intervalo 0-1. Isso nos dá uma máscara útil - coeficiente de
Lerp . O mínimo e o máximo inicial (por exemplo, de 150 a 700 cm) são transmitidos pelo usuário como parâmetros escalares. Um pouco de ruído é adicionado para tornar a transição mais natural.
A função TAA_Remap_01_Clamped foi criada por mim. Eu o uso em quase todos os shaders. Ele converte o valor no intervalo de origem no intervalo 0-1. Ótimo para criar máscaras com base na distância (da câmera, do solo ou até mesmo para formas no espaço UV).
Randomização de cores, elementos ocultos
22h55A obtenção de um valor aleatório a partir do ponto de referência da posição do segmento permite alterar a paleta de cores para objetos pequenos. Uma paleta é uma textura com cores alinhadas horizontalmente; portanto, mover a imagem usada para leitura nos dá a cor final.
A textura da paleta em uma escala ampliada. Seu tamanho usual é 8 × 1 pixel com a compactação desativadaO canal de cor verde do vértice serve como valor e máscara de randomização. Um valor 0 significa "não aplique cor aqui".
Aplicar deslocamento da posição local
A última função é mover objetos aleatoriamente ao longo do eixo X. Para fazer isso, um deslocamento de posição controlado por material é adicionado aos vértices. Ao usar esse truque, você precisa estar atento a duas coisas - colisões complexas (para fotografar) e campos de distância. Tanto o parâmetro quanto o outro não sabem que esse deslocamento foi realizado.
Vou pegar o canal azul novamente e adicionar um número aleatório - o mesmo ruído com base na posição do segmento que usamos anteriormente. Vamos convertê-lo do intervalo 0-1 para o intervalo de -0,5 a 0,5, para que o movimento seja realizado nas duas direções. Em seguida, multiplicamos por
PositionOffsetStrength . O
nó Anexar adicionará os eixos restantes (constante 0 em Y e Z).
Inesperadamente, o Unreal exige que a saída seja deslocada nas
coordenadas mundiais . Calculamos a
posição local . Como convertê-lo?
Isso pode ser feito transformando o espaço dessa nova posição local em espaço mundial usando o nó
Transformar . Então subtraio a posição inicial do vértice no mundo dessa nova posição, obtendo o
deslocamento do mundo em vez da posição. Combine isso com a liberação do material de
deslocamento da posição mundial , e este é o trabalho.
Material acabado
Espero que você tenha aprendido algo novo com este tutorial. Aqui está uma captura de tela de todo o gráfico do nó do material:
Arquivos de Projeto e Discussão
Você pode fazer o download dos arquivos do projeto gratuitamente (ou para doação, se desejado):
arquivos do projeto . Se você tiver comentários ou perguntas, entre na discussão
no Reddit .
Leitura adicional
- Uma maneira fácil de compactar texturas em canais RGB é salvar três texturas em escala de cinza em canais de uma única imagem RGB usando o Photoshop. A embalagem permite economizar espaço e, mais importante, obter três texturas em uma operação de leitura. Vale a pena o esforço, pois a leitura de texturas da memória é uma das operações de GPU mais demoradas.