Pourquoi les triangles voisins ont-ils tendance à disparaître?

8

Je viens d'activer l'abattage de la face arrière et je remarque un comportement étrange: lorsque tous les sommets de mon triangle sont en dehors de la vue et que 2 d'entre eux sont derrière moi (je pense), le triangle disparaît.

Alors pour le voir, voici un GIF.

entrez la description de l'image ici

Je soupçonne que la matrice de projection inverse l'ordre des deux sommets lorsqu'ils tombent derrière moi et modifie l'enroulement de mon triangle.

Mais on ne sait pas pourquoi les triangles disparaissent uniquement si tous les sommets sont hors de vue ...

Comment contourner ce problème, si possible?

Je développe sur Linux si cela compte.

MISE À JOUR:

Il a été souligné que cela n'était peut-être pas dû à l'abattage de la face arrière. Je l'ai désactivé et je peux en effet le reproduire. Les cubes sont de 20 × 20 et la vue de champ verticale est de 90 °. Sa taille apparente verticale remplit grossièrement la fenêtre.

MISE À JOUR 2:

Ok je posterai la partie pertinente du code, les matrices de projection et de vue sont configurées en utilisant mes propres fonctions:

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 de projection configurée avec cet appel:

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

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

Le dessin de niveau est simplement:

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);
}

Les cubes sont rendus mur par mur (l'optimisation sera une autre histoire):

    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 de fragment:

#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;
}

Le tampon de profondeur est simplement configuré en l'activant.

Calmarius
la source
Je ne peux pas comprendre de quel triangle vous parlez ici.
Trevor Powell
@TrevorPowell Les faces carrées du cube sont composées de 2 triangles, la moitié du carré disparaît sur la 2ème photo.
Calmarius
J'ai compris ça. Mais de quel carré parlez-vous? Je ne peux pas dire quel morceau de la deuxième image je suis censé regarder et quels sommets de la deuxième image correspondent à quels sommets de la première. Il semble que le mur bleu le plus à droite coupe à travers le plan de clip proche, peut-être? Ou parlez-vous du mur blanc le plus à droite? Ou quoi?
Trevor Powell du
1
Pourriez-vous nous montrer le code qui cause cela?
akaltar
1
Il semble donc que les triangles disparaissent au moment où le sommet en bas de l'écran disparaît. Cela a-t-il vraiment commencé à se produire uniquement lorsque vous avez activé l'abattage de la face arrière, ou est-il possible que vous l'ayez remarqué après? Les faces du cube sont-elles très grandes par rapport à la partie que nous pouvons voir (je pense à un éventuel débordement arithmétique)? Y a-t-il une chance de l'essayer sur un matériel différent (cela pourrait être un bug de pilote)?
GuyRT

Réponses:

6

Bien que des problèmes similaires soient souvent causés par l'écrêtage, l'avion proche n'est pas le problème ici. Si tel était le cas, la disparition se ferait par pixel et non par triangle.

Dans votre animation, les triangles disparaissent exactement au moment où ses trois sommets sortent de l'écran. Votre algorithme peut être basé sur l'hypothèse fausse que les triangles sont cachés lorsque tous leurs sommets sont cachés.

Voici un article qui parle d'une bonne implémentation du tri sélectif.

danijar
la source
Le triangle ne disparaît pas toujours lorsque tous les sommets sont hors de la vue. N'est-ce pas la coupure de la tâche d'OpenGL?
Calmarius
@Calmarius, ce que Danijar dit, c'est que c'est un problème dans votre algorithme d'élimination des troncs, que je pense que vous n'effectuez même pas, n'est-ce pas? Pour être honnête, je pense que c'est un problème / bug de pilote.
concept3d
@Calmarius concept3d a peut-être raison, vous utilisez Mesa et il peut y avoir un bogue qui provoque votre problème. Pouvez-vous exécuter votre code sur une machine avec un pilote Nvidia ou AMD officiel?
danijar
@danijar Peut-être plus tard, quand je retournerai au travail après les vacances. J'utilise de vieux ordinateurs mis au rebut qui n'ont pas de carte vidéo supplémentaire intégrée uniquement à bord.
Calmarius
4

Jusqu'à présent, il semble que ce soit un problème de pilote OpenGL. Je n'ai pas d'autre ordinateur pour tester cela pour confirmer.

Si je force le rendu logiciel par

$ export LIBGL_ALWAYS_SOFTWARE=1

Le problème disparaît. J'ai probablement besoin de regarder autour des bugs avec Mesa.

Calmarius
la source
J'accepte cela, le problème ne se produit pas sur mon ordinateur de bureau ni sur d'autres ordinateurs.
Calmarius
-1

son purement lié au plan de détourage proche pour la caméra et n'a rien à voir avec l'abattage de face arrière. Vous devez réduire le plan de détourage proche et le détourage se déclenchera.

Saurabh Passolia
la source
Si vous regardez attentivement, vous pouvez voir qu'un triangle disparaît simplement, cela n'a rien à voir avec le plan de détourage proche.
Calmarius
-1

Les triangles disparaissent à cause de l'avion proche de la caméra. Tout ce qui est plus proche de la caméra que du plan proche est automatiquement coupé. Il vous suffit de placer votre avion proche encore plus près de l'emplacement de la caméra. La façon dont vous pouvez configurer le plan proche dépend de votre bibliothèque graphique ou de votre moteur. Dans OpenGL, par exemple, vous devez définir le paramètre zNear de gluPerspective :

void gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar);
dsilva.vinicius
la source
oui, cela a l'air et n'a rien à voir avec l'abattage de face arrière.
concept3d
3
cela ferait-il disparaître tout le triangle qui traverse le plan de détourage proche? ne devrait-il pas simplement couper certains des fragments ?
3
Je ne pense pas que ce soit ça; cette caméra semble être orientée vers l'avant, et ces murs sont verticaux, ce qui signifie que tout ce qui est coupé en traversant le plan de détourage proche devrait faire une ligne verticale sur l'écran, pas ces angles peu profonds. Les images présentées ressemblent vraiment à un triangle abattu par erreur.
Trevor Powell
@TrevorPowell Oui, je pense que vous avez raison, j'ai retiré mon vote.
concept3d