Visibilidade e Oclusão
1. Distance Culling ou corte de distância
Este método de seleção é ideal para grandes níveis externos, onde você teria edifícios ou estruturas de algum tipo com interiores detalhados, onde você gostaria de selecionar aqueles objetos que são pequenos demais para considerar importantes a distâncias distantes.
1.1. Atores na cena
Atores selecionados em um Nível ou Blueprint contêm configurações de distância acessadas por meio de seu painel Detalhes. Eles permitem que distâncias por instância sejam definidas ou se o Ator é selecionado usando um Cull Distance Volume
.
Min Draw Distance
- Define a distância mínima de desenho na qual o objeto será renderizado na cena. Isso é medido em unidades de espaço mundial (centímetros) do centro da esfera delimitadora do objeto até a posição da câmera.
Desired Max Draw Distance
- Define a distância máxima de projeção para o Level Designer. A distância máxima “real” é a distância mínima de tração (desconsiderando 0).
Exemplo : Valores para os atores na cena.
Min Draw Distance = 0
Desired Max Draw Distance = 1000
Nota: O objeto vai ser renderizado quando a câmera se aproximar a uma distância MENOR que 1000 centímetros.
1.2. Cull Distance Volume
Cull Distance Volumes
permitem que você especifique uma variedade de tamanhos e distâncias de seleção para que os Atores não devam mais ser desenhados.
Adicionamos o volume Cull Distance Volume
localizado em Place Actors/Volumes
e alteramos as dimensões do objeto para definir a área de corte.
Cull Distances - Uma lista de conjuntos de pares de Tamanho e Distância de Seleção usada para definir a distância de desenho de objetos com base em seu tamanho dentro de um Cull Distance Volumes
. O código calculará o diâmetro da esfera da caixa delimitadora de um objeto e procurará o melhor ajuste nesta matriz para determinar qual distância de separação deve ser atribuída a um objeto.
-
Size
- O tamanho a ser associado à distância de eliminação. -
Cull Distance
- A distância a ser associada ao tamanho dos limites de um ator.
Exemplo : Valores dos cortes de distância.
// 0 - Os objetos de tamanho 300 centímetros não sofreram corte.
Size = 300
Cull Distance = 0
// 1 - Objetos de tamanho 200 centímetros serão cortados a partir de 1200 centímetros de distância.
Size = 200
Cull Distance = 1200
// 2 - Objetos de tamanho 100 centímetros serão cortados a partir de 1500 centímetros de distância.
Size = 100
Cull Distance = 1500
2. Frustum Culling ou corte de câmera
A seleção de View Frustum usa a área visível da tela do campo de visão (FOV) da câmera para selecionar objetos fora deste espaço.
1. O plano de recorte próximo é o ponto mais próximo da câmera em que os objetos ficarão visíveis;
2. A Camera Frustum é a representação em formato piramidal da área de visualização visível entre os planos de clipe próximo e distante;
3. O plano de recorte distante é o ponto mais distante da câmera em que os objetos serão visíveis.
Configurando o Unreal Engine para visualizar o corte de câmera.
3. Precomputed Visibility - Visibilidade pré-computada
Armazenam o estado de visibilidade de atores não móveis (Static) em células colocadas acima de superfícies de projeção de sombras. Este método de seleção gera dados de visibilidade offline (durante uma construção de iluminação) e funciona melhor para níveis de tamanho pequeno a médio.
A Precomputed Visibility é ideal para hardware inferior e dispositivos móveis. Para tais hardwares e dispositivos, ao considerar os custos de desempenho, você obterá o máximo negociando custos de Thread de renderização que são mais caros por aqueles com memória de tempo de execução, onde há mais flexibilidade em relação ao desempenho.
Informação: Divide a cena em um grid, onde cada célula do grid registra o que é visível naquele local. O tamanho das células é configurado no arquivo .ini do projeto.
É necessário definir o tamanho do volume para abranger a área analisada.
Nota: Se você já construiu a iluminação (Build
> Lighting
), pode usar o menu suspenso Build
na barra de ferramentas principal e selecionar Precompute Static Visibility
para gerar células de visibilidade sem reconstruir a iluminação todas as vezes.
A câmera ao entrar na célula pergunta:
- O que pode ser ocluído?;
- O que pode ser renderizando e o que eu não devo renderizar?;
- Neste local, lembramos que esses objetos eram visíveis e estes outros não eram.
4. Occlusion Culling
O sistema de oclusão dinâmica no Unreal Engine vem com vários métodos de abate para escolher. Cada um desses métodos rastreia os estados de visibilidade dos Atores em um nível dentro do tronco de visão da câmera (ou campo de visão) que são obstruídos por outro Ator. As consultas são emitidas para a GPU ou CPU para verificar o estado de visibilidade de cada ator. Uma heurística é usada para reduzir o número de verificações de visibilidade necessárias, por sua vez, aumentando a eficácia geral de seleção e o desempenho.
1. A seleção de oclusão verifica com precisão o estado de visibilidade em cada modelo;
2. Use o comando do console freezerendering
que congela ou retomar a renderização. Permite a visualização da cena conforme foi renderizada a partir do ponto em que o comando foi inserido;
freezerendering
3. Comando do console Stat initviews
exibe informações sobre quanto tempo levou a seleção de visibilidade e quão eficaz foi. A contagem de seções visíveis, é a estatística mais importante com relação ao desempenho do Thread de renderização e é dominada por Visible Static Mesh Elements
, Visible Dynamic Primitives
também influenciam.
Dynamic Primitives : Um componente de contém ou gera algum tipo de geometria, geralmente pode ser renderizado ou usado para dados de colisão. UPrimitiveComponent
Stat initviews
Exemplo: Occlusion Culling
Perceba que a média de objetos cortados na cena aumentou (Frustum Culled Primitives
) e os objetos visíveis diminuiu (Visible static mesh elements
).
Com o comando freezerendering
congele a renderização.
Após congelar a cena, ejete a câmera para poder navegar pela cena e aperte a tecla 1, que foi utilizada para marcar a posição da câmera antes.
Como resultado temos dois objetos sendo renderizados, pois se um pixel de um objeto estiver presente na cena, o caso do objeto mais longe da câmera, todo o objeto é renderizado.
Informação: Se os objetos grandes fossem divididos em vários pedaços isso poderia diminuir o processo de renderização pois não teríamos que renderizar objetos gigantes que não aparecem totalmente na cena, mas sobrecarregaria a verificação de cada objeto visível na cena, então devemos balancear entre os dois métodos.
Occlusion Culling é um processo pesado a partir de 10.000 objetos na cena, abaixo um exemplo em uma cena com 10.000 objetos:
Distance Culling
remove 3.000 restando 7.000;
Frustum Culling
remove e renderiza 4.000;
Precomputed Visibility
remove 1.000;
Occlusion Culling
remove 1.000.
A necessidade do sistema executar os passos acima e efetuar vários cálculos para cada um pode tornar o processo pesado.
4.1. Implicações de desempenho de oclusão
- Configurando
Distance Culling
os objetos não vão ser renderizados na cena mas o calculo de oclusão ainda é realizado; - Mais de 10-15k objetos podem ter grande impacto;
- Maior parte nos processos que usam muita CPU, mas tem algum impacto na GPU;
- Grandes ambientes não ocluem bem, pois a cena apresenta qualquer coisa e não podemos esconder os objetos, se você pode ver qualquer coisa não podemos ocluir algo;
- A mesma coisa para as partículas, pois as partículas usam
Bounding Box
e esse elemento é alterado várias vezes por segundo, se o elemento é visível ele vai ser renderizado; - Modelos grandes raramente irão ocluir e, assim, aumentar GPU;
-
Combinar modelos com modelos grandes irá diminuir o custo da CPU.
Exemplo:
Se um pedaço pequeno de um objeto grande está visível, TODO o objeto será renderizado, o que aumenta o processamento, mas se esse pedaço for somente uma parte de um conjunto de objetos agrupados, somente esse pedaço será renderizado.
Informação: Os objetos grandes que estão atrás de objetos são renderizados por inteiro.
Exemplo: Abaixo temos uma lista de modelos para renderizar:
- (Cubo) Modelos A Visível;
- (Cubo) Modelos B Visível;
- (Esfera) Modelos C Não Visível;
- (Cilindro) Modelos D Visível;
- (Cubo) Modelos E Não Visível.
O resultado é que somente os modelos A,B,D são processados na GPU.
4.2. Drawcalls
A GPU agora começa a renderizar, sendo feito objeto por objeto (DrawCall).
Um grupo de polígonos compartilha as mesmas propriedades em um Drawcall
, abaixo um exemplo de como é feita a renderização.
- Chão;
- Objetos 1, 2 e 3;
- Céu.
- Chão;
- Objetos 1, 2 e parte do objeto 3;
- Parte do Objeto 3;
- Céu.
O chão é renderizado primeiro e depois os cilindos, isto se deve porque a cena é classificada por tipo de material, isso é mais rápido do contrário, pois tem que fazer uma mudança de estado de renderização no hardware.
Nota: A ordem de renderização não tem impacto no processamento.
4.3. Comando Stat RHI
RHI significa Rendering Hardware Interface. Este comando exibe várias estatísticas exclusivas:
Render target memory
- Mostra o peso total de alvos de renderização como o GBuffer (que armazena as informações finais sobre iluminação e materiais) ou mapas de sombras. O tamanho dos buffers depende da resolução de renderização do jogo, enquanto as sombras são controladas pelas configurações de qualidade das sombras. É útil verificar esse valor periodicamente em sistemas com várias quantidades de RAM de vídeo e, em seguida, ajustar as predefinições de qualidade do seu projeto de acordo.
Triangles drawn
- Este é o número final de triângulos. É após o abate de frustum e oclusão. Pode parecer muito grande em comparação com o polycount de suas malhas. É porque o número real inclui sombras (que “copiam” malhas para desenhar mapas de sombras) e mosaico. No editor, também é afetado pela seleção.
DrawPrimitive calls
- As chamadas Draw podem ser um sério gargalo nos programas DirectX 11 e OpenGL4. São os comandos emitidos pela CPU para a GPU e, infelizmente, devem ser traduzidos pelo driver. Esta linha em stat RHI mostra a quantidade de chamadas de draw emitidas no quadro atual (excluindo apenas a IU do Slate - Interface do Editor). Este é o valor total, portanto, além da geometria (normalmente o maior número), também inclui decalques, sombras, volumes de iluminação translúcida, pós-processamento e muito mais.
Comando do console:
stat RHI
4.4. O comando Stat unit e Stat FPS
Stat fps nos mostra o número final de fps e o tempo que levou para renderizar o último quadro. É o tempo total. Mas ainda não sabemos se o custo foi causado pela CPU ou pela GPU. Como explicado antes, um tem que esperar o outro. A renderização rápida na placa de vídeo não ajudará, se a CPU precisar de mais tempo para terminar o trabalho de jogabilidade, desenho (gerenciando a GPU) ou física.
Frame - é igual ao FPS, o custo final;
Game - é o trabalho da CPU no código do jogo;
Draw - é o trabalho da CPU na preparação de dados para a placa gráfica;
GPU - é o tempo bruto necessário para renderizar um quadro na placa de vídeo.
Comandos do console FPS:
stat fps
stat unit
5. Considerações
1. 2000 - 3.000 é razoável;
2.Mais de 5.000 esta ficando alto;
3. Mais de 10.000 é provavelmente um problema;
4. Em dispositivos moveis esse valor é muito menor;
5. Para verificar experimente executar o comando stat RHI e alterar o View Mode de Lit para Unlit e verifique os valores Triângulos desenhados;
6. DrawCalls tem um impacto grande na performance;
7. DrawCalls tem um mais impacto que a quantidade de polígonos em muitos cenários.
Exemplo: Se temos um polígono com 32 triângulos e 34 tipos de materiais diferentes aplicados na sua superfície, terá mais impacto no FPS do que um polígono de 10.000 triângulos e 1 material. Cada triângulo com uma superfície diferentes é renderizado por vez.