画完三 Angular 形后,我想使用readPixels方法获取像素信息,但是用下面的代码无法获取。
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>
上面的代码没有正确获取对应的像素。
但是,如果我将实现更改为不使用drawArrays并使用clearColor之类的方法,我就可以获得像素。
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>
最佳答案
gl.readPixels 的坐标是窗口(帧缓冲区)坐标。这些坐标是整数,左上角是 (0, 0)。您实际上是从帧缓冲区的左上角读取像素。当您绘制三 Angular 形时,该片段不会改变并包含清晰的颜色。从不同位置读取片段:
gl.readPixels(0, 0.5, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, 像素);
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>
关于javascript - 为什么这样得不到对应的像素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74739176/