Advertisement

OpenGL 4.2 LookAt matrix only works with -z value for eye position

Started by September 17, 2019 12:04 PM
22 comments, last by DBisar 5 years, 3 months ago

I am trying to understand the model view projection matrix usage since a few days now, and still have some issues i just don't understand. I am using OpenTK (.NET OpenGL wrapper library).

Here is a "working" setup: (it displays the triangle)


// ### setup OpenGL ###
// not sure if this is important; this is basically just so that i can render only in part of a screen because the OpenGL thing is part of a larger project
// it's included just in case...
GL.Enable(EnableCap.ScissorTest);

GL.Viewport(0, 0, (int)windowPosition.Width, (int)windowPosition.Height);
GL.Scissor(x, y, width, height);

// maybe more important
GL.Enable(EnableCap.DepthTest);
GL.Disable(EnableCap.CullFace); // should be default value, but i am not sure if it is



// ### rendering ###
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

var projection = Matrix4.CreateOrthographic(3, 3, 0.001f, 50);

var view = Matrix4.LookAt(
                new Vector3(0.5f, 0.5f, -2),
                new Vector3(0.5f, 0.5f, 0),
                new Vector3(0, 1, 0));

var viewProjectionMatrix = projection * view;

// set uniforms...

var modelMatrix = ...
// values are: (scaling by factor 2)
// [2 0 0 0]
// [0 2 0 0]
// [0 0 2 0]
// [0 0 0 1]


// triangle vertices
var data = new float[]
{
    0, 0, 0,
    1, 0, 0,
    0, 1, 0
};



// ### vertex shader ###
Vertex Shader:

#version 420

layout(location = 0) in vec3 position;

uniform mat4 viewProjection;
uniform mat4 model;

out vec3 outColor;

void main()
{
    gl_Position = viewProjection * model * vec4(position, 1);
    outColor = vec3(1,1,1);
}

As I said this setup works. As far as I understand this will create a "camera" placed further down the z axis (which in open gl normally means farther behind), since positive z values point to the viewer by default.

The problem:

To keep the usual OpenGL setup I would like the the camera eye to placed at new Vector3(0.5f, 0.5f, 2) instead of new Vector3(0.5f, 0.5f, -2), but for some reason I can't see the triangle anymore. I drew it on paper and don't get it. As you can see FaceCulling is explicitly disabled, so this can't be the reason.

Maybe I am misunderstanding something.


And just in case the problem is the the Matrix4.LookAt function, here is the matrix it creates (no idea if this makes sense)

with eye-z = -2

view: (eye-z = -2)
(-1, 0, 0, 0)
(0, 1, 0, 0)
(0, 0, -1, 0)
(0.5, -0.5, -2, 1)

projection:
(0.6666667, 0, 0, 0)
(0, 0.6666667, 0, 0)
(0, 0, -0.0400008, 0)
(0, 0, -1.00004, 1)

projection * view:
(-0.6666667, 0, 0, 0)
(0, 0.6666667, 0, 0)
(0, 0, 0.0400008, 0)
(0.5, -0.5, -0.9999601, 1)


view: (eye-z = 2)
(1, 0, 0, 0)
(0, 1, 0, 0)
(0, 0, 1, 0)
(-0.5, -0.5, -2, 1)

projection:
(0.6666667, 0, 0, 0)
(0, 0.6666667, 0, 0)
(0, 0, -0.0400008, 0)
(0, 0, -1.00004, 1)

projection * view:
(0.6666667, 0, 0, 0)
(0, 0.6666667, 0, 0)
(0, 0, -0.0400008, 0)
(-0.5, -0.5, -3.00004, 1)

 

Your orthographic matrix looks strange, or has OpenTK a special version ?

Change it to left, right, bottom, up, e.g. 0, 640, 0, 480.

Scrub. It has. Sorry for the nonsense.

Aand: coordinate spaces.

I had to read it over and again ?

Advertisement

This is what OpenTK does


/// <summary>Creates an orthographic projection matrix.</summary>
    /// <param name="width">The width of the projection volume.</param>
    /// <param name="height">The height of the projection volume.</param>
    /// <param name="zNear">The near edge of the projection volume.</param>
    /// <param name="zFar">The far edge of the projection volume.</param>
    /// <rereturns>The resulting Matrix4 instance.</rereturns>
    public static Matrix4 CreateOrthographic(
      float width,
      float height,
      float zNear,
      float zFar)
    {
      Matrix4 result;
      Matrix4.CreateOrthographicOffCenter((float) (-(double) width / 2.0), width / 2f, (float) (-(double) height / 2.0), height / 2f, zNear, zFar, out result);
      return result;
    }

    /// <summary>Creates an orthographic projection matrix.</summary>
    /// <param name="left">The left edge of the projection volume.</param>
    /// <param name="right">The right edge of the projection volume.</param>
    /// <param name="bottom">The bottom edge of the projection volume.</param>
    /// <param name="top">The top edge of the projection volume.</param>
    /// <param name="zNear">The near edge of the projection volume.</param>
    /// <param name="zFar">The far edge of the projection volume.</param>
    /// <param name="result">The resulting Matrix4 instance.</param>
    public static void CreateOrthographicOffCenter(
      float left,
      float right,
      float bottom,
      float top,
      float zNear,
      float zFar,
      out Matrix4 result)
    {
      result = Matrix4.Identity;
      float num1 = (float) (1.0 / ((double) right - (double) left));
      float num2 = (float) (1.0 / ((double) top - (double) bottom));
      float num3 = (float) (1.0 / ((double) zFar - (double) zNear));
      result.Row0.X = 2f * num1;
      result.Row1.Y = 2f * num2;
      result.Row2.Z = -2f * num3;
      result.Row3.X = (float) -((double) right + (double) left) * num1;
      result.Row3.Y = (float) -((double) top + (double) bottom) * num2;
      result.Row3.Z = (float) -((double) zFar + (double) zNear) * num3;
    }

 

Yeah, my fault. I just looked it up ... looks right.

You can disable scissor and depth test. They are not needed here.

Try setting the camera at 0, 0, -2 and look at 0,0,0. I think that's where your triangle is ...

Scissor is just to render it only in part of the screen (actually this is a control with it's own OpenGL context as part of a usually 2d library; didn't want to make the question to complicated).

@Green_Baron: yes this works. Just as the setup above, doesn't really solve my problem. I don't know what is strange to me is, that the values that work for eye z coordinate are from  < 0 until -2 all other values do not render anything. When the value becomes 0 or less the triangle suddenly disappears and when the value become ~ greater 2 the same. It seems like some kind of clipping takes place...

 

By the way, my fragment shader:


#version 420

in vec3 outColor;
out vec4 fragmentColor;

void main()
{
    fragmentColor = vec4(outColor, 1);
}

 

Disabled DepthTest and ScissorTest does not change anything...

What makes me wondering the most now is the this:

target for both = 0, 0, 0

eye = 0,0,-1


projection:
(0.6666667, 0, 0, 0)
(0, 0.6666667, 0, 0)
(0, 0, -0.0400008, 0)
(0, 0, -1.00004, 1)
view:
(-1, 0, 0, 0)
(0, 1, 0, 0)
(0, 0, -1, 0)
(0, 0, -1, 1)
Vector 0
(0, 0, 0)
(0, 0, 0, 1) // is the vector multiplied with the view matrix
(0, 0, 0, 1) // is the vector multiplied with the view and projection matrix (means: value = proj * view * vec)
Vector 1
(1, 0, 0)
(-1, 0, 0, 1)
(-0.6666667, 0, 0, 1)
Vector 2
(0, 1, 0)
(0, 1, 0, 1)
(0, 0.6666667, 0, 1)

Shows the triangle. If i set eye to:

eye = 0, 0, -2.1f


projection:
(0.6666667, 0, 0, 0)
(0, 0.6666667, 0, 0)
(0, 0, -0.0400008, 0)
(0, 0, -1.00004, 1)
view:
(-1, 0, 0, 0)
(0, 1, 0, 0)
(0, 0, -1, 0)
(0, 0, -2.1, 1)
Vector 0
(0, 0, 0)
(0, 0, 0, 1)
(0, 0, 0, 1)
Vector 1
(1, 0, 0)
(-1, 0, 0, 1)
(-0.6666667, 0, 0, 1)
Vector 2
(0, 1, 0)
(0, 1, 0, 1)
(0, 0.6666667, 0, 1)

So not a thing different but still this leads to not displaying anything.

Now i am just more confused...

Code used to generate the debug output:


var va = new[] {new Vector3(0, 0, 0), new Vector3(1, 0, 0), new Vector3(0, 1, 0)};
                
Console.WriteLine("projection:\n" + projection);
Console.WriteLine("view:\n" + view);

for (int i = 0; i < va.Length; i++)
{
    Console.WriteLine("Vector " + i);
    Console.WriteLine(va[i]);
    Console.WriteLine(view * new Vector4(va[i], 1));
    Console.WriteLine(projection * view * new Vector4(va[i], 1));
}

How I set the uniform matrices for the shader:


GL.UniformMatrix4(Id, false, ref value);

which shouldn't be the problem either, because for rotating the triangle itself it just works fine.

Advertisement

So, you found the triangle at 0,0,0 ?

Clipping takes place at the near and far planes and at <0 and >3 in x and y ...

with 


Matrix4.CreateOrthographic(3, 3, 0.001f, 50);

means width and height = 3, zNear = 0.001f, zFar = 50

Do i have to tell OpenGL somehow specifically were the clipping planes are?

How about your model matrix uniform...is that in a garbage state because it's commented out client side? What does that log?

Dev careful. Pixel on board.

15 minutes ago, DBisar said:

Do i have to tell OpenGL somehow specifically were the clipping planes are?

No. That's hardcoded in the pipeline. There are margins that be set, but they don't play a role here.

11 minutes ago, GoliathForge said:

How about your model matrix uniform...is that in a garbage state because it's commented out client side? What does that log?

If it is not set it should be an identity matrix.

Edit: but good point, for clarity it should be constructed with = mat4( 1.0f );

'Nother thing, do you actually set the view projection matrix ? What is 'value' ?

This topic is closed to new replies.

Advertisement