Sign in to follow this  
sufimaster

OpenGL Orthographic matrix not working

Recommended Posts

sufimaster    113

Hi all,

 

I am having trouble creating an orthographic projection in opengl (without using glOrtho).  And before anyone tells me to use glOrtho, lets just pretend I'm using opengl 3.0 as an exercise.  Here is the way I have set up my matrix:

 

projectionMatrix.m00 = 2/WIDTH;
projectionMatrix.m11 = 2/HEIGHT;
projectionMatrix.m22 = -2/(far_plane - near_plane);
projectionMatrix.m32 = -((far_plane + near_plane)/(far_plane - near_plane));
projectionMatrix.m33 = 1;

This is your typical ortho projection matrix, taken straight from the opengl spec def. for glOrtho. 

 

When I set up a frustrum and use a perspective matrix, this works fine, but I can't use my regular screen coordinates properly.  But when I use the glOrtho matrix above, I see nothing but my background color. Anyone know what's going on? Is my matrix wrong?

 

My shader looks like this:

 

 

#version 150 core
uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform mat4 modelMatrix;


in vec4 in_Position;
in vec4 in_Color;
in vec2 in_TextureCoord;


out vec4 pass_Color;
out vec2 pass_TextureCoord;


void main(void){
    gl_Position = in_Position;
    
    //override gl position with new calculated position
    gl_Position = projectionMatrix * viewMatrix * modelMatrix * in_Position;
    
    pass_Color = in_Color;
    pass_TextureCoord = in_TextureCoord;


}

 

Any help appreciated.

 

Thanks!

 

 

 

Share this post


Link to post
Share on other sites
blueshogun96    2265

Try this:

 

void glOrtho(float* out, float left, float right,float bottom, float top,float near, float far)
{
    
    float a = 2.0f / (right - left);
    float b = 2.0f / (top - bottom);
    float c = -2.0f / (far - near);
    
    float tx = - (right + left)/(right - left);
    float ty = - (top + bottom)/(top - bottom);
    float tz = - (far + near)/(far - near);
    
    float ortho[16] = {
        a, 0, 0, 0,
        0, b, 0, 0,
        0, 0, c, 0,
        tx, ty, tz, 1
    };
    
    memcpy(out, ortho, sizeof(float)*16);
}

 

Your vertex program should be fine if it works with your perspective matrix.  Let me know if this fixes your problem, this has been confirmed to work for OpenGL ES 2.0.

 

Shogun.

Share this post


Link to post
Share on other sites
FLeBlanc    3141

What geometry are you feeding it?

 

A mistake I see sometimes is that people will be drawing, say, a quad: [b](-1,-1,0) -> (1,1,0)[/b] or some other geometry on a very small scale. Which will work fine with a perspective matrix, since you can always move your camera to near enough the object that it appears as large in the viewport as you need it to be. But in a screen-size orthographic projection, that 2x2 size quad will only ever be 2x2 pixels on screen, regardless of where you put your camera. This makes switching from perspective to ortho tricky, in that you have to think about the scale of your objects. If you make your base unit to be a meter for example (ie, 1 unit=1 meter) then you might have a character model that is 2 units tall. In an orthographic projection, this object will only be 2 pixels tall.

 

So if your geometry is small, you either need to scale the geometry or include a scaling factor when constructing your matrix.

Share this post


Link to post
Share on other sites
sufimaster    113

Well right now all I am trying to do is get a 40 pixel by 40 sprite displayed on the screen.  I have tried messing around with the size of the sprite to no avail.  Once I get home I will take a look at the code and give you some more details about it, but I have a feeling you ar right about the scaling/size/etc.

Share this post


Link to post
Share on other sites
sufimaster    113

Ok, so I have a sprite with x,y,z (10,10,0)  with w/h 10fx10f

 

I have left as 0 and right as 680

top as as 480, bottom as 0

 

Still I see nothing.

 

Also, I am using lwjgl, in which if you have a matrix4f, I think m23 means 2nd column, 3rd row. 

 

 

 

  

 

              Sprite sprite = new Sprite("assets/texture/redman.png", 50f, 50f, 10f, 10f );
 
projectionMatrix.m00 = 2/WIDTH;
        projectionMatrix.m11 = 2/HEIGHT;
        projectionMatrix.m22 = -2/(far_plane - near_plane);
        projectionMatrix.m30 = -1;
        projectionMatrix.m31 = -1;
        projectionMatrix.m32 = -((far_plane + near_plane)/(far_plane - near_plane));
        projectionMatrix.m33 = 1;

         cameraPos = new Vector3f(0,0,-1); ...

 

 

//Translate camera        
Matrix4f.translate(cameraPos, viewMatrix, viewMatrix);

        //Scale, translate and rotate model
        Matrix4f.scale(modelScale, modelMatrix, modelMatrix);
        Matrix4f.translate(modelPos, modelMatrix, modelMatrix);
        Matrix4f.rotate((float)Math.toRadians(modelAngle.z), new Vector3f(0,0,1), modelMatrix, modelMatrix);
        Matrix4f.rotate((float)Math.toRadians(modelAngle.y), new Vector3f(0,1,0), modelMatrix, modelMatrix);
        Matrix4f.rotate((float)Math.toRadians(modelAngle.x), new Vector3f(1,0,0), modelMatrix, modelMatrix);
 

 

 

..

Edited by sufimaster

Share this post


Link to post
Share on other sites
__SKYe    1784

Have you tried disabling back face culling?

If your sprite doesn't have the correct winding, and back face culling is enabled , then it will not be drawn.

 

Also, in OpenGL the Y coordinate goes from bottom to top, so make sure that you are positioning the sprite inside the view (unlike the projection matrix where point 0.0, 0.0, 0.0, is the center of the screen, on an orthographic projection, it is the left bottom corner).

Although you can change this when you build the matrix.

You can also try a bigger sprite, like with a size of (100, 100).

 

One last note. You should try the function Shogun posted to calculate your matrix. Somehow, and i might be wrong, but it doesn't seem like your matrix is being calculated like it should (again, it may be just me).

 

Don't know if this is your problem, but try it and see.

Edited by __SKYe

Share this post


Link to post
Share on other sites
sufimaster    113

Ok- so i used Shogun's method, I messed around with the camera position and near and far plane.

 

Now:

near plane is 1f, far plane is 100f (though I dont see why this matters in an ortho projection)

Camera is located at 0,0,-1

 

Sprite is at 0,0,0 dim: 10x10 pixels.

 

I can actually see it on the screen now, but it seems like everything is vanishing at the origin point, as attached:

 

This is supposed to be a quad, but the perspective is all wonky. Any idea what's going on now?

Share this post


Link to post
Share on other sites
mhagain    13430

How are you sending this to your shader?  Are you multiplying it by your previous projection matrix before doing so?  These are two other areas where things can go wrong, and you haven't provided sufficient info to diagnose.

Share this post


Link to post
Share on other sites
sufimaster    113

This is how I send it to the shader: I know this part works since the perspective projection matrix works, but the ortho produces wierd results. 

 

As for my previous projection matrix - this is my first projection matrix - so I am not multiplying it by anything before sending it tothe shader. Should I be?

///upload matrices to uniform varis in shader
        GL20.glUseProgram(shaderObject.pId);
        
        projectionMatrix.store(matrix44Buffer);matrix44Buffer.flip();            
        GL20.glUniformMatrix4(projectionMatrixLocation, false, matrix44Buffer);
        
        viewMatrix.store(matrix44Buffer);matrix44Buffer.flip();
        GL20.glUniformMatrix4(viewMatrixLocation, false, matrix44Buffer);
        
        modelMatrix.store(matrix44Buffer);matrix44Buffer.flip();
        GL20.glUniformMatrix4(modelMatrixLocation, false, matrix44Buffer);
        
        
        GL20.glUseProgram(0);
 

Share this post


Link to post
Share on other sites
sufimaster    113

I managed to figure this out - apparently I was not accessing the matrix elements correctly - transposing their accessors = m03 instead of m30 for example for the translation matrix.  All is well now! Thanks everyone. 

Share this post


Link to post
Share on other sites
Vincent_M    969

I noticed you're transforming your matrices as so:

 

projectionMatrix * viewMatrix * modelMatrix

 

This is also how I do it, but a lot of people do it opposite (and I think glOrtho does too). If this is the case, than the glOrtho() code provided above may be correct, but it just has to be transposed. Here's my camera's ortho code:

void Camera::Ortho(float width, float height, float zNear, float zFar)
	{
		Ortho(0.0f, width, 0.0f, height, zNear, zFar);
	}
	
	
	void Camera::Ortho(float left, float right, float top, float bottom, float zNear, float zFar)
	{
		// find the translation vector
		const float tx = - (right + left)/(right - left);
		const float ty = - (top + bottom)/(top - bottom);
		const float tz = - (zFar + zNear)/(zFar - zNear);
		
		// column 1
		projMat.m[ 0] = 2.0f / (right - left);
		projMat.m[ 1] = 0;
		projMat.m[ 2] = 0;
		projMat.m[ 3] = 0;
		
		// column 2
		projMat.m[ 4] = 0;
		projMat.m[ 5] = 2.0f / (top - bottom);
		projMat.m[ 6] = 0;
		projMat.m[ 7] = 0;
		
		// column 3
		projMat.m[ 8] = 0;
		projMat.m[ 9] = 0;
		projMat.m[10] = -2.0f / (zFar - zNear);
		projMat.m[11] = 0;
		
		// column 4
		projMat.m[12] = tx;
		projMat.m[13] = ty;
		projMat.m[14] = tz;
		projMat.m[15] = 1;
		
		mode = PROJECTION_MODE_ORTHOGONAL;
		Update(0.0f); // update the camera
	}

 

The first method is just a shortcut I created where the origin is in the upper-left corner of the screen is treated as the origin. The second method is what would emulate glOrtho() from the old OpenGL days, only it should be multiplied first like you have it.

 

Also, keep in mind that all matrix elements are an array of 16 floats stored on a column-by-column basis:

m[ 0] m[ 4] m[ 8] m[12]
m[ 1] m[ 5] m[ 9] m[13]
m[ 2] m[ 6] m[10] m[14]
m[ 3] m[ 7] m[11] m[15]

 

When you feed the matrix as a 4x4 to OpenGL, make sure that the transpose argument is GL_FALSE. That's very important.

Share this post


Link to post
Share on other sites
mhagain    13430

When you feed the matrix as a 4x4 to OpenGL, make sure that the transpose argument is GL_FALSE. That's very important.

 

Not really; please see http://www.opengl.org/archives/resources/faq/technical/transformations.htm

 

Column-major versus row-major is purely a notational convention. Note that post-multiplying with column-major matrices produces the same result as pre-multiplying with row-major matrices. The OpenGL Specification and the OpenGL Reference Manual both use column-major notation. You can use any notation, as long as it's clearly stated.

 

Also

 

Sadly, the use of column-major format in the spec and blue book has resulted in endless confusion in the OpenGL programming community. Column-major notation suggests that matrices are not laid out in memory as a programmer would expect.

 

OpenGL is perfectly capable of using either row-major or column-major matrices (and all the more so with the programmable pipeline); the only important thing is that you be consistent in your code.  That just means getting the multiplication orders correct in both your C/C++ code and your shader code.  You don't have to use the same major-ness in your shaders as you use in your C/C++: either transpose before sending (either manually or by using GL_TRUE in your glUniformMatrix call) or flip the multiplication order in your shader code.

 

So what's actually important is that you know which major-ness each element of your code uses and that you set things up appropriately for that; otherwise the importance of row-major versus column-major is hugely overstated.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Similar Content

    • By pseudomarvin
      I assumed that if a shader is computationally expensive then the execution is just slower. But running the following GLSL FS instead just crashes
      void main() { float x = 0; float y = 0; int sum = 0; for (float x = 0; x < 10; x += 0.00005) { for (float y = 0; y < 10; y += 0.00005) { sum++; } } fragColor = vec4(1, 1, 1 , 1.0); } with unhandled exception in nvoglv32.dll. Are there any hard limits on the number of steps/time that a shader can take before it is shut down? I was thinking about implementing some time intensive computation in shaders where it would take on the order of seconds to compute a frame, is that possible? Thanks.
    • By Arulbabu Donbosco
      There are studios selling applications which is just copying any 3Dgraphic content and regenerating into another new window. especially for CAVE Virtual reality experience. so that the user opens REvite or CAD or any other 3D applications and opens a model. then when the user selects the rendered window the VR application copies the 3D model information from the OpenGL window. 
      I got the clue that the VR application replaces the windows opengl32.dll file. how this is possible ... how can we copy the 3d content from the current OpenGL window.
      anyone, please help me .. how to go further... to create an application like VR CAVE. 
       
      Thanks
    • By cebugdev
      hi all,

      i am trying to build an OpenGL 2D GUI system, (yeah yeah, i know i should not be re inventing the wheel, but this is for educational and some other purpose only),
      i have built GUI system before using 2D systems such as that of HTML/JS canvas, but in 2D system, i can directly match a mouse coordinates to the actual graphic coordinates with additional computation for screen size/ratio/scale ofcourse.
      now i want to port it to OpenGL, i know that to render a 2D object in OpenGL we specify coordiantes in Clip space or use the orthographic projection, now heres what i need help about.
      1. what is the right way of rendering the GUI? is it thru drawing in clip space or switching to ortho projection?
      2. from screen coordinates (top left is 0,0 nd bottom right is width height), how can i map the mouse coordinates to OpenGL 2D so that mouse events such as button click works? In consideration ofcourse to the current screen/size dimension.
      3. when let say if the screen size/dimension is different, how to handle this? in my previous javascript 2D engine using canvas, i just have my working coordinates and then just perform the bitblk or copying my working canvas to screen canvas and scale the mouse coordinates from there, in OpenGL how to work on a multiple screen sizes (more like an OpenGL ES question).
      lastly, if you guys know any books, resources, links or tutorials that handle or discuss this, i found one with marekknows opengl game engine website but its not free,
      Just let me know. Did not have any luck finding resource in google for writing our own OpenGL GUI framework.
      IF there are no any available online, just let me know, what things do i need to look into for OpenGL and i will study them one by one to make it work.
      thank you, and looking forward to positive replies.
    • By fllwr0491
      I have a few beginner questions about tesselation that I really have no clue.
      The opengl wiki doesn't seem to talk anything about the details.
       
      What is the relationship between TCS layout out and TES layout in?
      How does the tesselator know how control points are organized?
          e.g. If TES input requests triangles, but TCS can output N vertices.
             What happens in this case?
      In this article,
      http://www.informit.com/articles/article.aspx?p=2120983
      the isoline example TCS out=4, but TES in=isoline.
      And gl_TessCoord is only a single one.
      So which ones are the control points?
      How are tesselator building primitives?
    • By Orella
      I've been developing a 2D Engine using SFML + ImGui.
      Here you can see an image
      The editor is rendered using ImGui and the scene window is a sf::RenderTexture where I draw the GameObjects and then is converted to ImGui::Image to render it in the editor.
      Now I need to create a 3D Engine during this year in my Bachelor Degree but using SDL2 + ImGui and I want to recreate what I did with the 2D Engine. 
      I've managed to render the editor like I did in the 2D Engine using this example that comes with ImGui. 
      3D Editor preview
      But I don't know how to create an equivalent of sf::RenderTexture in SDL2, so I can draw the 3D scene there and convert it to ImGui::Image to show it in the editor.
      If you can provide code will be better. And if you want me to provide any specific code tell me.
      Thanks!
  • Popular Now