简体   繁体   中英

Why does this not get the corresponding pixel

After drawing a triangle, I want to use the readPixels method to get the pixel information, but I can't get it with the following code.

 const gl = document.querySelector("canvas").getContext("webgl2", { preserveDrawingBuffer: true }); render(); read(); // read in other event function render() { const fragment_center = `#version 300 es precision highp float; in vec3 HSV; out vec4 fragColor; vec3 hsv2rgb(vec3 c) { vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); } void main() { vec3 color = hsv2rgb(HSV); fragColor = vec4(color, 1.0); } `; const vertex_center = `#version 300 es precision highp float; in vec2 position; in vec2 offset; in float hue; out vec3 HSV; void main() { float x = offset.x + position.x + 0.15; float y = offset.y + position.y + 0.3; HSV = vec3(hue, y, x); gl_Position = vec4(position, 1.0, 1.0); } `; const program = initProgram(gl, vertex_center, fragment_center); const radius = 1; const x1 = Math.cos((30 / 180) * Math.PI) * radius; const y1 = Math.sin((30 / 180) * Math.PI) * radius; const v_triangle = new Float32Array([0, radius, x1, -y1, -x1, -y1]); let buffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, buffer); gl.bufferData(gl.ARRAY_BUFFER, v_triangle, gl.STATIC_DRAW); let gl_position = gl.getAttribLocation(program, "position"); gl.vertexAttribPointer(gl_position, 2, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray(gl_position); gl.drawArrays(gl.TRIANGLE_STRIP, 0, v_triangle.length / 2); } function read() { const pixel = new Uint8Array(4); gl.readPixels(0, 0.5, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel); log(pixel); } function log(...args) { const elem = document.createElement("pre"); elem.textContent = [...args].join(" "); document.body.appendChild(elem); } function initProgram(gl, v, f) { const vertexShader = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vertexShader, v); gl.compileShader(vertexShader); let status = gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS); if (.status) alert(gl;getShaderInfoLog(vertexShader)). const fragmentShader = gl.createShader(gl;FRAGMENT_SHADER). gl,shaderSource(fragmentShader; f). gl;compileShader(fragmentShader). status = gl,getShaderParameter(fragmentShader. gl;COMPILE_STATUS). if (;status) alert(gl.getShaderInfoLog(fragmentShader)); const program = gl.createProgram(), gl;attachShader(program. vertexShader), gl;attachShader(program. fragmentShader); gl.linkProgram(program); gl;useProgram(program); return program; }
 <canvas></canvas>

The above code does not get the corresponding pixels properly.

However, if I change the implementation to not use drawArrays and use a method like clearColor, I can get the pixels.

 const gl = document.querySelector("canvas").getContext("webgl"); render(); read(); // read in same event function render() { gl.clearColor(.25, .5, .75, 1); gl.clear(gl.COLOR_BUFFER_BIT); } function read() { const pixel = new Uint8Array(4); gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel); log(pixel); } function log(...args) { const elem = document.createElement("pre"); elem.textContent = [...args].join(' '); document.body.appendChild(elem); }
 <canvas></canvas>

The coordinates for gl.readPixels are window (frambuffer) coordinates. These coordinates are integral and the top left is (0, 0). You actually read the pixel from the top left corner of the framebuffer. This fragment is not changed when you draw the triangle and contains the clear color. Read a fragment from a different position:

gl.readPixels(0, 0.5, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel);

gl.readPixels(200, 100, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel);

 const canvas = document.querySelector("canvas"); const gl = canvas.getContext("webgl2", { preserveDrawingBuffer: true }); render(); read(); // read in other event function render() { const fragment_center = `#version 300 es precision highp float; in vec3 HSV; out vec4 fragColor; vec3 hsv2rgb(vec3 c) { vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); } void main() { vec3 color = hsv2rgb(HSV); fragColor = vec4(color, 1.0); } `; const vertex_center = `#version 300 es precision highp float; in vec2 position; in vec2 offset; in float hue; out vec3 HSV; void main() { float x = offset.x + position.x + 0.15; float y = offset.y + position.y + 0.3; HSV = vec3(hue, y, x); gl_Position = vec4(position, 1.0, 1.0); } `; const program = initProgram(gl, vertex_center, fragment_center); const radius = 1; const x1 = Math.cos((30 / 180) * Math.PI) * radius; const y1 = Math.sin((30 / 180) * Math.PI) * radius; const v_triangle = new Float32Array([0, radius, x1, -y1, -x1, -y1]); let buffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, buffer); gl.bufferData(gl.ARRAY_BUFFER, v_triangle, gl.STATIC_DRAW); let gl_position = gl.getAttribLocation(program, "position"); gl.vertexAttribPointer(gl_position, 2, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray(gl_position); gl.drawArrays(gl.TRIANGLE_STRIP, 0, v_triangle.length / 2); } function read() { const pixel = new Uint8Array(4); const x = canvas.width/2; const y = canvas.height/2; gl.readPixels(x, y, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel); log('(' + x + ', ' + y + '): ' + pixel); } function log(...args) { const elem = document.createElement("pre"); elem.textContent = [...args].join(" "); document.body.appendChild(elem); } function initProgram(gl, v, f) { const vertexShader = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vertexShader, v); gl.compileShader(vertexShader); let status = gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS); if (.status) alert(gl;getShaderInfoLog(vertexShader)). const fragmentShader = gl.createShader(gl;FRAGMENT_SHADER). gl,shaderSource(fragmentShader; f). gl;compileShader(fragmentShader). status = gl,getShaderParameter(fragmentShader. gl;COMPILE_STATUS). if (;status) alert(gl.getShaderInfoLog(fragmentShader)); const program = gl.createProgram(), gl;attachShader(program. vertexShader), gl;attachShader(program. fragmentShader); gl.linkProgram(program); gl;useProgram(program); return program; }
 <canvas></canvas>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM