webgl читает пиксели, не возвращая правильное значение - PullRequest
0 голосов
/ 07 апреля 2020

Я использую 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);

clearColor и clear буфер вызывается перед рендерингом

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]

Это примерно правильные значения, но я установил альфа (канал 4) на 0, а красный должен быть 255, 0, 0, 0 оранжевым 255, 165, 0, 0 и зеленый 0, 255, 0, 0. Я попытался вернуть Float32Array из readPixels, но получить 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>

1 Ответ

1 голос
/ 07 апреля 2020

Понятно, что фрагментный шейдер генерирует разные цвета. Он рисует круги, и он смешивается между (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;
}
...