27

我想根据它们在世界上的 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:添加了我的完整代码

4

4 回答 4

33

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

现在的问题是,如果您使用 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 是像素坐标而不是世界坐标。

于 2011-02-04T15:18:54.957 回答
13

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

IE。

depth = gl_FragCoord.z / gl_FragCoord.w;

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

但是谁在乎剪掉的呢?

于 2012-02-16T23:36:05.463 回答
2

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

/*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;
}
于 2017-07-28T17:39:16.820 回答
-1

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

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

于 2011-02-04T15:19:51.820 回答