non*_*ult 10 html javascript canvas webgl
我是WebGL的新手,但不是Javascript或Canvas.基本上,我需要一种非常快速的方法来在任何坐标上更改画布上像素的颜色.我觉得这可以使用WebGL片段着色器完成.这有可能吗,还有更好的方法吗?我该怎么做呢?
sin*_*unk 11
这不是渲染的详尽指南,因为它不包括有关着色器管理的内容; 相反,它侧重于如何实际绘制WebGL基元,以及如何使用正交投影精确定位屏幕上的顶点.
有关更多信息,我强烈推荐这些来源:
WebGL使用顶点缓冲区对象(VBO)完成所有绘图,因此您需要将所有数据编译成3D顶点,并在尽可能少的VBO中将它们发送到视频卡(以最大限度地提高性能).
可以在WebGL中创建VBO,如下所示:
var vbo = gl.createBuffer();
Run Code Online (Sandbox Code Playgroud)
然后你需要将数据发送到缓冲区,通常是以a的形式Float32Array
.如果您已经以常规JavaScript数组的形式获得数据,那么您可以使用new Float32Array(jsArray)
初始化Float32Array
来自jsArray
内容的数据.尽量少尝试这样做.类型化数组非常快,但初始化速度非常慢.最好创建一次并尽可能重用它们.
一旦你有了Float32Array
,你可以将数据传递到缓冲区,如下所示:
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
gl.bufferData(gl.ARRAY_BUFFER, float32Data, gl.DYNAMIC_DRAW);
Run Code Online (Sandbox Code Playgroud)
每次数据更改时,您都需要执行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);
Run Code Online (Sandbox Code Playgroud)
请注意,尽管显卡可以容纳相当多的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);
Run Code Online (Sandbox Code Playgroud)
确切的数字取决于您的偏好; 如果你想将原点(0,0)放在画布的左下角,你可以这样做:
var ortho = mat4.ortho(0, canvas.width, 0, canvas.height, 0.01, 200);
Run Code Online (Sandbox Code Playgroud)
请注意,每个点的Z值仍然必须位于near
和之间,far
以便进行渲染,并且near
值不能设置为0
.
如果有任何需要澄清,请告诉我.