WebGL学习系列-片元着色器简介
Posted 那个天真的人
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WebGL学习系列-片元着色器简介相关的知识,希望对你有一定的参考价值。
前言
到目前为止,我们绘制过点、三角形、矩形等,但使用的都是单色系。之前曾经说过着色器的概念,着色器分为顶点着色器和片元着色器,我们一直在使用顶点着色器,而对片元着色器基本没有提及过,本小节将展开对片元着色器的简单介绍。
彩色的点
之前提到过,顶点着色器决定点的大小、位置和颜色,而片元着色器是用于给像素着色的,初步看,片元着色器的任务好像给顶点着色器完成了,但实际上不然,顶点着色器只能决定点的颜色,如果绘制成了图形,图形填充的颜色就该由片元着色器处理了。
先来看一下我们将要绘制的彩色点的效果图:
我们一共绘制了三个点,而且三个点的颜色不同,接下来分析下代码,先来看下顶点着色器的代码:
// 顶点着色器代码(决定顶点的位置、大小、颜色)
var VSHADER_SOURCE =
'attribute vec4 a_Position;\\n' +
'attribute vec4 a_Color;\\n' +
'varying vec4 v_Color;\\n' +
'void main() \\n' +
' gl_Position = a_Position;\\n' + // 设置顶点的位置
' v_Color = a_Color;\\n' + // 顶点设置一个varying类型的颜色值,用于线性化处理
' gl_PointSize = 10.0;\\n' + // 设置顶点的大小
'\\n';
上面的代码定义了两个color变量,然后把attribute类型的颜色变量赋值给了varying类型的颜色变量(你一定有很多疑惑,不要着急,下文会解释的)。
接着看看片元着色器的代码:
// 片元着色器代码(给像素上色)
var FSHADER_SOURCE =
'precision mediump float;\\n' +
'varying vec4 v_Color;\\n' +
'void main() \\n' +
' gl_FragColor = v_Color;\\n' + // 设置像素的颜色
'\\n';
片元着色器代码中,也定义了一个varying变量,而且变量名字也叫v_Color,最后把v_Color赋值给了内置颜色变量gl_FragColor,从而决定了像素点的颜色。一起来看一下变量传递说明图:
我们会定义好一个顶点颜色缓冲区,然后逐顶点传递给顶点着色器中的a_Color变量,而a_Color赋值给了v_Color变量。最需要关注的就是,在顶点着色器和片元着色器中,两个varying变量直接关联赋值了,这是两种不同着色器传递信息的方式,以后介绍纹理时也会使用此种方式来传递坐标信息。最后在片元着色器中的v_Color变量就获取到了一个线性化的颜色值,然而最终决定像素颜色值的是gl_FragColor这个内置变量,所以最后进行了赋值。
我初步看到的时候也发现实在是复杂,但没办法,底层就是这样处理的,我们要确保需要传值的两个varying变量名称是一致的。varying用于着色器间信息的传递,它命名为varying,表示变化的意思,还有更加深层次的应用,稍后我们会继续解释。
初始化颜色信息跟初始化顶点信息非常的类似,代码如下:
// 三个顶点的颜色
var verticesColors = new Float32Array([
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0
]);
// 创建一个缓存对象,用于存放顶点颜色数据
var colorBuffer = context.createBuffer();
// 绑定缓存对象
context.bindBuffer(context.ARRAY_BUFFER, colorBuffer);
// 把数据写到缓冲对象中
context.bufferData(context.ARRAY_BUFFER, verticesColors, context.STATIC_DRAW);
// 获取顶点着色器代码中的顶点颜色变量
var a_Color = context.getAttribLocation(context.program, 'a_Color');
// 设置变量获取数据规则
context.vertexAttribPointer(a_Color, 3, context.FLOAT, false, 0, 0);
// 允许变量从 ARRAY_BUFFER目标上绑定的缓冲区对象获取数据
context.enableVertexAttribArray(a_Color);
这里相信大家都很熟悉了,不再展开说明。
神奇的彩色三角形
到这里,我们已经学会使用varying变量来绘制多个不同颜色的点,接下来,我们把上一个示例给绘制成三角形,而不是点,如下代码所示:
// 绘制一个三角形
context.drawArrays(context.TRIANGLES, 0, n);
结果如下:
是不是感觉很惊讶,咱们只在三个顶点中定义了颜色,结果看起来像是自动会渐变的。这就是片元着色器之所以叫片元的地方了。我们先来看渲染原理图:
- 顶点着色器用于决定顶点的位置、大小和颜色(严格上来讲,是顶点关联了一个颜色值)
- 确定了顶点信息后,便可以绘制出三角形图形
- 有了三角形图形,webgl内部会对三角形进行光栅化,简单来讲,就是把三角形拆解成一个一个的像素点,然后发现了varying修饰的v_Color变量,利用顶点颜色信息,以及使用线性化计算方式,给每个像素点计算一个线性化的v_Color值,这就是varying有变化的意思的由来。在顶点中定义的varying变量,实际上,对于每个像素点,都有不同的值,最后调用片元着色器,把每个像素的颜色值(独有的v_Color值)传递给了片元着色器,最后设置到了颜色缓冲区,以便于最终在浏览器上显示。
着色器三大变量
通过前面的学习,我们一共接触了三种类型的着色器变量,分别是 attribute,uniform和 varying,现在简单回顾一下。
1. attribute 变量用于顶点着色器中,表示普通的变量。
2. uniform 变量用于顶点着色器和片元着色器中,用于表示不变的变量,比如,在顶点着色器中,表示点大小的变量,可以使用uniform,如果所有的顶点大小一致。
3. varying 变量用于顶点着色器和片元着色器之间的传递信息,通常用于传递颜色信息和坐标信息(比如纹理坐标)。
小结
理解片元着色器是按照逐像素进行着色是非常关键的,而顶点着色器则是逐顶点执行的。我们使用varying变量在顶点着色器和片元着色器之间共享数据,而且要注意的是,varying针对第个像素都有一个线性化的值,参考彩色三角形效果图就知道了。varying不仅仅用于传递颜色信息,它还经常用于传递纹理坐标信息,以便进行贴图。
源码下载
参考
<<WebGL编程指南:>>
以上是关于WebGL学习系列-片元着色器简介的主要内容,如果未能解决你的问题,请参考以下文章