OpenGL:glLoadMatrix 和深度缓冲区

OpenGL: glLoadMatrix & depth buffer

另一个深度缓冲问题:

我有基于矩阵的相机 - 矩阵计算在 OpenGL 端(glPushMatrix、旋转、从 OpenGL 获取矩阵、glPopMatrix),在更新相机时,我通过 glLoadMatrix 将这些计算的矩阵内容发送到 OpenGL。一切正常(移动和旋转),但深度缓冲区乱七八糟:

没有 glLoadMatrix(没有 movement/rotation):

使用 glLoadMatrix:

我不明白,为什么会发生这些事情(如果我用 "classic" 三角函数移动相机,一切正常)。

public class Camera implements ICamera {
private final FloatBuffer matrix = BufferUtils.createFloatBuffer(16);

private final FloatBuffer buffer = BufferUtils.createFloatBuffer(16);

/**
 * absolutní pozice kamery v prostoru
 */
private final Vector3f position = new Vector3f();

/**
 * aktuální pohled kamery
 */
private final Vector3f look = new Vector3f();

/**
 * nastavení pozice kamery
 */
@Override
public void setPosition(Vector3f aPosition) {
    matrix.clear();
    matrix.put(0, 1.0f);
    matrix.put(5, 1.0f);
    matrix.put(10, -1.0f);
    matrix.put(15, 1.0f);
    matrix.put(12, aPosition.getX());
    matrix.put(13, aPosition.getY());
    matrix.put(14, aPosition.getZ());
    position.set(matrix.get(12), matrix.get(13), matrix.get(14));
}

/**
 * commonly called with move vector
 */
public void move(Vector3f aPosition) {
    matrix.clear();
    float x = aPosition.getX();
    float y = aPosition.getY();
    float z = aPosition.getZ();
    matrix.put(12, matrix.get(12) + x * matrix.get(0) + y * matrix.get(4) + z * matrix.get(8));
    matrix.put(13, matrix.get(13) + x * matrix.get(1) + y * matrix.get(5) + z * matrix.get(9));
    matrix.put(14, matrix.get(14) + x * matrix.get(2) + y * matrix.get(6) + z * matrix.get(10));
    position.set(matrix.get(12), matrix.get(13), matrix.get(14));
}

/**
 * nastaví směr pohledu na zadaný bod (slouží k otáčení kamery)
 */
public void look(Vector3f aTarget) {
    matrix.clear();
    // realne neovlivni scenu, pouze vyuziva OpenGL pro vypocty matic
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadMatrix(matrix);
    glRotatef(aTarget.getY(), 1, 0, 0);
    glGetFloat(GL_MODELVIEW_MATRIX, matrix);
    glRotatef(-aTarget.getX(), matrix.get(1), matrix.get(5), matrix.get(9));
    glGetFloat(GL_MODELVIEW_MATRIX, matrix);
    glPopMatrix();
    /**
     * - není potřeba normalizovat, poněvadž v matici už normalizovaný je
     * - 12, 13, 14 je pozice kamery, 8, 9, 10 je rotace kamery; výsledek dá absolutní vektor pohledu kamery
     */
    look.set(matrix.get(12) - matrix.get(8), matrix.get(13) - matrix.get(9), matrix.get(14) - matrix.get(10));
}

// this thing update camera rotation/position
@Override
public void tick(float aTick) {
    // nevypada to hezky, nicmene usetri to nejmene 1 volani navic
    float m00 = matrix.get(0);
    float m01 = matrix.get(1);
    float m02 = matrix.get(2);
    float m04 = matrix.get(4);
    float m05 = matrix.get(5);
    float m06 = matrix.get(6);
    float m08 = matrix.get(8);
    float m09 = matrix.get(9);
    float m10 = matrix.get(10);
    float m12 = matrix.get(12);
    float m13 = matrix.get(13);
    float m14 = matrix.get(14);
    buffer.put(0, m00);
    buffer.put(1, m04);
    buffer.put(2, m08);
    buffer.put(4, m01);
    buffer.put(5, m05);
    buffer.put(6, m09);
    buffer.put(8, m02);
    buffer.put(9, m06);
    buffer.put(10, m10);
    buffer.put(12, -(m00 * m12 + m01 * m13 + m02 * m14));
    buffer.put(13, -(m04 * m12 + m05 * m13 + m06 * m14));
    buffer.put(14, -(m08 * m12 + m09 * m13 + m10 * m14));
    buffer.rewind();
    glMatrixMode(GL_MODELVIEW);
    // this line is true devil: if I comment this out, it produce image [1], in this case produce image [2]
    glLoadMatrix(buffer);
    }
}

我修改了打勾方法:

@Override
public void tick(float aTick) {
    float m01 = matrix.get(1);
    float m02 = matrix.get(2);
    float m04 = matrix.get(4);
    float m06 = matrix.get(6);
    float m08 = matrix.get(8);
    float m09 = matrix.get(9);
    float m12 = matrix.get(12);
    float m13 = matrix.get(13);
    float m14 = matrix.get(14);
    buffer.put(matrix);
    buffer.put(1, m04);
    buffer.put(2, m08);
    buffer.put(4, m01);
    buffer.put(6, m09);
    buffer.put(8, m02);
    buffer.put(9, m06);
    buffer.put(12, -(matrix.get(0) * m12 + m01 * m13 + m02 * m14));
    buffer.put(13, -(m04 * m12 + matrix.get(5) * m13 + m06 * m14));
    buffer.put(14, -(m08 * m12 + m09 * m13 + matrix.get(10) * m14));
    buffer.rewind();
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glLoadMatrix(buffer);
}

正如 immibis 所指出的那样 - 我没有复制 matrix 的所有值 buffer - 糟糕的副作用是错误的深度缓冲计算。

现在可以了。