[WebGL入门]八,着色器的说明和基础

注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中如果有我的额外说明,我会加上[lufy:],另外,鄙人webgl研究还不够深入,一些专业词语,如果翻译有误,欢迎大家指正。


认识GLSL

WebGL是无法利用固定渲染管线的,这个在之前的文章(四,渲染准备)里已经简单的说明过了。
所以,代替它的是可编辑渲染管线中的一种着色语言,叫做GLSL(OpenGL Shading Language)。

是用来在OpenGL中着色编程的语言,GLSL使用C语言为基础,并且有自己独立的语法。WebGL的难点之一,就是这个GLSL,不理解GLSL的话,就无法进行渲染。所以,学习WebGL不但要学习WebGL的基本知识,还需要了解GLSL,有点抓狂了吧。

但是,如果只做一些基本的东西的话,也不太难。等习惯了之后,能够自己编写着色器的话会有很大的好处。这一点要慢慢来,不能太着急。


着色器的作用

GLSL的知识不用从零开始彻底理解,只需要先了解一下最基本的东西就行。细节部分,留到后面再讲,先把基本的部分彻底理解。

*下面开始,我用最容易理解的方式来介绍,所以会简化很多东西。

首先,WebGL里有顶点着色器和片段着色器两种着色器。无论哪一种都可以使用GLSL来编写。顶点着色器和片段着色器是相互依赖的,缺一不可,并且首先被调用的是顶点着色器。

可以把顶点相关的所有情报都传给顶点着色器。比如,顶点的位置,顶点法线,纹理坐标,顶点颜色等等,跟顶点相关的所有情报都可以传给顶点着色器。在这里,你可以自由决定传入着色器的内容,这种灵活性就是可编辑渲染管线的好处。但是,虽然说传入着色器的内容是自由决定的,但是顶点的位置情报是必须的,因为如果不知道顶点的位置的话,是没有办法绘制模型的。

顶点着色器就跟它的字面上的意思一样,接受顶点相关的情报,最后决定如何处理这些顶点。而片段着色器则决定了画面上用什么颜色来输出。片段着色器的英文是fragment,其实就是断片,碎片的意思。而画面上的像素则是画面上的最小的断片,所以片段着色器操作的是颜色。

再简单一点说明的话,顶点着色器就是处理顶点相关的信息,片段着色器就是处理画面上的颜色信息。


GLSL的编写基础

好了,已经理解了着色器是干什么的了吧,下面接着来看一下GLSL的编写方法。

首先,不管是顶点着色器还是片段着色器,都必须定义一个main函数,函数里记录你要做的处理。而且,顶点着色器的话,必须要把顶点信息传给一个叫做gl_Position的变量。

比如下面是一个非常简单的顶点着色器的例子。

attribute vec3 position;

void main(void) {
    gl_Position = position;
}
这里出现了一个奇怪的单词吧,最上面一行里的attribute是个什么东东呢?
其实,就是用来声明变量的,用这个修饰符来定义的变量(上面的position),是用来接收顶点情报的。也就是说,上面的代码,WebGL程序中定义一个position,做一些处理之后,传给着色器。

再稍微说明一下,attribute修饰符是用来接收不同顶点传来的不同信息。如果存在很多个顶点的话,这些顶点的位置是不同的吧。用来接收这些不同顶点的不同信息的机制,用attribute修饰符来定义变量。


坐标变换也用GLSL

刚才说了,顶点着色器是处理顶点相关的信息,但是不要忘了,顶点相关的处理就是坐标变换。模型变幻,视图变换,投影变换这三个变换也是顶点着色器的工作之一。

基本上,用顶点着色器来做什么是比较自由的,但是在WebGL程序中,首先生成模型,视图,投影的各个矩阵,然后进行合并,最后将得到的坐标变换的矩阵传给顶点着色器,这是一般的做法。

那么,考虑一下,这个坐标变换的矩阵怎么样传给顶点着色器比较好呢?

使用之前的attribute吗,但是attribute是传递不同顶点的不同情报的。而坐标变换矩阵对于所有顶点来说都是相同的,使用attribute修饰符就有点奇怪了。

这个时候使用的修饰符是uniform。使用uniform修饰符的话,可以传递对于所有顶点一致的处理的情报。基于这一点,来修改一下刚才的代码吧。*只是一个示例。

attribute vec3 position;
uniform mat4 mvpMatrix;

void main(void) {
    gl_Position = mvpMatrix * position;
}
这里出现的mvpMatrix,是模型,视图,投影的各个变换矩阵结合后的矩阵。从WebGL一侧将这个坐标变换矩阵传给通过用uniform修饰符定义的变量。
>>GLSL中可以使用的类型

刚才给出的代码例子中,修饰符后面还跟着vec3和mat4等,这是变量的类型。这里只是代表一下,简单接触一下。

vec*表示的是向量,*的部分是一个24的数字,vec2就代表一个2维的响亮。

mat*表示的是方阵,和向量一样,可以指定的范围也是24,如果是mat3的话,就表示一个3x3的方阵。

另外,int是整型,float是浮点型,bool是布尔型,这些都跟C语言中是一个意思。vec*和mat*中的元素,都是浮点型。


与片段着色器的连接

虽然写的有点长了,但是再稍微加点东西。attribute和uniform这两个修饰符已经理解了吧。

GLSL里面还有一个特别重要的修饰符,就是varying修饰符。这个varying修饰符,是顶点着色器和片段着色器之间的桥梁。

举个例子,要把绘制的模型变成半透明,要怎么做呢?

方法虽然有很多,但是一般的做法是,向顶点里添加颜色的情报信息,然后通过操作颜色的透明度的变化来使模型半透明或者完全透明。这时候,如果想操作顶点里的颜色信息和画面上的颜色信息的话,就需要向片段着色器里传入一些必要的信息。

可是要怎么传递这些信息呢?这时候就用到varying了。根据前面给的代码例子,再稍微修改一下,这一次不光有顶点着色器,片段着色器也一起写进去。

首先,顶点着色器部分。

attribute vec4 position;
attribute vec4 color;
uniform mat4 mvpMatrix;
varying vec4 vColor

void main(void) {
    vColor = color;
    gl_Position = mvpMatrix * position;
}
接着,片段着色器接收通过varying修饰符所定义的变量vColor。

varying vec4 vColor;

void main(void)
{
    gl_FragColor = vColor;
}
就是这样,要从顶点着色器将数据传到片段着色器,需要使用varying修饰符所定义的变量。另外,和顶点着色器中必需要把数据传给gl_Position类似,片段着色器要把数据传给gl_FragColor。

与顶点着色器不同的是,片段着色器的gl_FragColor不是必须要赋值的。但是一般都会输出一种什么颜色,所以gl_FragColor就变成必要的了。


总结

这次的内容有点太长了,介绍的内容也有点深,一次性全都理解可能会有点儿难吧。

简单的把这次的内容总结一下。

顶点着色器和片段着色器,都可以通过GLSL来书写,基本上它们算是一个组合。着色器的内部,必须要定义一个main函数,在这个函数里面添加自己的处理。而且,要从WebGL一侧向着色器传递数据的时候,需要用到一些特殊的修饰符所定义的变量。

要向着色器传递各个顶点的不同的信息的时候,使用attribute修饰符声明变量,要向着色器传递对所有顶点来说都一样的信息的时候,使用uniform修饰符声明变量。

另外,从顶点着色器向片段着色器传递数据的时候,使用varying修饰符声明变量。

顶点着色器中内置的变量gl_Position必须赋值,而片段着色器的内置变量gl_FragColor虽然不是必须赋值的,但是一般情况下都会赋值。

关于GLSL,正式的内容的话是很深的,这次的内容是算是介绍了一些表层的最基本的部分。和这些相关的内容,以后会逐渐接触到,到时候再慢慢的说明。首先,把这次的内容彻底理解一下吧。


下次,介绍顶点缓存相关的内容。


转载请注明:转自lufy_legend的博客http://blog.csdn.net/lufy_legend

[WebGL入门]八,着色器的说明和基础,古老的榕树,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。