Transisi Shader

Starter pack

Dalam pelajaran ini kita akan belajar bagaimana membuat transisi menggunakan shader.

Efek pertama yang akan kita buat adalah efek transisi layar:

Kita memiliki kontrol penuh atas efek transisi, kita bisa mengubah durasi, fungsi easing, dan shader itu sendiri.

Efek kedua yang akan kita buat adalah efek transisi model:

Saat memudar keluar, model akan terlarut dan warna menjadi putih, kebalikannya terjadi saat memudar masuk.

Paket Awal

Berikut adalah semua model 3D yang akan kita gunakan dalam pelajaran ini oleh Ergoni dan dilisensikan di bawah Creative Commons Attribution:

Paket awal menggunakan paket-paket berikut:

Dua font yang digunakan adalah Kanit dan Rubik Doodle Shadow, keduanya dari Google Fonts.

Jangan ragu untuk menyesuaikan komponen apapun sesuai dengan preferensi Anda.

Anda dapat menyesuaikan warna dengan bermain menggunakan kontrol Leva di sudut kanan atas. Setelah Anda menemukan warna yang Anda suka, tambahkan prop hidden ke komponen Leva di App.jsx:

// ...

function App() {
  // ...
  return (
    <>
      <Leva hidden />
      {/* ... */}
    </>
  );
}

// ...

Transisi Layar

Mari kita mulai dengan membuat efek transisi layar kita. Kita akan membuat sebuah komponen bernama ScreenTransition yang akan menangani efek transisi.

Mari buat file baru bernama ScreenTransition.jsx di dalam folder components:

export const ScreenTransition = ({ transition, color }) => {
  return (
    <mesh>
      <planeGeometry args={[2, 2]} />
      <meshBasicMaterial color={color} />
    </mesh>
  );
};

Dalam komponen ini, kita membuat sebuah plane dengan warna yang akan menutupi seluruh layar. Kita akan menggunakan plane ini untuk melakukan transisi antar layar.

Komponen kita menerima dua props:

  • transition: sebuah boolean untuk mengetahui apakah komponen harus menampilkan efek transisi
  • color: warna utama dari efek transisi

Mari tambahkan komponen ScreenTransition ke App.jsx:

// ...
import { ScreenTransition } from "./components/ScreenTransition";

function App() {
  // ...
  return (
    <>
      {/* ... */}
      <Canvas camera={{ position: [0, 1.8, 5], fov: 42 }}>
        <color attach="background" args={[backgroundColor]} />
        <fog attach="fog" args={[backgroundColor, 5, 12]} />
        <ScreenTransition transition color="#a5b4fc" />
        <Suspense>
          <Experience />
        </Suspense>
      </Canvas>
    </>
  );
}

export default App;

Saat ini kita memaksa efek transisi ditampilkan dengan memberikan true pada prop transition. Kita akan menambahkan logika untuk mengendalikan efek transisi nanti.

Sesuaikan warna sesuai keinginan Anda. Jika Anda mengubahnya, pastikan untuk memperbarui warna di file index.css untuk menghindari kilatan warna saat situs web dimuat:

// ...

html {
  background-color: #a5b4fc;
}

Plane di tengah adegan

Plane berada di tengah adegan.

Bidang layar penuh

Kami ingin bidang kami menutupi seluruh layar. Kami bisa menggunakan dimensi viewport dan membuatnya menghadap kamera, tetapi kami juga ingin bidang tersebut berada di atas segala sesuatu.

Untuk mencapai ini, Drei menyediakan komponen Hud yang akan merender elemen anak-anaknya di atas segala sesuatu. Kita dapat menambahkan kamera tetap pada komponen Hud untuk memastikan itu sejajar sempurna dengan bidang kita:

import { Hud, OrthographicCamera } from "@react-three/drei";

export const ScreenTransition = ({ transition, color }) => {
  return (
    <Hud>
      <OrthographicCamera
        makeDefault
        top={1}
        right={1}
        bottom={-1}
        left={-1}
        near={0}
        far={1}
      />
      <mesh>
        <planeGeometry args={[2, 2]} />
        <meshBasicMaterial color={color} />
      </mesh>
    </Hud>
  );
};

Kami menggunakan OrthographicCamera untuk dengan mudah menutupi seluruh layar apa pun jarak antara kamera dan bidang.

Bidang menutupi seluruh layar

Bidang sekarang menutupi seluruh layar.

Logika Transisi

Satu hal terakhir sebelum membuat shader kustom kita, mari kita definisikan state transition di UI.jsx:

// ...
import { atom } from "jotai";

export const transitionAtom = atom(true);
// ...

Kita menetapkan nilai awal menjadi true untuk memulai dengan efek fade-out setelah situs web dimuat.

Kita akan menggunakan state ini untuk mengontrol efek transisi.

Masih di UI.jsx, kita akan mendefinisikan dua konstanta untuk mengontrol durasi dan penundaan dari efek transisi:

// ...
export const TRANSITION_DELAY = 0.8;
export const TRANSITION_DURATION = 3.2;
// ...

Sekarang mari kita ganti pemanggilan fungsi setScreen dengan yang baru yang akan menangani efek transisi:

// ...
import { useAtom } from "jotai";
import { useRef } from "react";
// ...

export const UI = () => {
  // ...
  const [transition, setTransition] = useAtom(transitionAtom);
  const timeout = useRef();

  // ...
  const transitionToScreen = (newScreen) => {
    setTransition(true);
    clearTimeout(timeout.current);
    timeout.current = setTimeout(() => {
      setScreen(newScreen);
      setTransition(false);
    }, TRANSITION_DURATION * 1000 + TRANSITION_DELAY * 1000);
  };
  // ...
};

Alih-alih langsung menetapkan layar baru, kita menetapkan state transition ke true dan menggunakan setTimeout untuk menetapkan layar baru setelah efek transisi selesai (durasi dari efek transisi ditambah penundaan).

Sekarang fungsi kita sudah siap, carilah pemanggilan setScreen dalam komponen UI dan gantilah dengan transitionToScreen.

Dari home ke menu:

<motion.button
  onClick={() => transitionToScreen("menu")}
  // ...
>

Dan dari menu ke home:

<motion.button
onClick={() => transitionToScreen("home")}
// ...
>
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.