前端之图形学-2 着色器

655 阅读3分钟

前端图形学篇为随手记,在学习推进过程会根据个人了解进行二次修改,文章中的观点可能来自看到的各个网站书籍,存在的错误或不完善的地方请谅解

It's not what you look at that matters, it's what you see.
重要的不是你正看着的是什么,而是你从中所看到的是什么。——亨利·戴维·梭罗


顶点

顶点是指二维或三维空间中的一个点,比如二维或者三维图形的端点或交点

片元

可以了解成像素,但包括大小、颜色、光源等元素。


顶点着色器(Vertex shader) 用于描述顶点特征(如位置、颜色等)的程序,它能改变几何形状的位置。它处理每个顶点的数据,例如顶点坐标,法线,色彩,和纹理坐标。

片元着色器(Fragment shader)进行逐片元处理过程如光照的程序


例子中绘制一个10像素大小的点


着色器采用GLSL ES编程语言,其是OpenGL中GLSL全称是 Graphics Library Shader Language (图形库着色器语言)的一个子集,但其采用类C的写法并不难理解。

注意:
GLSL ES是大小写敏感的强类型语言,语句必须以分号(;)结束
GLSL ES是从main()函数开始执行,程序只能有一个mian()函数


顶点着色器指定点的位置及大小

var VSHADER_SOURCE =

'void main() {\n}' +

' gl_Position = vec4(0.0, 0.0, 0.0, 1.0)\n' + //齐次坐标,浮点数,必须

' gl_PointSize = 10.0;\n' + //浮点数,非必须,默认为10.0

'}\n';

片元着色器指定点的颜色

var FSHADER_SOURCE =

'void main() {\n}' +

' gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0)'\n' +

'}\n';

着色器以JavaScript字符串形式编写,主程序就可以将其传给webGL进行编译

初始化着色器

辅助函数initShaders()对字符串编写的着色器进行初始化

initShaders(gl, vshader, fshader)
参数
gl 指定渲染的上下文
vshader 指定顶点着色器字符串
fshader 指定片元着色器字符串
返回值
true 初始化着色器成功
false 初始化着色器失败

注意:着色器运行在webGL中,而不是在javascript中。


完整代码

var VSHADER_SOURCE =
'void main() {\n}' +
' gl_Position = vec4(0.0, 0.0, 0.0, 1.0)\n' +
' gl_PointSize = 10.0;\n' +
'}\n';

var FSHADER_SOURCE =
'void main() {\n}' +
' gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0)\n' +
'}\n';

function main () {
// 获取节点元素
var canvas = document.getElementById('webGL');
// 获取webgl上下文
var gl = getWebGLContext(canvas);
if (!gl) {
console.log('Failed to get the rendering context for webgl');
return;
}
// 初始化着色器
if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
console.log('Failed to init shaders');
return;
}
// 设置背景色
gl.clearColor(0.0, 0.0, 0.0, 1.0);
//清空
gl.clear(gl.COLOR_BUFFER_BIT);
//绘制
gl.drawArrays(gl.POINTS, 0, 1);
}



JavaScript和着色器间的数据通信

WebGL程序将顶点的位置坐标从JS传到着色器,然后在对于位置上进行绘制。

attribute变量 传输的是顶点相关的数据,全局变量,只能用在顶点着色器

uniform变量 传输的是对于所有顶点都相同的数据,全局变量,如颜色

varying变量 是从顶点着色器向片元着色器传输数据,须在两种着色器中共同声明

主要步骤:

1.着色器中声明attribute变量

'attribute vec4 a_Position;\n' +

<存储限定符><类型><变量名>

词attribute为存储限定符,声明成全局变量


2.获取attribute变量的位置,赋值js中的变量

var a_Position = gl.getAttribLocation(al.program, 'a_Position');

3.对attribute变量进行赋值

gl.vertexAttrib3f(a_Position, 0.0, 0.0, 0.0);
vertexAttrib3f(location, v1, v2, v3)作为传值函数,第一个参数为传值参数的地址,后面为传递的数值
同理,存在
vertexAttrib1f(location, v1)
vertexAttrib2f(location, v1, v2)
vertexAttrib4f(location, v1, v2, v3, v4)
vertexAttrib3f中的3f为参数个数+参数类型,“f”为浮点数,“i”为整数

以上步骤可以动态设置webgl着色器的参数,因此这里就可以构成用户与图形交互的一个基础,如鼠标移动,获取移动的轨迹点,并通过attribute赋值着色器进行绘制。 相对应,如果需要对片元着色器进行处理,则使用uniform进行声明,getUniformLocation获取变量存储地址,uniform4f传输数据。



齐次坐标

通过(x, y, z, w)描述,等价于三维坐标上的(x/w, y/w, z/w),w为齐次坐标系中度量分量,当w为1时等同三维坐标系。