什么是 Shader
Shader是一种面向GPU的编程语言, 全称是 (OpenGL Shading Language) 由于GPU结构的特殊性,各个厂家对 Shader的支持也不是尽善尽美.就像浏览器厂商有时也不是严格 按照W3C规范来搞,但是大体上的规则还是遵守的. 由于shader语言十分复杂,本文只做简要概述,在后面的章节会有详细的解释. 下面就是一个webgl shader 例子:
vertex shader
attribute vec4 a_Position;
uniform vec4 u_Color;
void main(){
gl_Position = a_Position;
gl_PointSize = 10.0;
}
fragment shader
precision highp float;
uniform vec4 u_Color;
void main(){
gl_FragColor = u_Color;
}
shader 分为两种:
vertex shader
(顶点着色器). 控制点的位置和大小.
fragment shader
(片元着色器).控制点的颜色.
可以看到在shader中有一些内置的变量如gl_Position
gl_PointSize
gl_FragColor
他们都是有特殊含义的,这些我们后面再讲.
关于canvas标签
相对于webgl来说context2d api 则大家应该很熟悉了,它比较简单直观,还记得这样的代码吗?
var canvas =document.getElementById('canvas');
var ctx=canvas.getContext("2d");
...
...
ctx.lineTo()
context2d api 是在canvas上绘图的最简单的 API. 我们通过调用 canvas.getContext("2d")
获得了一个 context2d 对象ctx
,之后的绘图工作
只需要调用ctx下的相应绘图函数就行.
webgl 下图像也是显示在canvas中的,获取webgl对象的方式与获取context2d对象类似:
var canvas =document.getElementById('canvas');
var gl=canvas.getContext("webgl");
通过调用 canvas.getContext("webgl")
我们会获得一个 webgl绘图上下文对象 gl
,之后的绘图工作都会与这个对象相关.
如何在Javascript中关联 Shader
正如上一章讲的,js需要通过 webgl API 将数据发送到 shader上.但目前为止,就像上面的例子,shader还只是一些'字符串'而已.还并不是可用的程序, 所以要使用shader首先要编译它.
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader,vertexStr); //vertexStr 就是上例的shader字符串
gl.compileShader(vertexShader);
var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragShader,fragStr);//vertexStr 就是上例的shader字符串
gl.compileShader(fragShader);
这样我们获得了两个shangder对象 一个 vertex shader对象vertexShader
,一个fragment shader对象 fragShader
.
但是 vertexShader
和 fragShader
我们仍然不能直接使用, 我们还需要把它们链接起来.因为一个完整的shader是由一个顶点着色器 + 一个片元着色器 组成的.
我们还需要把他们链接起来.
var program = gl.createProgram();
gl.attachShader(program,vertexShader);
gl.attachShader(program,fragShader);
gl.linkProgram(program);
gl.useProgram(program);
这样生成的 program
对象既是一个可用对象. 最后一句 gl.useProgram(program)
指定当前正在使用的program
对象.
这里有点像用gcc 编译 c代码,首先我们编译源码文件,获得 .o文件.
g++ -o a.cpp
g++ -o b.cpp
.o文件我们不能直接用,我们还需要把他们链接起来
g++ a.o b.o -o test.exe
这样通过链接器链接后的 test.exe 我们就可以使用了.