webgl readpixels is always returning 0,0,0,0

Google网上论坛

You can grab data from a canvas by simply doing:

var pixels = new Uint8Array(gl.drawingBufferWidth * gl.drawingBufferHeight * 4);

gl.readPixels(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight, gl.RGBA, gl.UNSIGNED_BYTE, pixels);

console.log(pixels); 

If the canvas has been created with preserveDrawingBuffer: true, you'll get values back.

The problem here -I think- is that you're trying to read from a canvas that is not yours, and it hasn't been created with that flag.

It doesn't matter if you try to getContext again on that canvas, you can't change it.

So a solution would be to make getContext to always set preserveDrawing to true.

Try this (even though I don't endorse doing this, ever! just for education purposes:)

<!doctype html>

<html>

<head>

<meta charset="utf-8">

<meta http-equiv="X-UA-Compatible" content="IE=edge">

<meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">

<title>Map</title>

<link rel="stylesheet" href="http://cache.amap.com/lbs/static/main1119.css"/>

<script>

var getContext = HTMLCanvasElement.prototype.getContext;

HTMLCanvasElement.prototype.getContext = function(){

if( arguments[ 1 ] ) arguments[ 1 ].preserveDrawingBuffer = true;

var context = getContext.apply( this, arguments );

return context;

}

</script>

<script src="http://cache.amap.com/lbs/static/es5.min.js"></script>

<script src="http://webapi.amap.com/maps?v=1.3&key=123"></script>

<script type="text/javascript" src="http://cache.amap.com/lbs/static/addToolbar.js"></script>

</head>

<body>

<div id="container"></div>

<script>

var map = new AMap.Map('container', {

resizeEnable: true,

zoom:11,

center: [116.397421, 39.80923]

});

map.on('moveend', function() {

var canvas = document.getElementsByClassName("amap-layer")[0];

var gl = canvas.getContext("webgl");

var pixels = new Uint8Array(gl.drawingBufferWidth * gl.drawingBufferHeight * 4);

gl.readPixels(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight, gl.RGBA, gl.UNSIGNED_BYTE, pixels);

console.log(pixels);

});

</script>

</body>

This basically forces all getContext to use preserveDrawingBuffer to true. Since it runs before the AMap code, the library will create its WebGL rendering contexts with that flag set, and you'll be able to read it at a later point.

StackOverflow user

You don't need preserveDrawingBuffer: true to call readPixels. What you need is to call readPixels before exiting the current event.

The spec says if you call any function that affects the canvas (gl.clear, gl.drawXXX) then the browser will clear the canvas after the next composite operation. When that composite operation happens is up to the browser. It could be after it processes several mouse events or keyboard events or click events. The order is undefined. What is defined is that it won't do it until the current event exits so

render
read

Show code snippet

works where as

render
setTimeout(read, 1000);  // some other event

does not work

Show code snippet

Note that since it's the composite operation (the browser actually drawing the canvas on the page with the rest of the HTML) that triggers the clear, if the canvas is not on the page then it's not composited and won't be cleared.

In other words the case that didn't work above does work here

Show code snippet

Now, if you want to call readPixels in some other event, like when the user clicks an element, then you have at least 2 options

  1. Set preserveDrawingBuffer: true

  2. Render again in your event

    screenshotElement.addEventListener('click', event => {
      render();  
      gl.readPixels(...);
    });

猜你喜欢

转载自blog.csdn.net/wwwpcstarcomcn/article/details/81738606
0