Javascript 分别绘制每个像素

Javascript 分别绘制每个像素,javascript,canvas,webgl,pixels,Javascript,Canvas,Webgl,Pixels,首先,让我谈谈我的目标。我正在创建另一个单像素艺术在线编辑器,并决定只使用WebGL(根本不使用Canvas2D)。我真傻,因为我对这项技术一无所知,但我正在努力!所以问题是:如何改变只有一个像素的颜色?我一直在与另一个“误解”作斗争,并在粒子系统中找到了这个答案: 我重写了它,使它看起来更接近我的情况: 正如你所看到的,当你在画布上画画时,有10个相同颜色的像素。 以下是主要的绘制方法: function mouseMoveEvent(e) { /*... detect x and

首先,让我谈谈我的目标。我正在创建另一个单像素艺术在线编辑器,并决定只使用WebGL(根本不使用Canvas2D)。我真傻,因为我对这项技术一无所知,但我正在努力!所以问题是:如何改变只有一个像素的颜色?我一直在与另一个“误解”作斗争,并在粒子系统中找到了这个答案:

我重写了它,使它看起来更接近我的情况:

正如你所看到的,当你在画布上画画时,有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);
}
那么,如何将此示例更改为使用唯一颜色绘制的像素

你们中的一些人可能会说:“使用画布2D!”不我认为未来不是拉票。 “所以使用图书馆吧!”不,又来了!对于那个“简单”的东西,比如画正方形,我不想包含大的库


谢谢大家!

您问题的直接答案是,
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中包含如何实现这一点实在太长了,所以我建议在web上学习一些教程。webgl最好的atm是该系列。我建议从这里开始。

关于您发布的代码,您需要了解的是它正在将变量传递给片段着色器,而不是进行任何绘制。片段着色器正在进行绘制

OpenGL是在现代图形卡上操作渲染过程不同阶段的工具。它不试图涵盖将像素点到屏幕缓冲区的用例。(
glDrawPixels
已弃用,在ES 2.0或WebGL中不可用)

但是,您可以在应用程序中使用它

我推荐两个来理解先决条件,尽管你应该知道它是针对OpenGL 3.2和C++的,而不是WebGL和JavaScript。因此,您可以忽略上下文创建、加载纹理的方式以及不必创建顶点阵列等内容

WebGL解决方案1:

  • 创建一个空纹理
  • 每帧,在显示此纹理的屏幕上绘制一个四边形
  • 单击鼠标时,调用
    glTexSubImage2D
    修改纹理中的1个像素
WebGL解决方案2:

  • 更改
    gl_PointSize
    (顶点着色器第8行)
  • 只画1分
  • 不清除屏幕(javascript第45行)
  • 保留webGL屏幕缓冲区(javascript第86或89行)

这个解决方案不是修改1个精确的像素,我认为解决方案1是一个更好的方法

为什么要使用Canvas2D:

认为CavaS2D不如WebGL是错误的,一个是螺丝刀,另一个是榔头。一种是用螺丝钉固定的,另一种是用钉子固定的

要操纵三维渲染管道时使用WebGL,要操纵光栅图像时使用Canvas2D

TL;医生:


如果您使用Canvas2D,您可以开始制作您今天想要的应用程序,并获得良好的性能。如果您想使用WebGL,您应该努力了解渲染管道的各个阶段。

WebGL适用于3D,请使用Canvas:-p。我尊重您选择使用任何您想要的内容。但这等于说“我不会用锤子来敲打这个钉子,我会用我的卡车来敲打它,因为这就是我决定要做的”,但是有很多很棒的基于WebGL的2d图形引擎!(Pixi.js)你仍然想做一个“在线像素艺术编辑器”,那为什么不使用画布呢?它有很多很好的特性(导出jpg、png等,简单的2d绘图等)。它也有更多的支持。WebGL对于2D来说很好。WebGL不适用于3D。WebGL是一个光栅化引擎。你想用它做什么就做什么。如果您使用的是Chrome浏览器,则整个网页将在OpenGL ES 2.0中呈现。WebGL基于相同的技术。顺便说一下:您可以在同一个应用程序中混合使用这两种API。2d画布可以用作3d画布的纹理,3d画布可以用作2d画布的drawImage输入。但在webGL画布中,每次修改用作纹理的2d画布时,都必须再次将其发送到GPU内存中。此外,我看不出您将如何将其应用于此上下文。