Ich habe gerade das Keulen der Rückseite aktiviert und bemerke ein seltsames Verhalten: Wenn sich alle Scheitelpunkte meines Dreiecks außerhalb der Ansicht befinden und zwei von ihnen hinter mir liegen (glaube ich), verschwindet das Dreieck.
Um es zu sehen, hier ist ein GIF.
Ich vermute, dass die Projektionsmatrix die Reihenfolge der beiden Eckpunkte umkehrt, wenn sie hinter mich fallen, und die Wicklung meines Dreiecks ändert.
Es ist jedoch unklar, warum die Dreiecke nur verschwinden, wenn alle Scheitelpunkte nicht sichtbar sind ...
Wie kann ich dieses Problem nach Möglichkeit umgehen?
Ich entwickle unter Linux, wenn das wichtig ist.
AKTUALISIEREN:
Es wird darauf hingewiesen, dass dies möglicherweise nicht auf das Keulen der Rückseite zurückzuführen ist. Ich habe es deaktiviert und kann es tatsächlich reproduzieren. Die Würfel sind 20 × 20 und die vertikale Feldansicht beträgt 90 °. Seine vertikale scheinbare Größe füllt das Fenster ungefähr aus.
UPDATE 2:
Ok, ich werde den relevanten Teil des Codes veröffentlichen. Projektions- und Ansichtsmatrizen werden mit meinen eigenen Funktionen eingerichtet:
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);
}
Mit diesem Aufruf eingerichtete Projektionsmatrix:
createProjectionMatrix(projMatrix, VERTICAL_FOV, ASPECT_RATIO, Z_NEAR, 10000);
(VERTICAL_FOV = 90, ASPECT_RATIO = 4.0 / 3, Z_NEAR = 1)
Levelzeichnung ist einfach:
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);
}
Würfel werden Wand für Wand gerendert (dies zu optimieren wird eine andere Geschichte sein):
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;
}
Fragment Shader:
#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;
}
Der Tiefenpuffer wird einfach durch Aktivieren eingerichtet.