Практика рендеринга за кадром webgl и Three.js

WebGL
Практика рендеринга за кадром webgl и Three.js

1. Концепция закадрового рендеринга:

Друзья, которые использовали three.js, хорошо знакомы с WebGLRenderer, который отвечает за визуализацию ваших красочных 3D-объектов в сцену. Сегодня представлена ​​новая форма рендеринга ->Off-экран рендеринга WebGlrenderTarget,Официальное объяснение заключается в том, что буфер хранения данных рендеринга, обычно используемый до рендеринга на экране после обработки, чтобы сделать _ _.

2. Применение закадрового рендеринга в этой статье:

В этой статье мы применим технологию внеэкранного рендеринга для вывода сцены, визуализируемой webgl в режиме реального времени, в виде статического изображения, которое можно загрузить локально. Адрес источника проекта:GitHub.com/Лиянг00770…

3. Анализ основного кода:

А. Сначала создайте базовую сцену в initThree, загрузите модель истребителя F16 и скайбокс, используйте перспективную камеру и привяжите контроллер орбиты, и одновременно добавьте два луча света в камеру, чтобы истребитель F16 имел эффект яркого отражения света (если этот абзац я вообще не понимаю, что он означает, можете не читать, и я рекомендую прочитать другие базовые статьи...). В это время перетащите экран, чтобы рассмотреть модель с полной точки зрения. Как показано в следующем коде, в основном requestAnimationFrame средство визуализации отображает модель на экране в режиме реального времени.

function animate() {
    requestAnimationFrame( animate );
    controls.update();
    renderer.render( scene, camera );      
}
animate();

б) Главный герой выходит на сцену: закадровый рендеринг! Наше текущее требование состоит в том, чтобы иметь возможность получать данные рендеринга в сцене webgl и выводить их в виде изображения png для достижения эффекта, похожего на скриншот; но поскольку мы напрямую берем данные рендеринга, не существует такой вещи, как скриншот веб-страница.Проблема потери четкости, 100% перегравированная сцена рендеринга! Без лишних слов, давайте перейдем непосредственно к коду.

1. Создайте WebGLRenderTarget, пиксельные данные для внеэкранного рендеринга будут находиться в этой области буфера.

let rt = new THREE.WebGLRenderTarget(el.clientWidth * 4, el.clientHeight * 4, {  encoding: THREE.sRGBEncoding})

2. Перед рендерингом выполните сглаживание.

const renderPass = new RenderPass( scene, camera );
const pixelRatio = renderer.getPixelRatio();
const pass = new SMAAPass( el.clientWidth * pixelRatio, el.clientHeight * pixelRatio );
fxaaPass.material.uniforms[ 'resolution' ].value.x = 1 / ( el.offsetWidth * pixelRatio );
fxaaPass.material.uniforms[ 'resolution' ].value.y = 1 / ( el.offsetHeight * pixelRatio );
composer1 = new EffectComposer( renderer, rt );composer1.addPass( renderPass );composer1.addPass( pass );
composer1.renderToScreen = falsecomposer1.render()

3. Динамически создайте холст холста, визуализируйте кэшированные данные в WebGLRenderTarget на холсте, а затем используйте toDataURL() холста для вывода данных изображения в формате base64 или используйте canvas.toBlob() в сочетании с библиотекой сохранения файлов, Загрузить фотографии на локальный

const canvas2d = document.createElement('canvas')
document.body.appendChild(canvas2d);
const width = el.clientWidth * 4      
const height = el.clientHeight * 4     
const preview = canvas2d;    
preview.width = width    
preview.height = height   
const ctx = preview.getContext('2d');   
const buffer = new Uint8Array(width * height * 4);   
const clamped = new Uint8ClampedArray(buffer.buffer);     
const reversed = []    
composer1.renderer.readRenderTargetPixels(rt, 0, 0, width, height, buffer); // 读取像素到 buffer      
const imageData = new ImageData(clamped, width, height); // 创建可供 canvas 使用的图像数据类型      
ctx.putImageData(imageData, 0, 0);      // 图片输出前上下镜像,three的坑      
for (let i = height - 1; i >= 0; i--) {        
    reversed.push(...clamped.slice(width * 4 * i, width * 4 * (i + 1)))
}      
const imageDataFliped = new ImageData(new Uint8ClampedArray(reversed), width, height)      
ctx.putImageData(imageDataFliped, 0, 0);      
this.base64 = preview.toDataURL();      
if (type === 'download') {        
    canvas2d.toBlob((blob) => {          
        FileSaver.saveAs(blob, 'pretty image.png')        
    })      
}      
document.body.removeChild(canvas2d);

Конечным результатом является обложка.

4. Вывод:

В этой статье представлен механизм рендеринга вне экрана с использованием webgl для реализации эффекта вывода данных изображения и сохранения изображения на скриншоте webgl. Его можно использовать в некоторых сценариях, где DOM взаимодействует с webgl.

5. Реклама:

Команда ByteDance VR активно набирает сотрудников, и в настоящее время ее бизнес охватывает просмотр VR-домов, декорирование и другие сценарии.

Бизнес-сценарии охватывают виртуальную съемку, моделирование дома и кросс-энд виртуальную демонстрацию, охватывающую весь процесс.

быстро коммерциализируется. Приглашаем всех великих богов и студентов, интересующихся VR и webgl, присоединиться к нашей команде.

Личный почтовый ящик:liyang.peace@bytedance.com, WeChat liyang920308