GLSL: 如何获得像素的x,y,z世界位置？[英] GLSL: How to get pixel x,y,z world position?

问题描述

```varying vec4 verpos;

void main(){
vec4 c;
c.x = verpos.x;
c.y = verpos.y;
c.z = verpos.z;
c.w = 1.0;

gl_FragColor = c;
}
```

，但似乎颜色根据我的相机角/位置而变化，我如何使坐标独立于相机位置/角度?

```varying vec4 verpos;

void main(){
gl_Position = ftransform();
verpos = gl_ModelViewMatrix*gl_Vertex;
}
```

edit2:更改了标题，所以我想要世界坐标，而不是屏幕坐标！

edit3:添加了我的完整代码

推荐答案

1. 模型矩阵(映射模型坐标到世界坐标)和
2. 查看矩阵(将世界坐标映射到相机坐标).

```uniform mat4 view_matrix;
uniform mat4 model_matrix;
```

```gl_Position = gl_ProjectionMatrix * view_matrix * model_matrix * gl_Vertex;
```

gl_fragcoord是像素坐标，而不是世界坐标.

其他推荐答案

，或者您可以将Z坐标除以W坐标，从而基本上没有透视投影；给您原始的世界坐标.

```depth = gl_FragCoord.z / gl_FragCoord.w;
```

其他推荐答案

```/*Vertex Shader*/

layout (location = 0) in vec3 Position

uniform mat4 World;
uniform mat4 WVP;

//World FragPos
out vec4 FragPos;

void main()
{
FragPos = World * vec4(Position, 1.0);
gl_Position = WVP * vec4(Position, 1.0);
}

layout (location = 0) out vec4 Color;

...

in vec4 FragPos

void main()
{
Color = FragPos;
}
```

问题描述

I want to adjust the colors depending on which xyz position they are in the world.

I tried this in my fragment shader:

```varying vec4 verpos;

void main(){
vec4 c;
c.x = verpos.x;
c.y = verpos.y;
c.z = verpos.z;
c.w = 1.0;

gl_FragColor = c;
}
```

but it seems that the colors change depending on my camera angle/position, how do i make the coords independent from my camera position/angle?

```varying vec4 verpos;

void main(){
gl_Position = ftransform();
verpos = gl_ModelViewMatrix*gl_Vertex;
}
```

Edit2: changed title, so i want world coords, not screen coords!

推荐答案

In vertex shader you have gl_Vertex (or something else if you don't use fixed pipeline) which is the position of a vertex in model coordinates. Multiply the model matrix by gl_Vertex and you'll get the vertex position in world coordinates. Assign this to a varying variable, and then read its value in fragment shader and you'll get the position of the fragment in world coordinates.

Now the problem in this is that you don't necessarily have any model matrix if you use the default modelview matrix of OpenGL, which is a combination of both model and view matrices. I usually solve this problem by having two separate matrices instead of just one modelview matrix:

1. model matrix (maps model coordinates to world coordinates), and
2. view matrix (maps world coordinates to camera coordinates).

So just pass two different matrices to your vertex shader separately. You can do this by defining

```uniform mat4 view_matrix;
uniform mat4 model_matrix;
```

```gl_Position = gl_ProjectionMatrix * view_matrix * model_matrix * gl_Vertex;
```

In the main program you must write values to both of these new matrices. First, to get the view matrix, do the camera transformations with glLoadIdentity(), glTranslate(), glRotate() or gluLookAt() or what ever you prefer as you would normally do, but then call glGetFloatv(GL_MODELVIEW_MATRIX, &array); in order to get the matrix data to an array. And secondly, in a similar way, to get the model matrix, also call glLoadIdentity(); and do the object transformations with glTranslate(), glRotate(), glScale() etc. and finally call glGetFloatv(GL_MODELVIEW_MATRIX, &array); to get the matrix data out of OpenGL, so you can send it to your vertex shader. Especially note that you need to call glLoadIdentity() before beginning to transform the object. Normally you would first transform the camera and then transform the object which would result in one matrix that does both the view and model functions. But because you're using separate matrices you need to reset the matrix after camera transformations with glLoadIdentity().

gl_FragCoord are the pixel coordinates and not world coordinates.

其他推荐答案

Or you could just divide the z coordinate by the w coordinate, which essentially un-does the perspective projection; giving you your original world coordinates.

ie.

```depth = gl_FragCoord.z / gl_FragCoord.w;
```

Of course, this will only work for non-clipped coordinates..

But who cares about clipped ones anyway?

其他推荐答案

You need to pass the World/Model matrix as a uniform to the vertex shader, and then multiply it by the vertex position and send it as a varying to the fragment shader:

```/*Vertex Shader*/

layout (location = 0) in vec3 Position

uniform mat4 World;
uniform mat4 WVP;

//World FragPos
out vec4 FragPos;

void main()
{
FragPos = World * vec4(Position, 1.0);
gl_Position = WVP * vec4(Position, 1.0);
}

layout (location = 0) out vec4 Color;

...

in vec4 FragPos

void main()
{
Color = FragPos;
}
```