在前几节中我们分别学习 点 线 三角形的学习。今天我们给三角形添加一个渐变色
在这个章节中如果你跟着看了前几张的学习内容,你就很快可以理解本章的内容了。如果你并没有webgl的经验,你可以去我的博文中看我之前的文章;
这一章节中其实与上创建线段与三角形并没有上面区别,唯独有两个点需要注意一下;
第一需要注意的地方,在于glsl语言定义中我们需要把顶点着色器与片元着色器结合起来,请看下面的代码
///顶点着色皮
let vertexShaderSource = `
//浮点数设置为中等精度
precision mediump float;
//接收 JavaScript 传递过来的点的坐标(X, Y)
attribute vec2 a_Position;
// 接收canvas的尺寸。
attribute vec2 a_Screen_Size;
attribute vec4 a_Color;
varying vec4 v_Color;
void main(){
// 将 canvas 的坐标值 转换为 [-1.0, 1.0]的范围。
vec2 position = (a_Position / a_Screen_Size) * 2.0 - 1.0;
// canvas的 Y 轴坐标方向和 设备坐标系的相反。
position = position * vec2(1.0, -1.0);
// 最终的顶点坐标。
gl_Position = vec4(position, 0.0, 1.0);
v_Color = a_Color;
}
`
//片元着色器
let fragmentShaderSource = `
//设置浮点数精度为中等。
precision mediump float;
//接收 JavaScript 传过来的颜色值(rgba)。
varying vec4 v_Color;
void main(){
vec4 color = v_Color / vec4(255, 255, 255, 1);
gl_FragColor = color;
}
`
如果你并不太理解上面的内容是什么意思的话,可以去看这一章,你会大概的明白是什么意思
我们可以看到在顶点着色器与片元着色器中存在了同样的一个变量,入伙你对varying 不理解的话,可以点进去查看片的文章。看完你就知道了。打通顶点着色器与片元着色器。
varying vec4 u_Color
还有一个地方需要我们注意的是webgl.enableVertexArray();这个API函数。一定不要忘记。
canvas.addEventListener('click',evt => {
let x = evt.pageX;
let y = evt.pageY;
positions.push(x,y);
let color = randomColor();
colors.push(color.r,color,color.b,color.a)
if(positions.length % 6 == 0){
gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer);//绑定使用当前的缓冲区
gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(positions),gl.DYNAMIC_DRAW);//将数据放进去
gl.bindBuffer(gl.ARRAY_BUFFER,colorBuffer);//绑定使用颜色缓冲区
gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(colors),gl.DYNAMIC_DRAW);//将数据放入缓冲区中
this.render(gl);
}
});
文中有两个缓冲区,那应该如何使用呢,看判断中的内容,我们先绑定,然后传数据就可以了
另外还需要说一下的就是函数 webgl.enableVertexAttribArray();可以点进去看看哦,不要忘记这个;
enableVertexArray()
激活WebGL图层将单个顶点从顶点缓冲区传递到顶点着色器函数的属性的用法。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
///顶点着色皮
let vertexShaderSource = `
//浮点数设置为中等精度
precision mediump float;
//接收 JavaScript 传递过来的点的坐标(X, Y)
attribute vec2 a_Position;
// 接收canvas的尺寸。
attribute vec2 a_Screen_Size;
attribute vec4 a_Color;
varying vec4 v_Color;
void main(){
// 将 canvas 的坐标值 转换为 [-1.0, 1.0]的范围。
vec2 position = (a_Position / a_Screen_Size) * 2.0 - 1.0;
// canvas的 Y 轴坐标方向和 设备坐标系的相反。
position = position * vec2(1.0, -1.0);
// 最终的顶点坐标。
gl_Position = vec4(position, 0.0, 1.0);
v_Color = a_Color;
}
`
//片元着色器
let fragmentShaderSource = `
//设置浮点数精度为中等。
precision mediump float;
//接收 JavaScript 传过来的颜色值(rgba)。
varying vec4 v_Color;
void main(){
vec4 color = v_Color / vec4(255, 255, 255, 1);
gl_FragColor = color;
}
`
let canvas = document.getElementById('canvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
let gl = canvas.getContext('webgl');
//创建顶点着色器
let vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader,vertexShaderSource);
gl.compileShader(vertexShader);
//创建片元着色器
let fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader,fragmentShaderSource);
gl.compileShader(fragmentShader);
//创建一个完成的着色器
let program = gl.createProgram();
gl.attachShader(program,vertexShader);
gl.attachShader(program,fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
//读取相关的变量
let a_Position = gl.getAttribLocation(program,'a_Position');
let a_Color = gl.getAttribLocation(program,'a_Color');
//绑定相关变量 之后我们是对这两个在缓冲区进行操作的
gl.enableVertexAttribArray(a_Color);
gl.enableVertexAttribArray(a_Position);
//处理顶点着色器中的变量
let a_Screen_Size = gl.getAttribLocation(program,'a_Screen_Size');//取到屏幕的大小
gl.vertexAttrib2f(a_Screen_Size,canvas.width,canvas.height);//设置参数
//---处理创建缓冲区,并设置从缓冲区中数据读取规则
let positionBuffer = gl.createBuffer();//创建一个position的缓冲区
gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer);//绑定缓冲区
//这是positionBuffer的读取规则
let size = 2;//一次性读取两位数
let type = gl.FLOAT;//设置读取取出来之后的数据格式
let normalize = false;//向量
let stride = 0;//
let offset = 0;
gl.vertexAttribPointer(a_Position,size,type,normalize,stride,offset);
// 创建 颜色信息 buffer
let colorBuffer = gl.createBuffer();
// 将当前 buffer 设置为 postionBuffer,接下来对 buffer 的操作都是针对 positionBuffer 了。
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
// 设置 a_Position 变量读取 positionBuffer 缓冲区的方式。
let size1 = 4;
let type1 = gl.FLOAT;
let normalize1 = false;
let stride1 = 0;
let offset1 = 0;
gl.vertexAttribPointer(a_Color, size1, type1, normalize1, stride1, offset1);
let positions = [];
let colors = [];
this.render(gl);
canvas.addEventListener('click',evt => {
let x = evt.pageX;
let y = evt.pageY;
positions.push(x,y);
let color = randomColor();
colors.push(color.r,color,color.b,color.a)
if(positions.length % 6 == 0){
gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer);//绑定使用当前的缓冲区
gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(positions),gl.DYNAMIC_DRAW);//将数据放进去
gl.bindBuffer(gl.ARRAY_BUFFER,colorBuffer);//绑定使用颜色缓冲区
gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(colors),gl.DYNAMIC_DRAW);//将数据放入缓冲区中
this.render(gl);
}
});
function render(gl) {
gl.clearColor(0,0,0,1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
if (positions.length <= 0) {
return;
}
gl.drawArrays(gl.TRIANGLES,0,positions.length/2);
}
//随机取到相关的颜色
function randomColor() {
return {
r: Math.random() * 255,
g: Math.random() * 255,
b: Math.random() * 255,
a: Math.random() * 1
};
}
</script>
</body>
</html>