# Chromatic Aberration

A Suzanne model staged with drei's Stage helper, fringed with @react-three/postprocessing's ChromaticAberration effect.

Demo: https://pmndrs.github.io/examples/examples/chromatic-aberration
Source: https://github.com/pmndrs/examples/tree/main/examples/chromatic-aberration
Scaffold: npx degit pmndrs/examples/examples/chromatic-aberration
Authors: Sara Vieira
Tags: postprocessing, chromatic-aberration
Ported from: https://codesandbox.io/s/uoyge
Dependencies: @react-three/drei@10.7.8, @react-three/fiber@9.6.1, @react-three/postprocessing@^3.0.5, leva@^0.10.1, react@19.2.8, react-dom@19.2.8, three@0.165.0
Binary files, in the repository but not below: src/suzanne.gltf

## src/App.tsx

```tsx
import { Suspense } from "react";
import { Canvas } from "@react-three/fiber";
import { CameraControls, Stage } from "@react-three/drei";
import {
  ChromaticAberration,
  EffectComposer,
} from "@react-three/postprocessing";
import { useControls } from "leva";
import Model from "./Model";

export default function App() {
  const { offset } = useControls({
    offset: { value: [0.02, 0.002] },
  });

  return (
    <Canvas shadows dpr={[1, 2]} camera={{ fov: 50 }}>
      <Suspense fallback={null}>
        <Stage
          preset="rembrandt"
          intensity={Math.PI}
          environment="city"
          adjustCamera={false}
        >
          <Model />
        </Stage>
        <EffectComposer>
          <ChromaticAberration offset={offset} />
        </EffectComposer>
      </Suspense>
      <CameraControls makeDefault />
    </Canvas>
  );
}
```

## src/Model.tsx

```tsx
import { useRef } from "react";
import * as THREE from "three";
import { type GLTF } from "three-stdlib";
import { type ThreeElements } from "@react-three/fiber";
import { useGLTF } from "@react-three/drei";

import suzanneModel from "./suzanne.gltf?url";

type GLTFResult = GLTF & {
  nodes: {
    Suzanne: THREE.Mesh;
  };
};

export default function Model(props: ThreeElements["group"]) {
  const group = useRef<THREE.Group>(null!);
  const { nodes } = useGLTF(suzanneModel) as unknown as GLTFResult;

  return (
    <group ref={group} {...props} dispose={null}>
      <mesh
        castShadow
        receiveShadow
        geometry={nodes.Suzanne.geometry}
        material={nodes.Suzanne.material}
        position={[0, 0.19, -0.04]}
      />
    </group>
  );
}

useGLTF.preload(suzanneModel);
```

## src/index.tsx

```tsx
import { createRoot } from "react-dom/client";
import "./styles.css";
import App from "./App";

createRoot(document.getElementById("root")!).render(<App />);
```

## src/styles.css

```css
* {
  box-sizing: border-box;
}

html,
body,
#root {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
}

body {
  background: #202020;
}
```

## src/vite-env.d.ts

```ts
/// <reference types="vite/client" />
```
