在JavaScript程序通过attribute变量向着色器传值
1.demo效果
如上图,这个demo和上一个效果一样,但是实现时却不同,这一次在JavaScript程序中通过 gl.getAttribLocation() 方法获取着色器中的变量a_Position的地址,然后通过 gl.vertexAttrib3f() 方法向着色器变量a_Position传值,最后将图形呈现在页面中。
2.相关知识点
2.1 着色器中的attribute变量
attribute变量是一种GLSL ES变量,被用来从外部向顶点着色器传输数据。接下来介绍一下attribute变量的声明,该变量的声明有一定的格式要求:<存储限定符><类型><变量名>
友情提示:
- attribute变量必须声明成全局变量
- 所有的attribute变量最好以a_前缀开始,这样从变量的名字就可以区分出类型
2.2 gl.getAttribLocation()方法
我们在着色器程序中声明的attribute变量都会有一个自己的存储地址,通过这个地址我们可以在外部程序中给它赋值,gl.getAttribLocation() 方法就是帮我们获取这个地址的利器
函数功能:获取有name指定的着色器中attribute变量的存储地址
--------------------------------------------------------------------------
调用示例:gl.getAttribLocation(program, name)
--------------------------------------------------------------------------
参数
program 指定包含顶点着色器和片元着色器的着色器程序对象
name 指定想要获取其存储地址的attribute变量名称
--------------------------------------------------------------------------
返回值 >=0 attribute变量的存储地址
-1 指定的变量名不存在,或命名具有gl_或webgl_前缀
--------------------------------------------------------------------------
错 误 INVALID_OPERATION 程序对象未能连接成功
INVALID_VALUE name参数的长度大于最大长度,默认256字节
示例代码
//获取着色器attribute变量a_Position的存储地址
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
2.3 gl.vertexAttrib3f()方法
gl.getAttribLocation() 方法帮我们获取到了着色器变量的地址,这时就需要请出gl.vertexAttrib3f() 方法了,通过这个方法我们就可以在JavaScript程序中把想要赋的值赋给着色器中的attribute变量
函数功能:将数据v0, v1, v2 传给由location参数指定的着色器的attribute变量
------------------------------------------------------------------------------
调用示例:gl.vertexAttrib3f(location, v0, v1, v2)
------------------------------------------------------------------------------
参数
location 指定将要修改的attribute变量的存储地址
v0 指定填充attribute变量第一个分量的值
v1 指定填充attribute变量第二个分量的值
v2 指定填充attribute变量第三个分量的值
------------------------------------------------------------------------------
返回值 无
------------------------------------------------------------------------------
错 误 INVALID_OPERATION 没有当前的program对象
INVALID_VALUE location大于等于attribute变量的最大数据,默认为8
示例代码
//向着色器attribute变量a_Position传值
gl.vertexAttrib3f(a_Position, 0.0, 0.0, 0.0)
2.4 gl.vertexAttrib3f()的同族函数
gl.vertexAttrib3f() 方法是一系列同族函数中的一个,该系列函数的任务就是从JavaScript程序中向顶点着色器中的attribute变量传值
函数功能:将数据[1~4个分量]传给由location参数指定的着色器的attribute变量
------------------------------------------------------------------------------
gl.vertexAttrib1f(location, v0)
gl.vertexAttrib2f(location, v0, v1)
gl.vertexAttrib3f(location, v0, v1, v2)
gl.vertexAttrib4f(location, v0, v1, v2, v3)
------------------------------------------------------------------------------
参数
location 指定将要修改的attribute变量的存储地址
v0,v1,v2,v3 指定传输给attribute变量的四个分量的值
------------------------------------------------------------------------------
返回值 无
------------------------------------------------------------------------------
错 误 INVALID_VALUE location大于等于attribute变量的最大数据,默认为8
你同样可以使用这些方法的矢量版本,它们的名字以"v"作为结尾。并接受类型化数组作为参数,函数名中数字表示数组中元素的个数
var position = new Float32Array([1.0,2.0,3.0,1.0]);
gl.vertexAttrib4fv(position);
2.5 attribute变量使用流程介绍
attribute变量的使用大致流程为:
- 在着色器中声明attribute变量
- 在JavaScript程序中获取attribute变量的存储地址
- 通过attribute变量的存储地址向着色器中的attribute变量传值
为了帮大家更直观的理解,我画了一张图,如有不足,请多多指正
3.demo代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<!--通过canvas标签创建一个400px*400px大小的画布-->
<canvas id="webgl" width="400" height="400"></canvas>
<script>
//通过getElementById()方法获取canvas画布
var canvas = document.getElementById('webgl');
//通过方法getContext()获取WebGL上下文
var gl = canvas.getContext('webgl');
//顶点着色器
var VSHADER_SOURCE = '' +
'attribute vec4 a_Position;\n' + //声明attribute变量a_Position,用来存放顶点位置信息
'attribute float a_PointSize;\n' + //声明attribute变量a_PointSize,用来存放顶点大小信息
'void main(){\n' +
' gl_Position = a_Position;\n' + //变量a_Position赋值给顶点着色器内置变量gl_Position
' gl_PointSize = a_PointSize;\n' + //变量a_PointSize赋值给顶点着色器内置变量gl_PointSize
'}\n';
//片元着色器
var FSHADER_SOURCE = '' +
'void main(){\n' +
//设置片元颜色(红色)
' gl_FragColor = vec4(1.0,0.0,0.0,1.0);\n' +
'}\n';
//初始化着色器
initShader(gl, VSHADER_SOURCE, FSHADER_SOURCE);
//获取着色器attribute变量a_Position的存储地址
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
//向着色器attribute变量a_Position传值
gl.vertexAttrib3f(a_Position, 0.0, 0.0, 0.0)
//获取着色器attribute变量a_PointSize的存储地址
var a_PointSize = gl.getAttribLocation(gl.program, 'a_PointSize');
//向着色器attribute变量a_PointSize传值
gl.vertexAttrib1f(a_PointSize, 30.0)
// 设置canvas的背景色
gl.clearColor(0.0, 0.0, 0.0, 1.0);
//清空canvas
gl.clear(gl.COLOR_BUFFER_BIT);
//开始绘制,绘制顶点,从第一个顶点开始绘制,绘制一个顶点
gl.drawArrays(gl.POINTS, 0, 1);
//初始化着色器函数
function initShader(gl, VSHADER_SOURCE, FSHADER_SOURCE) {
//创建顶点着色器对象
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
//创建片元着色器对象
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
//引入顶点、片元着色器源代码
gl.shaderSource(vertexShader, VSHADER_SOURCE);
gl.shaderSource(fragmentShader, FSHADER_SOURCE);
//编译顶点、片元着色器
gl.compileShader(vertexShader);
gl.compileShader(fragmentShader);
//创建程序对象program
var program = gl.createProgram();
//附着顶点着色器和片元着色器到program
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
//链接program
gl.linkProgram(program);
//使用program
gl.useProgram(program);
gl.program = program
//返回程序program对象
return program;
}
</script>
</body>
</html>