Por que triângulos próximos tendem a desaparecer?

8

Acabei de ativar a seleção do rosto para trás e estou percebendo um comportamento estranho: quando todos os vértices do meu triângulo estão fora da vista e 2 deles estão atrás de mim (acho), o triângulo desaparece.

Então, para vê-lo, aqui está um GIF.

insira a descrição da imagem aqui

Suspeito que a matriz de projeção inverta a ordem dos dois vértices quando eles ficam atrás de mim e altera o enrolamento do meu triângulo.

Mas não está claro por que os triângulos desaparecem apenas se todos os vértices estão fora de vista ...

Como posso solucionar esse problema, se possível?

Eu desenvolvo no Linux, se isso importa.

ATUALIZAR:

É indicado que pode não ser devido ao abate da face traseira. Eu o desativei e posso reproduzi-lo. Os cubos são 20 × 20 e a vista do campo vertical é 90 °. Seu tamanho aparente vertical enche aproximadamente a janela.

ATUALIZAÇÃO 2:

Ok, eu vou postar a parte relevante do código, as matrizes de projeção e visualização são configuradas usando minhas próprias funções:

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

Matriz de projeção configurada com esta chamada:

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

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

O desenho de nível é simplesmente:

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

Os cubos são renderizados parede a parede (otimizar isso será outra história):

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

Shader de vértice:

#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 fragmento:

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

O buffer de profundidade simplesmente é configurado ativando-o.

Calmarius
fonte
Não consigo descobrir de que triângulo você está falando aqui.
Trevor Powell
@TrevorPowell As faces quadradas do cubo são compostas por 2 triângulos, metade da praça desaparece na 2ª foto.
Calmarius
Eu entendi isso. Mas a qual quadrado você está se referindo? Não sei dizer para qual parte da segunda imagem devo estar olhando e quais vértices na segunda imagem correspondem a quais vértices na primeira. Parece que a parede azul mais à direita está cortando o clipe próximo, talvez? Ou você está falando sobre a parede branca mais à direita? Ou o que?
Trevor Powell
11
Você poderia nos mostrar o código que está causando isso?
Akaltar
11
Parece que os triângulos desaparecem no momento em que o vértice na parte inferior da tela fica fora de vista. Definitivamente, isso começou a acontecer apenas quando você ativou o descarte de face traseira ou é possível que você tenha percebido isso depois? As faces do cubo são muito grandes em relação à parte que podemos ver (estou pensando em um possível estouro aritmético)? Alguma chance de experimentá-lo em hardware diferente (pode ser um bug do driver)?
GuyRT

Respostas:

6

Embora problemas semelhantes geralmente sejam causados ​​por recortes, o plano próximo não é o problema aqui. Se assim fosse, o desaparecimento seria por pixel e não por triângulo.

Na sua animação, os triângulos desaparecem exatamente no momento em que todos os seus três vértices saem da tela. Seu algoritmo pode ser baseado na falsa suposição de que triângulos estão ocultos quando todos os seus vértices estão ocultos.

Aqui está um artigo falando sobre uma boa implementação de seleção de frustum.

danijar
fonte
O triângulo nem sempre desaparece quando todos os vértices ficam fora da vista. Esse recorte não é tarefa do OpenGL?
Calmarius
@Calmarius, o que danijar está dizendo é que é um problema no seu algoritmo de seleção de frustum, que eu acho que você nem está realizando, está? Para ser sincero, acho que é um problema / bug de driver.
usar o seguinte
O @Calmarius concept3d pode estar certo, você está usando o Mesa e pode ter um bug que causa o seu problema. Você pode executar seu código em uma máquina com driver oficial Nvidia ou AMD?
Danijar
@danijar Talvez mais tarde, quando eu voltar ao trabalho depois das férias. Estou usando computadores antigos descartados que não têm placa de vídeo adicional incorporada apenas na placa de vídeo.
Calmarius
4

Até agora, parece que é um problema de driver do OpenGL. Não tenho outro computador para testar isso para confirmar.

Se eu forçar a renderização de software por

$ export LIBGL_ALWAYS_SOFTWARE=1

O problema desaparece. Provavelmente eu preciso olhar em volta de bugs com o Mesa.

Calmarius
fonte
Eu aceito isso, o problema não acontece na minha área de trabalho nem em outros computadores.
Calmarius
-1

está puramente relacionado ao plano de recorte próximo da câmera e não tem nada relacionado ao abate da face posterior. Você precisa reduzir o plano de recorte próximo e o recorte será disparado.

Saurabh Passolia
fonte
Se você olhar com cuidado, poderá ver que um triângulo simplesmente desaparece, não tem nada a ver com o plano de recorte próximo.
Calmarius
-1

Os triângulos estão desaparecendo devido ao plano próximo do frustrum da câmera. Tudo o que está mais próximo da câmera do que o plano próximo é automaticamente cortado. Você só precisa colocar o seu plano próximo ainda mais próximo da localização da câmera. Como você pode configurar o plano próximo depende da sua biblioteca ou mecanismo gráfico. No OpenGL, por exemplo, você deve definir o parâmetro zNear de gluPerspective :

void gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar);
dsilva.vinicius
fonte
yes parece ser assim e não tem nada a ver com o descarte da face posterior.
precisa
3
isso faria com que todo o triângulo que cruza o plano de recorte próximo desapareça? não deveria apenas cortar alguns fragmentos ?
3
Eu não acho que é isso; essa câmera parece estar voltada para a frente e essas paredes são verticais, o que significa que qualquer coisa cortada ao cruzar o plano de corte próximo deve criar uma linha vertical na tela, não esses ângulos rasos. As imagens mostradas realmente parecem um triângulo sendo descartado erroneamente.
Trevor Powell
@TrevorPowell Sim, acho que você está correto, retirei meu voto.
usar o seguinte