WebGL — считывание пиксельных данных из буфера рендеринга

#javascript #html #image-processing #canvas #webgl

#javascript #HTML #обработка изображений #холст #webgl

Вопрос:

Есть ли способ получить необработанные пиксельные данные из буфера рендеринга WebGL или буфера кадров, который находится за пределами экрана?

Я использую WebGL для некоторой обработки изображений, например, размытия изображения, настройки цвета и т.д. Я использую буферы кадров для рендеринга текстур в полном размере изображения, а затем использую эту текстуру для отображения в окне просмотра в меньшем размере. Могу ли я получить пиксельные данные буфера или текстуры, чтобы я мог работать с ними в обычном контексте canvas 2d? Или я застрял с изменением области просмотра на полный размер изображения и захватом данных с помощью canvas.toDataURL()?

Спасибо.

Комментарии:

1. Вы действительно получили ответ на это? Ответ, который вы отметили, не выглядит так, как будто он на самом деле отвечает на вопрос.

2. Я полагаю, что фактический ответ отрицательный, вы не можете получить пиксельные данные из буфера. Вы должны использовать readPixels() Это было самое близкое, что я получил к ответу, поэтому я принял его. Должен ли я пропустить этот ответ?

3. Я не думаю, что это необходимо. Если кто-нибудь не предоставит более полезный ответ, brainjam косвенно ответил на ваш вопрос. Мне было просто любопытно.

Ответ №1:

Это очень старый вопрос, но я искал то же самое в three.js недавно. Прямого способа рендеринга в буфер кадра не существует, но на самом деле это делается с помощью процесса рендеринга в текстуру (RTT). Я проверяю исходный код фреймворка и выясняю следующий код:

 renderer.render( rttScene, rttCamera, rttTexture, true );

// ...

var width = rttTexture.width;
var height = rttTexture.height;
var pixels = new Uint8Array(4 * width * height); // be careful - allocate memory only once

// ...

var gl = renderer.context;
var framebuffer = rttTexture.__webglFramebuffer;
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);        
gl.viewport(0, 0, width, height);
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
  

Ответ №2:

readPixels() должно делать то, что вы хотите. Подробнее читайте в спецификации WebGL наhttp://www.khronos.org/registry/webgl/specs/latest /

Комментарии:

1. Спасибо, я попробую это. Однако, к сожалению, похоже, что мне все равно придется изменить размер холста до того размера, который я хочу прочесть в пикселях. Это вызывает «вспышку» при изменении размера. Может быть, используя отдельный контекст за пределами экрана, тогда чтение пикселей из этого может сработать …?

2. Да, использование отдельного закадрового контекста должно сработать.. но я этого не пробовал. Кроме того, вы, по-видимому, можете создавать вспомогательные фреймбуферы, которые можно использовать для рендеринга, но которые не отображаются. Смотрите learningwebgl.com/blog/?p=1786 для объяснения того, как создать такой фреймбуфер и использовать его содержимое в качестве текстуры. Надеюсь, это поможет вам продвинуться.

3. Я использую фреймбуфер в качестве текстуры в контексте webgl, однако проблема, с которой я сталкиваюсь, заключается в извлечении этих данных из контекста для использования в другом месте моего приложения. У меня вроде как работает отдельный контекст вне экрана, так что пока я собираюсь следовать этому маршруту. Спасибо.

Ответ №3:

Да, вы можете читать необработанные пиксельные данные. Установите значение preserveDrawingBuffer равным true при получении контекста webgl, а затем используйте readPixels с помощью WebGL.

 var context = canvasElement.getContext("webgl", {preserveDrawingBuffer: true}
var pixels = new Uint8Array(4 * width * height);
context.readPixels(x, y, width, height, context.RGBA, context.UNSIGNED_BYTE, pixels)
  

Комментарии:

1. Зачем устанавливать для preserveDrawingBuffer значение true?