Perché i triangoli vicini tendono a scomparire?


8

Ho appena abilitato l'abbattimento della faccia posteriore e sto notando un comportamento strano: quando tutti i vertici del mio triangolo sono fuori dalla vista e 2 di loro sono dietro di me (penso) il triangolo scompare.

Quindi, per vederlo, ecco una GIF.

inserisci qui la descrizione dell'immagine

Ho il sospetto che la matrice di proiezione inverta l'ordine dei due vertici quando cadono dietro di me e cambia l'avvolgimento del mio triangolo.

Ma non è chiaro perché i triangoli scompaiono solo se tutti i vertici sono fuori vista ...

Come posso aggirare questo problema, se possibile?

Sviluppo su Linux se questo è importante.

AGGIORNARE:

È stato sottolineato che potrebbe non essere dovuto all'abbattimento della faccia posteriore. L'ho disabilitato e posso davvero riprodurlo. I cubi sono 20 × 20 e la vista del campo verticale è 90 °. La sua dimensione apparente verticale riempie approssimativamente la finestra.

AGGIORNAMENTO 2:

Ok, posterò la parte pertinente del codice, le matrici di proiezione e visualizzazione sono impostate usando le mie funzioni:

void createViewMatrix(
    GLfloat matrix[16],
    const Vector3 *forward,
    const Vector3 *up,
    const Vector3 *pos
)
{
    /* Setting up perpendicular axes */
    Vector3 rright;
    Vector3 rup = *up;
    Vector3 rforward = *forward;

    vbonorm(&rright, &rup, &rforward); /* Orthonormalization (right is computed from scratch) */

    /* Filling the matrix */
    matrix[0] = rright.x;
    matrix[1] = rup.x;
    matrix[2] = -rforward.x;
    matrix[3] = 0;

    matrix[4] = rright.y;
    matrix[5] = rup.y;
    matrix[6] = -rforward.y;
    matrix[7] = 0;

    matrix[8] = rright.z;
    matrix[9] = rup.z;
    matrix[10] = -rforward.z;
    matrix[11] = 0;

    matrix[12] = -vdp(pos, &rright);
    matrix[13] = -vdp(pos, &rup);
    matrix[14] = vdp(pos, &rforward);
    matrix[15] = 1;
}

void createProjectionMatrix(
    GLfloat matrix[16],
    GLfloat vfov,
    GLfloat aspect,
    GLfloat near,
    GLfloat far
)
{
    GLfloat vfovtan = 1 / tan(RAD(vfov * 0.5));

    memset(matrix, 0, sizeof(*matrix) * 16);
    matrix[0] = vfovtan / aspect;
    matrix[5] = vfovtan;
    matrix[10] = (near+far)/(near-far);
    matrix[11] = -1;
    matrix[14] = (2*near*far)/(near-far);
}

Matrice di proiezione impostata con questa chiamata:

createProjectionMatrix(projMatrix, VERTICAL_FOV, ASPECT_RATIO, Z_NEAR, 10000);

(VERTICAL_FOV = 90, ASPECT_RATIO = 4.0 / 3, Z_NEAR = 1)

Il disegno di livello è semplicemente:

void drawStuff()
{
    GLfloat projectView[16];

    glClearColor(0, 0, 0, 1);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    createViewMatrix(viewMatrix, &camera.forward, &camera.up, &camera.pos);

    multiplyMatrix(projectView, viewMatrix, projMatrix); /*< Row mayor multiplication. */

    glUniformMatrix4fv(renderingMatrixId, 1, GL_FALSE, projectView);
    bailOnGlError(__FILE__, __LINE__);

    renderLevel(&testLevel);
}

I cubi vengono resi muro per muro (ottimizzare questa sarà un'altra storia):

    for (j = 0; j < 6; j++)
    {
        glBindTexture(GL_TEXTURE_2D, cube->wallTextureIds[j]);
        bailOnGlError(__FILE__, __LINE__);

        glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_INT, (void*)(sizeof(GLuint) * 4 * j));
        bailOnGlError(__FILE__, __LINE__);
        glUniform4f(extraColorId, 1, 1, 1, 1);
        bailOnGlError(__FILE__, __LINE__);
    }

Vertex shader:

#version 110

attribute vec3 position;
attribute vec3 color;
attribute vec2 texCoord;

varying vec4 f_color;
varying vec2 f_texCoord;

uniform mat4 renderingMatrix;

void main()
{
    gl_Position =  renderingMatrix * vec4(position, 1);
    f_color = vec4(color, 1);
    f_texCoord = texCoord;
}

Shader di frammenti:

#version 110

varying vec4 f_color;
varying vec2 f_texCoord;

uniform sampler2D tex;

uniform vec4 extraColor;

void main()
{
    gl_FragColor = texture2D(tex, f_texCoord) * vec4(f_color) * extraColor;
}

Il buffer di profondità è semplicemente impostato abilitandolo.


Non riesco a capire di quale triangolo stai parlando, qui.
Trevor Powell,

@TrevorPowell Le facce quadrate del cubo sono composte da 2 triangoli, metà del quadrato scompare nella seconda foto.
Calmarius,

Io ho capito quello. Ma a quale quadrato ti riferisci? Non so dire quale parte della seconda immagine dovrei guardare e quali vertici nella seconda immagine corrispondono a quali vertici nella prima. Sembra proprio che la parete blu più a destra stia tagliando il piano di clip vicino, forse? O stai parlando del muro bianco più a destra? O cosa?
Trevor Powell,

1
Potresti mostrarci il codice che sta causando questo?
Akaltar il

1
Quindi sembra che i triangoli scompaiano nel momento in cui il vertice nella parte inferiore dello schermo scompare. Questo ha sicuramente iniziato a succedere solo quando hai abilitato l'abbattimento della faccia posteriore o è possibile averlo notato solo in seguito? Le facce del cubo sono molto grandi rispetto alla parte che possiamo vedere (sto pensando a un possibile trabocco aritmetico)? Qualche possibilità di provarlo su hardware diverso (potrebbe essere un bug del driver)?
GuyRT,

Risposte:


6

Sebbene problemi simili siano spesso causati dal clipping, l'aereo vicino non è il problema qui. Se lo fosse, la scomparsa sarebbe per pixel e non per triangolo.

Nella tua animazione i triangoli scompaiono esattamente nel momento in cui tutti e tre i suoi vertici escono dallo schermo. L'algoritmo potrebbe essere basato sul falso presupposto che i triangoli siano nascosti quando tutti i loro vertici sono nascosti.

Ecco un articolo che parla di una buona implementazione di abbattimento del frustum.


Il triangolo non scompare sempre quando tutti i vertici sono fuori dalla vista. Questo clipping non è compito di OpenGL?
Calmarius,

@Calmarius, cosa sta dicendo Daniani, è che è un problema nel tuo algoritmo di abbattimento del frustum, che penso non stia nemmeno eseguendo, vero? Ad essere sincero, penso che sia un problema / bug del driver.
concept3d

@Calmarius concept3d potrebbe avere ragione, stai usando Mesa e potrebbe avere un bug che causa il tuo problema. Puoi eseguire il tuo codice su una macchina con Nvidia ufficiale o driver AMD?
danijar,

@danijar Forse più tardi, quando torno al lavoro dopo le vacanze. Sto usando vecchi computer scartati che non hanno una scheda video aggiuntiva integrata solo a quella di bordo.
Calmarius,

4

Finora sembra che sia un problema di driver OpenGL. Non ho altri computer su cui testarlo per confermare.

Se forzo il rendering del software

$ export LIBGL_ALWAYS_SOFTWARE=1

Il problema scompare. Probabilmente ho bisogno di cercare bug con Mesa.


Accetto questo, il problema non si verifica sulla mia scatola del desktop né su altri computer.
Calmarius,

-1

è puramente correlato al piano di ritaglio vicino per la fotocamera e non ha nulla a che fare con l'abbattimento del backface. È necessario ridurre il piano di ritaglio vicino e il ritaglio verrà disattivato.


Se osservi attentamente, puoi vedere che un triangolo scompare semplicemente, non ha nulla a che fare con il piano di ritaglio vicino.
Calmarius,

-1

I triangoli stanno scomparendo a causa del piano vicino del frustrazione della fotocamera. Tutto ciò che è più vicino alla telecamera rispetto al piano vicino viene automaticamente ritagliato. Devi solo mettere il tuo aereo vicino ancora più vicino alla posizione della telecamera. La modalità di configurazione del piano vicino dipende dalla libreria grafica o dal motore. In OpenGL, ad esempio, dovresti impostare il parametro zNear di gluPerspective :

void gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar);

sì sembra così, e non ha nulla a che fare con l'abbattimento del backface.
concept3d

3
ciò causerebbe la scomparsa dell'intero triangolo che attraversa il piano di ritaglio vicino? non dovrebbe semplicemente tagliare alcuni dei frammenti ?

3
Non penso che sia così; quella telecamera sembra essere rivolta in avanti, e quelle pareti sono verticali, il che significa che qualsiasi cosa venga tagliata attraversando il piano di ritaglio vicino dovrebbe creare una linea verticale sullo schermo, non questi angoli poco profondi. Le immagini mostrate sembrano davvero un triangolo che viene eliminato erroneamente.
Trevor Powell,

@TrevorPowell Sì, penso che tu abbia ragione, ho ritirato il mio voto.
concept3d
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.