Game Development Stack Exchange is a question and answer site for professional and independent game developers. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'm making a windows forms application with opengl view. I need to get the mouse coords converted to the opengl world coords. Well, my Y coord gets converted wrong. It's hard to explain, so here is the video: I'm constantly pressing left mouse button and the red dot should be where the mouse is(but it isn't). Here is the code:

    private void glview_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
        if (e.Button == MouseButtons.Left)
            Point worldCoords = convertScreenToWorldCoords(e.X, e.Y);
            shitx = worldCoords.X;
            shity = worldCoords.Y;

    // functions:
    public static Point convertScreenToWorldCoords(int x, int y)
        int[] viewport = new int[4];
        Matrix4 modelViewMatrix, projectionMatrix;
        GL.GetFloat(GetPName.ModelviewMatrix, out modelViewMatrix);
        GL.GetFloat(GetPName.ProjectionMatrix, out projectionMatrix);
        GL.GetInteger(GetPName.Viewport, viewport);
        Vector2 mouse;
        mouse.X = x;
        mouse.Y = viewport[3] - y;
        Vector4 vector = UnProject(ref projectionMatrix, modelViewMatrix, new Size(viewport[2], viewport[3]), mouse);
        Point coords = new Point((int)vector.X, (int)vector.Y);
        return coords;
    public static Vector4 UnProject(ref Matrix4 projection, Matrix4 view, Size viewport, Vector2 mouse)
        Vector4 vec;

        vec.X = 2.0f * mouse.X / (float)viewport.Width - 1;
        vec.Y = -(2.0f * mouse.Y / (float)viewport.Height - 1);
        vec.Z = 0;
        vec.W = 1.0f;

        Matrix4 viewInv = Matrix4.Invert(view);
        Matrix4 projInv = Matrix4.Invert(projection);

        Vector4.Transform(ref vec, ref projInv, out vec);
        Vector4.Transform(ref vec, ref viewInv, out vec);

        if (vec.W > float.Epsilon || vec.W < float.Epsilon)
            vec.X /= vec.W;
            vec.Y /= vec.W;
            vec.Z /= vec.W;

        return vec;
share|improve this question
up vote 1 down vote accepted

Finally, I got this fixed. I just changed

mouse.Y = viewport[3] - y;


mouse.Y = y + (ClientRectangle.Height - glview.Size.Height);

still not very accurate but not very bad.

share|improve this answer

I have exactly the same problem and have used your code. I think I fixed it fully now.

in ConvertScreenToWorld()
mouse.Y = viewport[3] - y;
mouse.Y = y;

in UnProject()
vec.Y = -(2.0f * mouse.Y / (float)viewport.Height - 1);
vec.Y = 2.0f * mouse.Y / (float)viewport.Height - 1;

then call it like convertScreenToWorldCoords(e.X,ClientRectangle.Height - e.Y);

it's very precise too bye!

share|improve this answer

I changed

-(vec.Y = 2.0f * mouse.Y / (float)viewport.Height) - 1;


-(vec.Y = 2.0f * mouse.Y / (float)viewport.Height) + 1;

and it works.

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.