PDA

View Full Version : COVERSION: world coord -> screen coord -> world coord



Albert85
01-09-2015, 09:02 AM
Hello everybody
this is what I would like to do:

starting from 3D points in world coordinates, using the geometry shader I would like to:
1) move each point for example 5 pixels on the left
2) reconvert each point in world coordinates
3) extract the points using the trasformfeedbackbuffer

I have a problem with the reconversion of the points (from screen coordinates to world coordinates). Although I don't move the points (step (1)) their position is not the same.

This is the geometry shader:




#version 330 compatibility
#extension GL_ARB_geometry_shader4: enable

#define MAX_VERTICES 2


layout(points) in;
layout(points) out;

in vec3 my_Position[]; // Position
out vec3 movedPosition; // Position



vec3 fromWorldCoordsToScreenCoords(in vec3 wc)
{
vec4 pos0 = gl_ModelViewProjectionMatrix * vec4(wc, 1.0);
pos0 /= pos0.w;
return pos0.xyz;
}

vec3 fromScreenCoordsToWorldCoords(in vec3 sc)
{
vec4 wc = gl_ModelViewProjectionMatrixInverse * vec4(sc,1.0) ;
wc /= wc.w;
return (wc.xyz);
}


void main(void)
{

vec3 inputPos_ScreenCoord = fromWorldCoordsToScreenCoords(my_Position[0]);

vec3 movedPosition = fromScreenCoordsToWorldCoords(inputPos_ScreenCoord );

gl_Position = vec4(movedPosition,1.0);
gl_PointSize = 5;
EmitVertex();

// my_Position[0] is slightly different from gl_Position!!! WHY??
}



Can you help me?

Thanks!

Alfonse Reinheart
01-09-2015, 09:18 AM
You can't expect to get the same value back when you discard part of the value in the process.

In "fromWorldCoordsToScreenCoords", you divide by the clip-space W. However, you also destroy the clip-space W, since W/W == 1 (or NAN if W is zero). And even if you had properly retained the clip-space W, you still just drop that value on the floor, by returning just the XYZ. Then, in "fromScreenCoordsToWorldCoords", you divide by... er, something. I have no idea what vec4(sc,1.0) is supposed to be, but it is most certainly not something which can be multiplied by the inverse projection matrix to get a reasonable result.

There's a reason why the Fragment shader input gl_FragCoord (https://www.opengl.org/wiki/Fragment_Shader#System_inputs) is a vec4. And there's a reason why it's W component is 1/clipW, rather than 1.0 as you calculate.

Also, if you want to invert an operation, you have to invert each step, but you also must do the steps backwards. The division is the last thing in "fromWorldCoordsToScreenCoords", so it must be the first thing in the inverse.

And another thing: you're not in world space. The modelview matrix, as the name suggests, goes from model space to view space. And this, the inverse of this goes from view space to model space. World space never actually happens.

BTW, the OpenGL Wiki has a decent article on transforming back and forth between window space and camera/eye/etc space (https://www.opengl.org/wiki/Compute_eye_space_from_window_space). Adding world space to that is only a matter of using the right matrix.

Albert85
01-09-2015, 09:43 AM
The strange thing is that this shader is not completely wrong, it returns points that are just few "units" away from the original positions....

Another thing:

here (http://www.matrix44.net/cms/notes/opengl-3d-graphics/coordinate-systems-in-opengl)there is written the following:

There are multiple coordinate Systems involved in 3D Graphics:

Object Space
World Space (aka Model Space)
Camera Space (aka Eye Space or View Space)
Screen Space (aka Clip Space)

So World space IS EQUAL to Model Space.
Right?

Albert85
01-09-2015, 10:44 AM
I simplified the geometry shader in this way:


vec4 fromWorldCoordsToScreenCoords(in vec3 wc)
{
vec4 pos0 = gl_ModelViewProjectionMatrix * vec4(wc, 1.0);
return pos0;
}

vec3 fromScreenCoordsToWorldCoords(in vec4 sc)
{
vec4 wc = gl_ModelViewProjectionMatrixInverse * sc ;
return (wc.xyz);
}



void main(void)
{

vec4 inputPos_ScreenCoord = fromWorldCoordsToScreenCoords(my_Position[0]);
movedPosition = fromScreenCoordsToWorldCoords(inputPos_ScreenCoord );
EmitVertex();
}

But I have again the same problem. Can be a problem of float approximations?

This is the input:
point1: 0.0 | 4487348.5 | 4517591.0
point2:157785.03 | 4490884.0 | 4518372.5
point3:315624.47 | 4494419.5 | 4513640.0

this is the output:
point1: 8325.018 | 4442600.5 | 4463351.0
point2: 161462.64 | 4441388.5 | 4463836.0
point3: 314383.06 | 4437409.0 | 4456076.5

GClements
01-09-2015, 12:58 PM
There are multiple coordinate Systems involved in 3D Graphics:

Object Space
World Space (aka Model Space)
Camera Space (aka Eye Space or View Space)
Screen Space (aka Clip Space)

So World space IS EQUAL to Model Space.
Right?

That's just the author's choice of terminology.

Legacy OpenGL doesn't have any equivalent of "World Space (aka Model Space)". Vertices are specified in object space and transformed by the model-view matrix to eye space, then by the projection matrix to clip space.

If you're using shaders, you can have as many different spaces as you wish. OpenGL just treats the value written to gl_Position in the vertex shader as the vertex position in clip space. It doesn't care what you did to generate that value.

Alfonse Reinheart
01-09-2015, 01:16 PM
here (http://www.matrix44.net/cms/notes/opengl-3d-graphics/coordinate-systems-in-opengl)there is written the following:

There are multiple coordinate Systems involved in 3D Graphics:

Object Space
World Space (aka Model Space)
Camera Space (aka Eye Space or View Space)
Screen Space (aka Clip Space)

So World space IS EQUAL to Model Space.
Right?

Um, no. That page is criminally wrong.

Model space is a synonym for object space. Again, this is why it's called the "modelview" matrix. Old-school OpenGL makes this abundantly clear.

Also, clip space is not a synonym for screen space. Screen space and window space are interchangeable, but I've never seen anyone call clip space "screen space". Again, the OpenGL specification defines these two concepts, and they are not the same. Clip space is most assuredly not in screen-relative coordinates.

If that page has such glaring errors, I would strongly suggest you forget everything on it.

Dark Photon
01-09-2015, 06:59 PM
Um, no. That page is criminally wrong..
Yes, not good.

For a much better reference, Albert85, see this page:

* OpenGL Transformation (http://www.songho.ca/opengl/gl_transform.html) (Song Ho Ahn)

In particular, the coordinate space and transform (matrix) diagram:


http://www.songho.ca/opengl/files/gl_transform02.png



Sometimes the MODELVIEW matrix (see 1st box on left) is split into its component transforms: MODELING * VIEWING. When this is done, the coordinate space between these two transforms is WORLD coordinates (aka WORLD space).

The MODELING matrix transforms objects in OBJECT space into WORLD space, and then the VIEWING matrix takes them from WORLD space and transforms them into EYE space.

Albert85
01-12-2015, 01:49 AM
I simplified the geometry shader in this way:


vec4 fromWorldCoordsToScreenCoords(in vec3 wc)
{
vec4 pos0 = gl_ModelViewProjectionMatrix * vec4(wc, 1.0);
return pos0;
}

vec3 fromScreenCoordsToWorldCoords(in vec4 sc)
{
vec4 wc = gl_ModelViewProjectionMatrixInverse * sc ;
return (wc.xyz);
}



void main(void)
{

vec4 inputPos_ScreenCoord = fromWorldCoordsToScreenCoords(my_Position[0]);
movedPosition = fromScreenCoordsToWorldCoords(inputPos_ScreenCoord );
EmitVertex();
}

But I have again the same problem. Can be a problem of float approximations?

This is the input:
point1: 0.0 | 4487348.5 | 4517591.0
point2:157785.03 | 4490884.0 | 4518372.5
point3:315624.47 | 4494419.5 | 4513640.0

this is the output:
point1: 8325.018 | 4442600.5 | 4463351.0
point2: 161462.64 | 4441388.5 | 4463836.0
point3: 314383.06 | 4437409.0 | 4456076.5

Thanks for the useful information.
Do you have some suggestions about my problem?

Dark Photon
01-12-2015, 06:41 PM
Do you have some suggestions about my problem?...
starting from 3D points in world coordinates, using the geometry shader I would like to:
1) move each point for example 5 pixels on the left
2) reconvert each point in world coordinates
3) extract the points using the trasformfeedbackbuffer


Conceptually:

1. Compute eye-space position of point (eye_space = gl_ModelViewMatrix * gl_Vertex).
2. Compute pixels/unit_of_distance (approx)
3. Offset eye-space position of point (eye_space += 5*pixels/unit_of_distance)
4. Project (movedPosition = gl_ProjectionMatrix * eye_space )

You can do it this way, or you can apply it in clip space at the end of the shader. The latter has several advantages. First, it doesn't require you to pass in ModelView and Projection separately -- you can just pass in ModelViewProjection (one matrix instead of two). Second, you can get exact displacements in pixels with this, whereas the eye-space technique (while easier to understand) only approximates this.