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
- 糟糕的副作用是错误的深度缓冲计算。
现在可以了。
另一个深度缓冲问题:
我有基于矩阵的相机 - 矩阵计算在 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
- 糟糕的副作用是错误的深度缓冲计算。
现在可以了。