正在寻找 glm::unProject 的备份 winZ
Finding backup winZ for glm::unProject
我有一个基本上只渲染一堆点的 OpenGL 程序。我需要从任意光标位置找到 world-space 坐标,我这样做是这样的:
glm::mat4 modelview = graphics.view*graphics.model;
glm::vec4 viewport = { 0.0, 0.0, windowWidth, windowHeight };
float winX = cursorX;
float winY = viewport[3] - cursorY;
float winZ;
glReadPixels(winX, winY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ);
glm::vec3 screenCoords = { winX, winY, winZ };
glm::vec3 cursorPosition = glm::unProject(screenCoords, modelview, graphics.projection, viewport);
如果光标在某个对象上,这会很好地工作,但如果它在屏幕的空白部分(即大部分),则假定它在远裁剪平面上 (winZ = 1),并且 glm::unProject returns inf 值。理想情况下,我想向它传递一个不同的 winZ,对应于世界 space 坐标中 z=0 处的 xy 平面,但我不知道如何获得该值。
因为还有一个 glm::unProject
function, the is a glm::project
功能。
如果你想知道一个点的深度,它位于视图 space 的平行平面上,z 坐标为 0,那么你必须 glm::project
一个点在这架飞机上。它可以是平面上的任何一点,因为您只对它的 z 坐标感兴趣。您可以为此使用世界的起源:
glm::vec3 world_origin{ 0.0f, 0.0f, 0.0f };
glm::vec3 origin_ndc = glm::project(screenCoords, view, graphics.projection, viewport);
float depth0 = world_origin[2];
其中 view
是视图矩阵,它从世界 space 转换为摄像机 space(来自 glm::lookAt
)。
因此实现可能如下所示:
glm::mat4 modelview = graphics.view * graphics.model;
glm::vec4 viewport = { 0.0, 0.0, windowWidth, windowHeight };
float winX = cursorX;
float winY = viewport[3] - cursorY;
float depth;
glReadPixels(winX, winY- cursorY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
const float epsi = 0.00001f;
if ( depth > 1.0f-epsi )
{
glm::vec3 world_origin{ 0.0f, 0.0f, 0.0f };
glm::vec3 origin_ndc = glm::project(world_origin, graphics.view, graphics.projection, viewport);
depth = origin_ndc[2];
}
glm::vec3 screenCoords{ winX, winY, depth };
glm::vec3 cursorPosition = glm::unProject(screenCoords, modelview, graphics.projection, viewport);
我有一个基本上只渲染一堆点的 OpenGL 程序。我需要从任意光标位置找到 world-space 坐标,我这样做是这样的:
glm::mat4 modelview = graphics.view*graphics.model;
glm::vec4 viewport = { 0.0, 0.0, windowWidth, windowHeight };
float winX = cursorX;
float winY = viewport[3] - cursorY;
float winZ;
glReadPixels(winX, winY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ);
glm::vec3 screenCoords = { winX, winY, winZ };
glm::vec3 cursorPosition = glm::unProject(screenCoords, modelview, graphics.projection, viewport);
如果光标在某个对象上,这会很好地工作,但如果它在屏幕的空白部分(即大部分),则假定它在远裁剪平面上 (winZ = 1),并且 glm::unProject returns inf 值。理想情况下,我想向它传递一个不同的 winZ,对应于世界 space 坐标中 z=0 处的 xy 平面,但我不知道如何获得该值。
因为还有一个 glm::unProject
function, the is a glm::project
功能。
如果你想知道一个点的深度,它位于视图 space 的平行平面上,z 坐标为 0,那么你必须 glm::project
一个点在这架飞机上。它可以是平面上的任何一点,因为您只对它的 z 坐标感兴趣。您可以为此使用世界的起源:
glm::vec3 world_origin{ 0.0f, 0.0f, 0.0f };
glm::vec3 origin_ndc = glm::project(screenCoords, view, graphics.projection, viewport);
float depth0 = world_origin[2];
其中 view
是视图矩阵,它从世界 space 转换为摄像机 space(来自 glm::lookAt
)。
因此实现可能如下所示:
glm::mat4 modelview = graphics.view * graphics.model;
glm::vec4 viewport = { 0.0, 0.0, windowWidth, windowHeight };
float winX = cursorX;
float winY = viewport[3] - cursorY;
float depth;
glReadPixels(winX, winY- cursorY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
const float epsi = 0.00001f;
if ( depth > 1.0f-epsi )
{
glm::vec3 world_origin{ 0.0f, 0.0f, 0.0f };
glm::vec3 origin_ndc = glm::project(world_origin, graphics.view, graphics.projection, viewport);
depth = origin_ndc[2];
}
glm::vec3 screenCoords{ winX, winY, depth };
glm::vec3 cursorPosition = glm::unProject(screenCoords, modelview, graphics.projection, viewport);