Reputation: 719
I am using WebGL to generate points on top of a leaflet map. Depending on an attribute of the data three colors are plotted: red, orange and green. (Colors are float i.e. 0.0 -> 1.0) Which are pushed onto an array:
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
This array is passed to my webgl drawing function the critical part of the code that sets vertices and the colors for the shader, is as follows:
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
and clear
buffer are called before rendering
gl.clearColor(0, 0, 0, 0);
gl.clear(this.gl.COLOR_BUFFER_BIT);
The points are all drawn in correct location and correct colors. The end goal is to record which point the user clicked. When the user clicks a point this code is called.
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);
}
This is where the problem is, for example, if I click a red point I get the output:
Uint8Array(4) [229, 0, 0, 207]
Orange:
Uint8Array(4) [229, 154, 0, 207]
Green:
Uint8Array(4) [0, 229, 0, 207]
These are roughly the correct values but I set alpha (channel 4) to 0 and red should be 255, 0, 0, 0 orange 255, 165, 0, 0 and green 0, 255, 0, 0. I have tried to return a Float32Array
from readPixels
but get INVALID_ENUM: readPixels: invalid type
for a gl.FLOAT
.
Also is I click where there are no points I get [0, 0, 0, 0] which is black which is correct.
Does someone know why this is happening? And potentially a solution.
Thanks :)
edit: shader code:
<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>
Upvotes: 0
Views: 431
Reputation:
It's clear the fragment shader is generating different colors. It's drawing circles and it's blending between (r, g, b, 0.9) and (0, 0, 0, 0)
If you want to get colors you put in change it to
precision mediump float;
varying vec4 v_color;
void main() {
gl_FragColor = v_color;
}
or change it to have no blending
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;
}
Upvotes: 2