使用 glm::perspective 时,如何将鼠标的实际像素位置映射到标准化位置?

Posted

技术标签:

【中文标题】使用 glm::perspective 时,如何将鼠标的实际像素位置映射到标准化位置?【英文标题】:How I can map the position in real pixels of the mouse to a normalized one when using glm::perspective? 【发布时间】:2021-01-02 01:33:56 【问题描述】:

我正在使用 OpenGL 绘制 2D 平铺地图,我希望能够知道鼠标的位置与我的场景相对应的位置。这是我目前拥有的:

使用这个投影来绘制这个屏幕

glm::mat4 projection = glm::perspective(
  glm::radians(45.0f),
  (float)screenWidth / (float)screenHeight,
  1.0f,
  100.0f
);

然后这个相机用来移动和缩放tilemap

glm::vec3 camera(0.0f, 0.0f, -1.00f);

然后转化为相机视图

glm::mat4 cameraView = glm::translate(state.projection, camera);

最终通过制服传递给顶点着色器

#version 330 core

layout(location = 0) in vec2 aPosition;

uniform mat4 uCameraView;

void main() 
  gl_Position = uCameraView * vec4(aPosition.x, aPosition.y, 0.0f, 1.0f);

这个着色器接收一个归一化的顶点,这意味着我永远不知道我的屏幕上一个图块有多少像素。

现在我正在尝试以某种方式计算鼠标在我的场景中的位置,如果它像射线一样投射到瓷砖地图中然后击中它。如果我设法获得了碰撞的位置,我将能够知道鼠标悬停在哪个瓷砖上。

找到这个坐标的最佳方法是什么?

【问题讨论】:

glm(广义线性模型)!= glm-math(GLM - OpenGL 数学) 相关OpenGL - Mouse coordinates to Space coordinates 【参考方案1】:

最后我找到了将鼠标像素坐标映射到透视图的解决方案:

glm::vec4 tile = glm::translate(projection, glm::vec3(0.0f, 0.0f, camera.z)) *
  glm::vec4(size.tile.regular, size.tile.regular, camera.z, 1.0f);
glm::vec3 ndcTile =
  glm::vec3(tile.x / tile.w, tile.y / tile.w, tile.z / tile.w);

float pixelUnit = windowWidth * ndcTile.x;

float pixelCameraX = (camera.x / size.tile.regular) * pixelUnit;
float pixelCameraY = (camera.y / size.tile.regular) * pixelUnit;

float originX = (windowWidth / 2.0f) + pixelCameraX;
float originY = (windowHeight / 2.0f) - pixelCameraY;

float tileX = (state.input.pixelCursorX - originX) / pixelUnit;
float tileY = (state.input.pixelCursorY - originY) / pixelUnit;

selectedTileX = tileX > 0 ? tileX : tileX - 1;
selectedTileY = tileY > 0 ? tileY : tileY - 1;

【讨论】:

以上是关于使用 glm::perspective 时,如何将鼠标的实际像素位置映射到标准化位置?的主要内容,如果未能解决你的问题,请参考以下文章

更改 glm::perspective 中的角度反映对象

Model, View(Camera), Perspective

在 Opengl 中使用 glm 旋转

glm::透视解释

一些opengl和glm解释

为对象生成 MVP