---
# System prepended metadata

title: A Guide to 3D Animation with ThreeJs and React Three Fiber

---

User experience has become a significant feature in the development of scalable applications. The need for unique 3D web experience among users continues to drive the adoption of the [`React Three Fiber (R3F)`](https://docs.pmnd.rs/react-three-fiber/getting-started/introduction) and [`ThreeJs`](https://threejs.org/docs/) libraries by developers for building user-friendly applications. In recent times, 3D animation has continued to gain traction for its ability to allow users to interact, visualize, and engage with web animations. It also equips web developers to craft creative and immersive online experiences.

[`React Three Fiber (R3F)`](https://docs.pmnd.rs/react-three-fiber/getting-started/introduction) is specifically tailored to create 3D animation in React, while [`ThreeJs`](https://threejs.org/docs/) is a multi-purpose library for building 3D experiences on the web. A solid understanding of R3F requires a good grasp of ThreeJs fundamentals. To get started, you will learn about the basics of both libraries and their usage. 

In this article, I will guide you through the fundamentals of `ThreeJs` and `React Three Fiber`, how to install the libraries, explain their features and functionality, and demonstrate how to implement both 3D libraries in your web application. 

## Prerequisite

To fully get the best from this article, you should have the following:

* A well-functioning computer with a code editor installed.
* Fundamental knowledge of [`JavaScript` ](https://developer.mozilla.org/en-US/docs/Web/JavaScript), [`React.js`](https://legacy.reactjs.org/docs/getting-started.html), and [`Node.js`](https://nodejs.org/en/learn/getting-started/introduction-to-nodejs) installed on your machine.
* A good understanding of [`HTML/CSS`](https://developer.mozilla.org/en-US/docs/Learn/CSS).

## Benefits of Using 3D Animation in Web Applications
Integrating 3D animation into your application comes with enormous benefits. 3D animation showcases scale and unique features, making it a go-to tool for communicating product ideas and showing large crowds and landscapes. The following are the benefits of using 3D animation.

### Enhances User Satisfaction
Animation enhances user satisfaction by adding intuitiveness and interactivity. A well-implemented animation leaves users with a pleasant and memorable experience. Users are more likely to revisit an application or website that offers fluid, aesthetically pleasing animations that meet their needs.

### Increases Brand Impressions
3D animation captures users' attention and gradually embeds your brand perception in their minds. It can effectively convey a brand's story and communicate its identity, including colours, logos, and features. Animation can also assist a brand in achieving its marketing strategy through immersive 3D displays and motion graphics that resonate with users.

### Enhancing the Appeal of Web Application
Integrating 3D animation into your web applications keeps users engaged, appeals to their emotions, and stimulates their awareness through micro-interactions and transitions. 3D animation also improves web usability and clarity, eliminating crowded displays and ensuring an enhanced user experience.

### Establishes Visual Hierarchy
3D animation in a web application introduces a visual hierarchy by directing user attention to important information and key features. A well-implemented 3D animation guides users' gaze by utilising motions to make it easier to engage with the interface. 

### Visually Conveying of information
Animation simplifies communication by visually conveying information. 3D animation provides visual clues that help users understand the interface's status and message. It also reveals hidden information and delivers relevant content, ensuring users correctly interpret the interface's context. 

## Getting Started with ThreeJs
The `ThreeJs` library has become the go-to tool for web developers in building intuitive 3D animations because it provides an easy and efficient way to create and manipulate 3D [`scene`](https://threejs.org/docs/#manual/en/introduction/Creating-a-scene) without complex math formulas or a strong command of [`WebGL`](https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Getting_started_with_WebGL). It leverages [`GPU` (Graphics Processing Unit)](https://www.intel.com/content/www/us/en/products/docs/processors/what-is-a-gpu.html#:~:text=What%20does%20GPU%20stand%20for,video%20editing%2C%20and%20gaming%20applications.) technology to render web graphics, including 2D and 3D animations, directly in your browser. The library is integrated with `WebGL`, which works behind the scenes to display 3D animations effectively. The best approach to learning how to work with the `ThreeJs` library and achieve better results is to familiarize yourself with the fundamentals and how it works.


## What is ThreeJs
`ThreeJs` is a powerful `JavaScript` library for creating 3D experiences on the web. It provides a straightforward path to work directly with `WebGL`, the `API` for rendering 3D web graphics in web browsers. As an open-source and cross-browser `JavaScript` library, `ThreeJs` enables flexibility in displaying multi-dimensional objects and scenes on the web. One of its biggest strengths is that it allows you to create web graphics, including 2D and 3D animations, without requiring additional plugins. If you are wondering what a ThreeJs-powered animation looks like, you can explore some dynamic [ThreeJs projects]([https:/](https://threejs.org/)/) to see what the library offers.

## Fundamentals and Features of ThreeJs
The `ThreeJs` library provides comprehensive features for creating a 3D experience in web applications. These include the `scene graph` with 3D transformations, objects, and custom shaders. Other functionality and features of `ThreeJs` include [`Lights`](https://threejs.org/docs/#api/en/lights/Light), [`shadows`](https://threejs-journey.com/lessons/shadows#), [`Materials`](https://threejs.org/docs/#api/en/constants/Materials), [`Cameras` ](https://threejs.org/docs/#api/en/cameras/Camera) , and an adaptable renderer for providing optimal performance and quality visuals on the browser. Here are the key features of `ThreeJs`:
 
### Geometries and Meshes
The `ThreeJs` library comes with built-in `geometries` that you can employ to create 3D `scenes`. [`Geometries`](https://threejs.org/docs/#api/en/geometries/BoxGeometry) constitute a collection of points within a 3D environment, known as `vertices`, with various `faces` connecting these points. Examples of `geometries` include cubes, spheres, and planes. Here are examples of ThreeJs built-in geometries:

![geometries_basic](https://hackmd.io/_uploads/Hy_pOFQmA.svg)

[source.](https://discoverthreejs.com/book/first-steps/built-in-geometries/)

[`Mesh`](https://threejs.org/docs/#api/en/objects/Mesh.geometry) objects represent 3D shapes resulting from combining `geometries` and `materials`. `Geometries`, comprising `vertices`, `edges`, and `faces`, are needed along with one or more `materials` to create a `mesh`. `Vertices` represent a single point with an x, y, and z coordinate, defining the `geometry` and enabling the creation of complex shapes. Creating `geometry` also involves generating `vertices` and `faces`. In `ThreeJs`, a `face` consists of multiple `vertices`. 

### Materials and Shaders 
[`Materials`](https://threejs.org/docs/#api/en/constants/Materials) are like the skin of an `object`; they define the outer appearance of the `object`. They specify an `object's` appearance by determining its colour, texture, reflectivity, and other attributes. `ThreeJs` is built with a variety of `materials` to choose from and apply to your 3D `object`. The material and shades work in synergy siince they have a relation. While the shaders contain code that controls properties and assets to use, the material enables you to adjust properties and assign assets. Some of the built-in `materials` are [`MeshBasicMaterial`](https://threejs.org/docs/#api/en/materials/MeshBasicMaterial), [`MeshNormalMaterial`](https://threejs.org/docs/#api/en/materials/MeshNormalMaterialhttps://), [`MeshPhongMaterial` ](https://threejs.org/docs/#api/en/materials/MeshPhongMaterial), [`MeshLambertMaterial`](https://threejs.org/docs/#api/en/materials/MeshLambertMaterial), and [`MeshStandardMaterial`](https://threejs.org/docs/#api/en/materials/MeshStandardMaterial). The `MeshBasicMaterial` and `MeshNormalMaterial` do not depend on external light to add objects to the `scene` or are affected by shadows. Here is an example of the `MeshLambertMaterial`:

![material5](https://hackmd.io/_uploads/ryGLV9mmA.jpg)

[Source.](https://chriscourses.com/blog/a-comprehensive-guide-to-materials-in-threejs)

The `MeshLambertMaterial` image above demonstrates its behaviour. It reflects light from the materials and showcases a non-shiny appearance.

### Scenes Graph 
The `ThreeJs` [`scene`](https://threejs.org/docs/#manual/en/introduction/Creating-a-scene) is also called a `scene graph`. A graph is a framework that holds all essential information for rendering graphical `scenes`, including `lights`, `cameras`, and `objects`. A `scene` is like a container, where `objects`, `particles`, `cameras` and `lights` are placed to be rendered on the screen. The `scene` provides the platform to connect these elements and displays them to the screen. The diagram below illustrates the structure of a scene graph.

![scene_graph](https://hackmd.io/_uploads/r1FnX2XQ0.svg)

[Source.](https://discoverthreejs.com/book/first-steps/transformations/)

The `scene graph` diagram illustrates the tree structure within the `scene graph`. It follows a parent-child pattern, as shown in the diagram. The top scene is the first parent and it has three other children. One of the meshes has two children, demonstrating the parent-child structure.

### Cameras
[`Cameras` ](https://threejs.org/docs/#api/en/cameras/Camera) dictate how an object is displayed on the screen and manage the perspective and view of the 3D `scene`. In a graphics or 3D environment, the `camera` defines the `viewpoints` of the `scene` and determines how users view the objects within it. Adjusting the `camera` position and settings will affect the viewport of the `scene`. `ThreeJs` boasts a collection of `cameras`, each possessing unique attributes and functionalities. Examples include [`PerspectiveCamera`](https://threejs.org/docs/#api/en/cameras/PerspectiveCamera), [`OrthographicCamera`](https://threejs.org/docs/#api/en/cameras/OrthographicCamera), [`StereoCamera`](https://threejs.org/docs/#api/en/cameras/StereoCamera), [`ArrayCamera`](https://threejs.org/docs/#api/en/cameras/ArrayCamera), and [`CubeCamera`](https://threejs.org/docs/#api/en/cameras/CubeCamera), each tailored to meet specific needs. Here is an example of the `Perspective` and `Orthographic cameras`.

![three-js-3](https://hackmd.io/_uploads/S1DDoTQ7A.jpg)

[Source.](https://intexsoft.com/blog/introduction-to-3d-three-js-basics/)

The image above illustrates two popular `ThreeJs` cameras: the `PerspectiveCamera` and the `OrthographicCamera`. In the `OrthographicCamera`, the size of the projected image remains constant, as observed in the near clip plane. On the other hand, the `PerspectiveCamera`, which is commonly used in rendering a scene, mimics the human eye. This means that objects appear smaller when they are far from the camera and larger when they are close, similar to how the human eyes work.

### Lighting and Shadows
[`Lights`](https://threejs.org/docs/#api/en/lights/Light) make objects visible. In `ThreeJs`, lighting illuminates `scenes`, serving the same purpose as light sources. Three.js provides various types of lights with specific functions; some light sources in `ThreeJs` are [`AmbientLight`](https://threejs.org/docs/#api/en/lights/AmbientLighthttps://), [`PointLight`](https://threejs.org/docs/#api/en/lights/PointLight), and [`DirectionalLight`](https://threejs.org/docs/#api/en/lights/DirectionalLight). Additionally, `ThreeJs` facilitates [`shadow`](https://threejs-journey.com/lessons/shadows#) mapping to simulate and cast `shadows` within the `scene`. 

![image0-en](https://hackmd.io/_uploads/HJ6fl07XA.jpg)

[Source.](https://mofu-dev.com/en/blog/threejs-shadow-map/)

The diagram above illustrates the light sources and the direction of the shadows. The direction of the light determines where the shadow appears in the `scene`. When the light sources shine on the objects, they cast a shadow.

### Renderer
The [`Renderer`](https://threejs.org/docs/#api/en/constants/Renderer) in `ThreeJs` renders the 3D `scene` on the screen. It renders the `scene` based on the `camera` direction, and in return, it displays the result on the `canvas`. The `canvas` enables you to create dynamic 3D animations that respond to changes in the `scene` and `camera` position. The `canvas` is where the surface displays animations, 3D `objects`, and effects.

## How to Set up the ThreeJs Environment
A recommended approach for integrating `ThreeJs` in our project is by utilizing a build tool. The build tools fast-track the development process of the `ThreeJs` environment and ensure smooth integration. In this example, we will use the [`vite`](https://vitejs.dev/guide/) build tool and deploy [`NPM (Node Package Manager)`](https://docs.npmjs.com/) to configure the `ThreeJs` package. Follow these steps to set up the `ThreeJs` environment:

### Creating Project Folder and Installing Package File
After selecting the build tool for setting up our `ThreeJs` projects, you should navigate to your preferred path on your computer to create a new folder. To install the package file, go to the folder directory, then enter the following command in your project directory:
```
npm init -y 
```
The command above creates a package.json file containing the necessary information and dependencies for the project.

### Add Dependencies
To add dependencies, we will install two packages: `ThreeJs` and [`Vite`](https://vitejs.dev/guide/). First, we'll add `Vite`, followed by` ThreeJs`. To install `Vite`, enter the following command in your terminal:
```
npm install vite
```

`Dependencies`, `packages`, and `modules` holds the structure of our project folder, including files, libraries, and packages. After following all the steps above, we should have a project folder that contains the following `packages`, `dependencies`, and `modules`:

[`node_modules:`](https://nodejs.org/docs/v0.4.1/api/modules.html) The `node_modules` directory houses the project dependencies and resides at the root of the `Node.js` project.

[`Package.json:`](https://docs.npmjs.com/cli/v10/configuring-npm/package-json) The `package.json` file contains an array of `dependencies` listed within the dependencies property. It serves as a manifest and also stores information about an application. 

[`package-lock.json:`](https://docs.npmjs.com/cli/v10/configuring-npm/package-lock-json) The `package-lock.json` file contains details about the dependencies and their versions.

### Create the Website Structure
The website structure forms the foundation of our `ThreeJs` project and provides the development environment for other components. We've set up our project and installed `Vite` with other `packages`. Now, let's move on to establishing the website's structure. Within our project folder, let's create an `index.html` file.

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, 
    initial-scale=1.0" />
    <title>Three.js Project</title>
  </head>
  <body>
    <h1>Building my Three.js website</h1>
  </body>
</html>
```
The code block above explains the basic `HTML` code structure. The content within the `<head>` tag is not visible on the screen; only the content within the `<body>` tag will display on the screen.

### Update the Script Section

The `package.json` file needs to be updated to enable the activation of the `Vite` development `server` and build process. We will make changes to the `package.json` file. Let's replace the `scripts` section with the following:  
```
//package.json
"scripts": {
  "dev": "vite",
  "build": "vite build"
},
```
Since both scripts are available in the script section, we can now trigger the `dev` and build commands to initiate `Vite's` development server and build process. `Npm` runs respectively by utilizing the `Vite` dependency located within the `node_modules/` folder.

To run the development server, run the following command in your terminal:
```
npm run dev
```
In your code editor terminal, you should see a similar `URL`: `http://localhost:5173/`. Copy it and paste it into your browser to open a web page like the one below:

![Untitled-new](https://hackmd.io/_uploads/HyGeB0DZR.png)

The output above illustrates the result of the `HTML` code block placed within the `<body>` tags.

### Add Javascript 
The `JavaScript` file will serve as the structure of our project. To integrate `JavaScript` into our project, we will create a file named `script.js` within our project folder. At the end of the `<body>` tag in the `index.html` file, add the following `<script>`:

```html
<body>
    <h1>Building my Three.js website</h1>
    <script type="module" src="./script.js"></script>
</body>
```
### Install ThreeJs Package

A typical `ThreeJs` project requires at least an `HTML` file to set up the webpage and a `JavaScript` file to run the `ThreeJs` code. Now that we have established our project structure, we need to install and run our project on our local machine using npm and a build tool. To install the `ThreeJs` package, run the following command:
```
npm install three
```
### Import ThreeJs 
Importing `ThreeJs` into our `script.js` file is the final step in setting up our `ThreeJs` environment. It is best practice to import `ThreeJs` at the top of the `script.js` file. To import `ThreeJs` from the `Three dependencies` into the `script.js` file, type:

```javascript
import * as THREE from 'three'
```
If you have followed up to this point, you have successfully set up the `ThreeJs` library. 

## Understanding React Three Fiber

`React Three Fiber (R3F)` simplifies integrating 3D animation into a `React` application by leveraging familiar `React` concepts such as components and state management. With `ThreeJs`, you can build a 3D `scene` by leveraging `React.js` `components`, `hooks` such as `useState` and `useEffect`, and `state management` to manage `scene` changes. The `R3F` renders `ThreeJs` 3D contents in a `React.js` application by converting `JSX` code into a `ThreeJs` `scene`. `R3F` is a simplified tool developers utilize to create immersive 3D graphics within `React.js` applications.

## How to set up a React Three Fiber Project
To set up `React Three Fiber`, we will install the required dependencies and conditions for creating a 3D `scene`. We'll also use npm to install `React Three Fiber` in our `React.js` application. Here are the steps and guidelines for setting up `React Three Fiber`:

### Setting up a React Project
The first step in creatinging a `React.js` Three Fiber project is to set up a `React.js` Application using a build tool or create-react-app. We will utilise the [`Vite`](https://vitejs.dev/guide/) build tool in initialising our `React.js` application. To set up a `React.js` application using `Vite` take the following steps:

### Creating React Application with Vite

To create `React` application using `Vite`, go to your terminal and run this command:
```
npm create vite@latest
```
You will get a prompt, then select `React.js` as the framework and `JavaScript` as the programmng language. 

### Adding React Three Fiber and ThreeJs Dependency 
`ThreeJs` is a third-party library that was not created with `React.js`. To use `ThreeJs` in a `React.js` application, you need to integrate and initialize both the `R3F` and `ThreeJs` libraries within `React.js`. To install `R3F` and its dependencies and initialize `ThreeJs` in your application, run the following command in your terminal:
```
npm install three@0.158 @react-three/fiber@8.15
```

At this stage, our` R3F` project is set up and ready to launch. To begin the development server, navigate to your application directory and execute the following command:
```
npm run dev
```
When your `React.js` app compiles and displays in the browser, it will look like this:

![create-react-app](https://hackmd.io/_uploads/Bk84WB7XA.gif)

[source.](https://www.copycat.dev/blog/react-three-fiber/)

## How React Three Fiber Works	
`React Three Fiber (R3F)` is a renderer for `ThreeJs` and can be used within a `React.js` application. With `R3F`, you can create new `objects` and define `meshes`, `lights`, and `cameras`. These `objects` are rendered to the `scene` using `React.js` components. To set up a 3D `scene` with `R3F` in a `React.js` application, you need to initialise `R3F` and use the [`<Canvas>`](https://docs.pmnd.rs/react-three-fiber/api/canvas) element to create a 3D `scene`. The `<Canvas>` serves as the platform where the `ThreeJs` scene created by `R3F` is rendered. `R3F` makes it easier to create 3D `scenes` by allowing you to initiate new `objects` through components and place them in the `scene graph` for rendering on the screen.

In this section, we will take a practical step in learning `R3F` by building a 3D application and guiding you through setting up an `R3F` component.

### Setting up the Scene
Building a 3D scene in `R3F` can be likened to creating a web user interface with `HTML` and `CSS`. With `React Three Fiber`, we assemble `geometry`, `renderer`, `mesh`, `material`, and `light` within the `<Canvas>` tag to produce a 3D `scene`. Within the `<Canvas>` tag is where you develop the 3D `scene`. Below is an example of a code snippet to set up a `scene`:  

```jsx
import { Canvas } from "@react-three/fiber"; // Imports Canvas component from @react-three/fiber
import React from "react"; // Imports React for JSX syntax
import "./App.css"; // Imports a CSS file for styling

const App = () => {
  return (
     // Uses the Canvas component to create a 3D canvas
    <Canvas>
      {/* Adds a directional light to the scene */}
      <directionalLight position={[0, 0, 2]} />

      {/* Adds a mesh (3D object) to the scene */}
      <mesh position={[1, 0, 0]}>
        {/* Uses a boxGeometry for the mesh */}
        <boxGeometry />
        {/* Applies a standard material with an orange color to the mesh */}
        <meshStandardMaterial color={"orange"} />
      </mesh>
    </Canvas>
  );
};

export default App;
```
At the beginning of our code, we import `Canva` and wrap the entire code within it. `<Canva>` enables `scene` creation, `camera` setup, `lighting`, and more. The `<mesh>` tag combines the [`<boxGeometry />`](https://threejs.org/docs/#api/en/geometries/BoxGeometry) and [`<meshStandardMaterial />`](https://threejs.org/docs/#api/en/materials/MeshStandardMaterial) tags to create a cube.

We use the [`<directionalLight />`](https://threejs.org/docs/#api/en/lights/DirectionalLight) to add lighting, where colour and position properties work with the `<directionalLight />` tag to allow colour adjustments.The position property sets the x, y, and z coordinates of an object, for example, `position={[0=x, 0=y, 2=z]}`.

![Screenshot 2024-05-16 013640](https://hackmd.io/_uploads/r1JIBRM70.png)

The image above displays the code block preview for our React Three Fiber scene, which displays a cube.

### Setting up React Three Fiber Component
A `React.js` component is a reusable block of code that contains logic and user interface element. In the case of an `R3F` component, it contains a `<Canvas>`, `meshes`, `lights`, and `materials` to define and render a `scene`. `React.js` and `R3F` enable us to create re-usable components in building a 3D `scene` that is also responsive to `React.js states`. We will set up a `React.js` functional component in order to render our Cube. 

```jsx
import { Canvas } from "@react-three/fiber";
import React from "react";
import "./App.css";

// Define a functional component for rendering a cube
const Cube = ({ position, size, color }) => {
  return (
    <mesh position={position}>
      <boxGeometry args={size} />
      <meshStandardMaterial color={color} />
    </mesh>
  );
};

// Define the main App component
const App = () => {
  return (
    // Set up a canvas for rendering 3D content
    <Canvas>
      {/* Add a directional light to the scene */}
      <directionalLight position={[0, 0, 2]} />

      {/* Render cube components with specified positions, colors, and sizes */}
      <Cube position={[1, 0, 0]} color={"green"} size={[1, 1, 1]} />
      <Cube position={[-1, 0, 0]} color={"orange"} size={[1, 1, 1]} />
    </Canvas>
  );
};

export default App;
```

We created a `Cube` function component in the `App.jsx` file that receives props from the `<Cube />` component. The `<Cube />` component then renders the cubes in the browser.

![ViteReact-GoogleChrome2024-05-1519-55-41-ezgif.com-video-to-gif-converter](https://hackmd.io/_uploads/H13Vi3f70.gif)

The video above showcases the `React Three Fiber` animation of our React component. It displays a rotating 3D cube by zooming in and out.

### Animating React Three Fiber Objects with useFrame
To animate the `R3F` object with [`useFrame`](https://docs.pmnd.rs/react-three-fiber/tutorials/basic-animations), we imported `useFrame` and [`useRef`](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&ved=2ahUKEwiirrWG5veFAxXnV0EAHUrNBkMQFnoECCIQAQ&url=https%3A%2F%2Freact.dev%2Freference%2Freact%2FuseRef&usg=AOvVaw21oRfiJiDTo9Yh9AiVIixj&opi=89978449). Using `ref`, we access the cube and set its rotation on the `x-axis`. We import `useFrame` and `useRef`. Using `ref`, we access the cube and set its rotation on the x-axis. 

The `intensity` property enhances the sharpness of the object's color, while `<ambientLight />` unifies its color. `elapsedTime` controls the object's movement, and `* 2.0` increases its speed. The `useFrame` hook allows us to execute code on all rendered frames, such as running effects and updating controls. 

```jsx
import { Canvas, useFrame } from "@react-three/fiber";
import React, { useRef } from "react";
import "./App.css";

// Define a functional component for rendering a cube
const Cube = ({ position, size, color }) => {
  // This reference gives us direct access to the mesh
  const ref = useRef();

  // The useFrame hook controls and executes actions on every render
  useFrame((state, delta) => {
    // Rotate the cube around the x and y axes based on delta time
    ref.current.rotation.x += delta;
    ref.current.rotation.y += delta * 2.0;

    // Move the cube along the z-axis using a sine wave
    ref.current.position.z = Math.sin(state.clock.elapsedTime) * 2;
  });

  return (
    // Render a cube mesh with specified position, size, and color
    <mesh position={position} ref={ref}>
      <boxGeometry args={size} />
      <meshStandardMaterial color={color} />
    </mesh>
  );
};

// Define the main App component
const App = () => {
  return (
    // Render a Canvas component for WebGL rendering
    <Canvas>
      {/* Add a directional light to the scene */}
      <directionalLight position={[0, 0, 2]} intensity={0.5} />

      {/* Add an ambient light to the scene */}
      <ambientLight intensity={0.1} />

      {/* Render a Cube component with specified position, color, and size */}
      <Cube position={[-1, 0, 0]} color={"orange"} size={[1, 1, 1]} />
    </Canvas>
  );
};

export default App;
```
> `delta` represents the time difference between the current frame and the previous frame.

## How to Implement 3D Animation with ThreeJs
The `ThreeJs` animation `loop` is made up of various components that work together to produce stunning animations. These components include [`Date.now()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now), which calculates time, the [`animate function`](https://tutorial.techaltum.com/javascript-animate.html) that defines and updates the `scene`, demolishes objects that represent elements to animate, and [`requestAnimationFrame` ](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame), which creates a smooth animation `loop`.

To begin the animation `loop`, `Date.now()` marks the start of the `loop` and tracks time, allowing for the calculation of differences between `time frames`. Inside the `animate function`, properties of objects, such as rotation angles, position, and scale, are updated in the scene. The `demoMesh` object represents the elements that will be animated, and its rotational angles are updated accordingly. For `demoMesh` to rotate, it must be refreshed based on the `deltaTime`.

The `requestAnimationFrame` creates an animation loop by sending requests to the browser to apply the `animate function` to the next frame. When these components work in harmony, they produce amazing animations by updating the scene's object repeatedly and implementing the rendering process of the browser.

### Fundamentals of 3D engines
The fundamentals of 3D engines introduce key concepts of 3D, software selection, and workflow understanding. These basics familiarize you with 3D principles, including `faces`, `vertices`, `meshes`, and `edges`, which are crucial for creating intuitive and visually realistic applications. Blender, an essential tool, enables various 3D model enhancements such as realism, movement, shaping, textures, and colours. `Lighting`, `camera`, and rendering play vital roles in bringing 3D applications to life, influencing object appearance in `scenes`. A pictorial diagram demonstrates the functioning of the `ThreeJs` 3D engine.

![Untitled-2024-03-09-23400new](https://hackmd.io/_uploads/rycWxR7MC.png)

The `ThreeJs` 3D engine functions as a connectivity of objects. The `scene` graph serves as the building block of a 3D project, holding the objects aligned in a hierarchical tree-like parent/child structure, as depicted above.

A `camera` doesn't necessarily have to be in the `scene` graph, but it still adheres to a parent/child structure with the potential for multiple `cameras` in a `scene`. To create a `Mesh`, one needs a combination of material and geometry. An object can serve several meshes. The Renderer takes the 3D `scenes` and `cameras`, transforming them into a `2D Canvas` or `HTML` for display on the screen.

### How to use ThreeJs Materials
Materials give objects their surface properties such as colour, texture, reflection, etc. Some examples of materials include [`MeshBasicMaterial`](https://threejs.org/docs/#api/en/materials/MeshBasicMaterial), [`MeshDepthMaterial`](https://threejs.org/docs/#api/en/materials/MeshDepthMaterial) [](https://), [`MeshPhongMaterial`](https://threejs.org/docs/#api/en/materials/MeshPhongMaterial), etc. Three.js provides a material base class, [`THREE.Material`](https://threejs.org/docs/#api/en/materials/Material), which lists all common properties such as Basic, Blending, and Advanced properties.

The code snippet below adds a `MeshPhongMaterial` class to a `ThreeJs` project:

```javascript
const material = new THREE.MeshPhongMaterial({
    color: 0xFF0000,   // red (can also use a CSS color string here)
});
```
Here is the output of the `MeshPhongMaterial` on the browser:

![material2](https://hackmd.io/_uploads/SkUYyNm7C.jpg)

### Working with Mesh Geometry
A mesh geometry in `ThreeJs` represents a shape. The shape can be a cube or a pyramid. A `geometry` comprises points called `vertices` and multiple `faces` that connect those points. An example of `vertices` in `Three.js` is the numbers on each corner of the cube in the image above. The illustration below describes how `mesh geometry` works.

![Imagenew](https://hackmd.io/_uploads/HyMpb0w-0.png)

In the diagram above, the `mesh` is added to the `scene`, and the geometry defines the shape of the cube. 

Here's how you add a mesh to a project:
```javascript
const box = new THREE.Mesh(boxGeometry, boxMaterial);
```
### ThreeJs Components and Scenes
The diagram below replicates the structure of the `ThreeJs component`. The component functions as a container for holding `ThreeJs objects`, such as the `camera`, `lights`, `materials`, `geometry`, and more, enabling the definition and organization of 3D elements within the component and the `scene`. The illustration below describes how `mesh` components and `scenes` work.

![unnamed (5)new](https://hackmd.io/_uploads/HJnKAaWbC.png)

Here is the output of the `MeshPhongMaterial` on the browser:

```javascript
const scene = new THREE.Scene();
```
## Animating with React Three Fiber
To execute animations in our React application, `R3F` leverages the `useFrame` and `useRef` hooks to access the `mesh` and control how 3D `objects` are manipulated and rendered. With `useRef`, `ThreeJs` can interact with [`Document Object Model (DOM)`](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Introduction) properties and modify object properties without unexpectedly rendering components. The `useFrame` hook allows you to execute your animation at each `frame` of the animation `loop`. It controls and updates the rotation, scale, and position of 3D `objects` on every `frame`.

### Animating with useFrame
[`UseFrame`](https://docs.pmnd.rs/react-three-fiber/tutorials/basic-animations) is a standard animation hook for the `React Three Fiber` library. It enables you to execute code on each `frame` during every `loop`. You can update the `scene` and render an animation or property on every `loop`. With `useFrame`, you can control the appearance and movement in the 3D `scene` during each animation `loop`. Its ability to manage the movements, scale, and rotation of 3D `objects` results in smooth animation in the `scene`. Let's see the example below:

```jsx
import { useFrame } from '@react-three/fiber'

// Define a functional component for an animated box
function MyAnimatedBox() {
  // Use the useFrame hook to execute code on every frame
  useFrame(() => {
    console.log("executing every frame code!")
  })
  
  // Return a mesh representing a box with a basic material
  return (
    <mesh>
      <boxGeometry />
      <meshBasicMaterial color="royalblue" />
    </mesh>
  )
}
```
In the code above, `useFrame` hook inside `MyAnimatedBox` will be called on every `frame`, passing an object containing the state of our Fiber scene.

![Screenshot 2024-05-16 083307](https://hackmd.io/_uploads/SJdonEXmR.png)


The image above previews a static 3D cube created using the `useFrame` hook. It displays the shape of the the cube with dark corners. You can animate the static cube, by include the `useRef()` hook in inbetween `useFrame`.

### Animating with useRef
The `useRef` hook in `React Three Fiber` allows us to change the `mesh` on each `frame` of an animation loop. An animation loop is a repeated process that updates and renders continuously, while a `frame` is a single repetition of this loop. To change the mesh on each `frame`, we use the `useRef` to obtain a reference. The `useRef` is also mutable, which means that it doesn't cause a `React.js` component to rerender when properties are changed. Let's see the example below of `useRef` hook:

<!-- prettier-ignore -->
```jsx
import { Canvas, useFrame } from "@react-three/fiber";
import React, { useRef } from "react";
import "./App.css";

// Custom component for a rotating cube
const Cube = ({ position, size, color }) => {
  const ref = useRef(); // Create a reference for the cube

  // Use useFrame to update the cube's rotation on each frame
  useFrame((state, delta) => {
    ref.current.rotation.x += delta; // Rotate the cube along the x-axis
  });

  return (
    <mesh position={position} ref={ref}> {/* Define the cube */}
      <boxGeometry args={size} /> {/* Set the cube's size */}
      <meshStandardMaterial color={color} /> {/* Apply material to the cube */}
    </mesh>
  );
};

// Main App component
const App = () => {
  return (
    <Canvas>
      <directionalLight position={[0, 0, 2]} intensity={0.5} /> {/* Add a directional light */}
      <ambientLight intensity={0.1} /> {/* Add ambient light for soft illumination */}
      {/* Render the Cube component with specific properties */}
      <Cube position={[-1, 0, 0]} color="royalblue" size={[1, 1, 1]} />
    </Canvas>
  );
};

export default App; 
```

In the code above, the `useRef` hook creates a reference ``(myMesh)`` to the `<mesh>` element, enabling manipulation of the `mesh` within the component's logic and mutation of `useFrame`. Here is the output in our browser of the 3D cube animation as we animate using `useRef`:

![ViteReact-GoogleChrome2024-05-1613-15-47-ezgif.com-crop (1)](https://hackmd.io/_uploads/HypwRu7XR.gif)


### Implementing Cameras and Lights
`Cameras` in `R3F` determine how users view the scene. Different types of `R3F` `cameras` influence the position and perspective of how you render a `scene`; as a result, they influence what the user sees. Each `camera` has its unique properties, allowing developers to apply different types of `cameras` to modify how a `scene` appears. For instance, the `perspective camera` provides details and information about distance and depth. It also affects everything in the perspective projection, meaning that the further the `object`, the smaller it appears. On the other hand, the `orthographic camera` accurately captures the sizes of all `objects`. Its projection mode keeps the `object` size constant regardless of the distance from the `camera`.

Without light in a scene, nothing can be visible to the eyes. The presence of light brings visibilty to the scene. 

![Untitled-2024-03-09-2340](https://hackmd.io/_uploads/BJBVN0--0.png)

When it comes to lighting in `R3F` and `ThreeJs`, the scene doesn't light up automatically. We have to manually add a Light source to the scene. The different light sources in these frameworks come from specific directions or spots, and they work similarly to natural light sources. This means that nothing is visible in the scene until light is present. It's important to note that different light sources have different behaviors. For instance, the `AmbientLight` doesn't cast shadows since it lacks direction, while the `PointLight` can cast shadows. You should choose the type of light source based on the specific needs of your application. Some commonly used light sources include [`DirectionalLight`](https://threejs.org/docs/#api/en/lights/DirectionalLight), [`PointLight`](https://threejs.org/docs/#api/en/lights/PointLight), [`spotlights`](https://threejs.org/docs/#api/en/lights/SpotLight), and [`AmbientLight`](https://threejs.org/docs/#api/en/lights/AmbientLighthttps://).

![upload_0d375b63106c214468ef554ab04ca593new](https://hackmd.io/_uploads/Hk47oTWbR.png)

The diagram illustrates the behaviours, light directions, and positions of the various light sources. Each light source shines from a different direction, which affects the object's appearance.

## Conclusion
The article provides a comprehensive overview of the `ThreeJs` and `R3F` libraries, covering their fundamentals, features, and how they can enhance web applications with interactive 3D animations. Both the `ThreeJs` library and `React Three Fiber` offer robust features that enable developers to explore the scope of 3D animation and create stunning 3D applications. Choosing between these libraries depends on the specific project requirements and your familiarity with the technologies. Leave a comment if you have any questions or need further clarification.