未投影的鼠标坐标在 0-1 之间
UnProjected mouse coordinates are between 0-1
我正在尝试从我的鼠标位置创建一个 3D 射线 space,显然为了做到这一点,我需要 "UnProject()" 它。
这样做会为每个轴提供一个介于 0 和 1 之间的值。
这 不可能是正确的 从视口绘制 "Ray" 或一条线,可以吗?所有这一切,基本上是我的鼠标占视口大小的百分比。
如果这确实是对的,那么我不明白以下内容:
- 我绘制的三角形的顶点 不受 0-1 的约束,而是像 (0,100,0), (100,100,0), (100, 0,0), 这些画得很好
- 而且,绘制未从我的鼠标坐标投影的顶点 lines/points 也绘制得非常好。
- 然后我怎么比较我的鼠标坐标和我的对象的坐标?
如果这实际上是错误的,那么是什么导致了这样的错误?
我尝试取消投影我自己对象的顶点,但这些顶点不受 0-1 的限制。
我不知道我在渲染时处理 "projections" 的方式是否与 gluUnproject 兼容。我一直按照这些教程显示的方式进行操作(接近底部):http://qt-project.org/wiki/Developer-Guides#28810c65dd0f273a567b83a48839d275
这是我尝试获取鼠标坐标的方法:
GLdouble modelViewMatrix[16];
GLdouble projectionMatrix[16];
GLint viewport[4];
GLfloat winX, winY, winZ;
glGetDoublev(GL_MODELVIEW_MATRIX, modelViewMatrix);
glGetDoublev(GL_PROJECTION_MATRIX, projectionMatrix);
glGetIntegerv(GL_VIEWPORT, viewport);
winX = (float)x;
winY = (float)viewport[3] - (float)y;
glReadPixels( winX, winY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ );
GLdouble nearPlaneLocation[3];
gluUnProject(winX, winY, 0, modelViewMatrix, projectionMatrix,
viewport, &nearPlaneLocation[0], &nearPlaneLocation[1],
&nearPlaneLocation[2]);
GLdouble farPlaneLocation[3];
gluUnProject(winX, winY, 1, modelViewMatrix, projectionMatrix,
viewport, &farPlaneLocation[0], &farPlaneLocation[1],
&farPlaneLocation[2]);
QVector3D nearP = QVector3D(nearPlaneLocation[0], nearPlaneLocation[1],
nearPlaneLocation[2]);
QVector3D farP = QVector3D(farPlaneLocation[0], farPlaneLocation[1],
farPlaneLocation[2]);
也许我的实际预测不对?
void oglWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
QMatrix4x4 mMatrix;
QMatrix4x4 vMatrix;
QMatrix4x4 cameraTransformation;
cameraTransformation.rotate(alpha, 0, 1, 0);
cameraTransformation.rotate(beta, 1, 0, 0);
QVector3D cameraPosition = cameraTransformation * QVector3D(camX, camY, distance);
QVector3D cameraUpDirection = cameraTransformation * QVector3D(0, 1, 0);
vMatrix.lookAt(cameraPosition, QVector3D(camX, camY, 0), cameraUpDirection);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(cameraPosition.x(), cameraPosition.y(), cameraPosition.z(), camX, camY, 0, cameraUpDirection.x(), cameraUpDirection.y(), cameraUpDirection.z());
shaderProgram.bind();
shaderProgram.setUniformValue("mvpMatrix", pMatrix * vMatrix * mMatrix);
shaderProgram.setUniformValue("texture", 0);
for (int x = 0; x < tileCount; x++)
{
shaderProgram.setAttributeArray("vertex", tiles[x]->vertices.constData());
shaderProgram.enableAttributeArray("vertex");
shaderProgram.setAttributeArray("textureCoordinate", textureCoordinates.constData());
shaderProgram.enableAttributeArray("textureCoordinate");
//Triangle Drawing
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, tiles[x]->image.width(), tiles[x]->image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, tiles[x]->image.bits());
glDrawArrays(GL_TRIANGLES, 0, tiles[x]->vertices.size());
}
shaderProgram.release();
}
其中,pMatrix 是一个 4x4 矩阵,在调整大小事件期间进行控制,例如:
pMatrix.setToIdentity();
pMatrix.perspective(fov, (float) width / (float) height, 0.001, 10000);
glViewport(0, 0, width, height);
我的顶点着色器是这样设置的:
uniform mat4 mvpMatrix;
in vec4 vertex;
in vec2 textureCoordinate;
out vec2 varyingTextureCoordinate;
void main(void)
{
varyingTextureCoordinate = textureCoordinate;
gl_Position = mvpMatrix * vertex;
}
glReadPixels 采用整数(x 和 y),而您似乎出于某种原因在 gluUnProject 中没有使用 winZ。
这样试试:
gluUnProject(winX, winY, winZ, glView, glProjection, viewport, &posX, &posY, &posZ);
此外,如果您希望光线在遇到深度缓冲区中的某物时停止,则不要在渲染后清除深度缓冲区。如果你执行 glClear(GL_DEPTH_BUFFER_BIT) 那么光线应该到达你在投影矩阵中设置的远剪辑。
我也不知道为什么你需要多次调用它。最后三个浮点数将是目标向量,您可以只使用您的相机位置作为光线的来源(取决于您在做什么)。
我的部分问题是描述不当。我不小心留下了疯狂测试的残留代码,导致一些“读取像素”函数和相关的废话,这对解决问题没有用。
我的其他问题是由于矩阵的数据类型不一致,并且试图从 OpenGL 中提取矩阵,而 OpenGL 一开始就没有存储它们。
问题已解决:
- Using GLM to hold all my matrices
- 自己进行计算(逆视图矩阵*逆模型矩阵*逆投影矩阵)*持有NDC转换屏幕的向量space坐标(-1到1的范围:x或y除以宽度或高度, * 2 - 1), 它的远平面或近平面的 z 也为 -1 或 1,w 为 1.
- 将结果除以向量的第四个点。
我仍然不知道为什么 unprojecting 对我不起作用,因为我用 GLU 和 GLM 的 unproject 函数得到了错误的结果,但是手动操作对我有用。
由于我的问题持续了相当长的时间,并提出了几个问题,我要感谢一路上帮助过我的几个人:
- srobins of facepunch, in this thread
- derhass from here, in this question, and this discussion
我正在尝试从我的鼠标位置创建一个 3D 射线 space,显然为了做到这一点,我需要 "UnProject()" 它。
这样做会为每个轴提供一个介于 0 和 1 之间的值。
这 不可能是正确的 从视口绘制 "Ray" 或一条线,可以吗?所有这一切,基本上是我的鼠标占视口大小的百分比。
如果这确实是对的,那么我不明白以下内容:
- 我绘制的三角形的顶点 不受 0-1 的约束,而是像 (0,100,0), (100,100,0), (100, 0,0), 这些画得很好
- 而且,绘制未从我的鼠标坐标投影的顶点 lines/points 也绘制得非常好。
- 然后我怎么比较我的鼠标坐标和我的对象的坐标?
如果这实际上是错误的,那么是什么导致了这样的错误? 我尝试取消投影我自己对象的顶点,但这些顶点不受 0-1 的限制。 我不知道我在渲染时处理 "projections" 的方式是否与 gluUnproject 兼容。我一直按照这些教程显示的方式进行操作(接近底部):http://qt-project.org/wiki/Developer-Guides#28810c65dd0f273a567b83a48839d275
这是我尝试获取鼠标坐标的方法:
GLdouble modelViewMatrix[16];
GLdouble projectionMatrix[16];
GLint viewport[4];
GLfloat winX, winY, winZ;
glGetDoublev(GL_MODELVIEW_MATRIX, modelViewMatrix);
glGetDoublev(GL_PROJECTION_MATRIX, projectionMatrix);
glGetIntegerv(GL_VIEWPORT, viewport);
winX = (float)x;
winY = (float)viewport[3] - (float)y;
glReadPixels( winX, winY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ );
GLdouble nearPlaneLocation[3];
gluUnProject(winX, winY, 0, modelViewMatrix, projectionMatrix,
viewport, &nearPlaneLocation[0], &nearPlaneLocation[1],
&nearPlaneLocation[2]);
GLdouble farPlaneLocation[3];
gluUnProject(winX, winY, 1, modelViewMatrix, projectionMatrix,
viewport, &farPlaneLocation[0], &farPlaneLocation[1],
&farPlaneLocation[2]);
QVector3D nearP = QVector3D(nearPlaneLocation[0], nearPlaneLocation[1],
nearPlaneLocation[2]);
QVector3D farP = QVector3D(farPlaneLocation[0], farPlaneLocation[1],
farPlaneLocation[2]);
也许我的实际预测不对?
void oglWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
QMatrix4x4 mMatrix;
QMatrix4x4 vMatrix;
QMatrix4x4 cameraTransformation;
cameraTransformation.rotate(alpha, 0, 1, 0);
cameraTransformation.rotate(beta, 1, 0, 0);
QVector3D cameraPosition = cameraTransformation * QVector3D(camX, camY, distance);
QVector3D cameraUpDirection = cameraTransformation * QVector3D(0, 1, 0);
vMatrix.lookAt(cameraPosition, QVector3D(camX, camY, 0), cameraUpDirection);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(cameraPosition.x(), cameraPosition.y(), cameraPosition.z(), camX, camY, 0, cameraUpDirection.x(), cameraUpDirection.y(), cameraUpDirection.z());
shaderProgram.bind();
shaderProgram.setUniformValue("mvpMatrix", pMatrix * vMatrix * mMatrix);
shaderProgram.setUniformValue("texture", 0);
for (int x = 0; x < tileCount; x++)
{
shaderProgram.setAttributeArray("vertex", tiles[x]->vertices.constData());
shaderProgram.enableAttributeArray("vertex");
shaderProgram.setAttributeArray("textureCoordinate", textureCoordinates.constData());
shaderProgram.enableAttributeArray("textureCoordinate");
//Triangle Drawing
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, tiles[x]->image.width(), tiles[x]->image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, tiles[x]->image.bits());
glDrawArrays(GL_TRIANGLES, 0, tiles[x]->vertices.size());
}
shaderProgram.release();
}
其中,pMatrix 是一个 4x4 矩阵,在调整大小事件期间进行控制,例如:
pMatrix.setToIdentity();
pMatrix.perspective(fov, (float) width / (float) height, 0.001, 10000);
glViewport(0, 0, width, height);
我的顶点着色器是这样设置的:
uniform mat4 mvpMatrix;
in vec4 vertex;
in vec2 textureCoordinate;
out vec2 varyingTextureCoordinate;
void main(void)
{
varyingTextureCoordinate = textureCoordinate;
gl_Position = mvpMatrix * vertex;
}
glReadPixels 采用整数(x 和 y),而您似乎出于某种原因在 gluUnProject 中没有使用 winZ。
这样试试:
gluUnProject(winX, winY, winZ, glView, glProjection, viewport, &posX, &posY, &posZ);
此外,如果您希望光线在遇到深度缓冲区中的某物时停止,则不要在渲染后清除深度缓冲区。如果你执行 glClear(GL_DEPTH_BUFFER_BIT) 那么光线应该到达你在投影矩阵中设置的远剪辑。
我也不知道为什么你需要多次调用它。最后三个浮点数将是目标向量,您可以只使用您的相机位置作为光线的来源(取决于您在做什么)。
我的部分问题是描述不当。我不小心留下了疯狂测试的残留代码,导致一些“读取像素”函数和相关的废话,这对解决问题没有用。
我的其他问题是由于矩阵的数据类型不一致,并且试图从 OpenGL 中提取矩阵,而 OpenGL 一开始就没有存储它们。
问题已解决:
- Using GLM to hold all my matrices
- 自己进行计算(逆视图矩阵*逆模型矩阵*逆投影矩阵)*持有NDC转换屏幕的向量space坐标(-1到1的范围:x或y除以宽度或高度, * 2 - 1), 它的远平面或近平面的 z 也为 -1 或 1,w 为 1.
- 将结果除以向量的第四个点。
我仍然不知道为什么 unprojecting 对我不起作用,因为我用 GLU 和 GLM 的 unproject 函数得到了错误的结果,但是手动操作对我有用。
由于我的问题持续了相当长的时间,并提出了几个问题,我要感谢一路上帮助过我的几个人:
- srobins of facepunch, in this thread
- derhass from here, in this question, and this discussion