Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/389.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何使用WebGL设置画布上像素的颜色?_Javascript_Html_Canvas_Webgl - Fatal编程技术网

Javascript 如何使用WebGL设置画布上像素的颜色?

Javascript 如何使用WebGL设置画布上像素的颜色?,javascript,html,canvas,webgl,Javascript,Html,Canvas,Webgl,我对WebGL非常陌生,但不是Javascript或Canvas。本质上,我需要一种非常快速的方法来改变画布上任意坐标的像素颜色。我觉得这可以使用WebGL片段着色器来完成。这可能吗?还有更好的方法吗?我该怎么做呢?如果您只想绘制单个像素,那么最好使用canvas 2d 否则,您可能会从本教程中找到答案,本教程以像素为单位绘制矩形,因此将宽度和高度设置为1x1,您将获得单个像素 您可以在绘图时使用GL_点。基本上,您将向GPU传递一组点,以及颜色和位置。然后使用正确的数据调用DrawArray

我对WebGL非常陌生,但不是Javascript或Canvas。本质上,我需要一种非常快速的方法来改变画布上任意坐标的像素颜色。我觉得这可以使用WebGL片段着色器来完成。这可能吗?还有更好的方法吗?我该怎么做呢?

如果您只想绘制单个像素,那么最好使用canvas 2d

否则,您可能会从本教程中找到答案,本教程以像素为单位绘制矩形,因此将宽度和高度设置为1x1,您将获得单个像素


您可以在绘图时使用GL_点。基本上,您将向GPU传递一组点,以及颜色和位置。然后使用正确的数据调用DrawArray

这可能与其他事情联系太多,但这可能会帮助您:


这就是我为chesterGL渲染基本体块中的几个点的方式。

这不是一个详尽的渲染指南,因为它不包括着色器管理的细节;相反,它关注如何实际执行WebGL基本体的绘制,以及如何使用正交投影在屏幕上精确定位顶点

有关更多信息,我强烈推荐以下来源:

WebGL使用顶点缓冲区对象(VBO)绘制所有图形,因此您需要将所有数据编译为3D顶点,并用尽可能少的VBO将它们发送到视频卡(以最大限度地提高性能)

可以在WebGL中创建VBO,如下所示:

var vbo = gl.createBuffer();
然后,您需要将数据向下发送到缓冲区,通常以
Float32Array
的形式。如果您已经拥有常规JavaScript数组形式的数据,那么您可以使用
newfloat32array(jsArray)
jsArray
的内容初始化
Float32Array
。不过,尽量少这样做。类型化数组非常快,但初始化速度非常慢。最好只创建一次,并尽可能重用它们

一旦有了
Float32Array
,就可以像这样将数据向下传递到缓冲区:

gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
gl.bufferData(gl.ARRAY_BUFFER, float32Data, gl.DYNAMIC_DRAW);
每次数据更改时,您都需要执行
bufferData
bufferSubData
调用

此时数据已在图形卡上,因此您只需实际绘制:

请注意,尽管图形卡可以容纳相当多的VBO,但您应该尽可能少地使用它们,因为必须执行的
drawArrays
调用越多,速度就越慢。事实上,如果在给定的VBO中一次只渲染一个像素,那么运行起来会太慢

Float32Array
的长度被3除的原因是,每个数据元素都是一个3D(X,Y,Z)坐标,因此每个数据元素由3个float组件组成。请注意,
gl.drawArrays
的第一个参数是
gl.POINTS
。这指示图形卡为阵列中的每个项目绘制单个点(默认情况下,大小为单个像素)。还有其他绘制方法,如果需要填充一组像素,其他绘制模式之一(例如,
gl.TRIANGLES
)可能更符合您的喜好

至于照亮特定像素,这取决于着色器的编写方式,但最有可能的是使用modelview矩阵和投影矩阵。模型视图矩阵表示相机相对于绘制点的方向,投影矩阵表示相机尺寸(宽度和高度、视野、最近和最远可见范围等)。因此,如果要照亮特定像素,最好应用宽度和高度等于画布宽度和高度的正交投影矩阵;以及设置为标识的modelview矩阵(无转换)。在正交投影中,对象不会随着远离摄影机而收缩,因此它们非常有助于指定相对于屏幕的精确位置。另外,如果你给它们适当的尺寸,你可以非常精确地定位顶点——如果你愿意,在特定的像素上

不同的矩阵库以不同的方式工作,但例如,要在中设置正交矩阵,您可以这样做:

var ortho = mat4.ortho(left, right, bottom, top, near, far);
var ortho = mat4.ortho(0, canvas.width, 0, canvas.height, 0.01, 200);
具体数字取决于您的偏好;如果要将原点(0,0)放置在画布的左下角,可以这样做:

var ortho = mat4.ortho(left, right, bottom, top, near, far);
var ortho = mat4.ortho(0, canvas.width, 0, canvas.height, 0.01, 200);
请注意,每个点的Z值仍然必须位于
near
far
之间才能渲染,并且
near
值不能设置为
0


如果有任何问题需要澄清,请告诉我。

就一个像素?还是很多像素?对于单个像素而言,调用开销可能比仅使用Canvas2D更糟糕。很多像素。使用imageData是可行的,但是对于400x400像素来说太慢了。您从哪里获取像素数据?如果可以在一批中计算着色器中的所有值,WebGL将更快。如果您从数组中获取数据,WebGL可能不会比imageData快很多。它们可能来自数组。不过,谢谢你的帮助!