Acabo de habilitar el sacrificio de la cara posterior y noto un comportamiento extraño: cuando todos los vértices de mi triángulo están fuera de la vista y 2 de ellos están detrás de mí (creo) el triángulo desaparece.
Entonces, para verlo, aquí hay un GIF.
Sospecho que la matriz de proyección invierte el orden de los dos vértices cuando caen detrás de mí y cambia el devanado de mi triángulo.
Pero no está claro por qué los triángulos desaparecen solo si todos los vértices están fuera de la vista ...
¿Cómo puedo solucionar este problema, si es posible?
Me desarrollo en Linux si eso importa.
ACTUALIZAR:
Se señaló que podría no ser debido a la eliminación de la cara posterior. Lo deshabilité y de hecho puedo reproducirlo. Los cubos son de 20 × 20 y la vista del campo vertical es de 90 °. Su tamaño aparente vertical llena más o menos la ventana.
ACTUALIZACIÓN 2:
Ok, publicaré la parte relevante del código, la proyección y las matrices de vista se configuran usando mis propias funciones:
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 proyección configurada con esta llamada:
createProjectionMatrix(projMatrix, VERTICAL_FOV, ASPECT_RATIO, Z_NEAR, 10000);
(VERTICAL_FOV = 90, ASPECT_RATIO = 4.0 / 3, Z_NEAR = 1)
El dibujo de nivel es simplemente:
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);
}
Los cubos se representan pared por pared (optimizar esta será otra historia):
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__);
}
Sombreador de vértices:
#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;
}
Sombreador de fragmentos:
#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;
}
El búfer de profundidad simplemente se configura habilitándolo.
Respuestas:
Aunque a menudo los problemas similares son causados por el recorte, el plano cercano no es el problema aquí. Si así fuera, la desaparición sería por píxel y no por triángulo.
En su animación, los triángulos desaparecen exactamente en el momento en que sus tres vértices salen de la pantalla. Su algoritmo puede basarse en la suposición falsa de que los triángulos están ocultos cuando todos sus vértices están ocultos.
Aquí hay un artículo que habla sobre una buena implementación de eliminación de frustum.
fuente
Hasta ahora parece que es un problema del controlador OpenGL. No tengo otra computadora para probar esto para confirmar.
Si forzo la representación del software por
El problema desaparece. Probablemente necesito mirar los errores con Mesa.
fuente
está puramente relacionado con el plano de recorte cercano para cámara y no tiene nada relacionado con el sacrificio de la cara posterior. U necesita reducir el plano de recorte cercano y el recorte se disparará.
fuente
Los triángulos están desapareciendo debido al plano cercano de la cámara frustrum. Todo lo que esté más cerca de la cámara que el plano cercano se recorta automáticamente. Solo necesita poner su avión cercano aún más cerca de la ubicación de la cámara. Cómo puede configurar el plano cercano depende de su biblioteca gráfica o motor. En OpenGL, por ejemplo, debe establecer el parámetro zNear de gluPerspective :
fuente