OpenGL ES手册翻译---3.栅格化(四)

3.8 碎片着色器

接下来的应用到碎片的操作,是用栅格化点,线段,多边形之后的结果,通过使用碎片着色器来继续进行的。

一个碎片着色器定义为一个包含着描述操作的源代码的字符串数组,这些操作会作用在每个栅格化点,线段,多边形的结果的碎片上。碎片着色器使用的语言在OPenGL ES着色器语言规范中会有详细介绍。

或者,碎片着色器也可以通过预编译的二进制码定义,和在2.10节中介绍的顶点着色器使用相同的方法。

碎片着色器如在2.10.1节中描述的那样创建,设置参数typeFRAGMENT_SHADER即可。如果2.10.3节中介绍的一样,他们会被附着在program对象上并被program对象使用。

GL中正在使用的program对象上附着的碎片着色器被认为是活跃的,通常被用来处理碎片。如果当前没有正在被使用的program对象,碎片着色器的执行结果是无定义的。

3.8.1 着色器变量

碎片着色器可以访问属于当前着色器对象的uniform变量。碎片着色器的uniform变量的可用的存储数量通过依赖于实现的常量MAX_FRAGMENT_UNIFORM_VECTORS来指定。其值表示一个四元素的浮点指针,整数,或者布尔向量,这些值可以填充碎片着色器的uniform变量的存储空间。如果尝试使用比碎片着色器uniform变量更多的空间将会产生链接错误。

碎片着色器可以读由栅格化产生的碎片的属性相应的varying变量。OpenGL ES着色器语言规范定义了一系列的内建的varying变量,他们可以被碎片着色器访问。这些内建的varying变量包括碎片的位置,视角的z坐标和朝前面的标志。

image

一个顶点着色器可能会定义一个或者多个varying变量(见2.10.4节和OpenGL ES着色器语言规范)。这些值在图元上被插值,渲染。在碎片着色器中定义相同名字的varying变量时,这些插值的结果才是适用的。

3.8.2 着色器执行

如果碎片着色器是活跃的,用碎片着色器的可执行版本来处理点,线段,多边形栅格画的结果值。

  • 纹理访问

当纹理查找表在碎片着色器中执行时,GL计算滤波纹理值\tau,如果按照3.7.7和3.7.8中描述的方式,然后根据表3.12将它转换为纹理的源的颜色C_s。GL给碎片着色器返回了一个四通道的向量(R_s,G_s,B_s,A_s)。由于细节等级计算的目的,导数\frac{du}{dx},\frac{du}{dy},\frac{dv}{dx},\frac{dv}{dy},\frac{dw}{dx},\frac{dw}{dy}可能会被一个不一样的算法近似,详细的会在OpenGL ES着色器语言指南8.8节中介绍。

如果下面的任何一个条件成立时,从碎片着色器中调用一个采样器将会返回(R,G,B,A)= (0,0,0,1):

  • 当一个二维的采样器被调用时,缩小滤波器要求一个mipmap(既不是NEAREST也不是LINEAR),采样器对应的纹理对象不完整,如果3.7.1和3.7.10中定义的那样。
  • 当一个二维采样器被调用时,缩小滤波器不需要mipmap(既不是NEAREST也不是LINEAR),对应纹理对象的0级阵列的维度不是正的。
  • 当一个二维采样器被调用时,对应的纹理图像不是2的幂指数的图像(如同3.7.7接种关于Mipmapping的讨论中介绍过),纹理包裹模式不是CLAMP_TO_DEGE,缩小滤波器也不是NEAREST或者LINEAR
  • 一个立方体贴图采样器被调用时,对应的纹理图像不是2的幂指数图像,纹理包裹模式不是CLAMP_TO_EDGE模式,缩小滤波器不是NEAREST或者LINEAR
  • 一个立方体贴图采样器被调用时,对应的立方体贴图纹理不是完整的立方体,TEXTURE_MIN_FILTER需要mipmap但是纹理不是完整的mipmap立方体。

分离的纹理单元的数目被依赖实现的常量MAX_TEXTURE_IMAGE_UNITS指定,这些纹理单元可以在基本图元的渲染期间在碎片着色器中被访问。

  • 着色器输入

OpenGL ES着色器语言指南描述了适合作为碎片着色器输入的值。

内建变量gl_FragCoord维持着碎片的窗口坐标x,y,z,\frac{1}{w}gl_FragCoord的z通道经历了到浮点指针的隐式转换。这个转换比如保留0和1不变。注意,如果允许的话,这个z通道已经添加了一个多边形的偏移量。(见3.5.2节,\frac{1}{w}值从w_c坐标中计算得到。(见2.12节))。

内建变量gl_FrontFacing在碎片是由面朝前的图元产生式,设置为true,否则设置为false。对于多边形图元产生的碎片,则是由通过3.5.1节中的3.4等式计算的面积的符号计算决定的(包括由函数FrontFace控制后可能会发生的符号的逆转)。如果符号是正的,图元产生的碎片是面朝前的;否则,他们是背朝前的。所有其他的碎片都被认为是面朝前的。

  • 着色器输出

OpenGL ES着色器语言指南介绍了可以被碎片着色器当做输出的值。就是gl_FragColorgl_FragData[0]。在碎片着色器中的最终的碎片颜色值或者最终的碎片数据值都限制在[0,1]范围内,然后入2.1.2中描述的那样为了帧缓冲的颜色组件而被转换成修正指针类型。

gl_FragColor或者gl_FragData[0]写数据就是制定了碎片的颜色(颜色数字为0),这些颜色会被用在渲染管线的接下来的阶段。和碎片有关的任何颜色,颜色通道如果不是写在碎片着色器中,将是无定义的。碎片着色器不会静态的给gl_FragColorgl_FragData[0]赋值。这种情况下,将会导致编译或者链接错误。如果在预处理后,着色器包含了将会写入变量的声明,不论运行时的控制流是否会导致声明被执行,着色器都会被静态的给变量分配值。

推荐阅读更多精彩内容