webgl 读取像素未返回正确值
webgl read pixels not returning the correct value
我正在使用 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]
这些大致是正确的值,但我将 alpha(通道 4)设置为 0,红色应为 255, 0, 0, 0 橙色 255, 165, 0, 0 和绿色 0, 255, 0, 0。我曾尝试从 readPixels
return 得到 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>
很明显片段着色器正在生成不同的颜色。它正在绘制圆圈并在 (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;
}
我正在使用 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]
这些大致是正确的值,但我将 alpha(通道 4)设置为 0,红色应为 255, 0, 0, 0 橙色 255, 165, 0, 0 和绿色 0, 255, 0, 0。我曾尝试从 readPixels
return 得到 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>
很明显片段着色器正在生成不同的颜色。它正在绘制圆圈并在 (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;
}