跟着书走,今天该画点了。
1、html就不说了,直接把js代码放上来,然后慢慢分析。
// HelloPint2.js (c) 2012 matsuda
// 顶点着色器
var VSHADER_SOURCE =
'attribute vec4 a_Position;\n' + // attribute variable
'void main() {\n' +
' gl_Position = a_Position;\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() {
// 获取canvas元素
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 intialize shaders.');
return;
}
// Get the storage location of a_Position
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
if (a_Position < 0) {
console.log('Failed to get the storage location of a_Position');
return;
}
// Pass vertex position to attribute variable
gl.vertexAttrib3f(a_Position, 0.0, 0.0, 0.0);
// 设置清空用的背景色
gl.clearColor(0.0, 0.0, 0.0, 1.0);
// 清空背景色,用上行代码设置的颜色
gl.clear(gl.COLOR_BUFFER_BIT);
// Draw
gl.drawArrays(gl.POINTS, 0, 1);
}
2、顶点着色器、片元着色器
// VSHADER_SOURCE 、FSHADER_SOURCE 分别存储的是顶点点着色器与片元着色器的程序,字符串的形式。
// \n有助于定位你的着色器程序运行出错的地方,当然也可以不加了。
var VSHADER_SOURCE =
//此处是定义了一个 vec4 类型的变量。为的是接受外面传来的位置。
'attribute vec4 a_Position;\n' +
'void main() {\n' +
' gl_Position = a_Position;\n' + //
' gl_PointSize = 10.0;\n' + //设定点的尺寸
'}\n';
在本地他就是一个字符串,
// Fragment shader program
var FSHADER_SOURCE =
'void main() {\n' +
' gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n' + //设定点的颜色
'}\n';
里面的顶点着色器与片元着色器是很复杂的明天开始详细说。
3、获取webgl绘图上下文
var gl = getWebGLContext(canvas);
4、初始化shader
if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
console.log('Failed to intialize shaders.');
return;
}
这个函数是《webg编程指南》的作者封装的函数。初始化shader不复杂,就是麻烦。
首先字符串是肯定没用滴,得经过一番操作。我这边倒着推。
1)、想要使用着色器,首先要知道哪个函数是‘使用’,传递什么参数。
答:.useProgram(
WebGLProgram
)。
他的作用是将定义好的WebGLProgram
对象添加到当前的渲染状态中。
2)、WebGLProgram又是啥呐?
答:WebGLProgram 是 WebGL API 的一部分,它由两个WebGLShader
s (webgl 着色器)组成,分别为顶点着色器和片元着色器。创建一个 WebGLProgram 需要调用 GL 上下文的createProgram()
方法,然后调用attachShader()
方法附加上着色器,之后你才能将它们连接到一个可用的程序。
例:
//创建一个WebGlProgram
var program = gl.createProgram();
// 往WebGlProgram添加预先存在的着色器
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
//用linkProgram()搞成一个可用的程序
gl.linkProgram(program);
//getProgramParameter检测linkProgram()的执行结果
if ( !gl.getProgramParameter( program, gl.LINK_STATUS) ) {
///错误的信息
var info = gl.getProgramInfoLog(program);
throw 'WebGL program 不能编译. \n\n' + info;
}
3)、问题2中的attachShader()有两个参数,分别是 WebGLProgram
对象和WebGLShader对象。
WebGLProgram对象就是createProgram()返回的。
那么WebGLShader对象是啥?
答:
要创建一个 WebGLShader 需要使用 .createShader()。然后
通过 .shaderSource()
然后挂接GLSL源代码 , 最后调用 .compileShader()
完成着色器(shader)的编译。 此时 WebGLShader 仍不是可用的形式,他需要被添加到一个 WebGLProgram
里。
例
//创建WebGLShader对象,参数为gl.VERTEX_SHADER(顶点着色器) 或 gl.FRAGMENT_SHADER(片元着色器)两
//者中的一个。
var shader = gl.createShader( type );
//sourceCode 就是js文件开头存储的顶点着色器与片元着色器(字符串,要与上一行代码的type对应)。
gl.shaderSource( shader, sourceCode );
//编译
gl.compileShader( shader );
//编译结果
if ( !gl.getShaderParameter(shader, gl.COMPILE_STATUS) ) {
var info = gl.getShaderInfoLog( shader );
throw "Could not compile WebGL program. \n\n" + info;
}
4)、整理得
//已知着色器
var VSHADER_SOURCE =
'attribute vec4 a_Position;\n' + // attribute variable
'void main() {\n' +
' gl_Position = a_Position;\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';
//已知上下文
gl
步骤:
1、将string着色器整理成WebGLShader
let vertexShader= gl.createShader(gl.VERTEX_SHADER);
let fragmentShader= gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader,VSHADER_SOURCE );
gl.compileShader(shaderSource);
gl.shaderSource(fragmentShader,FSHADER_SOURCE );
gl.compileShader(shaderSource);
2、创建WebGLProgram,并将WebGLShader怼进去
let program= gl.createProgram();
program.attachShader(program,vertexShader);
program.attachShader(program,fragmentShader);
gl.linkProgram(program);
3、使用WebGLProgram
gl.useProgram(program);
注:看作者的代码发现如果linkProgram()失败了,就删除program、shader
gl.deleteProgram(program);
gl.deleteShader(fragmentShader);
gl.deleteShader(vertexShader);
5、获取着色器中定义的变量
//这是着色器中定义的变量
attribute vec4 a_Position;
//用这种方法获取WebGLProgram对象中 attribute变量a_Position的位置
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
6、给attribute变量赋值
gl.vertexAttrib3f(a_Position, 0.0, 0.0, 0.0);
WebGLRenderingContext.vertexAttrib[1234]f[v]() 是 WebGL API 的方法,可以为顶点attibute变量赋值。
7、最终绘图gl.drawArrays(gl.POINTS, 0, 1);
drawArrays用法