PDA

View Full Version : Final pixel position after transformations



Fugitive
10-08-2009, 03:55 AM
Hi guys,

I have two questions. First, i am trying to determine the final on-screen position of a vertex (actually a GL_POINT) in a shader. Here is what I am doing (in the vertex shader):



float WIDTH = 800.0;
float HEIGHT=650.0;

gl_FrontColor = gl_Color;
gl_Position = ftransform();

FinalPos.x = (gl_Position.x+1.0) * (WIDTH/2.0);
FinalPos.y = (gl_Position.y+1.0) * (HEIGHT/2.0);


1) Is this the correct way of doing it?

2) If the final on-screen position (in pixels) is fractional, will the final pixel position be chosen using round(),floor(), or ceil()? As far as I know, the OpenGL spec doesnt specify. Anyone know what ATI or NVidia do?

Kind regards,
Fugi

yooyo
10-08-2009, 05:46 AM
nope... This is what you need:


float HOROFFSET = 0.0;
float VERTOFFSET = 0.0;
float WIDTH = 800.0;
float HEIGHT=650.0;

gl_Position = ftransform();

// perspective divide
float oow = 1.0/gl_Position.w;
gl_Position.xyz *= oow;

// map to range 0..1
gl_Position.xyz = gl_Position.xyz * 0.5 + 0.5;

// map to viewport
gl_Position.x = gl_Position.x * WIDTH + HOROFFSET;
gl_Position.y = gl_position.y * HEIGHT + VERTOFFSET;

overlay
10-08-2009, 06:05 AM
No this is not correct.

Look at figure 2.6 "vertex transformation sequence", page 41, OpenGL spec 2.1.


gl_Position are the clip coordinates of the vertex.

From the clip coordinates, you first have to get the normalized coordinates with a perspective division:

vec3 n=gl_Position.xyz/gl_Position.w

Then apply the viewport transformation (section 2.11.1 controlling viewport, page 42)

vec2 lowerLeft; // lower left corner of the viewport, given
vec2 o; // center of the viewport, computed

// From end of page 42:
o.x=lowerLeft.x+WIDTH/2.0;
o.y=lowerLeft.y+HEIGHT/2.0;

vec3 win // window coordinates of the point

// from section 2.11.1
win.x=(WIDTH/2)*n.x+o.x
win.y=(HEIGHT/2)*n.y+o.y
// we don't care about win.z for this computation

Then, because you are looking for point coordinates, you have to refer to "section 3.3.1 Basic Point Rasterization", page 97.

"In the default state, a point is rasterized by truncating its x_w and y_w coordinates (...) to integer."

So the operation is not round(), floor() or ceil() but truncate, so it is just a matter of casting a "float" into an "int".

ivec2 FinalPos;
FinalPos.x=int(win.x);
FinalPos.y=int(win.y);

As a side note, chapter 3, page 90, remember that a fragment is a grid box (assumed square), located by its lowerleft corner, which lies on integer grid coordinates. The fragment's center is offset by (1/2,1/2) from its lower left corner, and so lies on half-integer coordinates.

yooyo
10-08-2009, 12:41 PM
yes.. you are right.. I should replace gl_Position with new variable after perspective division

overlay
10-08-2009, 01:04 PM
yooyo: My "No this is not correct." was addressed to Fugitive. When I started writing my post, yours wasn't there yet. It's only when I submitted it that I saw your answer :-)

yooyo
10-09-2009, 02:59 AM
:)

Fugitive
10-10-2009, 09:57 AM
Wow, thanks guys! That was very clear, and very useful. I will try it out and report back on know how it went.

Kind regards,
Fugi

Fugitive
10-10-2009, 12:08 PM
@Overlay,
Shouldnt win.x and win.y be normalized from 0 to1 by adding 1.0?

@Yooyo,
Shouldnt the last two lines be WIDTH/2 and HEIGHT/2 respectively?

Kind regards,
Fugi