同步与异步绘图
-
如果想要画出多个点,而不是每次点击只生成一个点,这时候就需要保存点击的痕迹
-
但是如果代码中,有异步去绘制webgl的点,则会出现问题,如下关键代码
// 修改attribute 变量 gl.vertexAttrib2f(a_Position, -0.3, 0); // 绘制顶点 gl.drawArrays(gl.POINTS, 0, 1); // 修改attribute 变量 gl.vertexAttrib2f(a_Position, 0.3, 0); // 绘制顶点 gl.drawArrays(gl.POINTS, 0, 1); setTimeout(() => { //修改attribute 变量 gl.vertexAttrib2f(a_Position, 0, 0); //绘制顶点 gl.drawArrays(gl.POINTS, 0, 1); }, 1000); -
这里同步代码中有两次drawArrays,异步代码中有一次drawArrays
-
异步的代码会取代同步的代码,最终只会有一个点,如果移除setTimeout异步代码,则就是正常的两个点
异步绘图导致同步绘图数据丢失与解决方案
- webgl的同步绘图的现象,其实是由webgl底层内置的颜色缓冲区导致的,这个颜色缓冲区它在电脑里会占用一块内存
- 在使用webgl绘图的时候,是先在颜色缓冲区中画出来,这样的图像还在胸中,所以外人看不见,只有webgl系统自己知道
- 在我们想要将图像显示出来的时候,那就照着颜色缓冲区中的图像去画,这个步骤是webgl 内部自动完成的,我们只要执行绘图命令即可
- 颜色缓冲区中存储的图像,只在当前线程有效,我们先在js 主线程中绘图,主线程结束后,会再去执行信息队列里的异步线程
- 在执行异步线程时,颜色缓冲区就会被webgl系统重置,之前的图像也就没了
解决方案
-
将数据存储在一起,画图的时候,重新绘制即可,也就是用个数组就能解决问题
<canvas id="canvas"></canvas> <!-- 顶点着色器 --> <script id="vertexShader" type="x-shader/x-vertex"> attribute vec4 a_Position; void main() { // 点位 gl_Position = a_Position; // 尺寸 gl_PointSize = 50.0; } </script> <!-- 片元着色器 --> <script id="fragmentShader" type="x-shader/x-fragment"> void main() { gl_FragColor = vec4(1,1,0,1); } </script> <script type="module"> import { initShaders } from "./utils.js"; const canvas = document.querySelector("#canvas"); canvas.width = 200; canvas.height = 200; // 获取着色器文本 const vsSource = document.querySelector("#vertexShader").innerText; const fsSource = document.querySelector("#fragmentShader").innerText; // 三维画笔 const gl = canvas.getContext("webgl"); // 初始化着色器 initShaders(gl, vsSource, fsSource); // 设置attribute 变量 const a_Position = gl.getAttribLocation(gl.program, "a_Position"); // 声明颜色 rgba gl.clearColor(0, 0, 0, 1); // 刷底色 gl.clear(gl.COLOR_BUFFER_BIT); // 存储顶点数据的数组 const a_points = [ { x: -0.3, y: 0 }, { x: 0.3, y: 0 }, ]; render(); setTimeout(() => { // 数据同步 a_points.push({ x: 0, y: 0 }); // 重新渲染 render(); }, 1000); // 渲染方法 function render() { gl.clear(gl.COLOR_BUFFER_BIT); a_points.forEach(({ x, y }) => { gl.vertexAttrib2f(a_Position, x, y); gl.drawArrays(gl.POINTS, 0, 1); }); } </script> -
utils.js
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; return true; } function loadShader(gl, type, source) { // 根据着色类型,建立着色器对象 const shader = gl.createShader(type); // 将着色器源文件传入着色器对象中 gl.shaderSource(shader, source); // 编译着色器对象 gl.compileShader(shader); // 返回着色器对象 return shader; }
1万+



被折叠的 条评论
为什么被折叠?



