GLSL:如何获取像素 x、y、z 世界位置?

发布于 2024-10-16 06:54:29 字数 530 浏览 8 评论 0原文

我想根据它们在世界中的 xyz 位置来调整颜色。

我在片段着色器中尝试了这个:

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:添加了我的完整代码

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?

Heres my vertex shader:

varying vec4 verpos;

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

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

Edit3: added my full code

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

驱逐舰岛风号 2024-10-23 06:54:29

在顶点着色器中,您有 gl_Vertex (或其他东西,如果您不使用固定管道),它是模型坐标中顶点的位置。将模型矩阵乘以 gl_Vertex,您将获得世界坐标中的顶点位置。将其分配给一个variing变量,然后在片段着色器中读取它的值,您将获得片段在世界坐标中的位置。

现在的问题是,如果你使用OpenGL的默认模型视图矩阵,你不一定有任何模型矩阵,它是模型和视图矩阵的组合。我通常通过使用两个单独的矩阵而不是只有一个模型视图矩阵来解决这个问题:

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

因此,只需分别将两个不同的矩阵传递给顶点着色器即可。您可以通过

uniform mat4 view_matrix;
uniform mat4 model_matrix;

在顶点着色器的开头定义来完成此操作。然后,不要使用 ftransform(),而是说:

gl_Position = gl_ProjectionMatrix * view_matrix * model_matrix * gl_Vertex;

在主程序中,您必须将值写入这两个新矩阵。首先,要获取视图矩阵,请使用 glLoadIdentity()、glTranslate()、glRotate() 或 gluLookAt() 或您通常喜欢的方式进行相机转换,然后调用 glGetFloatv(GL_MODELVIEW_MATRIX, &array) ;为了将矩阵数据获取到数组中。其次,以类似的方式,获取模型矩阵,也调用 glLoadIdentity();并使用 glTranslate()、glRotate()、glScale() 等进行对象转换,最后调用 glGetFloatv(GL_MODELVIEW_MATRIX, &array);从 OpenGL 中获取矩阵数据,以便您可以将其发送到顶点着色器。特别注意,在开始转换对象之前需要调用 glLoadIdentity()。通常,您将首先变换相机,然后变换对象,这将产生一个同时执行视图和模型功能的矩阵。但是因为您使用的是单独的矩阵,所以需要在使用 glLoadIdentity() 进行相机转换后重置矩阵。

gl_FragCoord 是像素坐标而不是世界坐标。

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;

In the beginning of your vertex shader. And then instead of ftransform(), say:

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.

北陌 2024-10-23 06:54:29

或者您可以将 z 坐标除以 w 坐标,这实际上取消了透视投影;给你你原来的世界坐标。

IE。

depth = gl_FragCoord.z / gl_FragCoord.w;

当然,这仅适用于非裁剪坐标。

但是谁又关心裁剪坐标呢?

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?

鹤舞 2024-10-23 06:54:29

您需要将世界/模型矩阵作为统一传递到顶点着色器,然后将其乘以顶点位置并将其作为变量发送到片段着色器:

/*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);
}

/*Fragment Shader*/

layout (location = 0) out vec4 Color;

... 

in vec4 FragPos

void main()
{
 Color = FragPos;
}

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);
}

/*Fragment Shader*/

layout (location = 0) out vec4 Color;

... 

in vec4 FragPos

void main()
{
 Color = FragPos;
}
夏九 2024-10-23 06:54:29

最简单的方法是通过可变变量从顶点着色器传递世界位置。

但是,如果您确实必须从 gl_FragCoord 重建它,唯一的方法是反转导致 gl_FragCoord 坐标的所有步骤。如果您确实必须这样做,请查阅 OpenGL 规范,因为需要深入了解转换。

The easiest way is to pass the world-position down from the vertex shader via a varying variable.

However, if you really must reconstruct it from gl_FragCoord, the only way to do this is to invert all the steps that led to the gl_FragCoord coordinates. Consult the OpenGL specs, if you really have to do this, because a deep understanding of the transformations will be necessary.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文