Opengl:尝试绘制线条以可视化鼠标射线投射时出现意外行为

Posted

技术标签:

【中文标题】Opengl:尝试绘制线条以可视化鼠标射线投射时出现意外行为【英文标题】:Opengl:Unexpected behaviour when trying to draw a line to visualise mouse Ray cast 【发布时间】:2020-05-28 12:05:52 【问题描述】:

我正在尝试使用光线投射来在我的应用程序中实现鼠标拾取。 我想要做的是从字面上画出单击鼠标时从屏幕投射的线条。 这是我所做的:

float xNormalised = ((float)200/w.getWidth())*2 -1;
float yNormalised = -(((float)300/w.getHeight())*2 -1);

glm::vec4 nearP = glm::vec4(xNormalised,yNormalised,-1,1);
glm::vec4 farP = glm::vec4(xNormalised,yNormalised,1,1);

为简单起见,我硬编码了应该投射光线的鼠标坐标, 我将它们映射到标准化的设备坐标,然后创建两个向量,代表两个点:离屏幕最近的点和同一条线上最远的点。

worldNear = getInversedPoint(nearP,proj, view);
worldFar = getInversedPoint(farP,proj, view);

然后我在每个点上调用这个函数来基本上反转管道以在世界空间中获取它们的版本,这就是它的作用:

glm::vec4 getInversedPoint(glm::vec4 point,glm::mat4& proj,glm::mat4 view)

    //glm::mat4 inv = inverse(proj*view);
    point = point*inverse(proj);
    auto v = vec4(point.x/point.w,point.y/point.w,point.z/point.w,1);
    //auto v = vec4(point.x/point.w,point.y/point.w,point.z/point.w,point.w);
    point = v*inverse(view);
    return vec4(point.x,point.y,point.z,point.w);

在这之后,如果我没有弄错的话,我应该在世界空间中得到两分, 所以我把这两个点放在一个缓冲区中并调用 gldraw 来绘制连接它们的线。

我所期待的基本上是我放置的坐标中的一个红点,因为它是从点击点到它前面的点的一条直线......但我或多或少地得到了一条奇怪的线屏幕的中心,不是我指定的位置.. 我做错了什么?

您可以看到中间的红线,靠近横向三角形。 我的顶点着色器:

#version 330 core

layout(location = 1)in vec4 pos;
uniform mat4 projectMat;
uniform mat4 viewMat;

void main()
    gl_Position = pos;
 

我也尝试将点乘以这两个矩阵,但只是略有变化。

【问题讨论】:

【参考方案1】:

您可以使用 glm::unproject 获取远近点:

glm::vec3 near = glm::unProject(glm::vec3(mouseX, winSize.y - mouseY, 0), // the screen-space coordinate
                                camera.view,
                                camera.projection,
                                glm::vec4(0, 0, winSize)); // your viewport

glm::vec3 far = glm::unProject(glm::vec3(mouseX, winSize.y - mouseY, 0), // the screen-space coordinate
                               camera.view,
                               camera.projection,
                               glm::vec4(0, 0, winSize)); // your viewport

您也可以通过读取帧缓冲区直接获得鼠标下的点:

/** read depth buffer and get the point under the cursor **/
        float depth;
        glReadPixels(mouseX, winSize.y - mouseY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
        if (depth < 1.0)
            point_on_plane = glm::unProject(glm::vec3(mouseX, winSize.y - mouseY, depth), camera.view,
                                            camera.projection,
                                            glm::vec4(0, 0, winSize));

【讨论】:

以上是关于Opengl:尝试绘制线条以可视化鼠标射线投射时出现意外行为的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL:尝试使用 VBO(顶点缓冲区对象)绘制线条,它不显示

在 OpenGL 中绘制 2D 形状的轮廓,同时更改线条粗细

OpenGL 中的射线球相交

如何让用户在 WPF 中使用画布绘制线条

opengl 通过射线鼠标拾取怎么都得不到准确数据

OpenGL画好的线条,怎么用鼠标拾取