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.
Antworten:
Obwohl ähnliche Probleme häufig durch Abschneiden verursacht werden, ist das nahe Flugzeug hier nicht das Problem. Wenn dies der Fall wäre, würde das Verschwinden pro Pixel und nicht pro Dreieck erfolgen.
In Ihrer Animation verschwinden die Dreiecke genau in dem Moment, in dem alle drei Eckpunkte den Bildschirm verlassen. Ihr Algorithmus basiert möglicherweise auf der falschen Annahme, dass Dreiecke ausgeblendet sind, wenn alle ihre Scheitelpunkte ausgeblendet sind.
In diesem Artikel geht es um eine gute Implementierung von Frustum Culling.
quelle
Bisher scheint es sich um ein OpenGL-Treiberproblem zu handeln. Ich habe keinen anderen Computer, auf dem ich dies testen kann, um dies zu bestätigen.
Wenn ich das Rendern von Software erzwinge
Das Problem verschwindet. Wahrscheinlich muss ich mich mit Mesa umsehen.
quelle
Es ist rein verwandt mit der nahen Clipping-Ebene für die Kamera und hat nichts mit dem Keulen der Rückseite zu tun. Sie müssen die nahe Clipping-Ebene reduzieren, und der Clipping wird ausgelöst.
quelle
Die Dreiecke verschwinden aufgrund der nahen Ebene des Kamera-Frustrums. Alles, was näher an der Kamera als an der nahen Ebene liegt, wird automatisch abgeschnitten. Sie müssen nur Ihr nahes Flugzeug noch näher an den Kamerastandort bringen. Wie Sie die Near-Ebene konfigurieren können, hängt von Ihrer grafischen Bibliothek oder Engine ab. In OpenGL sollten Sie beispielsweise den Parameter zNear von gluPerspective festlegen :
quelle