上一节绘制了圆点,调用的绘制方法如下:gl.drawArrays(gl.POINTS, 0, 1); 第一个参数明显是个枚举类型,肯定还有其他值,如下所示:
这小节尝试一下 绘制单独线段、线条、闭合线条、三角带(可构成矩形)
代码如下所示:
- <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;
- }