Render Target

Starter pack

Ketika kita menggunakan React Three Fiber, kita cukup menambahkan komponen Canvas dan memasukkan scene 3D kita ke dalamnya, dan itu akan merendernya ke layar.

Jika Anda memiliki sedikit pengalaman dengan Three.js, Anda tahu bahwa pertama kita perlu membuat WebGLRenderer dan kemudian memanggil renderer.render(scene, camera) untuk merender scene kita ke layar.

Untungnya, React Three Fiber melakukan semua ini untuk kita tanpa terlihat, tetapi untuk kasus penggunaan yang lebih canggih, penting untuk mengetahui cara kerjanya.

Peran renderer adalah memproses scene 3D untuk membuat gambar 2D yang sebenarnya kita lihat di layar.

Secara default, output renderer diatur ke komponen Canvas dan ditampilkan di layar, tetapi kita juga bisa mengarahkannya ke sebuah tekstur (melalui WebGLRenderTarget).

Untuk saat ini, ini mungkin terdengar sedikit konseptual, mari kita lihat bagaimana cara kerjanya dalam praktik dan dengan cara kreatif apa kita bisa menggunakannya.

Kamera Keamanan

Untuk memahami bagaimana Render Targets bekerja dan apa yang bisa kita lakukan dengan itu, saya telah menyiapkan sebuah scene 3D yang berisi:

  • Model 3D ruang tamu oleh Alex Safayan CC-BY melalui Poly Pizza
  • Avatar Ready Player Me (seperti yang kita gunakan dalam pelajaran portfolio) yang menonton Spongebob Squarepants di TV
  • Remote control 2D dengan beberapa tombol

3D avatar watching to the TV

Tujuannya adalah untuk membuat sistem pengawasan dengan merender scene dari sudut pandang kamera keamanan di TV.

Me-render scene ke tekstur

Untuk merender scene kita saat ini ke tekstur, kita perlu membuat Render Target.

Berkat perpustakaan Drei, kita dapat dengan mudah membuat Render Target dengan hook useFBO:

// ...
import { useFBO } dari "@react-three/drei";

export const Experience = () => {
  const cornerRenderTarget = useFBO();
  // ...
};

Jika Anda ingin tahu cara membuat Render Target dari awal, Anda bisa memeriksa kode sumber dari hook useFBO di sini. Merupakan reflek yang baik untuk memahami bagaimana sesuatu bekerja di balik layar.

Sekarang setelah kita memiliki Render Target, kita perlu memberi tahu renderer kita untuk merender scene menggunakan camera kita.

Semua objek tersebut tersedia dalam root state dari aplikasi React Three Fiber kita. Ini adalah objek yang dikembalikan oleh hook useThree.

Properti gl adalah renderer.

Namun, karena kita ingin menampilkan apa yang terjadi secara real-time di TV, kita akan melakukan proses ini pada setiap frame menggunakan hook useFrame.

Fungsi callback menyertakan root state sehingga kita dapat mengakses variabel kita secara langsung dari sana:

// ...
import { useFrame } dari "@react-three/fiber";

export const Experience = () => {
  // ...
  useFrame(({ gl, camera, scene }) => {
    gl.setRenderTarget(cornerRenderTarget);
    gl.render(scene, camera);
    gl.setRenderTarget(null);
  });
  // ...
};

Apa yang kita lakukan di sini adalah:

  • Menetapkan Render Target sebagai output renderer
  • Merender scene menggunakan camera dan karena output renderer diset ke Render Target, maka scene akan dirender ke sana
  • Menetapkan output renderer menjadi null agar dapat merender scene ke kanvas lagi

Sekarang setelah kita memiliki Render Target kita, kita perlu menampilkannya di TV. Mari tambahkan referensi ke material yang saat ini merender video:

// ...
import { useRef } dari "react";

export const Experience = () => {
  // ...
  const tvMaterial = useRef();
  // ...
  return (
    <>
      {/* ... */}
      <group position-y={-0.5}>
        <group>
          <Sky />
          <Avatar rotation-y={Math.PI} scale={0.45} position-z={0.34} />
          <Gltf src="models/Room.glb" scale={0.3} rotation-y={-Math.PI / 2} />
          <mesh position-x={0.055} position-y={0.48} position-z={-0.601}>
            <planeGeometry args={[0.63, 0.44]} />
            <meshBasicMaterial ref={tvMaterial} />
          </mesh>
        </group>
      </group>
      {/* ... */}
    </>
  );
};

Dan kemudian, kita dapat menggunakan hook useFrame untuk memperbarui properti map dari material dengan Render Target kita:

// ...
export const Experience = () => {
  // ...
  useFrame(({ gl, camera, scene }) => {
    // ...
    tvMaterial.current.map = cornerRenderTarget.texture;
  });
  // ...
};

Avatar 3D menonton TV dengan tampilan kamera keamanan

Kita sekarang dapat melihat tampilan kamera keamanan di TV tetapi layar TV dalam tampilan kamera keamanan kosong.

Hal ini karena ketika kita merender scene ke Render Target, layar kita kosong.

Efek Inception

Untuk melihat tampilan kamera keamanan di dalam layar TV dari layar TV 🤯, kita perlu:

  • Membuat render target lain (kita akan menamakannya bufferRenderTarget)
  • Merender scene pada target ini
  • Menempelkannya pada material layar TV
  • Merender scene ke cornerRenderTarget
  • Menempelkannya pada material TV
// ...
export const Experience = () => {
  const bufferRenderTarget = useFBO();

  // ...
  useFrame(({ gl, camera, scene }) => {
    gl.setRenderTarget(bufferRenderTarget);
    gl.render(scene, camera);
    tvMaterial.current.map = bufferRenderTarget.texture;
    gl.setRenderTarget(cornerRenderTarget);
    gl.render(scene, camera);
    gl.setRenderTarget(null);
    tvMaterial.current.map = cornerRenderTarget.texture;
  });
  // ...
};

Mungkin terdengar menakutkan, tetapi sebenarnya cukup sederhana. Pikirkan saja apa yang terjadi di setiap langkah.

Sekarang scene kita ter-render tanpa batas di dalam layar TV!

Meskipun ini adalah efek paling realistis yang bisa kita buat, ini bukan yang paling kreatif. Mari kita hapus efek inception dan tampilkan Spongebob Squarepants di layar sebagai gantinya:

Three.js logoReact logo

React Three Fiber: The Ultimate Guide to 3D Web Development

✨ You have reached the end of the preview ✨

Go to the next level with Three.js and React Three Fiber!

Get full access to this lesson and the complete course when you enroll:

  • 🔓 Full lesson videos with no limits
  • 💻 Access to the final source code
  • 🎓 Course progress tracking & completion
  • 💬 Invite to our private Discord community
Unlock the Full Course – Just $85

One-time payment. Lifetime updates included.