OpenGL - 顶点着色器

概述:
顶点着色器提供顶点操作的通用可编程方法.

属性 :                    用顶点数组提供的逐顶点数据.
统一变量和统一变量缓冲区 :   顶点着色器使用的不变数据
采样器 :                  代表顶点着色器使用的纹理的特殊统一变量类型.
着色器程序 :               顶点着色器程序源代码或者描述在操作顶点的可执行文件.
顶点着色器

一个典型的着色器有下面的结构:

#version version_number
in type in_variable_name;
in type in_variable_name;

out type out_variable_name;

uniform type uniform_name;

int main()
{
  // 处理输入并进行一些图形操作
  ...
  // 输出处理过的结果到输出变量
  out_variable_name = weird_stuff_we_processed;
}

修饰符

  • uniform
uniform变量是外部application程序传递给(vertex和fragment)shader的变量.
uniform变量一般用来表示:变换矩阵,材质,光照参数和颜色等信息。
以下是例子:
uniform mat4 viewProjMatrix; //投影+视图矩阵
uniform mat4 viewMatrix;        //视图矩阵
uniform vec3 lightPosition;     //光源位置
  • attribute
attribute变量是只能在vertex shader中使用的变量。
它不能在fragment shader中声明attribute变量,也不能被fragment shader中使用.
一般用attribute变量来表示一些顶点的数据,如:顶点坐标,法线,纹理坐标,顶点颜色等。
  • varying
varying变量是vertex和fragment shader之间做数据传递用的。一般vertex shader修改varying变量的值,
然后fragment shader使用该varying变量的值。因此varying变量在vertex和fragment shader二者之间的声明必须是一致的。application不能使用此变量。

顶点着色器内建变量

  • 特殊变量(顶点着色器的输入输出)
  • 统一状态(如深度范围)
  • 规定最大值(如属性数量,顶点着色器输出变量数量和统一变量数量)的常量

內建特殊变量

  • gl_VertexID是一个输入变量,用于保存顶点的整数索引.
这个整数型变量用highp精度限定符声明.
  • gl_InstanceID是一个输入变量,用于保存实例化绘图调用中图元的示例编号.
对于常规的绘图调用,该值为0.
gl_InstanceID是一个整数型变量,用highp精度限定符声明.
  • gl_Position用于输出顶点位置的裁剪坐标.
该值在裁剪和视窗阶段用于执行相应的图元裁剪以及从裁剪坐标到屏幕坐标的顶点位置转换.
如果顶点着色器未写入gl_Position.则该值未定义.
gl_Position是一个浮点变量,用highp精度限定符声明.
  • gl_PointSize用于写入以像素表示的点精灵尺寸,在渲染点精灵时使用.
顶点着色器输出的gl_PointSize值被限定在OpenGL ES 3.0实现支持的非平滑点大小范围之内.
该值是一个浮点变量,用highp精度限定符声明.
  • gl_FrontFacing是一个特殊变量,但不是由顶点着色器直接写入的,而是根据顶点着色器生成的位置和渲染的图元类型生成的.
该值是一个布尔变量

內建统一状态

struct gl_DepthRangeParameters {
    highp float near;
    highp float far;
    highp float diff;
}
uniform gl_DepthRangeParameters gl_depthRange;

內建常量

const mediump int gl_maxVertexAttribs                  = 16
const mediump int gl_maxVertexUniformVectors           = 256
const mediump int gl_maxVertexOutputVectors            = 16
const mediump int gl_maxVertexTextureImageUnits        = 16
const mediump int gl_maxCombindedTextureImageUnits     = 32
  • gl_maxVertexAttribs : 是可以指定的顶点属性的最大数量.
  • gl_maxVertexUniformVectors : 顶点着色器可以使用的vec4统一变量项目的最大数量
  • gl_maxVertexOutputVectors : 输出向量的最大数量
  • gl_maxVertexTextureImageUnits : 顶点着色器中可用的纹理单元的最大数量.
  • gl_maxCombindedTextureImageUnits : 顶点和片段着色器中可用纹理单元最大数量的总和.
PS : 以上的內建常量指定的值是所有OpenGL ES 3.0 实现必须支持的最小值.实现各种可能支持超过上面所述的最小值的常量值.实际支持的值可以用下面的代码查询.
    GLint maxVerterAttribs,maxVerterUniforms, maxVaryings;
    glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVerterAttribs);
    glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxVerterUniforms);
    glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
    
    GLint maxVerterTextureUnits,maxCombinedTextureUnits;
    glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxVerterTextureUnits);
    glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxCombinedTextureUnits);

精度限定符

highp lowp mediump

顶点着色器示例

演示如何在顶点着色器中实现如下功能

  • 用一个矩阵变化顶点位置
  • 进行照明计算,生成逐定点漫射和反射颜色
  • 纹理坐标生成
  • 顶点蒙皮
  • 用纹理查找值代替顶点位置

矩阵变化

描述一个用OpenGLES 着色器语言编写的简单顶点着色器.这个顶点着色器获取一个位置和其相关的颜色数据作为输入或者属性.用一个4x4矩阵变换位置,并输出变化后的位置和颜色.

#version 300 es
uniform mat4 u_mvpMatrix;
layout (location = 0) in vec4 a_position;
layout (location = 1) in vec4 a_color;
out vec4 v_color;
void main() {
  v_color = a_color;
  gl_Position = u_mvpMatrix * a_position;
}

顶点着色器的位置输入保存为物体坐标,而输出位置保存为裁剪坐标.
MVP矩阵是3D图形中进行这种变化的3个非常重要的变化矩阵的乘积:模型矩阵,视图矩阵和投影矩阵.
组成MVP矩阵的每个单独矩阵执行的变化如下:

  • 模型矩阵 ---- 将 物体 坐标变换为 世界 坐标.
  • 视图矩阵 ---- 将 世界 坐标变换为 眼镜 坐标.
  • 投影矩阵 ---- 将 眼睛 坐标变换为 裁剪 坐标.

推荐阅读更多精彩内容