【问题标题】:webgl read pixels not returning the correct valuewebgl 读取的像素没有返回正确的值
【发布时间】:2020-04-07 09:01:08
【问题描述】:

我正在使用 WebGL 在传单地图上生成点。 根据数据的属性绘制三种颜色:红色、橙色和绿色。 (颜色是浮动的,即 0.0 -> 1.0) 哪些被推送到一个数组中:

points.push(point.x, point.y, 1, 0, 0, 0); //for red
points.push(point.x, point.y, 1, 0.67, 0, 0); //for orange
points.push(point.x, point.y, 0, 1, 0, 0); // green

这个数组被传递给我的 webgl 绘图函数,设置顶点和着色器颜色的代码的关键部分如下:

let vertArray = new Float32Array(verts);
let fsize = vertArray.BYTES_PER_ELEMENT;
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, vertBuffer);
this.gl.bufferData(this.gl.ARRAY_BUFFER, vertArray, this.gl.STATIC_DRAW);
this.gl.vertexAttribPointer(vertLoc, 2, this.gl.FLOAT, false, fsize*6, 0); //2 vertices & 4 colors
this.gl.enableVertexAttribArray(vertLoc);
      // -- offset for color buffer
this.gl.vertexAttribPointer(colorLoc, 4, this.gl.FLOAT, false, fsize*6, fsize*2); //offset ignore 2 vertices
this.gl.enableVertexAttribArray(colorLoc);

在渲染之前调用clearColorclear缓冲区

gl.clearColor(0, 0, 0, 0);
gl.clear(this.gl.COLOR_BUFFER_BIT);

所有点都绘制在正确的位置和正确的颜色上。 最终目标是记录用户点击了哪个点。当用户单击一个点时,此代码将被调用。

if (mouseclick !== null) {
    let pixel = new Uint8Array(4);
    this.gl.readPixels(mouseclick.layerX, this.canvas.height - mouseclick.layerY, 1, 1, this.gl.RGBA, 
    this.gl.UNSIGNED_BYTE, pixel);
}

这就是问题所在,例如,如果我点击一个红点,我会得到输出:

Uint8Array(4) [229, 0, 0, 207]

橙色:

Uint8Array(4) [229, 154, 0, 207]

绿色:

Uint8Array(4) [0, 229, 0, 207]

这些是大致正确的值,但我将 alpha(通道 4)设置为 0,红色应为 255、0、0、0 橙色 255、165、0、0 和绿色 0、255、0、0。我有试图从readPixels 返回Float32Array,但得到INVALID_ENUM: readPixels: invalid type 以获得gl.FLOAT。 也是我点击没有点的地方,我得到 [0, 0, 0, 0] 是黑色的,这是正确的。 有人知道为什么会这样吗?并且可能是一个解决方案。 谢谢:)

编辑: 着色器代码:

<script id="vshader" type="x-shader/x-vertex">
  uniform mat4 u_matrix;
  attribute vec4 a_vertex;
  attribute float a_pointSize;
  attribute vec4 a_color;
  varying vec4 v_color;

  void main() {
      gl_PointSize =  a_pointSize;
      gl_Position = u_matrix * a_vertex;
      v_color = a_color;
  }
</script>
<script id="fshader" type="x-shader/x-fragment">
    precision mediump float;
    varying vec4 v_color;

    void main() {

        float border = 0.05;
        float radius = 0.5;
        vec4 color0 = vec4(0.0, 0.0, 0.0, 0.0);
        vec4 color1 = vec4(v_color[0], v_color[1], v_color[2], 0.9);

        vec2 m = gl_PointCoord.xy - vec2(0.5, 0.5);
        float dist = radius - sqrt(m.x * m.x + m.y * m.y);

       float t = 0.0;
       if (dist > border)
       t = 1.0;
       else if (dist > 0.0)
       t = dist / border;
       gl_FragColor = mix(color0, color1, t);
    }
  </script>

【问题讨论】:

  • 你能在snippet 中发布一个回购吗?只需绘制 1 个点,然后在其上调用 readPixels。和/或将您的着色器添加到问题中。
  • @gman - 添加了着色器代码。是的,我认为片段着色器是问题所在。这将教会我在不了解代码的情况下盲目复制代码。
  • @gman 如果您发布答案,我将标记为已接受。

标签: javascript leaflet webgl


【解决方案1】:

很明显,片段着色器正在生成不同的颜色。它在画圆,在 (r, g, b, 0.9) 和 (0, 0, 0, 0) 之间混合

如果你想得到颜色你把它改成

precision mediump float;
varying vec4 v_color;
void main() {
   gl_FragColor = v_color;
}

或将其更改为没有混合

precision mediump float;
varying vec4 v_color;

void main() {
    float radius = 0.5;

    vec2 m = gl_PointCoord.xy - vec2(0.5, 0.5);
    float dist = radius - sqrt(m.x * m.x + m.y * m.y);

    gl_FragColor = dist < 0.0 ? vec4(0) : v_color;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-11-26
    • 2014-06-14
    • 2019-03-21
    • 1970-01-01
    • 2014-07-15
    • 1970-01-01
    相关资源
    最近更新 更多