在着色器中设置矢量,它是如何工作的? OpenGL GLSL

时间:2015-03-02 09:37:14

标签: android opengl-es glsl opengl-es-2.0 glsles

我试图了解顶点和片段着色器如何在OpenGL ES 2.0中工作。

我的着色器看起来像这样:

顶点着色器:

// source code for the vertex shader
attribute vec4 vPosition
attribute vec2 a_texCoord;
varying vec2 v_texCoord;

void main() {
    gl_Position = vPosition;
    v_texCoord = a_texCoord;
}

片段着色器:

// source code for the fragment shader
precision mediump float;
uniform sampler2D s_texture;
varying vec2 v_texCoord;

void main() {
    gl_FragColor = texture2D(s_texture, v_texCoord);
}

使用这些着色器的程序绘制一个带纹理(图像)的简单2D矩形。首先,它将矩形的顶点和纹理坐标传递给带有属性的顶点着色器。然后顶点着色器将纹理坐标传递给片段着色器。

令我困惑的是,矢量vPosition,a_texCoord和v_texCoord只能保存1点,但需要保存4个不同的点。我在某处读到了为每个顶点调用顶点着色器的地方。这是否意味着对于我想要绘制的每个图像,顶点和片段着色器将被处理4次?当我定义属性(glVertexAttribPointer)时我使用的是一个有4个点的数组,着色器如何在一个只能存储1个点的变量中保存4个点?

我想使用制服而不是属性,我读得更好。我也不需要变量变量。我想这样:

顶点着色器:

// source code for the vertex shader
uniform vec4 vPosition;

void main() {
    gl_Position = vPosition;
}

片段着色器:

// source code for the fragment shader
precision mediump float;
uniform sampler2D s_texture;
uniform vec2 v_texCoord;

void main() {
    gl_FragColor = texture2D(s_texture, v_texCoord);
}

这可能吗?我还能将所需的所有点传递给着色器吗?这是个好主意吗?

1 个答案:

答案 0 :(得分:1)

不,您不能将每个顶点数据存储到制服中。均匀设计为每个绘制调用,顶点属性设计为每个顶点。使用制服的顶点位置的唯一方法是绘制点,因为它只使用1个坐标。

关于顶点和处理:是的,如果使用4个顶点绘制,那么对于要处理的顶点,将至少有4次调用顶点着色器。你没有什么可担心的,想象一下,使用4个顶点绘制一个100x100的图像,将有4个调用顶点着色器和10000个(100x100)调用片段着色器。这就是GPU的设计目标,它非常有效。

您可以查看一些完整的openGL管道图表,以便更好地了解所有内容,但只是为了让您了解在调用openGL绘制时发生的事情:

  • 根据您正在绘制的形状(例如三角形),将在顶点着色器中拍摄并处理多个点,这包括所有属性,例如位置,纹理坐标,法线......
  • 接下来将发生光栅化,此时将确定缓冲区上的所有像素将被绘制,并且对于每个像素着色器将被分配。
  • 然后发生片段着色器,它将接收所需的所有插值和固定的制服,并刷新当前使用的每个连接缓冲区中的单个特定像素(颜色,深度......)。

现在我再次介绍了这个管道,但是对于你提出的问题,这些管道最为有趣。

尝试理解着色器只是长固定管道的一部分,现在可以被覆盖,你不应该问自己,至少它们被调用了多少次,而不是像你正在做的简单操作那样。如果需要优化这些调用的次数,则很可能需要在CPU上进行优化。例如,如果你要绘制几千个相互重叠的大矩形,你可以想到算法减少绘制一个矩形所需的大小,这个矩形大多与其他矩形重叠,或者如果完全重叠则根本不绘制它。 / p>

所以要了解你发布的着色器发生了什么:如果你正在绘制一个纹理矩形,你将有4或6个调用顶点着色器(6个使用两个三角形)。顶点着色器将接收所有已启用的属性,在您的情况下是位置和纹理坐标。这两个值没有做任何事情,但在这一点上向前传递。然后位置是自动的(您不需要另外的变化参数来传递它),但纹理坐标被分配给您称为v_texCoord的变化属性。这意味着将为要绘制的每个像素插值纹理坐标,然后在片段着色器中接收这些值。这就是为什么你可以实际看到绘制的纹理的原因,因为每个像素都具有从纹理中获取的不同颜色,并且片段着色器接收到不同的插值坐标。因此,用统一替换属性会破坏所有这些,不会发生插值,所有像素看起来都完全一样。