Kevin Reid's preserveDrawingBuffer
sugerencia es la correcta, pero hay (generalmente) una mejor opción. El tl; dr es el código al final.
Puede ser costoso juntar los píxeles finales de una página web renderizada, y coordinar eso con la renderización del contenido WebGL aún más. El flujo habitual es:
- JavaScript cuestiones Comandos de dibujo con el contexto WebGL
- retornos de JavaScript, devolver el control al bucle principal evento navegador
- contexto WebGL convierte dibujo búfer (o su contenido) hacia el compositor de integración en la página web actualmente está representando en la pantalla
- página, con contenido de WebGL, que se muestra en la pantalla
Tenga en cuenta que esto es diferente de la mayoría de las aplicaciones OpenGL. En ellos, el contenido renderizado generalmente se muestra directamente, en lugar de componerse con muchas otras cosas en una página, algunas de las cuales pueden combinarse con el contenido WebGL.
La especificación WebGL se cambió para tratar el búfer de dibujo como esencialmente vacío después del paso 3. El código que está ejecutando en devtools viene después del paso 4, por lo que obtiene un búfer vacío. Este cambio en la especificación permitió grandes mejoras de rendimiento en las plataformas donde el borrado después del Paso 3 es básicamente lo que realmente sucede en el hardware (como en muchas GPU móviles). Si desea evitar esto para que algunas veces haga copias del contenido WebGL después del paso 3, el navegador debería siempre hacer una copia del búfer de dibujo antes del paso 3, lo que hará que su velocidad de fotogramas caiga precipitadamente en algunas plataformas.
Puede hacer exactamente eso y forzar al navegador a realizar la copia y mantener el contenido de la imagen accesible configurando preserveDrawingBuffer
en verdadero. Desde la especificación:
Este comportamiento predeterminado se puede cambiar estableciendo el atributo preserveDrawingBuffer del objeto WebGLContextAttributes. Si este indicador es verdadero, el contenido del buffer de dibujo se conservará hasta que el autor lo borre o sobrescriba.Si este indicador es falso, intentar realizar operaciones usando este contexto como una imagen de origen después de que la función de renderización haya retornado puede conducir a un comportamiento indefinido. Esto incluye llamadas readPixels o toDataURL, o usar este contexto como la imagen fuente de la llamada texImage2D o drawImage de otro contexto.
En el ejemplo que nos ha facilitado, el código es simplemente cambiando la línea de creación del contexto:
gl = canvas.getContext("experimental-webgl", {preserveDrawingBuffer: true});
sólo tener en cuenta que va a obligar a que la ruta más lenta en algunos navegadores y el rendimiento se verá afectada, dependiendo de qué y cómo estás renderizando Debería estar bien en la mayoría de los navegadores de escritorio, donde la copia no tiene que estar hecha en realidad, y esos constituyen la gran mayoría de los navegadores con capacidad WebGL ... pero solo por ahora.
Sin embargo,, hay otra opción (como se menciona de manera algo confusa en el siguiente párrafo de la especificación).
Esencialmente, usted mismo hace la copia antes del paso 2: después de que todas sus llamadas al sorteo hayan terminado pero antes de que regrese al control del navegador desde su código. Esto es cuando el búfer de dibujo WebGL todavía está en contacto y es accesible, y entonces no debería tener problemas para acceder a los píxeles. Utiliza las mismas llamadas toDataUrl
o readPixels
que usaría, de lo contrario, es el momento lo que es importante.
Aquí obtienes lo mejor de ambos mundos. Obtiene una copia del búfer de dibujo, pero no lo paga en cada fotograma, incluso en aquellos en los que no necesita una copia (que puede ser la mayoría), como lo hace con preserveDrawingBuffer
establecido en verdadero.
En el ejemplo que nos ha facilitado, sólo tiene que añadir su código a la parte inferior de drawScene
y debería ver la copia de la tela justo debajo:
function drawScene() {
...
var webglImage = (function convertCanvasToImage(canvas) {
var image = new Image();
image.src = canvas.toDataURL('image/png');
return image;
})(document.querySelectorAll('canvas')[0]);
window.document.body.appendChild(webglImage);
}
¿Usted consigue los errores? ¿Es '$$' un error tipográfico, o tiene jQuery usando un signo de dólar doble, en lugar de solo? – MrOBrian
'$$' es una función incorporada a la consola JavaScript de Chrome, que se comporta de manera similar a jQuery. No obtengo ningún error, no. – Randomblue
Ah, no sabía eso ... Estoy pensando que está pasando algo con esa página. Si hago 'toDataURL()' en el lienzo de esa página, obtengo una imagen en blanco de 500x500 y el lienzo se borra. Si hago exactamente el mismo código en el sitio en el que estoy trabajando que utiliza lienzo, obtengo los datos correctos y el lienzo no se borra. – MrOBrian