Perspecitve divide in vertex shader?
Asked Answered
S

1

5

When using a perspective matrix in a vertex shader am I supposed to write code to divide by w or is it done automatically in a later stage?

The reason for my question is that I have seen lots of vertex shaders using:

gl_Position = matrix * pos;

which makes sense if there is a later stage that divides the vector with its w component.

However I never got it to work until I used the following in my vertex shader:

gl_Position = matrix * pos;
gl_Position = gl_Position / gl_Position.w;

Is the second example the correct one or could some other setting be missing?

Put it another way: which of the steps shown in the OpenGL Vertex transformation(first image) do I have to write in the vertex shader?

I know for sure that ModelView and Projection matrix belongs there(or a merge of the two). The viewport transform is not a part of the vertex shader, but what about the divide by w?

My setup is some simple triangles having coordinates within [-1 1] for x/y/z.

The Perspective matrix is supposed to project coordinates from z=-1 to -10 onto z=-1, x=[-1,1], y=[-1,1].

-1.0   0.0   0.0   0.0
 0.0  -1.0   0.0   0.0
 0.0   0.0  -1.2  -2.2
 0.0   0.0   1.0   0.0

It was generated by:

x = 2.0f * zNear / (xMax - xMin);
y = 2.0f * zNear / (yMax - yMin);
a = -(xMax + xMin) / (xMax - xMin);
b = -(yMax + yMin) / (yMax - yMin);
c = (zFar + zNear) / (zNear - zFar);
d = -(2.0f * zFar * zNear) / (zNear - zFar);

To make the matrix P:

x, 0, a, 0
0, y, b, 0
0, 0, c, d
0, 0, 1, 0;

Finally I generate the final matrix by matrix = P * T where T is a translation (0,0,-2)

I have tried to do the math on the CPU and it appears to work generating expected results, however there I also do the divide by w manually.

Update: Solved but need understanding

I negated all components in the matrix (multiply by -1) and now it works. The example above also had an issue with projecting both positive and negative z-coordinates onto the projection plane which also got solved by this change.

Any references or explanation why it got solved by this change is welcome.

Sanbenito answered 27/4, 2012 at 16:14 Comment(2)
I'm still not sure where you got those equations from, but if I look at gluPerspective, your 'd' value is exactly negated of what they use.Hoag
The formulas was derived from scratch with the matrix shown above with unknowns to start with.Sanbenito
H
5

You should not do the perspective divide yourself in the vertex shader, it will be done automatically later in the pipeline.

If that's not working, can you show some code or describe the problem more? I'm surprised that it's making a difference for you.

Hoag answered 27/4, 2012 at 16:23 Comment(5)
Good to know, then I know where not to "solve" my problem, I added more example about my configuration.Sanbenito
@phq - I'm confused by this statement: from z=-1 to -10 onto z=-1. What were your znear/zfar arguments, did you generate this with gluPerspective or equivalent? Clipping is done before perspective divide, so the only explanation could be is that your polygons are being clipped in the non-divide example, and not when you divide them manually.Hoag
I'm trying to generate the matrix myself withe the code above. the z-range [-1, -10] is supposed to map to [1, -1] and the projection place is perpendicular to the z-axis at z=-1.Sanbenito
You wouldn't happen to be uploading the matrix transposed, would you? In your example 'd' should be element 14. Otherwise I don't know where you got those equations from, but I'd recommend trying to emulate something like the equations given on gluPerspective man page, unless this is some kind of academic exercise.Hoag
Yes the goal is understanding, I'm using M*v multiplication thus column vectors which should be reflected in the matrix if it is correct. See question update, a small change made it work. Still not sure why.Sanbenito

© 2022 - 2024 — McMap. All rights reserved.