上一节绘制了圆点,调用的绘制方法如下:gl.drawArrays(gl.POINTS, 0, 1); 第一个参数明显是个枚举类型,肯定还有其他值,如下所示:
- POINTS 可视的点
- LINES 单独线段
- LINE_STRIP 线条
- LINE_LOOP 闭合线条
- TRIANGLES 单独三角形
- TRIANGLE_STRIP 三角带
- TRIANGLE_FAN 三角扇
这小节尝试一下 绘制单独线段、线条、闭合线条、三角带(可构成矩形)
代码如下所示:
<template><div class="wrapper"><div class="point-wrapper"><div style="margin-bottom: 20px">绘制点</div><canvas id="point" width="280" height="250"></canvas></div><div class="point-mouse"><div style="margin-bottom: 20px">鼠标绘制点</div><canvas id="pointByMouse" width="280" height="250"></canvas></div></div>
</template><script>
export default {name: "point",
};
</script><script setup>
import { onMounted } from "vue";
import { initShaders } from "@/utils/myGL.js";const vertexShaderSrc = `
attribute vec4 a_Position;
attribute float a_PointSize;
void main() {gl_Position = a_Position;gl_PointSize = a_PointSize;
}
`;const fragmentShaderSrc = `
precision mediump float;
uniform vec4 u_FragColor;
void main() {gl_FragColor = u_FragColor;
}
`;const fragmentShaderSrcCircle = `
precision mediump float;
void main() {float d = distance(gl_PointCoord, vec2(0.5, 0.5));if(d < 0.5) {gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);} else { discard; }
}
`;const drawPointStatic = () => {const canvas = document.getElementById("point");// webgl画笔const gl = canvas.getContext("webgl");// 初始化着色器initShaders(gl, vertexShaderSrc, fragmentShaderSrc);const a_position = gl.getAttribLocation(gl.program, "a_Position");const a_pointSize = gl.getAttribLocation(gl.program, "a_PointSize");const u_FragColor = gl.getUniformLocation(gl.program, "u_FragColor");gl.vertexAttrib3f(a_position, 0, 0.0, 0.0);gl.vertexAttrib1f(a_pointSize, 20.0);gl.uniform4f(u_FragColor, 1.0, 0.0, 0.0, 1.0);// 指定将要用来清理绘图区的颜色gl.clearColor(0.0, 0.0, 0.0, 1.0);// 清理绘图区gl.clear(gl.COLOR_BUFFER_BIT);// 绘制顶点gl.drawArrays(gl.POINTS, 0, 1);setTimeout(() => {initShaders(gl, vertexShaderSrc, fragmentShaderSrcCircle);// 指定将要用来清理绘图区的颜色gl.clearColor(0.0, 0.0, 0.0, 1.0);// 清理绘图区gl.clear(gl.COLOR_BUFFER_BIT);// 绘制顶点gl.drawArrays(gl.POINTS, 0, 1);}, 2000);
};const drawPointByMouse = () => {const canvas = document.getElementById("pointByMouse");// webgl画笔const gl = canvas.getContext("webgl");// 初始化着色器initShaders(gl, vertexShaderSrc, fragmentShaderSrc);// // 指定将要用来清理绘图区的颜色gl.clearColor(0.0, 0.0, 0.0, 1.0);// // 清理绘图区gl.clear(gl.COLOR_BUFFER_BIT);let pointArrs = [];document.addEventListener("click", (event) => {const { clientX, clientY } = event;const { left, top, width, height } = canvas.getBoundingClientRect();const [cssX, cssY] = [clientX - left, clientY - top];const [halfWidth, halfHeight] = [width / 2, height / 2];const [xBaseCenter, yBaseCenter] = [cssX - halfWidth, cssY - halfHeight];const yBaseCenterTop = -yBaseCenter;const [x, y] = [xBaseCenter / halfWidth, yBaseCenterTop / halfHeight];const a_Position = gl.getAttribLocation(gl.program, "a_Position");const a_pointSize = gl.getAttribLocation(gl.program, "a_PointSize");const u_FragColor = gl.getUniformLocation(gl.program, "u_FragColor");pointArrs.push({x,y,z: Math.random() * 50,color: {r: Math.random() * 1,g: Math.random() * 1,b: Math.random() * 1,},});gl.clear(gl.COLOR_BUFFER_BIT);pointArrs.forEach((item) => {gl.vertexAttrib2f(a_Position, item.x, item.y);gl.vertexAttrib1f(a_pointSize, item.z);gl.uniform4f(u_FragColor, item.color.r, item.color.g, item.color.b, 1.0);gl.drawArrays(gl.POINTS, 0, 1);});});
};
onMounted(() => {drawPointStatic();drawPointByMouse();
});
</script><style lang="scss" scoped>
.wrapper {display: flex;
}
.point-wrapper {width: 300px;height: 300px;background-color: gray;
}
.point-mouse {margin-left: 20px;width: 300px;height: 300px;background-color: gray;
}
</style>
绘制图形如下所示:
注意在代码中引入了initShaders 方法,如下:
function loadShader(gl, type, source) {//根据着色类型,建立着色器对象const shader = gl.createShader(type);//将着色器源文件传入着色器对象中gl.shaderSource(shader, source);//编译着色器对象gl.compileShader(shader);//返回着色器对象return shader;
}
export function initShaders(gl, vsSource, fsSource) {//创建程序对象const program = gl.createProgram();//建立着色对象const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource);const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource);//把顶点着色对象装进程序对象中gl.attachShader(program, vertexShader);//把片元着色对象装进程序对象中gl.attachShader(program, fragmentShader);//连接webgl上下文对象和程序对象gl.linkProgram(program);//启动程序对象gl.useProgram(program);//将程序对象挂到上下文对象上gl.program = program;
}