【问题标题】:Draw coloured dot using WebGL使用 WebGL 绘制彩色点
【发布时间】:2014-05-21 20:22:21
【问题描述】:

不知何故,我似乎无法找到这样一个简单问题的答案 - 使用 webGL 绘制一个单点。

具体来说,我正在使用以下函数来绘制 3D 图形(但是,Z 轴由颜色表示):

不要被“3D”这个词弄糊涂了——我不想要真正的 3D,我只想使用 webGL 生成上面的图像。

每个像素行都是从一个数组生成的,Y轴代表时间。

在这里你可以看到我现在是如何填充数据的:

       //Normal canvas rendering
       for(var i=0, l=data.length;i<l;i++) {
            h_ctx.beginPath();
            //The color of the dot
            h_ctx.fillStyle = "hsl("+(120-120*(data[i]/255))+", 100%, 45%)";
            //Create a dot using color above
            h_ctx.rect(i,iteration,1, 1);
            h_ctx.fill();
            h_ctx.closePath();
        }

如果您想看到它的实际效果,我创建了一个JSFiddle。它需要 AudioContext 的支持。

【问题讨论】:

  • 不清楚您要做什么。如果您只想在 WebGL 中绘制该图像,那么可以,最简单的方法是将这些像素放入纹理中并绘制纹理。如果你真的想画点,那么this answer 更好的问题是你为什么要在 WebGL 中这样做?您发布的 canvas 2d 解决方案有什么问题?
  • 速度很慢,这是错误的。我看过一些 WebGL 演示,证明 WebGL 渲染速度更快(也许它是双缓冲的……?)。另外,我不想开始学习 webGL。我已经有一个基于画布的地图编辑器,速度很慢。

标签: canvas graph webgl


【解决方案1】:

将大量数据放入着色器的最佳方式是作为纹理。如果您的音频分析器已经是一个类型化的 Uint8Array,那么您可以像传递纹理一样将其传递给 WebGL。

gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,16,16,0,gl.RGBA,gl.UNSIGNED_BYTE,yourDataArray)

您当然可以像在 2d 上下文中那样“几乎”绘制矩形,这可能更容易过渡,因为在几乎所有教程中,您首先要做的就是这样做。在 WebGL 中,矩形由 2 个三角形定义,每个三角形有 3 个顶点。颜色可以通过多种方式定义,但最接近 2d 上下文的是使用 per-vertex-color。

因此,您需要一个缓冲区,其中包含一个数组,其中包含 6 个顶点(范围从 -1.0 到 1.0)中每个顶点的坐标。请记住,在 WebGL 中,Y 轴翻转

您对每个矩形重复此操作,将它们批处理到单个绘图调用,然后将它们绘制到屏幕上(您可以单独绘制它们,但如果每帧执行 1024 次,则可能会滞后)。

那么你当然需要编写基本的顶点和片段着色器。对于顶点着色器,没什么好说的,它是一个基本的每个顶点颜色着色器,将颜色属性传递给每个顶点的不同 vec4 中的片段着色器,并根据您的顶点位置属性计算空间中的顶点位置。

对 gpu 来说是好事,如果你已经提供了从 -1 到 1 的坐标,它不需要计算太多,对你不利,因为 gpu 也可以轻松地获取屏幕空间中的坐标(范围从 0 到你的屏幕尺寸(以像素为单位)并计算此时剪辑空间中的相应坐标(-1 到 1)。为此,它需要知道您的屏幕尺寸,您可以通过统一的 vec2 提供这些尺寸。

片段着色器然后只使用顶点着色器提供的可变 vec4,并根据它设置 fragColor(像素颜色),无需任何额外计算。 (与第一种方法不同,我建议您将声音频率作为纹理提供,几乎所有其他事情都将在片段着色器中发生)

所以你看到在 WebGL 中绘制矩形非常容易,而我对它的解释非常糟糕。但是我可以给你一个教程的链接,它可以更好地解释它并提供代码 sn-ps 来玩。

http://games.greggman.com/game/webgl-fundamentals/

【讨论】:

  • 感谢您写下这一切。我相信我会不止一次地回到这篇文章:) 从第一个函数开始,那个只接受数组的函数 - 它怎么知道这些值的含义?
  • 它不知道这些值的含义。数据基本上会被解释为 RGBA 中的 16x16 纹理(您在对 texImage2d 的调用中定义尺寸和颜色),所以这就是您将在片段着色器中开始的内容。由于声音数据已经以 1024 个无符号整数数组的形式出现(每个 0-255 类似于纹理中的颜色值),因此它基本上与图像数据相同。 (1024 / 4 种颜色 = 256 像素 = 16*16 纹理)
【解决方案2】:

我认为这不是一个简单的问题。在屏幕上绘制一个点至少需要对渲染管道有一定的了解。

你需要一些东西来说明这一点。例如,您可以创建顶点并使用 gl_PointSize 渲染它们,这会将点光栅化为您指定的大小。通过控制这个或多个顶点,您可以随时随地在屏幕上渲染点。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-09-04
    • 2015-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-03
    相关资源
    最近更新 更多