Evitando z-fighting com superfícies coincidentes


26

Ao renderizar duas superfícies co-planares sobrepostas, um problema comum é "z-fighting", onde o renderizador não pode decidir qual das duas superfícies está mais próxima da câmera, fornecendo artefatos visuais na área de sobreposição.

A solução padrão para isso é dar às superfícies um pequeno deslocamento ao projetar o modelo. existe alguma outra solução?


2
Você pode verificar buffers de profundidade logarítmicos. Existe um artigo sobre gamasutra
Soapy

11
Quando você diz "co-planar", você quer dizer "quase" ou "exatamente" co-planar e, se o último, essas superfícies são sempre superfícies / triângulos idênticos? O hardware de renderização deve ser determinístico (supondo que você não esteja enviando em ordem aleatória) para o último caso e não tenha brigas. Se for um caso de superfícies não idênticas, mas exatamente co-planar, você poderia atualizar o modelo para dividir superfícies em partes sobrepostas e não sobrepostas?
Simon F

@SimonF, por "co-planar", quero dizer "exatamente co-planar". A solução da Soapy funciona apenas no caso "quase co-planar".
Mark

Você poderia dar um exemplo de suas superfícies? A única coisa que consigo pensar em cima da minha cabeça são triângulos duplicados, como o @SimonF mencionou.
precisa saber é o seguinte

@RichieSams o caso mais comum que consigo pensar é em decalques, onde você não precisa exatamente de triângulos duplicados.
rys

Respostas:


10

Se as superfícies são exatamente co-aplainadoras, seu destino depende dos deuses da FPU; você provavelmente terá Z-fighting. Se os triângulos são idênticos e você fazer o exato mesma matemática para cada um, você vai acabar com o mesmo Z-valores para ambos. Mas, novamente, isso só acontecerá se suas operações matemáticas forem idênticas para ambos. (Como, geralmente, as operações da FPU não são comutativas)

Uma solução possível é não usar o buffer Z. Em vez disso, você pode usar o algoritmo do pintor . É verdade que isso também vem com todos os problemas do algoritmo dos pintores. Mas isso resolveria o Z-fighting.

No seu exemplo de exemplo de decalques de espaço de tela (SSDs), a solução comum é usar um deslocamento, também conhecido como cubo fino simples. Veja a apresentação do Warhammer 40k sobre SSDs para referência. Ou o post de Bart Wronski, que aborda alguns outros problemas com decalques, mas também inclui algumas outras apresentações sobre SSDs


5
Re-renderizar a mesma geometria com as mesmas transformações gera de forma confiável os mesmos valores de profundidade todas as vezes. (Ou seja, não é uma força , é uma vontade ). É por isso que a iluminação de passagem múltipla funciona, por exemplo.
Nathan Reed

@NathanReed Corrected. Obrigado pelo esclarecimento
RichieSams

11
Para obter essa funcionalidade você precisa usar o qualificador invariante em GLSL: opengl.org/wiki/Type_Qualifier_%28GLSL%29#Invariance_qualifiers
ashleysmithgpu

Observe que expressões idênticas de sombreador (e entradas, obviamente) ao avaliar posições de vértices podem não ser suficientes para obter resultados idênticos, pois algumas otimizações podem depender do restante do sombreador. GLSL possui a palavra-chave "invariável" para declarar saídas de sombreador que devem ser avaliadas de forma idêntica em diferentes sombreadores.
Firadeoclus 10/08/2015

2

Aqui está como eu resolvi isso no passado:

  1. Desenhe o primeiro objeto (aquele que deve aparecer atrás do outro objeto) testando em profundidade, mas não em profundidade
  2. Desenhe o segundo objeto testando e escrevendo profundidade. Isso não causará z-fighting, já que não escrevemos nenhuma profundidade na etapa 1.
  3. Desenhe o primeiro objeto escrevendo apenas no buffer de profundidade e não no buffer de cores. Isso garante que o buffer de profundidade esteja atualizado para todos os pixels cobertos pelo objeto 1, mas não pelo objeto 2.

Observe que os objetos precisam ser desenhados consecutivamente para que isso funcione.


0

Dependendo do seu renderizador, você pode tornar as superfícies mais "nebulosas", aplicando um deslocamento minúsculo na profundidade de várias amostras usando um algoritmo semelhante ao ruído. Isso deve resultar em um tipo de efeito de mesclagem para superfícies muito próximas. Pelo que sei, a configuração da profundidade por amostra no shader de fragmento é bastante recente no OpenGL e depois apenas como uma extensão.

O OpenGL possui o PolygonOffset, mas requer saber com antecedência que você está prestes a renderizar algo coplanar. Embora não seja viável para superfícies em um único modelo, poderia funcionar bem, por exemplo, ao renderizar uma estrada sobreposta em um pedaço de terra.

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.