首先,让我谈谈我的目标。我正在创建另一个像素艺术在线编辑器,并决定只使用WebGL(根本没有Canvas2D)。我很愚蠢,因为我对这项技术一无所知,但我正在努力!那么......问题:如何改变唯一一个像素的颜色?我一直在努力解决另一个“误解”,并用粒子系统找到了答案:
https://stackoverflow.com/a/16465343/4458277
我重写了它,使它看起来接近我的情况:
https://jsfiddle.net/kurz/rt2n7hmb/1/
正如您所看到的,当您在画布上绘制时,有10个像素具有相同的颜色。 这里主要绘制方法:
function mouseMoveEvent(e) {
/*... detect x and y...*/
gl.bindBuffer(gl.ARRAY_BUFFER, particleBuffer);
var data = new Float32Array(2);
data[0] = x;
data[1] = y;
gl.uniform4f(
gl.getUniformLocation(shaderProgram, "color"),
Math.random(),
Math.random(),
Math.random(),
1.0
);
gl.bufferSubData(gl.ARRAY_BUFFER, particleId * particleSize * sizeOfFloat, data);
particleId = (particleId + 1) % vertexBufferSize;
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.POINTS, 0, vertexBufferSize);
}
那么如何将此示例更改为使用唯一颜色绘制的像素?
有些人可能会说:“使用canvas2d!”。 - 不!我认为未来不是canvas2d。 “所以使用库!”。 - 不,再次!对于那种“简单”的东西,比如绘制正方形,我不想要包含大型库。
谢谢!
答案 0 :(得分:4)
您需要了解的是,您发布的代码是将变量传递给片段着色器,它没有进行任何绘制。片段着色器正在进行绘制。
OpenGL是一种在现代图形卡上操纵渲染过程的不同阶段的工具。它不会尝试将blitting像素的用例覆盖到屏幕缓冲区。 (glDrawPixels
已弃用,在ES 2.0或WebGL中不可用)
但是,您可以在应用程序中使用它。
我建议these两个articles来了解先决条件,但您应该知道它适用于OpenGL 3.2和C ++,而不是WebGL和Javascript。因此,您可以忽略诸如上下文创建,加载纹理的方式以及您不必创建VertexArrays等内容。
WebGL解决方案1:
glTexSubImage2D
修改纹理中的1个像素。WebGL解决方案2:
gl_PointSize
(顶点着色器第8行)此解决方案未修改1个精确像素,我认为解决方案1是更好的方法
为什么要使用Canvas2D:
考虑到Canvas2D不如WebGL是一个错误,一个是螺丝刀,另一个是锤子。一个非常适合用螺丝固定,另一个非常适合用钉子固定物品。
当您想要操纵3d渲染管道时使用WebGL,当您想要操作光栅图像时使用Canvas2D。
<强> TL; DR:强>
如果您使用Canvas2D,您可以开始制作您想要的应用程序并获得良好的性能。如果您想使用WebGL,您应该努力了解渲染管道的各个阶段。
答案 1 :(得分:2)
您问题的直接答案是gl.uniform4f
是一个全局变量。所以你实际上是这样做的:
var color = randomColor(); // uniform4f call
for each point:
drawPoint(p.x, p.y,color);
您需要将其更改为:
for each point:
var color = gl.uniform4f(...);
drawPoint(p.x, p.y, color);
但是,我想要注意,使用粒子系统进行像素编辑可能不是可行的方法。想象一下,如果用户反复在同一区域移动会发生什么,那么您将拥有大量冗余数据。其次,你如何(有效地)支持擦除操作?或者填写?
最终,我想你想继续使用纹理。纹理基本上是一个数据数组的奇特名称,但其格式和它可以包含的内容有限制。但是,GPU可以非常快速地访问它们。所以你要做的是绘制一个相同尺寸的四边形的四边形,并通过纹理给它单独的像素数据,告诉它要绘制什么。然后在用户执行操作并重绘时直接操作纹理数据。
在webgl中包含如何实现这一点真的太长了,所以我建议在网上学习一些教程。 webgl最好的一个atm是webgl fundamentals系列。我建议从那里开始。