1

I am trying to write a function that draws an image, given screen coordinates, and it places it in world coordinates in 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;
}

been called by :

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);

This is the vertex shader :

#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);
};

This is the fragment shader :

#version 330

out vec4 FragColor;
in vec2 TexCoord;
uniform sampler2D texture_sampler;
void main() 
{
   FragColor = texture(texture_sampler, TexCoord);
};

The result is never the same depending on the image size, it kind of works if I place it at the middle (960, 540), but when I try to display at the left/upper corner or right/lower corner, it is a mess. I know there are several of these questions around (glm::unproject) but been trying for several days to solve it.

genpfault
  • 51,148
  • 11
  • 85
  • 139
Mrax
  • 63
  • 9
  • The algorithm seem to work fine. The vertex coordinate (0, 0) is placed at (x, y) respectively (100, 150) in the example. What are the vertex coordinates? Is the window size (1920.0, 1080.0)? – Rabbid76 Apr 03 '20 at 08:19
  • Yes, the window size is 1920x1080. But if you try with different images, it places randomly, and placing it 0,0 or nowhere near in the world coordinate, same thing happens if you try to place lower/right. – Mrax Apr 03 '20 at 14:49
  • What do you mean by different images!? I just can see that small snippet of your code. All I can say about is, that the algorithm in the method `showImage` works fine. – Rabbid76 Apr 03 '20 at 14:53
  • float width = (int)(sxImage * 100 + 0.5) / 1920; width = width / 100; float height = (int)(syImage * 100 + 0.5) / 1080; height = height / 100; float vertices[] = { // positions // texture coords width, -(height), 0.0f, 1.0f, 1.0f, // top right -(width), -(height), 0.0f, 0.0f, 1.0f, // bottom right width, height, 0.0f, 1.0f, 0.0f, // bottom left -(width), height, 0.0f, 0.0f, 0.0f // top left }; unsigned int indices[] = { 0, 1, 2, // first triangle 2, 1, 3 // second triangle }; – Mrax Apr 03 '20 at 14:55
  • Different Images, if you load, different images to be displayed, with different sizes, it gets lost. – Mrax Apr 03 '20 at 14:58
  • @Mrax take a look at [OpenGL 3D-raypicking with high poly meshes](https://stackoverflow.com/a/51764105/2521214) and inspect `void glMouse::pick(double x,double y) ` it computes among other things the 3D world position from 2D screen position and depth buffer ... – Spektre Jun 07 '20 at 08:36
  • As always Spektre, worked perfectly! Thank you so much for your pointers!!! Best regards always! – Mrax Jun 07 '20 at 15:18

1 Answers1

0

Answering my own question :

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;
}
Mrax
  • 63
  • 9