Cosa causa esattamente la sovrapposizione di una superficie ad un'altra?


10

Non riesco davvero a capire cosa fa sì che una superficie si sovrapponga ad un'altra. In un motore 3D che sto creando, la mia tecnica non riesce in casi limite.

Il mio metodo consiste nell'ordinare le superfici da dipingere dal più lontano al più vicino. Per determinare la vicinanza, sto confrontando i valori z medi. A volte, tuttavia, una superficie sovrapposta ha una maggiore valore z medio a quello che si sovrappone. Pertanto, la superficie più lontana viene dipinta su quella più vicina, risultando in un bizzarro rendering come questo:

Grande quadrato viola con una sezione di rosso sul lato

Ciò che si intende vedere è solo la superficie frontale viola del cubo, mentre la superficie laterale rossa è dipinta su quella viola. Il valore z medio della superficie viola è più alto, e quindi "più lontano". Quindi ho qualche dubbio sul fatto che questa tecnica sia corretta.

Ciò che ho anche provato è ottenere la distanza dalla fotocamera (cioè l'origine) alla superficie, ma poi avevo bisogno di un punto. Ho scelto il centro di ogni superficie ma anche questo non sembra sempre funzionare perché non tutte le superfici sono grandi l'una con l'altra.

Pertanto, qual è un modo affidabile per determinare l'ordine di vicinanza delle superfici rispetto all'origine?

Risposte:


11

Sembra che tu stia cercando di implementare l' algoritmo dei pittori . Immagino che stai provando a scrivere un rasterizzatore da zero come esercizio di apprendimento, poiché la maggior parte dell'hardware 3D moderno utilizza ciò che Bart ha menzionato (il buffer Z / Depth). Affinché l'algoritmo dei pittori funzioni in tutti i casi, dovresti essere pronto a suddividere le superfici mentre vengono renderizzate per risolvere possibili scenari (come il problema del poligono sovrapposto mostrato nella pagina Wikipedia).

Effettuando il rendering dal più lontano al più vicino, trascorri anche il tempo a renderizzare i pixel che potrebbero essere successivamente occlusi da altri poligoni, che quando inizi a mettere trame e shader complessi sui poligoni spreca preziosi cicli. Questo è il motivo per cui l'hardware moderno preferirebbe il rendering da davanti a dietro, usando il buffer di profondità per determinare se il pixel da renderizzare è più lontano di quello sullo schermo (e può quindi essere scartato).

Anche con la maggior parte dei moderni hardware di accelerazione dovrai comunque ordinare e renderizzare da dietro a tutti i poligoni semitrasparenti, rendendolo solo una volta resi tutti i poligoni opachi.


Hai ragione nel dire che sto creando un semplice renderer. Il punto è che non sto usando alcuna libreria 3D. Sto facendo tutti i calcoli della proiezione da solo e poi traccio le linee usando una libreria di disegni 2D. Questo non è il più veloce in circolazione e non sto facendo nulla per pixel. Ho solo 4 punti di ogni superficie e riempio la forma rettangolare con un colore. Dal momento che sto disegnando una superficie completa in una volta, ho ragione nel dire che devo disegnare indietro?
pimvdb,

Sembra molto divertente e un ottimo modo per imparare. Il retro è il tuo unico modo se lo stai facendo senza alcuna forma di buffer di profondità. Penso che dovrai elaborare tutte le coordinate dello schermo dei tuoi poligoni e quindi verificare eventuali sovrapposizioni. Laddove si sovrappongono in profondità, è necessario tagliare i poligoni per renderizzare, in modo da poter effettivamente risolvere correttamente l'ordinamento. Potresti anche voler esaminare Back Face Culling come un modo per rimuovere i poligoni che non dovrebbero essere necessariamente visibili
Roger Perkins,

Roger Perkins ha ragione. Non sarai in grado di ottenere lo z-sorting corretto in quel modo (il che significa che avrai sempre dei casi limite), a meno che non tagli i poligoni. Questo può diventare piuttosto lento però.
bummzack,

Ho funzionato! Quello che ho fatto è stata una combinazione di abbattimento e smistamento del backface: in un cubo solido, alcune facce non sono visibili mentre altre lo sono (massimo 3). Quindi ho dipinto prima le parti non visibili e le parti visibili su di esse. Funziona come un incantesimo, se rimuovo uno o più lati, si sovrappongono ma sono ancora disegnati nell'ordine corretto. Grazie!
pimvdb,

1
Funzionerà solo per semplici forme convesse, come i cubi. Sono felice che stia funzionando per te, ma non è una soluzione generale.
Richard Fabian,

3

Quello che hai è un problema di visibilità . Una soluzione sta usando un buffer z .


Grazie, ma il buffering z richiede il rendering per pixel se non sbaglio. Non lo sto facendo - sto disegnando linee rette tra i punti proiettati del cubo. Il buffering z è ancora possibile?
pimvdb,

Anche se stai disegnando linee rette, ad un certo punto prima che l'immagine arrivi allo schermo (o al file bitmap) sarà in formato pixel.
Bart van Heukelom,

È corretto, ma la mia libreria di disegni è troppo lenta per eseguire il rendering di pixel con 20 fps. Grazie comunque.
pimvdb,

2

L'ordinamento delle facce in base al loro valore z medio non funziona, poiché il valore z medio non fornisce informazioni sul valore z effettivo dei vertici o persino dei pixel di superficie.

Esempio (avviso, arte ASCII a venire):

          /
         /
cam     /
-->    / 
      /
     /--       <--B
    /
    ^--A

Ci sono due volti A e B. Dal punto di vista della fotocamera A è di fronte a B. Tuttavia, il valore z medio di B è più piccolo. Diamo un'occhiata agli altri valori z:

  • il valore z minimo di A è 4
  • il valore z massimo di A è 11
  • pertanto il valore z medio di A è 7,5
  • il valore z minimo di B è 6
  • il valore z massimo di B è 8
  • pertanto il valore z medio di B è 7

Potresti provare a ordinarli in base ai loro valori z minimi ma ci sono casi in cui anche quello non funzionerà. Non c'è modo di ordinare correttamente le facce arbitrarie usando solo un valore z.

Nell'algoritmo di Newell http://it.wikipedia.org/wiki/New_salgorithm quello che fai è ordinare gli intervalli min / max dei valori z. Se le gamme di due facce non si sovrappongono, puoi sapere con certezza quale si trova davanti. Se lo fanno, a volte devi assolutamente dividere i volti. A volte basterà raytrace ogni vertice per occlusione o qualche altra tecnica.


Quel diagramma è una vista dall'alto di ciò che stavo per indovinare sta succedendo nel suo screenshot.
jhocking

1

È positivo che tu stia imparando il rendering facendo. Complimenti. In questo caso, non esiste una soluzione di "algoritmo di pittori", invece di provare a risolverlo ordinando, su PS1 eravamo soliti cercare di mantenere poligoni della stessa dimensione quando erano vicini l'uno all'altro (cosa che stai facendo come per quanto ne so), e backface cull (cosa che non stai facendo)

L'abbattimento del backface sta controllando la normale della superficie nello spazio dello schermo per la sua direzione (basta ottenere il segno dell'elemento di profondità dallo spazio dello schermo trasformato normale (nel nostro caso era la z della normale), o il prodotto incrociato di due vettori del triangolo cioè croce (v1-v0, v2-v0))

Se si implementa l'abbattimento del backface, si riduce anche la quantità di rasterizzazione che si sta facendo .. doppia vincita.


Grazie per la risposta. Ho letto dell'abbattimento del backface ma il punto è che mi piacerebbe poter rimuovere un lato. Con un cubo solido questo potrebbe funzionare alla grande, ma se rimuovo un lato allora si sta verificando un'occulisione - quindi ho ancora bisogno di ordinarli, immagino. Ad ogni modo, mi è venuta l'idea di sparare un raggio dall'origine attraverso il punto medio di una superficie. Se quel raggio attraversa successivamente un'altra superficie, la prima superficie si sovrappone alla seconda. Potresti dirmi se quell'idea è corretta? Grazie!
pimvdb,

Sebbene la tua idea funzioni per il tuo esempio, ci sono molti altri casi in cui non funzionerà. Ad esempio, la stessa scena che hai lì, ma con la videocamera inclinata in modo che il centro del quadrante di rendering errato non si sovrapponga. Penso che dovrai tessere le tue primitive in pezzi più piccoli.
Richard Fabian,
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.