🌃 ~ 

WebGLRenderTargetでオフスクリーンレンダリングする

2023.12.22
RELATED CATEGORY
TABLE OF CONTENTS

概要

WebGLRenderTargetでオフスクリーンレンダリングするフローをメモしました。

※ Three.js r156

フレームバッファオブジェクトの生成

// fbo作成
const size = 1024;  // テクスチャの解像度
const fbo = new THREE.WebGLRenderTarget(size, size);

フレームバッファオブジェクト用のシーンを作成

const fboScene = new THREE.Scene();

テクスチャを板ポリに貼り付ける

画面サイズぴったりにする場合は板ポリのサイズを2にします。

サイズが2の理由は gl_Position の座標系が下記の画像のように「-1.0 ~ 1.0」の正規化デバイス座標空間になるためです。

gl_Positionの座標
const geometry = new THREE.PlaneGeometry(2, 2, 1, 1);
const material = new THREE.ShaderMaterial({
  fragmentShader: fragmentShader,
  vertexShader: vertexShader,
  uniforms: {
    uTexture: { type: "t", value: this.fbo.texture },
  },
});
const fboMesh = new THREE.Mesh(geometry, material);
fboScene.add(fboMesh);
// fragment shader
uniform sampler2D uTexture;
varying vec2 vUv;

void main( void ) {
  vec4 t = texture2D(uTexture, vUv);
  gl_FragColor = LinearTosRGB(t);
}

LinearTosRGB で出力しているのは WebGLRenderTargetで色味が変わってしまう で確認してください🙏

// vertex shader
varying vec2 vUv;

void main(){
  vUv = uv;
  gl_Position = vec4(position, 1.0);
}

レンダリング

  1. フレームバッファをバインドする(有効化)
  2. レンダリング結果をフレームバッファのテクスチャに焼き付ける
  3. フレームバッファのバインドを解除する
  4. 板ポリのシーンをレンダリングする
// requestAnimationFrame
renderer.setRenderTarget(fbo);
renderer.render(scene, camera);

renderer.setRenderTarget(null);
renderer.render(fboScene, camera);

その他

解像度をデバイスによって調整する

▼ 解像度を固定している場合 ▼

sphereがギザギザしている

▼ 解像度をデバイスによって変更している場合 ▼

sphereのギザギザが少し滑らかになった
const clamp = (num, min, max) => {
  return min > num ? min : max < num ? max : num;
};
const pixelRatio = clamp(window.devicePixelRatio, 1, 2);
const size = 1024;
const fbo = new THREE.WebGLRenderTarget(size * pixelRatio, size * pixelRatio);

WebGLRenderTargetのオプションについて

const type = /(iPad|iPhone|iPod)/g.test(navigator.userAgent) ? THREE.HalfFloatType : THREE.FloatType;
const pixelRatio = clamp(window.devicePixelRatio, 1, 2);
const size = 1024;

const fbo = new THREE.WebGLRenderTarget(size * pixelRatio, size * pixelRatio, {
  // 深度バッファ
  depthBuffer: false,

  // ステンシルバッファ
  stencilBuffer: false,

  // フォーマット
  format: THREE.RGBAFormat,

  // テクスチャのタイプ
  type: THREE.UnsignedByteType,
  
  // 出力時のエンコード設定
  colorSpace: THREE.SRGBColorSpace,
  // THREE.NoColorSpace: 
  // THREE.SRGBColorSpace: 
  // THREE.LinearSRGBColorSpace: 
  
  // テクスチャが拡大縮小するときの設定
  magFilter: THREE.LinearFilter,
  minFilter: THREE.LinearFilter,
  // THREE.LinearFilter: 対象のピクセルに近い4つのピクセルから平均した色になる
  // THREE.NearestFilter: 対象のピクセルに最も近い色になる

  // テクスチャのラッピングの設定
  wrapS: THREE.ClampToEdgeWrapping, // st.s === uv.x
  wrapT: THREE.ClampToEdgeWrapping, // st.t === uv.y
  // THREE.RepeatWrapping: 無限に繰り返す
  // THREE.ClampToEdgeWrapping: テクスチャの端のピクセルがメッシュの端まで引き伸ばされる
  // THREE.MirroredRepeatWrapping: 無限に繰り返しながら繰り返しでミラーリングする
});

参考サイト

PICKUP ARTWORK