 # openGL/GLSL Projection matrix

Hi everyone. I am new on this forum and I have the following question.

I want to use a glsl shader to set the view matrix and the projection matrix of the camera.
Basically, the shader would look like (tell me if I’m wrong).

uniform mat4 projMatrix;
uniform mat4 viewMatrix;
void main()
{

``````gl_FrontColor = gl_Color;
``````
``````gl_Position = projMatrix*viewMatrix * gl_Vertex;
``````

}

The problem is that in my case, I want to impose a given mapping from Camera coordinate system to window coordinate system (rather than to the clip plane coordinate system). This mapping is characterized by a 3 by 3 matrix P of this form:

P=
[fx 0 cx
0 fy cy
0 0 1 ]

My main problem is to compute projMatrix (4x4 matrix used in the shader) from P.
Unfortunately, I don’t know well enough the transformations applied by OpenGL to map clip plane coordinate system to window coordinate system.
Thanks to anyone helping on this.
regards
Loic

if M ur modelview matrix, P ur projection matrix and V ur vertex in object space.
so ur vertex in eye space Ve=MV;
now to project it to the camera space u have to do the following :
//normalize
Ve.x=Ve.x/Ve.z;
Ve.y=Ve.y/Ve.z;
Ve.z=1;
now to find ur screen coordinate u ,v:
u=fx
Ve.x+cx;
v=fy*Ve.y+cy;

You’re perfectly right, but I don’t see how it would help me to compute projMatrix. To be clearer, my original problem was not to compute the projection of V in the screen coordinate (what you explained very well), but rather to compute the necessary projection matrix so that the pipeline :
V --> Ve=MV --> Vclip = projMatrixVe --> Vscreen= unknown function of Vclip

is equivalent to the pipeline you described :
V --> Ve=MV --> Ve/=Ve.z --> Vscreen=(u,v,1)=PVe

I insist that, what I can’t figure out is how Vscreen depends on Vclip in openGl pipeline. If I knew this, I think I could determine projMatrix so that both path give the same Vscreen…

Hope, I’m more precise.

glFrustum(-zNearcx/fx,zNear(image_width-cx)/fx,
-zNearcy/fy,zNear(image_height-cy)/fy,zNear,Zfar);
with zNear>0
this will generate a virtual camera perspective identical to ur real camera perspective with fx,fy,cx,cy ( assuming that u have removed the distortions)

now to find the matrix generated by glFrustum go to the sdk doc :
http://www.opengl.org/sdk/docs/man/xhtml/glFrustum.xml
and calculate the matrix paramters then u can send this matrix to ur shader.
hope this will help u !

Hi Abdallah,
Thanks a lot for your persistence. And indeed, I owe you one, I’m very close to the solution. Just in case someone in the future have similar issue I will try to post the solution.

Before that, here is a link that made my mind clear about openGL transform (mainly w.r.t. the clip plane to viewport c.s. part)
openGL Transform pipeline

For the sake of comprehension, I will make my notations more explicit.

``````
V_dcs=V_dcs.xyz is the window coordinate of the projected point
V_vcs=V_vcs.xyzw are the camera coordinate of the 3D point.

``````

Then given an openGL projection matrix P (possibly created with glFrustum), openGl takes care of the transformation in the way exposed in the above link.

``````
First, V_vcs is turned into V_ccs = P*V_vcs
Then, V_ccs is turned into V_ndcs = V_ccs.xyz/V_ccs.w
and finally, V_ndcs is turned into V_dcs as follows
(in the case the view port is glViewport(0,0,w,h)) :
V_dcs.x = w*(V_ndcs.x+1)/2 and similar for y coordinate

``````

Then the problem is that I want to impose a given global transformation from V_vcs to V_dcs. This transformation is specified as follow.

``````
V_vcs is turned into V_tmp.xyz= Q*V_vcs.xyz/V_vcs.w
V_dcs.xy=V_tmp.xy/V_tmp.z
and
Q=
[fx 0 cx
0 fy cy
0 0 1 ]
Finally, we get the following formula (assuming that V_vcs.w=1):
V_dcs.x = cx+ fx*V_vcs.x/V_vcs.z

``````

So the problem is that I know Q (ie fx, cx,…), but as I want to use openGL power, I need to specify P that would do the same job. And using Abdallah’s hints here is what I get:

Setting P=glFrustum(-zNearcx/fx,zNear(w-cx)/fx,-zNearcy/fy,zNear(h-cy)/fy,zNear,Zfar), we get:

``````
P=
[2*fx/w    0    (w-2*cx)/w    0
0    2*fy/h (h-2*cy)/h    0
0      0        C         D
0      0        -1        0]

``````

Hence,

``````
V_ccs.x=2*fx/w*V_vcs.x+(w-2*cx)/w*V_vcs.z
V_ccs.w=-V_vcs.z

``````

Then

``````
V_ndcs.x=-(2*fx*V_vcs.x/V_vcs.z + (w-2*cx))/w

``````

And finally,

``````
V_dcs.x=(1-(2*fx*V_vcs.x/V_vcs.z + (w-2*cx))/w)*w/2
= -2*fx*V_vcs.x/V_vcs.z + cx

``````

which differs from what I want by the minus in front of 2fxV_vcs.x/V_vcs.z
The modification, to make it works as I want seems obvious :
P=glFrustum( zNearcx/fx,-zNear(w-cx)/fx, zNearcy/fy, -zNear(h-cy)/fy,zNear,Zfar).
Unfortunately, cx,fx,cy and fy are positive parameters. This would mean that the right corner of the frustum is on the left and vice versa. I don’t know how bad it is, but I think It’s rather likely that I am missing something obvious which leads to this situation.
I’ll keep you informed if I find the answer.

It seems that having P=glFrustum( zNearcx/fx,-zNear(w-cx)/fx, zNearcy/fy, -zNear(h-cy)/fy,zNear,Zfar) ie putting the right boundary of the frustum on the left and vice versa works.