将图像从屏幕坐标转换为世界坐标

Posted

技术标签:

【中文标题】将图像从屏幕坐标转换为世界坐标【英文标题】:convert image from screen coordinate to world coordinate 【发布时间】:2020-04-02 23:25:41 【问题描述】:

我正在尝试编写一个函数来绘制图像,给定屏幕坐标,并将其放置在 OpenGL 中的世界坐标中。

glm::vec3 CImage::showImage(float x, float y)

    float screenW = 1920.0f;
    float screenH = 1080.0f;
    float xPosition = x;
    float yPosition = y;
    xPosition = xPosition * 2 / screenW - 1;
    yPosition = yPosition * (-2 / screenH) + 1;

    glm::vec4 viewport = glm::vec4(0.0f, 0.0f, screenW, screenH);
    glm::mat4 projectionMatrix = glm::ortho(0.0f, screenW, screenH, 0.0f, -1.0f, 1.0f);
    glm::mat4 model = glm::mat4(1.0f);
    glm::vec2 pixel_pos = glm::vec2(xPosition, screenH - yPosition);
    glm::vec3 world = glm::unProject(glm::vec3(pixel_pos, 0), model, projectionMatrix, viewport);

    return world;

被调用:

glm::mat4 transform = glm::mat4(1.0f);
transform = glm::translate(transform, showImage(100, 150));//screen coordinates
glUseProgram(shaderProgram);
unsigned int transformLoc = glGetUniformLocation(shaderProgram, "transform");
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(transform));
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

这是顶点着色器:

#version 330

layout(location = 0) in vec3 aPos;
layout(location = 1) in vec2 aTexCoord;
out vec2 TexCoord;
uniform mat4 transform;
void main() 

   gl_Position = transform * vec4(aPos, 1.0);
   TexCoord = vec2(aTexCoord.x, aTexCoord.y);
;

这是片段着色器:

#version 330

out vec4 FragColor;
in vec2 TexCoord;
uniform sampler2D texture_sampler;
void main() 

   FragColor = texture(texture_sampler, TexCoord);
;

根据图像大小,结果永远不会相同,如果我将它放在中间(960、540),它会起作用,但是当我尝试在左/上角或右/下角显示时,这是一团糟。 我知道周围有几个这样的问题 (glm::unproject),但我已经尝试了几天来解决它。

【问题讨论】:

算法似乎运行良好。在示例中,顶点坐标 (0, 0) 分别放置在 (x, y) 处 (100, 150)。什么是顶点坐标?窗口大小是(1920.0、1080.0)吗? 是的,窗口大小为 1920x1080。但是,如果您尝试使用不同的图像,它会随机放置,并将其放置在世界坐标的 0,0 或附近,如果您尝试将其放置在下方/右侧,则会发生同样的情况。 不同的图像是什么意思!?我只能看到你代码的那个小sn-p。我只能说,showImage 方法中的算法运行良好。 浮点宽度 = (int)(sxImage * 100 + 0.5) / 1920;宽度 = 宽度 / 100;浮动高度 = (int)(syImage * 100 + 0.5) / 1080;高度 = 高度 / 100; float vertices[] = // 位置 // 纹理坐标 width, -(height), 0.0f, 1.0f, 1.0f, // 右上角 -(width), -(height), 0.0f, 0.0f, 1.0 f, // 右下角 width, height, 0.0f, 1.0f, 0.0f, // 左下角 -(width), height, 0.0f, 0.0f, 0.0f // 左上角 ; unsigned int indices[] = 0, 1, 2, // 第一个三角形 2, 1, 3 // 第二个三角形 ; 不同的图片,如果你加载,不同的图片显示,不同的大小,会丢失。 【参考方案1】:

回答我自己的问题:

glm::vec3 CImage::showImage(float x, float y)

    float screenW = 1920;
    float screenH = 1080;
    float xPosition = x;
    float yPosition = y;
    float sxImage = 100; 
    float syImage = 100; 

    xPosition = xPosition * 2 / screenW - 1;
    yPosition = yPosition * (-2 / screenH) + 1;
    glm::vec4 viewport = glm::vec4(0.0f, 0.0f, screenW, screenH);
    glm::mat4 projectionMatrix = glm::ortho(0.0f, screenW, screenH, 0.0f, -1.0f, 1.0f);
    glm::mat4 model = glm::mat4(1.0f);
    glm::vec2 pixel_pos = glm::vec2(xPosition, screenH - yPosition);
    pixel_pos = pixel_pos + glm::vec2(sxImage / screenW, syImage / screenH);
    glm::vec3 world = glm::unProject(glm::vec3(pixel_pos, 0), model, projectionMatrix, viewport);

    return world;

【讨论】:

以上是关于将图像从屏幕坐标转换为世界坐标的主要内容,如果未能解决你的问题,请参考以下文章

将窗口坐标转换为屏幕坐标??

OpenGL:如何将世界坐标转换为屏幕坐标?

在 CUDA 中,如何在内核函数中将屏幕空间坐标转换为世界空间坐标

如何将 2D 世界转换为屏幕坐标 OpenGL

Unity3D之笛卡尔坐标系转换——屏幕坐标转换世界坐标,世界坐标转换相机坐标工具

Unity3D之笛卡尔坐标系转换——屏幕坐标转换世界坐标,世界坐标转换相机坐标工具