La discontinuità delle coordinate della trama con le mipmap crea giunture


9

Ho appena iniziato a studiare OpenGL e sto ottenendo questo artefatto quando trame una sfera con mipmap. Fondamentalmente quando il frammento campiona il bordo della mia trama, rileva la discontinuità (diciamo da 1 a 0) e sceglie la più piccola mipmap, che crea questa brutta cucitura:

brutta cucitura http://cdn.imghack.se/images/6bbe0ad0173cac003cd5dddc94bd43c7.png

Quindi ho provato a sovrascrivere manualmente i gradienti usando textureGrad:

//fragVert is the original vertex from the vertex shader
vec2 ll = vec2((atan(fragVert.y, fragVert.x) / 3.1415926 + 1.0) * 0.5, (asin(fragVert.z) / 3.1415926 + 0.5));
vec2 ll2 = ll;
if (ll.x < 0.01 || ll.x > 0.99)
    ll2.x = .5;
vec4 surfaceColor = textureGrad(material.tex, ll, dFdx(ll2), dFdy(ll2));

Ora ho due cuciture invece di una. Come posso liberarmene? E perché il codice sopra genera 2 cuciture?

2 eams http://cdn.imghack.se/images/44a38ef13cc2cdd801967c9223fdd2d3.png

Non si può dire dalle due immagini ma le 2 cuciture si trovano su entrambi i lati della cucitura originale.


2
La tua sfera è una mesh o stai analizzando raytracing la sfera nello shader o simili? Se è una mesh, la gente di solito risolve questo problema duplicando i vertici lungo la cucitura in modo che i verts su un lato possano avere u = 0 e l'altro lato abbia u = 1.
Nathan Reed

Per quanto riguarda il motivo per cui il tuo codice genera due cuciture, mi aspetto che sia perché sta creando due discontinuità: una in cui salti da 0,01 a 0,5 e una in cui salti da 0,99 a 0,5. È lo stesso problema di quando salti da 0 a 1 - non così grande come un salto ma comunque un grande salto.
Nathan Reed,

Ho una maglia per la sfera. È un decaedro quindi i vertici non si allineano alla giuntura. La cosa divertente delle due cuciture è che la cucitura originale è sparita. Inoltre, ottengo le stesse 2 cuciture anche se lo stringo a .01 o .99.
omikun,

Puoi pubblicare uno screenshot del caso a due cuciture? E come stai generando gli UV (puoi pubblicare la parte pertinente del tuo codice)? Presumo che tu li stia generando proceduralmente nello shader, non solo interpolandoli dai vertici, altrimenti la tua rete di dodecaedro non funzionerebbe affatto.
Nathan Reed,

Ho aggiornato la domanda con un'immagine delle 2 cuciture, sono entrambi i lati della cucitura originale, ma la cucitura originale non è lì. Penso che gli UV siano interpolati dai vertici, non sono sicuro. Il codice è nella domanda ora.
omikun,

Risposte:


4

In base al codice shader che hai pubblicato, non stai interpolando gli UV dai vertici, ma sembra che stai interpolando la posizione 3D ( fragVert), quindi calcolando gli UV trasformandoli in coordinate sferiche.

L'analisi è corretta in quanto viene scelta la mipmap più piccola in caso di discontinuità, poiché la selezione della mipmap si basa su derivati ​​stimati numericamente dagli UV utilizzati nei pixel adiacenti. Quando un pixel ha u = 0 e un altro ha u = 1 ottieni una derivata molto grande. La tua tentata correzione ha lo stesso problema in quanto si verificano grandi derivati ​​intorno a u = 0,01 e u = 0,99, motivo per cui appaiono due cuciture su entrambi i lati di dove era la cucitura originale.

Un approccio relativamente semplice per risolvere il problema sarebbe quello di decidere quale livello di mip usare te stesso e chiamare textureLodper campionarlo direttamente. Se il pianeta sarà sempre abbastanza vicino alla videocamera, potresti semplicemente codificare il livello di mip su 0 (o, del resto, semplicemente non includere affatto i livelli di mip nella trama). Altrimenti, potrebbe essere basato sul log2 della distanza del punto dalla telecamera, ridimensionato da alcuni fattori adeguati. Si noti che ciò disabiliterà efficacemente il filtro anisotropico.

Un approccio più "corretto" sarebbe quello di calcolare alcuni derivati ​​di qualità superiore. Invece di utilizzare dFdxe dFdysui UV, che hanno discontinuità a causa della atan2, si potrebbe applicare dFdxe dFdyai fragVert(che sarà in continuo tutto intorno alla sfera), quindi usare un po 'di calcolo (regola della catena) per trovare la formula per ottenere i derivati UV dai derivati ​​di posizione. Questo sarà più complicato e più lento, ma ha il vantaggio che il filtro anisotropico dovrebbe funzionare.

Infine, dato che sei nuovo di OpenGL, noterò solo che mentre il calcolo degli UV da coordinate sferiche è un modo perfettamente valido per strutturare una sfera, non è il modo "solito" che la maggior parte delle persone sceglie. È più comune costruire una mesh di sfere che abbia i raggi UV specificati per vertice e sia semplicemente passata dallo shader di vertice allo shader di pixel (interpolato linearmente su ogni triangolo). I vertici sono posizionati lungo la giuntura, in questo modo , in modo tale che ci siano due copie di ciascun vertice, esattamente nelle stesse posizioni, ma metà con u = 0 collegato ai triangoli su un lato e l'altra metà con u = 1 collegato a i triangoli dall'altra parte. Questo elimina qualsiasi cucitura visibile e non richiede alcun trucco nel pixel shader.

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.