COVERSION: world coord -> screen coord -> world coord

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!

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 [var]vec4(sc,1.0)[/var] 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 [var]gl_FragCoord[/var] 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. Adding world space to that is only a matter of using the right matrix.

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:

herethere 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?

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

[QUOTE=Albert85;1263657]
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?[/QUOTE]

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.

[QUOTE=Albert85;1263657]herethere 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?[/QUOTE]

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.

Yes, not good.

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

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

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.

[QUOTE=Albert85;1263660]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[/QUOTE]

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

[QUOTE=Albert85;1263700]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
    [/QUOTE]

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.

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.