Рендер в текстуру з використанням Three.js

Все, що ви рендерите в Three.js за промовчанням відображається на екрані. Навіщо взагалі потрібен рендеринг, якщо не можна побачити результат? Виявляється, для того, щоб зібрати дані, перш ніж вони виведуться на екран (і, отже, будуть загублені). Це набагато спрощує застосування ефектів постобробки, таких як корекція/спотворення кольорів і розмиття зображення, а також дуже корисно для шейдерних ефектів. Такий прийом називається рендеринг в текстуру або рендерінг в буфер кадру. Кінцевий результат зберігається в текстурою, яку потім можна відобразити на екрані. У цій статті я покажу, як це робиться, на конкретному прикладі візуалізації анімованого куба на поверхню іншого анімованого куба.




Примітка: ця стаття розрахована на тих, хто вже володіє базовими знаннями Three.js. Якщо ви не знайомі з цією бібліотекою, для початку рекомендую прочитати статтю How to Learn Three.js for Game Development.

Базова реалізація

В інтернеті є багато схожих прикладів, які показують більш складні ефекти. Але в цій статті представлений лише необхідний мінімум.

// @автор: Омар Шехата. 2016.
// Завантажуємо бібліотеку Three.js за посиланням:
// http://cdnjs.com/libraries/three.js/

//// Установки звичайної сцени ////

var scene = new THREE.Scene();
var width, height = window.innerWidth, window.innerHeight;
var camera = new THREE.PerspectiveCamera( 70, width/height, 1, 1000 );
var renderer = new THREE.WebGLRenderer(); 
renderer.setSize( width,height);
document.body.appendChild( renderer.domElement );

//// Створюємо внеэкранный буфер ////

// Створюємо нову сцену, в якій будуть зберігатися буферні об'єкти
var bufferScene = new THREE.Scene();
// Створюємо структуру, в якій буде зберігатися результат рендера
var bufferTexture = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, { minFilter: THREE.LinearFilter, magFilter: THREE.NearestFilter});

////
// Додаємо сюди будь-які об'єкти для малювання в bufferScene //
////

function render() {
requestAnimationFrame( render );
// Встановлюємо рендер під внеэкранную текстуру
renderer.render(bufferScene, camera, bufferTexture);
// І, нарешті, промальовуємо результат на екрані
renderer.render( scene, camera );
}

render(); // Готово!


Для початку у нас є встановлення звичайної сцени. Потім ми створюємо ще одну – bufferScene. Будь-який об'єкт, доданий у цю сцену, буде рендеритись не на екран, а під внеэкранный буфер. Потім ми створюємо текстуру bufferTexture, що представляє собою буфер WebGLRenderTarget, який використовується в Three.js для внеэкранного рендеринга. Залишилося поставити малювання bufferScene:

renderer.render(bufferScene, camera, bufferTexture);


По суті, це все одно що рендери звичайну сцену, лише з зазначенням третього аргументу – буфера. Отже, основні етапи:

1. Створення сцени, в якій будуть зберігатися об'єкти.
2. Створення текстури, в якій буде зберігатися результат рендера.
3. Рендеринг сцени в текстуру.

Ось, власне, і все. Але поки нічого не видно. Навіть якщо ви додали об'єкти в bufferScene, ви нічого не побачите, тому що спочатку потрібно візуалізувати створену текстуру в основній сцені. Далі ми подивимося, як це зробити.

Приклад

Ми створимо куб, отрисуем його текстуру, а потім використовуємо в якості текстури для нового куба.


bufferTexture – екран

1. Починаємо з звичайної сцени

Ось так виглядає наша сцена з обертовим червоним кубом на блакитному тлі. Якщо вам цікаво, можете подивитися код, перемикаючись між вкладками CSS і JS на CodePen.



2. Рендерим сцену в текстуру

Тепер отрисуем отриману сцену в текстуру. Для цього потрібно всього лише створити bufferScene, як описано в попередньому розділі, і додати в неї об'єкти.



Навіть якщо ви зробили все правильно, ви нічого не побачите, тому що зараз наша сцена рендерится не на екран, а в bufferTexture.

3. Рендерим текстуру куба

bufferTexture нічим не відрізняється від будь-якої іншої текстури. Ми можемо просто створити новий об'єкт і використовувати його в якості текстури:

var boxMaterial = new THREE.MeshBasicMaterial({map:bufferTexture});
var boxGeometry2 = new THREE.BoxGeometry( 5, 5, 5 );
var mainBoxObject = new THREE.Mesh(boxGeometry2,boxMaterial);

// Move it back so we can see it
mainBoxObject.position.z = -10;
// Add it to the main scene
scene.add(mainBoxObject);



В русі об'єкт можна подивитися тут.

На першій текстурі можна намалювати що завгодно і отрендерить її на будь-яку поверхню.

Варіанти використання

Такий рендеринг дуже добре підходить для будь-яких ефектів постобробки. Припустимо, ви хочете зробити корекцію або спотворення кольорів у сцені. Замість того щоб змінювати кожен окремий об'єкт, ви можете отрендерить всю сцену в текстуру та застосувати до неї потрібний ефект, перш ніж відображати на екрані.

Рендер в текстуру також може використовуватися в будь-якому шейдере, що складається з декількох проходів (наприклад Blur). У попередній статті я пояснював, як використовувати кадрові буфери для створення ефекту диму.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.