webgl 绘图需要两种着色器:
顶点着色器(Vertex shader):描述顶点的特征,如位置、颜色等。
片元着色器(Fragment shader):进行逐片元处理,如光照。
webgl 的着色器语言是GLSL ES语言
片元着色程序,要写在type=“x-shader/x-fragment” 的script中。
void main() {…… } 是主体函数。 在顶点着色器中,gl_Position 是顶点的位置,gl_PointSize 是顶点的尺寸,这种名称都是固定的,不能写成别的。 在片元着色器中,gl_FragColor 是片元的颜色。 vec4() 是一个4维矢量对象。 将vec4() 赋值给顶点点位gl_Position 的时候,其中的前三个参数是x、y、z,第4个参数默认1.0,其含义我们后面会详解; 将vec4() 赋值给片元颜色gl_FragColor 的时候,其中的参数是r,g,b,a。 至于GLSL ES语言的其它知识,咱们会在后面另开一篇详解,这里先以入门为主。
着色器初始化
1. 建立程序对象,目前这只是一个手绘板的外壳。
const shaderProgram = gl.createProgram();
2. 建立顶点着色器对象和片元着色器对象,这是手绘板里用于接收触控笔信号的零部件,二者可以分工合作,把触控笔的压感(js信号)解析为计算机语言(GLSL ES),然后让计算机(浏览器的webgl 渲染引擎)识别显示。
const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource);
const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource);
3. 将顶点着色器对象和片元着色器对象装进程序对象中,这就完成的手绘板的拼装。
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
4. 连接webgl 上下文对象和程序对象,就像连接触控笔和手绘板一样(触控笔里有传感器,可以向手绘板发送信号)。
gl.linkProgram(shaderProgram);
5. 启动程序对象,就像按下了手绘板的启动按钮,使其开始工作。
gl.useProgram(program);
在以后的学习里,initShaders 会经常用到,所以我们可以将其模块化。
function initShaders(gl,vsSource,fsSource){
//创建程序对象
const program = gl.createProgram();
//建立着色对象
const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource);
const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource);
//把顶点着色对象装进程序对象中
gl.attachShader(program, vertexShader);
//把片元着色对象装进程序对象中
gl.attachShader(program, fragmentShader);
//连接webgl上下文对象和程序对象
gl.linkProgram(program);
//启动程序对象
gl.useProgram(program);
//将程序对象挂到上下文对象上
gl.program = program;
return true;
}
function loadShader(gl, type, source) {
//根据着色类型,建立着色器对象
const shader = gl.createShader(type);
//将着色器源文件传入着色器对象中
gl.shaderSource(shader, source);
//编译着色器对象
gl.compileShader(shader);
//返回着色器对象
return shader;
}
export {initShaders}
后面在需要的时候,import 引入即可。 ```js import {initShaders} from '../jsm/Utils.js'; ```
【定义着色器字符串】
顶点着色器有二个固定的属性gl_Position和gl_PointSize,分别表示位置和尺寸:
片段着色器有一个固定的属性gl_FragColor表示颜色: