如何使用WebGL设置画布上像素的颜色
How can I set the color of a pixel on a canvas using WebGL?
我是WebGL的新手,但不是Javascript或Canvas。本质上,我需要一种非常快速的方法来改变画布上任何坐标下像素的颜色。我觉得这可以使用WebGL片段着色器来完成。这可能吗?有更好的方法吗?我该怎么做?
这不是一个详尽的渲染指南,因为它不包括有关着色器管理的部分;相反,它专注于如何实际执行WebGL基元的绘制,以及如何使用正交投影在屏幕上精确定位顶点。
有关更多信息,我强烈推荐这些来源:
- 学习WebGL-教程
- WebGL规范
- Typed Arrays规范
WebGL的所有绘图都使用顶点缓冲对象(VBO(,因此您需要将所有数据编译为3D顶点,并在尽可能少的VBO中将其发送到视频卡(以最大限度地提高性能(。
VBO可以在WebGL中创建,如下所示:
var vbo = gl.createBuffer();
然后,您需要将数据发送到缓冲区,通常以Float32Array
的形式。如果您已经有了常规JavaScript数组形式的数据,那么您可以使用new Float32Array(jsArray)
从jsArray
的内容初始化Float32Array
。尽量少这样做。类型化数组非常快,但初始化速度非常慢。最好只创建一次,并尽可能重复使用它们。
一旦有了Float32Array
,就可以将数据向下传递到缓冲区,如下所示:
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
gl.bufferData(gl.ARRAY_BUFFER, float32Data, gl.DYNAMIC_DRAW);
每次数据更改时,您都需要执行bufferData
或bufferSubData
调用。
此时数据已在图形卡上,因此您只需要实际绘制即可:
// bind the VBO to be drawn if you haven't already
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
// send the vertex data to the shader program
gl.vertexAttribPointer(vertexAttributeLocation, 3, gl.FLOAT, false, 0, 0);
// draw the buffer
gl.drawArrays(gl.POINTS, 0, float32Data.length / 3);
请注意,尽管图形卡可以容纳相当多的VBO,但您应该尽可能少地使用它们,因为您必须执行的drawArrays
调用越多,速度就会越慢。事实上,如果在给定的VBO中一次只渲染一个像素,那么运行速度会太慢。
Float32Array
的长度除以3的原因是,每个单个数据元素都是3D(X,Y,Z(坐标,因此每个数据元素由3个浮点分量组成。注意,gl.drawArrays
的第一个自变量是gl.POINTS
。这指示图形卡为阵列中的每个项目绘制一个点(默认情况下,大小为一个像素(。还有其他绘制方式,如果您需要填充一组像素,其他绘制模式之一(例如gl.TRIANGLES
(可能更符合您的喜好。
至于点亮特定像素,这取决于着色器的编写方式,但很可能您正在使用模型视图矩阵和投影矩阵。模型视图矩阵表示相机相对于绘制点的方向,投影矩阵表示相机尺寸(宽度和高度、视野、最近和最远的可见范围等(。因此,如果你想照亮特定的像素,最好的办法是应用正交投影矩阵,其宽度和高度等于画布的宽度和高度;以及模型视图矩阵被设置为该恒等式(无变换(。在正交投影中,对象在远离摄影机时不会收缩,因此它们非常有助于指定相对于屏幕的确切位置。此外,如果你给它们适当的尺寸,你可以非常精确地定位顶点——在特定像素,如果你愿意的话。
不同的矩阵库以不同的方式工作,但例如,要在gl矩阵中设置正交矩阵,可以这样做:
var ortho = mat4.ortho(left, right, bottom, top, near, far);
确切的数字取决于您的喜好;如果你想把原点(0,0(放在画布的左下角,你可以这样做:
var ortho = mat4.ortho(0, canvas.width, 0, canvas.height, 0.01, 200);
然而,请注意,每个点的Z值仍然必须位于near
和far
之间才能进行渲染,并且near
值不能设置为0
。
如果需要澄清,请告诉我。
如果你只想画单个像素,你最好使用画布2d。
否则,你可能会从本教程中找到它,该教程以像素为单位绘制矩形,因此将宽度和高度设置为1x1,你将获得单个像素。
http://games.greggman.com/game/webgl-fundamentals/
绘制时可以使用GL_POINTS。基本上,你会把一组点,连同颜色和位置一起传递给GPU。然后使用正确的数据调用drawArrays。
这可能与其他事情联系太紧密,但这可能会对你有所帮助:
https://github.com/funkaster/ChesterGL/blob/master/chesterGL/primitivesBlock.js#L126
https://github.com/funkaster/ChesterGL/blob/master/chesterGL/primitivesBlock.js#L260
这就是我在chesterGL的基元块中渲染几个点的方法。
- 获取图像的平均外部像素颜色
- 画布-在多个画布叠加中获取像素颜色
- Circle-Canvas获取lineWidth的像素颜色
- 如果滚动 300 像素,请更改背景颜色
- 如何使用WebGL设置画布上像素的颜色
- Javascript - 如何使用基于站点像素颜色的画布创建图像
- 在 JavaScript 画布中获取图像的颜色像素
- 从画布获取像素颜色
- 获取图像的第一个像素颜色(JS/jQuery)
- 如何根据某些功能为 svg 中的每个像素分配颜色
- HTML5画布-在屏幕上显示像素颜色阵列的最快方式
- 从图像中获取像素颜色
- 通过Three.js中的getImageData像素颜色数据循环生成多个立方体
- 从IMG获取像素颜色总是0 0 0 0
- 不同的像素颜色值相同
- 使用Javascript查找网页上特定坐标的像素颜色
- javascript getImageData未从png图像返回正确的像素颜色
- 在javascript中获取像素颜色
- 手动在JS画布上分配像素颜色
- 当检测画布上的像素颜色时,DOM异常18