您的位置:首页 > 其它

[置顶] 第二节 WebGL中着色器语言(GLSL ES)的简介

2017-11-16 22:15 417 查看


1 着色器简介

着色器语言(GLSL ES)由OpenGL的着色器语言GLSL简化而来, 主要是为了适应目前的移动端手持设备,例如智能手机和平板电脑,由于这些手持设备受限于硬件条件,其性能远不如电脑。这意味着对这些手持设备硬件的利用和开销就要恰到好处,故由此催生了GLSL ES,是为了降低硬件的功耗和性能开销。具体的着色器技术文档我们可以参考官方网址:https://www.khronos.org/registry/OpenGL-Refpages/


2 着色器类型

WebGL着色器只用到众多着色器中的两种:顶点着色器(vertex shader)和片段着色器(fragment shader)。对于这两个着色器,在这里并不去过多的做详述,可以先这样理解:顶点着色器负责接收来自javaScript程序的顶点数据和颜色信息,经过一系列操作(像剪切,光栅化等,这一系列操作可以不用去深入理解),再将颜色信息传至片段着色器,最后生成图像呈现在我们面前。下面就对这两个着色器的代码做一个初步了解:
(1) 顶点着色器

attribute vec4 vPosition;//收js程序的顶点信息的变量
attribute vec4 vColor;//接受js程序的顶点颜色信息的变量
uniform mat4 vMvpMatrix;//接收视图变换矩阵
varying vec4 fColor;//顶点着色器与片段着色器传颜色信息的变量
void main(){
gl_Position = vMvpMatrix * vPosition;//图像所有顶点位置
}

下面的任务可由顶点着色器完成: 

顶点变换 

纹理坐标生成和变换 

光照的计算 

颜色材料的应用
(2) 片段着色器

precision mediump float;//精度要求为中精度
varying vec4 fColor;//与顶点着色器中fColor一致,为了接收颜色信息
void main() {
gl_FragColor = fColor;//给片元设置颜色
}

下面的任务可由片段着色器完成: 

插值操作 

纹理访问和应用 

雾化效果 

颜色总和
看到这里是不是觉得着色器语言似曾相识?学过C或C++的同学都能看出来了吧,着色器语言与C是多么的相像,但它们之间还是存在差异的,这里不赘述。所以如果你熟悉C,那么就会比较好理解GLSL ES。下面进行着色器一些变量的定义和语法讲述。


3 着色器数据值类型

在这里,我并不是要完完整整的将着色器的所有变量和用法都讲一遍,解释着色器的变量和语法是一个工作量大而庞杂的工作。在这里我们只讲其中最常用的部分,对于初学者来说完全够用。如果当你入门后想继续深入了解着色器,可以去查看官方文档。也可参考《WebGL编程指南》一书的第六章和附录B,这里面对着色器有较详尽的介绍。
(1) attribute变量 

attribute变量用于接收与顶点数据相关的一切变量,例如顶点着色器里面的:

attribute vec4 vPosition;
attribute vec4 vColor;

第一个变量定义的是顶点的位置信息,第二个变量定义了顶点的颜色信息。但大家注意到,这里还有一个 vec4 是什么鬼? vec4 用于定义向量(x, y, z, w)这样一个四维向量,vec3 即(x, y, z),以此类推,并不难得出 vec2 为(x, y);那平常表示一个三维空间点的坐标(x,
y, z)就够了,为什么还要多一个 w 呢 ?这个肯定是有道理的,主要是为了解决后续对模型的一些旋转、平移、缩放计算方便才这样做的,因这些运算都是用矩阵运算的,三行三列矩阵不能表示平移,只能四行四列矩阵才可以。对于顶点坐标来说,通常w=1.0;
(2) uniform变量

uniform mat4 vMvpMatrix;//用于接收来自js程序的一个与顶点坐标信息无关的 4*4 矩阵

uniform变量主要用于定义与顶点信息无关的变量,只要是与顶点坐标无关的变量,基本都会用uniform来定义。 

其中mat4用于定义一个四行四列的矩阵,mat3用于定义三行三列的矩阵,以此类推mat2为二行二列。

uniform vec4 vector;//用于接收来自js程序的一个与顶点坐标信息无关的4维向量

(3) varying变量

varying vec4 fColor;//用于沟通顶点着色器和片段着色器的桥梁

varying变量将顶点的颜色信息发送给片段着色器。


4 着色器的创建和编译

var vshader = gl.createShader(gl.VERTEX_SHADER);//创建顶点着色器类型
var fshader = gl.createShader(gl.FRAGMENT_SHADER);//创建片段着色器类型
var program = gl.createProgram();//创建一个程序对象

//附加着色器文件到Shader
gl.shaderSource(program, vshader);
gl.shaderSource(program, fshader);

//编译着色器
gl.compileShader(vshader);
gl.compileShader(fshader);

//向程序对象分配着色器
gl.attachShader(program, vShader);
gl.attachShader(program, fShader);

//链接着色器
gl.linkProgram(program);

//将程序设置为有效
gl.useProgram(program);//只有这一步执行着色器才能正常工作

上述代码的过程正是着色器创建和编译的完整过程,只有将这个做好,着色器代码才可以被编译和执行。通常上述着色器的穿件和编译的方法只适用于一些比较小的着色器,建议初学者使用。而对大部分着色器来说,一旦涉及复杂的着色器设计,这个并不实用,因此,在这里建议使用另外一种方式,将着色器代码放于单独的文件中,每个文件只包含着色器代码,如:



然后再通过js读取本地文件的方法new XMLHttpRequest(), 将着色器文件读取后进行创建和编译。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: