我正在尝试在WebGl中进行选择.我有两个渲染的形状,每个都映射了不同的纹理.我试图在某些坐标上抓取像素.这是一个例子.
var pixelValues = new Uint8Array(4);
gl.readPixels(10, 35, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixelValues);
console.log(pixelValues);
Run Code Online (Sandbox Code Playgroud)
但是pixelValues总是包含[0,0,0,0].我究竟做错了什么?我需要做一些与帧缓冲相关的事情吗?
fse*_*erb 13
根据WebGL最新规范,您现在需要调用getContext
设置preserveDrawingBuffer
标志,如:
var ctx = canvas.getContext("experimental-webgl", {preserveDrawingBuffer: true});
Run Code Online (Sandbox Code Playgroud)
这可以防止绘图缓冲区(颜色,深度,模板)在绘制到屏幕后被清除.请记住,这可能会导致性能下降.
你不需要preserveDrawingBuffer: true
打电话readPixels
.您需要的是readPixels
在退出当前事件之前调用.
规范说如果你调用影响画布的任何函数(gl.clear,gl.drawXXX),浏览器将在下一个复合操作后清除画布.当复合操作发生时,由浏览器决定.可能是在它处理了几个鼠标事件或键盘事件或点击事件之后.订单未定义.定义的是,在当前事件退出之前不会这样做
render
read
Run Code Online (Sandbox Code Playgroud)
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);
}
Run Code Online (Sandbox Code Playgroud)
<canvas></canvas>
Run Code Online (Sandbox Code Playgroud)
适用于
render
setTimeout(read, 1000); // some other event
Run Code Online (Sandbox Code Playgroud)
不起作用
const gl = document.querySelector("canvas").getContext("webgl");
render();
setTimeout(read, 1000); // read in other 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);
}
Run Code Online (Sandbox Code Playgroud)
<canvas></canvas>
Run Code Online (Sandbox Code Playgroud)
请注意,因为它是复合操作(浏览器实际上在页面上绘制画布,其余的HTML)触发清除,如果画布不在页面上,那么它不会被合成,也不会被清除.
换句话说,上面没有工作的情况在这里起作用
// create an offscreen canvas. Because it's offscreen it won't be composited
// and therefore will not be cleared.
const gl = document.createElement("canvas").getContext("webgl");
render();
setTimeout(read, 1000); // read in other 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);
}
Run Code Online (Sandbox Code Playgroud)
现在,如果您想要调用readPixels
其他事件,例如当用户单击某个元素时,您至少有2个选项
组 preserveDrawingBuffer: true
在您的活动中再次渲染
screenshotElement.addEventListener('click', event => {
render();
gl.readPixels(...);
});
Run Code Online (Sandbox Code Playgroud)