Evitare combattimenti z con superfici coincidenti


26

Quando si eseguono il rendering di due superfici complanari sovrapposte, un problema comune è il "combattimento con z", in cui il renderer non può decidere quale delle due superfici è più vicina alla telecamera, dando artefatti visivi nell'area di sovrapposizione.

La soluzione standard è quella di dare alle superfici un leggero offset durante la progettazione del modello. c'è un'altra soluzione?


2
È possibile verificare i buffer di profondità logaritmici. C'è un articolo su gamasutra
Soapy,

1
Quando dici "co-planare" intendi "quasi" o "esattamente" co-planare e se quest'ultimo, quelle superfici sono mai identiche superfici / triangoli? L'hardware di rendering dovrebbe essere deterministico (supponendo che non si stia inviando in ordine casuale) per l'ultimo caso e che non si debba combattere. Se si tratta di superfici non identiche ma esattamente complanari, potresti aggiornare il modello per dividere le superfici in porzioni sovrapposte e non sovrapposte?
Simon F

@SimonF, per "co-planare" intendo "esattamente co-planare". La soluzione di Soapy funziona solo nel caso "quasi co-planare".
Segna il

Potresti dare un esempio delle tue superfici? L'unica cosa che mi viene in mente dalla parte superiore della mia testa sono triangoli duplicati come menzionato da @SimonF.
RichieSams,

@RichieSams il caso più comune che mi viene in mente sono le decalcomanie, in cui non hai bisogno di triangoli esattamente duplicati.
rys

Risposte:


10

Se le superfici sono esattamente co-planer, il tuo destino dipende dagli dei FPU; molto probabilmente avrai combattimenti a Z. Se i triangoli sono identici e si fanno lo esatto stessa matematica per ciascuno, si sarà finisce con gli stessi valori z per entrambi. Ma ancora una volta, questo accadrà solo se le tue operazioni matematiche sono identiche per entrambi. (Poiché, in generale, le operazioni FPU non sono commutative)

Una possibile soluzione è di non utilizzare affatto il buffer Z. Piuttosto puoi usare l' algoritmo del pittore . Certo, questo comporta anche tutti i problemi dell'algoritmo dei pittori. Ma risolverebbe il combattimento con Z.

Nel tuo esempio di Screen Space Decals (SSD), la soluzione comune è quella di utilizzare un offset, ovvero un semplice cubo sottile. Vedi la presentazione di Warhammer 40k sugli SSD come riferimento. O il post di Bart Wronski che affronta alcuni altri problemi con le decalcomanie, ma collega anche alcune altre presentazioni sugli SSD


5
Il nuovo rendering della stessa geometria con le stesse trasformazioni genera in modo affidabile gli stessi valori di profondità ogni volta. (Cioè non è una forza , è una volontà ). Ecco perché l'illuminazione diretta multi-pass funziona, ad esempio.
Nathan Reed,

@NathanReed Corrected. Grazie per il chiarimento
RichieSams

1
Per ottenere questa funzionalità è necessario utilizzare il qualificatore invariante in glsl: opengl.org/wiki/Type_Qualifier_%28GLSL%29#Invariance_qualifiers
ashleysmithgpu

Si noti che espressioni dello shader identiche (e input, ovviamente) durante la valutazione delle posizioni dei vertici potrebbero non essere sufficienti per ottenere risultati identici poiché alcune ottimizzazioni possono dipendere dal resto dello shader. GLSL ha la parola chiave "invariante" per dichiarare gli output degli shader che devono essere valutati in modo identico in shader diversi.
Firadeoclus

2

Ecco come l'ho risolto in passato:

  1. Disegna il primo oggetto (quello che dovrebbe apparire dietro l'altro oggetto) testando la profondità ma non la scrittura della profondità
  2. Disegna il secondo oggetto mediante test di profondità e scrittura di profondità. Ciò non causerà il combattimento con gli z poiché non abbiamo scritto alcuna profondità nel passaggio 1.
  3. Disegna il primo oggetto scrivendo solo nel buffer di profondità e non nel buffer di colore. Questo assicura che il buffer di profondità sia aggiornato per tutti i pixel coperti dall'oggetto 1 ma non dall'oggetto 2.

Nota, gli oggetti devono essere disegnati consecutivamente affinché questo funzioni.


0

A seconda del tuo renderer potresti rendere le superfici più "sfocate" applicando un minuscolo offset in profondità multisampling usando un algoritmo simile al rumore. Ciò dovrebbe comportare una sorta di effetto di fusione per le superfici in prossimità della profondità. Per quello che so, l'impostazione della profondità per campione nello shader di frammenti è abbastanza recente in OpenGL e quindi solo come estensione.

OpenGL ha PolygonOffset ma richiede di sapere in anticipo che stai per renderizzare qualcosa di complanare. Sebbene non sia fattibile per le superfici all'interno di un singolo modello, potrebbe funzionare bene, ad esempio, quando si esegue il rendering di una strada sovrapposta su un pezzo di terra.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.