Wawa Sensei logo

シェーダー遷移

Starter pack

このレッスンでは、シェーダーを使用して遷移を作成する方法を学びます。

最初に作成する効果は画面遷移効果です:

遷移効果を完全に制御でき、期間、イージング関数、シェーダーそのものを変更することができます。

次に作成する効果はモデル遷移効果です:

フェードアウト時にはモデルが溶解し、色が白に変わります。フェードイン時には逆のことが起こります。

スターターパック

以下はErgoniによって提供され、Creative Commons Attributionのライセンスの元で使用できる、今回のレッスンで利用するすべての3Dモデルです:

スターターパックで使用しているパッケージは以下の通りです:

使用しているフォントは、Google FontsからのKanitRubik Doodle Shadowの2つです。

自由にコンポーネントを調整して、自分の好みに合わせてください。

右上のLevaコントロールを使って色を調整することができます。好みの色が見つかったら、App.jsx内のLevaコンポーネントにhiddenプロップを追加します:

// ...

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

// ...

画面遷移

画面遷移効果を作成することから始めましょう。遷移効果を処理するScreenTransitionというコンポーネントを作成します。

componentsフォルダーにScreenTransition.jsxという新しいファイルを作成しましょう:

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

このコンポーネントでは、全画面を覆う色付きのplaneを作成しています。このplaneを使用して画面間の遷移を行います。

コンポーネントは以下の2つのpropsを受け取ります:

  • transition: コンポーネントが遷移効果を表示すべきかどうかを知るためのboolean
  • color: 遷移効果の主要な色

App.jsxScreenTransitionコンポーネントを追加しましょう:

// ...
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;

とりあえず、transition propにtrueを渡すことで遷移効果を強制的に表示させています。後で遷移効果を制御するロジックを追加します。

色は好みに合わせて調整してください。変更した場合、index.cssファイルの色も更新して、ウェブサイトがロードされたときに色のフラッシュが発生しないようにしてください:

// ...

html {
  background-color: #a5b4fc;
}

Plane in middle of the scene

planeがシーンの中央にあります。

Fullscreen plane

私たちのplaneは画面全体を覆う必要があります。viewportの寸法を使用してカメラを向けることもできますが、さらにすべての上に表示されるようにしたいです。

これを実現するために、Dreiは、すべての上に子要素をレンダリングするHudコンポーネントを提供しています。Hudコンポーネントに固定カメラを追加して、planeと完全に一致するようにすることができます:

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>
  );
};

私たちはOrthographicCameraを使用して、カメラとplaneの距離が何であっても簡単に画面全体を覆うことができます。

Plane covering the entire screen

planeは現在、画面全体を覆っています。

トランジションロジック

カスタムシェーダーを作成する前に、UI.jsxトランジション状態を定義しましょう:

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

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

ウェブサイトがロードされた後にフェードアウト効果を開始するために、初期値を true に設定します。

この状態を使用してトランジション効果を制御します。

引き続き UI.jsx 内で、トランジション効果の持続時間と遅延を制御する2つの定数を定義します:

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

次に、setScreen 関数の呼び出しをトランジション効果を処理する新しいものに置き換えましょう:

// ...
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);
  };
  // ...
};

新しい画面を直接設定する代わりに、transition 状態を true に設定し、setTimeout を使用してトランジション効果が完了した後に新しい画面を設定します (トランジション効果の持続時間プラス遅延時間)

これで関数の準備が整ったので、UI コンポーネント内の setScreen 呼び出しを検索し、transitionToScreen に置き換えましょう。

home から menu へ:

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

そして menu から home へ:

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

End of lesson preview

To get access to the entire lesson, you need to purchase the course.