接下来通过鼠标点击动态的在画布上添加点,以此了解webgl基础绘制的关键步骤
我们以main函数为切入点来逐个击破
initShader:初始化着色器
- 参数vsSource和fsSource是什么?
-
vsSource是顶点着色器变量,下面是它的定义形式
-
fsSource是片元着色器变量,下面是它的定义形式
-
initShader函数
作用:
- 创建一个着色器程序对象
- webgl上下文启用program对象,将创建的着色器程序对象复制给webgl上下文的程序对象。
-
createProgram:创建着色器程序对象
- 通过
loadShader函数加载顶点着色器和片元着色器 gl.attachShader是将创建好的着色器attach到我们着色器程序上,然后调用gl.linkProgram方法将program整合起来。getProgramParameter是为了验证program有没有整合成功,如果成功会返回程序对象的基本信息,否则整合失败,删除程序对象和创建的着色器。
loadShader:加载着色器
- 参数分别代表
gl上下文、着色器类型、着色器代码片段。 - 通过
createShader创建一个着色器对象。 - 通过
shaderSource将着色器代码注入着色器对象。 - 通过
compileShader编译着色器对象。 - 通过
getShaderParameter来获取编译后的着色器基本信息,如果编译成功,返回着色器对象,否则删除创建的着色器对象。
☝☝☝以上内容,重要的第一步:初始化着色器程序对象就完成了,接下来我们还是回到main函数👇👇👇
找到着色器变量的存储地址
- 参数分别为:着色器程序对象、变量名称。
getAttribLocation方法是为了找到着色器程序对象当中的着色器代码定义以attribute为存储限定符的变量的存储地址。getUniformLocation方法是为了找到着色器程序对象当中的着色器代码定义的以uniform为存储限定符的的变量的存储地址。- getAttribLocation和getUniformLocation的区别在于前者用于顶点着色器,后者用于片元着色器。
给变量赋值
- vertexAttrib
nf:其中n可以为1,2,3,4表示变量的个数。 - 参数:第一个参数表示变量存储地址,后面参数表示变量(个数为
n个)。
初始化面板,指定颜色
点击canvas面板,添加点
-
参数解析:
- ev:浏览器客户区
- gl:webgl上下文
- canvas:画布
- a_Position:顶点位置存储地址
- u_FragColor:片元颜色存储地址
-
获取触发点相对浏览器可视区域左上角距离x,y
-
获取canvas原点的基本信息,rect.left和rect.top分别为canvas坐标原点距离浏览器左上角的距离。
-
将触发点坐标转化成webgl的坐标
- 首先需要了解的是canvas坐标系和webgl坐标系是不一样的(下图转载自blog.csdn.net/u011332271/… 感谢博主)
- 首先需要了解的是canvas坐标系和webgl坐标系是不一样的(下图转载自blog.csdn.net/u011332271/… 感谢博主)
-
剩下的部分其实就是比较简单的步骤,主要是根据不用的象限赋值不同的颜色,然后绘制点,就不细述了。
源代码片段,拿走不谢~~
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>2Dcanvas</title>
</head>
<body>
<canvas id="canvas" width="400" height="400"></canvas>
<script>
var vsSource = `
attribute vec4 a_Position;
attribute float a_PointSize;
void main() {
gl_Position = a_Position;
gl_PointSize = a_PointSize;
}
`;
var fsSource = `
precision mediump float;
uniform vec4 u_FragColor;
void main() {
gl_FragColor = u_FragColor;
}
`;
function initShaders(gl, vshader, fshader) {
var program = createProgram(gl, vshader, fshader);
if (!program) {
console.log('Failed to create program');
return false;
}
gl.useProgram(program);
gl.program = program;
return true;
}
/**
* Create the linked program object
* @param gl GL context
* @param vshader a vertex shader program (string)
* @param fshader a fragment shader program (string)
* @return created program object, or null if the creation has failed
*/
function createProgram(gl, vshader, fshader) {
var vertexShader = loadShader(gl, gl.VERTEX_SHADER, vshader);
var fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fshader);
if (!vertexShader || !fragmentShader) {
return null;
}
var program = gl.createProgram();
if (!program) {
return null;
}
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
var linked = gl.getProgramParameter(program, gl.LINK_STATUS);
if (!linked) {
var error = gl.getProgramInfoLog(program);
console.log('Failed to link program: ' + error);
gl.deleteProgram(program);
gl.deleteShader(fragmentShader);
gl.deleteShader(vertexShader);
return null;
}
return program;
}
/**
* Create a shader object
* @param gl GL context
* @param type the type of the shader object to be created
* @param source shader program (string)
* @return created shader object, or null if the creation has failed.
*/
function loadShader(gl, type, source) {
var shader = gl.createShader(type);
if (shader == null) {
console.log('unable to create shader');
return null;
}
// Set the shader program
gl.shaderSource(shader, source);
// Compile the shader
gl.compileShader(shader);
// Check the result of compilation
var compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
if (!compiled) {
var error = gl.getShaderInfoLog(shader);
console.log('Failed to compile shader: ' + error);
gl.deleteShader(shader);
return null;
}
return shader;
}
var g_points = [];
var g_colors = [];
function click(ev, gl, canvas, a_Position, u_FragColor) {
var x = ev.clientX;
var y = ev.clientY;
var rect = ev.target.getBoundingClientRect();
x = ((x - rect.left) - canvas.height / 2) / (canvas.height / 2);
y = (canvas.width / 2 - (y - rect.top)) / (canvas.width / 2);
g_points.push([x, y]);
if (x >= 0.0 && y >= 0.0) {
g_colors.push([1.0, 0.0, 0.0, 1.0]);
} else if (x < 0.0 && y < 0.0) {
g_colors.push([0.0, 1.0, 0.0, 1.0]);
} else {
g_colors.push([0.0, 0.0, 1.0, 1.0]);
}
gl.clear(gl.COLOR_BUFFER_BIT);
var len = g_points.length;
for (var i = 0; i < len; i++) {
var rgb = g_colors[i];
var points = g_points[i];
gl.vertexAttrib3f(a_Position, points[0], points[1], 0.0);
gl.uniform4f(u_FragColor, rgb[0], rgb[1], rgb[2], rgb[3]);
gl.drawArrays(gl.POINTS, 0, 1);
}
}
function main() {
var canvas = document.getElementById('canvas');
if (!canvas) {
return;
}
var gl = canvas.getContext('webgl');
initShaders(gl, vsSource, fsSource);
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
var a_PointSize = gl.getAttribLocation(gl.program, 'a_PointSize');
var u_FragColor = gl.getUniformLocation(gl.program, 'u_FragColor');
gl.vertexAttrib3f(a_Position, 0.0, 0.0, 0.0);
gl.vertexAttrib1f(a_PointSize, 10.0);
gl.clearColor(0.5, 0.5, 0.5, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
canvas.onmousedown = function (ev) {
click(ev, gl, canvas, a_Position, u_FragColor);
}
}
main();
</script>
</body>
</html>
以上内容为个人理解,仅用于学习记录,如有任何问题,请指正🤌🤌🤌