(八)顶点着色器

OpenGL ES 3.0可编程管线如下图所示。其中阴影部分的顶点着色器和片段着色器是可编程阶段。


可编程管线.png

本章将举几个常用例子,例如:模型视图和投影矩阵变换顶点位置、生成逐顶点漫反射和反射颜色的顶点照明、纹理坐标生成、顶点蒙皮和位移贴图。

顶点着色器概述

顶点着色器.png

顶点着色器的输入包括:
1、属性:用顶点数组提供的逐顶点数据
2、统一变量和统一变量缓冲区:顶点着色器使用的不变数据
3、采样器:代表顶点着色器使用的纹理的特殊统一变量类型
4、着色器程序:顶点着色器程序源代码或者生成的可执行文件
顶点着色器的输出:图元光栅化时,为了生成的片段需要计算这些输出变量。

顶点着色器内建变量

内建变量可以分成
1、特殊变量(顶点着色器的输入输出)
2、统一状态(深度范围)
3、规定最大值(属性数量、顶点着色器输出变量数量和统一变量数量)

内建特殊变量

OpenGL ES 3.0有内建的特殊变量。

gl_VertexID // 顶点的整数索引
gl_InstanceID // 实例化绘图调用中图元的实例编号
gl_Position // 输出顶点位置的裁剪坐标
gl_PointSize // 以像素表示的点精灵尺寸
gl_FrontFacing // 根据顶点着色器生成的位置值和渲染的图元类型生成的

内建统一状态

顶点着色器内可用的唯一内建统一状态是窗口坐标中的深度范围。

struct gl_DepthRangeParameters {
    highp float near; // near Z
    highp float far; // far Z
    highp float diff; // far – near
}
uniform gl_DepthRangeParameters gl_DepthRange;

内建常量

// 指定的顶点属性的最大数量
const mediump int gl_MaxVertexAttribs = 16;
// 可以使用的的vec4统一变量数目的最大数量
const mediump int gl_MaxVertexUniformVectors = 256;
// 输出向量的最大值
const mediump int gl_MaxVertexOutputVectors = 16;
// 可用的纹理单元的最大数量
const mediump int gl_MaxVertexTextureImageUnits = 16;
// 顶点和片段着色器中可用的纹理单元最大数量的总和
const mediump int gl_MaxCombinedTextureImageUnits = 32;

精度限定符

指定精度的关键字是lowp、mediump和highp。

precision highp float;

指定所有float数变量的默认精度为高精度。

顶点着色器中的统一变量限制数量

任何兼容OpenGL ES 3.0实现必须支持的gl_MaxVertexUniformVectors的最小值为256个vec4项目。

统一变量存储用于存储如下变量:
1、用统一变量限定符声明的变量
2、常数变量
3、字面值
4、特定于实现的常量

顶点着色器示例

矩阵变换

下述代码是使用矩阵变换位置的顶点着色器:

#version 300 es
// uniforms used by the vertex shader
uniform mat4 u_mvpMatrix; // matrix to convert position from
// model space to clip space
// attribute inputs to the vertex shader
layout(location = 0) in vec4 a_position; // input position value
layout(location = 1) in vec4 a_color; // input color
// vertex shader output, input to the fragment shader
out vec4 v_color;
void main() {
    v_color = a_color;
    gl_Position = u_mvpMatrix * a_position;
}

上述的统一变量u_mvpMatrix的形式引入了模型-视图-投影(MVP)矩阵的概念。
模型矩阵:将物体坐标变换为世界坐标
视图矩阵:将世界坐标变换为眼睛坐标
投影矩阵:将眼睛坐标变换为裁剪坐标

顶点着色器中的照明

这个小节主要包括直射光和聚光灯两种种照明。

直射光.png
聚光灯.png

生成纹理坐标

球面图纹理坐标生成:

// position is the normalized position coordinate in eye space.
// normal is the normalized normal coordinate in eye space.
// This function returns a vec2 texture coordinate.
vec2 sphere_map ( vec3 position, vec3 normal ) {
    reflection = reflect ( position, normal );
    m = 2.0 * sqrt ( reflection.x * reflection.x + reflection.y * reflection.y + ( reflection.z + 1.0 ) * ( reflection.z + 1.0 ) );
    return vec2(( reflection.x / m + 0.5 ), ( reflection.y / m + 0.5 ) );
}

立方体图纹理坐标生成:

// position is the normalized position coordinate in eye space.
// normal is the normalized normal coordinate in eye space.
// This function returns the reflection vector as a vec3 texture
// coordinate.
vec3 cube_map ( vec3 position, vec3 normal ) {
    return reflect ( position, normal );
}

顶点蒙皮

顶点蒙皮用于平滑多边形之间的连接点,这通过向每个顶点应用具有相应权重的附加变换矩阵来实现。常用于3D游戏中的角色模型。计算公式如下图:

顶点蒙皮计算公式.png

n是用于变换顶点的矩阵数量
P是顶点位置
P'是变换蒙皮后的位置
N是顶点的法线
N'是变换蒙皮后的法线
Mi是每个顶点第i个矩阵相关的矩阵

变换反馈

变换反馈模式允许将顶点着色器的输出捕捉到缓冲区对象中。然后,输出缓冲区可以作为后续绘图调用中顶点数据的来源。这种方法用于再GPU上执行动画而无需任何CPU干预。
要指定变换反馈模式期间捕捉的一组顶点属性,可以使用如下命令:

void glTransformFeedbackVaryings(GLuint program,
    GLsizei count,
    const char** varyings,
    GLenum bufferMode)

顶点纹理

OpenGL ES 3.0支持顶点着色器中的纹理查找操作。
位移贴图技术的典型应用之一就是渲染地形和水面。

将OpenGL ES 1.1顶点管线作为ES 3.0顶点着色器

实现OpenGL ES 1.1顶点管线的如下固定功能:
1、再必要时将法线和位置变换到眼睛,还执行法线的比例调整或者规范化。
2、为8个光源计算顶点照明方程,每个顶点拥有双面照明和彩色材料。
3、换纹理坐标。
4、计算传递给片段着色器的雾化因子。
5、计算逐顶点用户裁剪平面因子。
6、将位置变换到裁剪空间。

小结

本章用几个例子高度概括了顶点着色器融入管线和再定点着色器中执行变换、照明、蒙皮和位移贴图的方法。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,245评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,749评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,960评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,575评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,668评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,670评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,664评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,422评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,864评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,178评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,340评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,015评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,646评论 3 323
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,265评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,494评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,261评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,206评论 2 352